Files
rust/src/rt/memory_region.cpp
T
Eric Holk 8acadb17c2 Work on debugging race conditions.
Ports and channels have been moved to the kernel pool, since they've
been known to outlive their associated task. This probably isn't the
right thing to do, the life cycle needs fixed instead.

Some refactorying in memory_region.cpp. Added a helper function to
increment and decrement the allocation counter. This makes it easier
to switch between atomic and non-atomic increments. Using atomic
increments for now, although this still does not fix the problem.
2011-07-07 18:22:27 -07:00

127 lines
3.5 KiB
C++

#include "rust_internal.h"
#include "memory_region.h"
// NB: please do not commit code with this uncommented. It's
// hugely expensive and should only be used as a last resort.
//
// #define TRACK_ALLOCATIONS
memory_region::memory_region(rust_srv *srv, bool synchronized) :
_srv(srv), _parent(NULL), _live_allocations(0),
_detailed_leaks(getenv("RUST_DETAILED_LEAKS") != NULL),
_synchronized(synchronized) {
}
memory_region::memory_region(memory_region *parent) :
_srv(parent->_srv), _parent(parent), _live_allocations(0),
_detailed_leaks(parent->_detailed_leaks),
_synchronized(parent->_synchronized) {
// Nop.
}
void memory_region::add_alloc() {
//_live_allocations++;
sync::increment(_live_allocations);
}
void memory_region::dec_alloc() {
//_live_allocations--;
sync::decrement(_live_allocations);
}
void memory_region::free(void *mem) {
// printf("free: ptr 0x%" PRIxPTR" region=%p\n", (uintptr_t) mem, this);
if (!mem) { return; }
if (_synchronized) { _lock.lock(); }
#ifdef TRACK_ALLOCATIONS
if (_allocation_list.replace(mem, NULL) == false) {
printf("free: ptr 0x%" PRIxPTR " is not in allocation_list\n",
(uintptr_t) mem);
_srv->fatal("not in allocation_list", __FILE__, __LINE__, "");
}
#endif
if (_live_allocations < 1) {
_srv->fatal("live_allocs < 1", __FILE__, __LINE__, "");
}
dec_alloc();
_srv->free(mem);
if (_synchronized) { _lock.unlock(); }
}
void *
memory_region::realloc(void *mem, size_t size) {
if (_synchronized) { _lock.lock(); }
if (!mem) {
add_alloc();
}
void *newMem = _srv->realloc(mem, size);
#ifdef TRACK_ALLOCATIONS
if (_allocation_list.replace(mem, newMem) == false) {
printf("realloc: ptr 0x%" PRIxPTR " is not in allocation_list\n",
(uintptr_t) mem);
_srv->fatal("not in allocation_list", __FILE__, __LINE__, "");
}
#endif
if (_synchronized) { _lock.unlock(); }
return newMem;
}
void *
memory_region::malloc(size_t size) {
if (_synchronized) { _lock.lock(); }
add_alloc();
void *mem = _srv->malloc(size);
#ifdef TRACK_ALLOCATIONS
_allocation_list.append(mem);
#endif
// printf("malloc: ptr 0x%" PRIxPTR " region=%p\n",
// (uintptr_t) mem, this);
if (_synchronized) { _lock.unlock(); }
return mem;
}
void *
memory_region::calloc(size_t size) {
if (_synchronized) { _lock.lock(); }
add_alloc();
void *mem = _srv->malloc(size);
memset(mem, 0, size);
#ifdef TRACK_ALLOCATIONS
_allocation_list.append(mem);
#endif
if (_synchronized) { _lock.unlock(); }
return mem;
}
memory_region::~memory_region() {
if (_live_allocations == 0) {
return;
}
char msg[128];
snprintf(msg, sizeof(msg),
"leaked memory in rust main loop (%" PRIuPTR " objects)",
_live_allocations);
#ifdef TRACK_ALLOCATIONS
if (_detailed_leaks) {
for (size_t i = 0; i < _allocation_list.size(); i++) {
if (_allocation_list[i] != NULL) {
printf("allocation 0x%" PRIxPTR " was not freed\n",
(uintptr_t) _allocation_list[i]);
}
}
}
#endif
_srv->fatal(msg, __FILE__, __LINE__, "%d objects", _live_allocations);
}
//
// Local Variables:
// mode: C++
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//