2016-01-18 10:44:49 -08:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <map>
|
2017-09-07 17:48:44 -07:00
|
|
|
#include <vector>
|
2018-05-11 16:53:47 -07:00
|
|
|
#include <mutex>
|
2016-01-18 10:44:49 -08:00
|
|
|
|
|
|
|
|
using std::map;
|
2017-09-07 17:48:44 -07:00
|
|
|
using std::vector;
|
2016-01-18 10:44:49 -08:00
|
|
|
|
2016-11-04 09:18:38 -07:00
|
|
|
static bool _enabled = false;
|
2016-01-18 10:44:49 -08:00
|
|
|
static size_t _allocation_count = 0;
|
|
|
|
|
static map<void *, size_t> _outstanding_allocations;
|
2018-05-11 16:53:47 -07:00
|
|
|
static std::mutex _outstanding_allocations_mutex;
|
|
|
|
|
static bool _multi_threaded_mode = false;
|
2016-01-18 10:44:49 -08:00
|
|
|
|
|
|
|
|
namespace record_alloc {
|
|
|
|
|
|
2018-05-11 16:53:47 -07:00
|
|
|
void start(bool multi_threaded_mode) {
|
2016-01-18 10:44:49 -08:00
|
|
|
_enabled = true;
|
|
|
|
|
_allocation_count = 0;
|
|
|
|
|
_outstanding_allocations.clear();
|
2018-05-11 16:53:47 -07:00
|
|
|
_multi_threaded_mode = multi_threaded_mode;
|
2016-01-18 10:44:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void stop() {
|
|
|
|
|
_enabled = false;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-07 17:48:44 -07:00
|
|
|
vector<size_t> outstanding_allocation_indices() {
|
|
|
|
|
vector<size_t> result;
|
2016-01-18 10:44:49 -08:00
|
|
|
for (const auto &entry : _outstanding_allocations) {
|
2017-09-07 17:48:44 -07:00
|
|
|
result.push_back(entry.second);
|
2016-01-18 10:44:49 -08:00
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t allocation_count() {
|
2018-05-11 16:53:47 -07:00
|
|
|
size_t result;
|
|
|
|
|
_outstanding_allocations_mutex.lock();
|
|
|
|
|
result = _allocation_count;
|
|
|
|
|
_outstanding_allocations_mutex.unlock();
|
|
|
|
|
return result;
|
2016-01-18 10:44:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace record_alloc
|
|
|
|
|
|
2016-11-04 09:18:38 -07:00
|
|
|
extern "C" {
|
2016-01-18 10:44:49 -08:00
|
|
|
|
2016-05-16 10:44:19 -07:00
|
|
|
static void *record_allocation(void *result) {
|
2017-09-07 17:48:44 -07:00
|
|
|
if (!_enabled) return result;
|
2018-05-11 16:53:47 -07:00
|
|
|
if (_multi_threaded_mode) _outstanding_allocations_mutex.lock();
|
2016-01-18 10:44:49 -08:00
|
|
|
_outstanding_allocations[result] = _allocation_count;
|
|
|
|
|
_allocation_count++;
|
2018-05-11 16:53:47 -07:00
|
|
|
if (_multi_threaded_mode) _outstanding_allocations_mutex.unlock();
|
2016-01-18 10:44:49 -08:00
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void record_deallocation(void *pointer) {
|
2018-05-11 16:53:47 -07:00
|
|
|
if (_multi_threaded_mode) _outstanding_allocations_mutex.lock();
|
2016-01-18 10:44:49 -08:00
|
|
|
auto entry = _outstanding_allocations.find(pointer);
|
|
|
|
|
if (entry != _outstanding_allocations.end()) {
|
|
|
|
|
_outstanding_allocations.erase(entry);
|
|
|
|
|
}
|
2018-05-11 16:53:47 -07:00
|
|
|
if (_multi_threaded_mode) _outstanding_allocations_mutex.unlock();
|
2016-01-18 10:44:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void *ts_record_malloc(size_t size) {
|
2016-11-04 09:18:38 -07:00
|
|
|
return record_allocation(malloc(size));
|
2016-01-18 10:44:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void *ts_record_realloc(void *pointer, size_t size) {
|
2016-11-04 09:18:38 -07:00
|
|
|
record_deallocation(pointer);
|
|
|
|
|
return record_allocation(realloc(pointer, size));
|
2016-01-18 10:44:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void *ts_record_calloc(size_t count, size_t size) {
|
2016-11-04 09:18:38 -07:00
|
|
|
return record_allocation(calloc(count, size));
|
2016-01-18 10:44:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ts_record_free(void *pointer) {
|
|
|
|
|
record_deallocation(pointer);
|
2017-06-14 11:02:59 -04:00
|
|
|
free(pointer);
|
2016-01-18 10:44:49 -08:00
|
|
|
}
|
|
|
|
|
|
2016-05-16 10:44:19 -07:00
|
|
|
bool ts_record_allocations_toggle(bool value) {
|
|
|
|
|
bool previous_value = _enabled;
|
|
|
|
|
_enabled = value;
|
|
|
|
|
return previous_value;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 10:44:49 -08:00
|
|
|
}
|