Lots of changes around memory managment in the Runtime. Added memory regions and fixed race caused by calling rust_srv::malloc() from multiple threads when sending messages.
This commit is contained in:
@@ -266,7 +266,8 @@ RUNTIME_CS := rt/sync/timer.cpp \
|
|||||||
rt/rust_timer.cpp \
|
rt/rust_timer.cpp \
|
||||||
rt/circular_buffer.cpp \
|
rt/circular_buffer.cpp \
|
||||||
rt/isaac/randport.cpp \
|
rt/isaac/randport.cpp \
|
||||||
rt/rust_srv.cpp
|
rt/rust_srv.cpp \
|
||||||
|
rt/memory_region.cpp
|
||||||
|
|
||||||
RUNTIME_HDR := rt/globals.h \
|
RUNTIME_HDR := rt/globals.h \
|
||||||
rt/rust.h \
|
rt/rust.h \
|
||||||
@@ -285,7 +286,9 @@ RUNTIME_HDR := rt/globals.h \
|
|||||||
rt/util/hash_map.h \
|
rt/util/hash_map.h \
|
||||||
rt/sync/sync.h \
|
rt/sync/sync.h \
|
||||||
rt/sync/timer.h \
|
rt/sync/timer.h \
|
||||||
rt/rust_srv.h
|
rt/rust_srv.h \
|
||||||
|
rt/memory_region.h \
|
||||||
|
rt/memory.h
|
||||||
|
|
||||||
RUNTIME_INCS := -Irt/isaac -Irt/uthash
|
RUNTIME_INCS := -Irt/isaac -Irt/uthash
|
||||||
RUNTIME_OBJS := $(RUNTIME_CS:.cpp=$(CFG_OBJ_SUFFIX))
|
RUNTIME_OBJS := $(RUNTIME_CS:.cpp=$(CFG_OBJ_SUFFIX))
|
||||||
|
|||||||
60
src/rt/memory.h
Normal file
60
src/rt/memory.h
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MEMORY_H
|
||||||
|
#define MEMORY_H
|
||||||
|
|
||||||
|
|
||||||
|
inline void *operator new(size_t size, void *mem) {
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void *operator new(size_t size, rust_dom *dom) {
|
||||||
|
return dom->malloc(size, memory_region::LOCAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void *operator new[](size_t size, rust_dom *dom) {
|
||||||
|
return dom->malloc(size, memory_region::LOCAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void *operator new(size_t size, rust_dom &dom) {
|
||||||
|
return dom.malloc(size, memory_region::LOCAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void *operator new[](size_t size, rust_dom &dom) {
|
||||||
|
return dom.malloc(size, memory_region::LOCAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void *operator new(size_t size, rust_dom *dom,
|
||||||
|
memory_region::memory_region_type type) {
|
||||||
|
return dom->malloc(size, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void *operator new[](size_t size, rust_dom *dom,
|
||||||
|
memory_region::memory_region_type type) {
|
||||||
|
return dom->malloc(size, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void *operator new(size_t size, rust_dom &dom,
|
||||||
|
memory_region::memory_region_type type) {
|
||||||
|
return dom.malloc(size, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void *operator new[](size_t size, rust_dom &dom,
|
||||||
|
memory_region::memory_region_type type) {
|
||||||
|
return dom.malloc(size, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void operator delete(void *mem, rust_dom *dom) {
|
||||||
|
dom->free(mem, memory_region::LOCAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void operator delete(void *mem, rust_dom *dom,
|
||||||
|
memory_region::memory_region_type type) {
|
||||||
|
dom->free(mem, type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* MEMORY_H */
|
||||||
100
src/rt/memory_region.cpp
Normal file
100
src/rt/memory_region.cpp
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "rust_internal.h"
|
||||||
|
#include "memory_region.h"
|
||||||
|
|
||||||
|
#define TRACK_ALLOCATIONS
|
||||||
|
|
||||||
|
memory_region::memory_region(rust_srv *srv, bool synchronized) :
|
||||||
|
_srv(srv), _parent(NULL), _live_allocations(0),
|
||||||
|
_synchronized(synchronized) {
|
||||||
|
// Nop.
|
||||||
|
}
|
||||||
|
|
||||||
|
memory_region::memory_region(memory_region *parent) :
|
||||||
|
_srv(parent->_srv), _parent(parent), _live_allocations(0),
|
||||||
|
_synchronized(parent->_synchronized) {
|
||||||
|
// Nop.
|
||||||
|
}
|
||||||
|
|
||||||
|
void memory_region::free(void *mem) {
|
||||||
|
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__, "");
|
||||||
|
}
|
||||||
|
_live_allocations--;
|
||||||
|
_srv->free(mem);
|
||||||
|
if (_synchronized) { _lock.unlock(); }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
memory_region::realloc(void *mem, size_t size) {
|
||||||
|
if (_synchronized) { _lock.lock(); }
|
||||||
|
if (!mem) {
|
||||||
|
_live_allocations++;
|
||||||
|
}
|
||||||
|
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(); }
|
||||||
|
_live_allocations++;
|
||||||
|
void *mem = _srv->malloc(size);
|
||||||
|
#ifdef TRACK_ALLOCATIONS
|
||||||
|
_allocation_list.append(mem);
|
||||||
|
#endif
|
||||||
|
if (_synchronized) { _lock.unlock(); }
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
memory_region::calloc(size_t size) {
|
||||||
|
if (_synchronized) { _lock.lock(); }
|
||||||
|
_live_allocations++;
|
||||||
|
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
|
||||||
|
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);
|
||||||
|
}
|
||||||
37
src/rt/memory_region.h
Normal file
37
src/rt/memory_region.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* The Rust runtime uses memory regions to provide a primitive level of
|
||||||
|
* memory management and isolation between tasks, and domains.
|
||||||
|
*
|
||||||
|
* TODO: Implement a custom lock-free malloc / free instead of relying solely
|
||||||
|
* on the standard malloc / free.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MEMORY_REGION_H
|
||||||
|
#define MEMORY_REGION_H
|
||||||
|
|
||||||
|
#include "sync/spin_lock.h"
|
||||||
|
|
||||||
|
class rust_srv;
|
||||||
|
|
||||||
|
class memory_region {
|
||||||
|
private:
|
||||||
|
rust_srv *_srv;
|
||||||
|
memory_region *_parent;
|
||||||
|
size_t _live_allocations;
|
||||||
|
array_list<void *> _allocation_list;
|
||||||
|
const bool _synchronized;
|
||||||
|
spin_lock _lock;
|
||||||
|
public:
|
||||||
|
enum memory_region_type {
|
||||||
|
LOCAL = 0x1, SYNCHRONIZED = 0x2
|
||||||
|
};
|
||||||
|
memory_region(rust_srv *srv, bool synchronized);
|
||||||
|
memory_region(memory_region *parent);
|
||||||
|
void *malloc(size_t size);
|
||||||
|
void *calloc(size_t size);
|
||||||
|
void *realloc(void *mem, size_t size);
|
||||||
|
void free(void *mem);
|
||||||
|
virtual ~memory_region();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* MEMORY_REGION_H */
|
||||||
@@ -21,11 +21,6 @@
|
|||||||
|
|
||||||
#include "rust_srv.h"
|
#include "rust_srv.h"
|
||||||
|
|
||||||
inline void *operator new(size_t size, rust_srv *srv)
|
|
||||||
{
|
|
||||||
return srv->malloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local Variables:
|
* Local Variables:
|
||||||
* fill-column: 78;
|
* fill-column: 78;
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ last_os_error(rust_task *task) {
|
|||||||
#endif
|
#endif
|
||||||
size_t fill = strlen(buf) + 1;
|
size_t fill = strlen(buf) + 1;
|
||||||
size_t alloc = next_power_of_two(sizeof(rust_str) + fill);
|
size_t alloc = next_power_of_two(sizeof(rust_str) + fill);
|
||||||
void *mem = dom->malloc(alloc);
|
void *mem = dom->malloc(alloc, memory_region::LOCAL);
|
||||||
if (!mem) {
|
if (!mem) {
|
||||||
task->fail(1);
|
task->fail(1);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -134,7 +134,7 @@ str_alloc_with_data(rust_task *task,
|
|||||||
{
|
{
|
||||||
rust_dom *dom = task->dom;
|
rust_dom *dom = task->dom;
|
||||||
size_t alloc = next_power_of_two(sizeof(rust_str) + n_bytes);
|
size_t alloc = next_power_of_two(sizeof(rust_str) + n_bytes);
|
||||||
void *mem = dom->malloc(alloc);
|
void *mem = dom->malloc(alloc, memory_region::LOCAL);
|
||||||
if (!mem)
|
if (!mem)
|
||||||
return NULL;
|
return NULL;
|
||||||
rust_str *st = new (mem) rust_str(dom, alloc, fill, d);
|
rust_str *st = new (mem) rust_str(dom, alloc, fill, d);
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ rust_dom::rust_dom(rust_srv *srv, rust_crate const *root_crate,
|
|||||||
root_crate(root_crate),
|
root_crate(root_crate),
|
||||||
_log(srv, this),
|
_log(srv, this),
|
||||||
srv(srv),
|
srv(srv),
|
||||||
|
local_region(&srv->local_region),
|
||||||
|
synchronized_region(&srv->synchronized_region),
|
||||||
name(name),
|
name(name),
|
||||||
running_tasks(this),
|
running_tasks(this),
|
||||||
blocked_tasks(this),
|
blocked_tasks(this),
|
||||||
@@ -144,36 +146,65 @@ rust_dom::fail() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
rust_dom::malloc(size_t sz) {
|
rust_dom::malloc(size_t size) {
|
||||||
void *p = srv->malloc(sz);
|
return malloc(size, memory_region::LOCAL);
|
||||||
I(this, p);
|
|
||||||
log(rust_log::MEM,
|
|
||||||
"%s @0x%" PRIxPTR " rust_dom::malloc(%d) -> 0x%" PRIxPTR,
|
|
||||||
name, (uintptr_t) this, sz, p);
|
|
||||||
return p;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
rust_dom::calloc(size_t sz) {
|
rust_dom::malloc(size_t size, memory_region::memory_region_type type) {
|
||||||
void *p = this->malloc(sz);
|
if (type == memory_region::LOCAL) {
|
||||||
memset(p, 0, sz);
|
return local_region.malloc(size);
|
||||||
return p;
|
} else if (type == memory_region::SYNCHRONIZED) {
|
||||||
|
return synchronized_region.malloc(size);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
rust_dom::realloc(void *p, size_t sz) {
|
rust_dom::calloc(size_t size) {
|
||||||
void *p1 = srv->realloc(p, sz);
|
return calloc(size, memory_region::LOCAL);
|
||||||
I(this, p1);
|
}
|
||||||
log(rust_log::MEM, "rust_dom::realloc(0x%" PRIxPTR ", %d) -> 0x%" PRIxPTR,
|
|
||||||
p, sz, p1);
|
void *
|
||||||
return p1;
|
rust_dom::calloc(size_t size, memory_region::memory_region_type type) {
|
||||||
|
if (type == memory_region::LOCAL) {
|
||||||
|
return local_region.calloc(size);
|
||||||
|
} else if (type == memory_region::SYNCHRONIZED) {
|
||||||
|
return synchronized_region.calloc(size);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
rust_dom::realloc(void *mem, size_t size) {
|
||||||
|
return realloc(mem, size, memory_region::LOCAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
rust_dom::realloc(void *mem, size_t size,
|
||||||
|
memory_region::memory_region_type type) {
|
||||||
|
if (type == memory_region::LOCAL) {
|
||||||
|
return local_region.realloc(mem, size);
|
||||||
|
} else if (type == memory_region::SYNCHRONIZED) {
|
||||||
|
return synchronized_region.realloc(mem, size);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rust_dom::free(void *p) {
|
rust_dom::free(void *mem) {
|
||||||
log(rust_log::MEM, "rust_dom::free(0x%" PRIxPTR ")", p);
|
free(mem, memory_region::LOCAL);
|
||||||
I(this, p);
|
}
|
||||||
srv->free(p);
|
|
||||||
|
void
|
||||||
|
rust_dom::free(void *mem, memory_region::memory_region_type type) {
|
||||||
|
log(rust_log::MEM, "rust_dom::free(0x%" PRIxPTR ")", mem);
|
||||||
|
if (type == memory_region::LOCAL) {
|
||||||
|
local_region.free(mem);
|
||||||
|
} else if (type == memory_region::SYNCHRONIZED) {
|
||||||
|
synchronized_region.free(mem);
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __WIN32__
|
#ifdef __WIN32__
|
||||||
@@ -264,7 +295,6 @@ void rust_dom::send_message(rust_message *message) {
|
|||||||
message,
|
message,
|
||||||
&_incoming_message_queue,
|
&_incoming_message_queue,
|
||||||
this);
|
this);
|
||||||
A(this, message->dom == this, "Message owned by non-local domain.");
|
|
||||||
_incoming_message_queue.enqueue(message);
|
_incoming_message_queue.enqueue(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,7 +307,8 @@ void rust_dom::drain_incoming_message_queue() {
|
|||||||
log(rust_log::COMM, "<== processing incoming message \"%s\" 0x%"
|
log(rust_log::COMM, "<== processing incoming message \"%s\" 0x%"
|
||||||
PRIxPTR, message->label, message);
|
PRIxPTR, message->label, message);
|
||||||
message->process();
|
message->process();
|
||||||
delete message;
|
message->~rust_message();
|
||||||
|
this->synchronized_region.free(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,8 +353,7 @@ rust_dom::get_port_proxy_synchronized(rust_port *port) {
|
|||||||
* Returns NULL if no tasks can be scheduled.
|
* Returns NULL if no tasks can be scheduled.
|
||||||
*/
|
*/
|
||||||
rust_task *
|
rust_task *
|
||||||
rust_dom::schedule_task()
|
rust_dom::schedule_task() {
|
||||||
{
|
|
||||||
I(this, this);
|
I(this, this);
|
||||||
// FIXME: in the face of failing tasks, this is not always right.
|
// FIXME: in the face of failing tasks, this is not always right.
|
||||||
// I(this, n_live_tasks() > 0);
|
// I(this, n_live_tasks() > 0);
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ struct rust_dom
|
|||||||
rust_crate const *root_crate;
|
rust_crate const *root_crate;
|
||||||
rust_log _log;
|
rust_log _log;
|
||||||
rust_srv *srv;
|
rust_srv *srv;
|
||||||
|
memory_region local_region;
|
||||||
|
memory_region synchronized_region;
|
||||||
const char *const name;
|
const char *const name;
|
||||||
ptr_vec<rust_task> running_tasks;
|
ptr_vec<rust_task> running_tasks;
|
||||||
ptr_vec<rust_task> blocked_tasks;
|
ptr_vec<rust_task> blocked_tasks;
|
||||||
@@ -58,10 +60,15 @@ struct rust_dom
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
void logptr(char const *msg, T* ptrval);
|
void logptr(char const *msg, T* ptrval);
|
||||||
void fail();
|
void fail();
|
||||||
void *malloc(size_t sz);
|
void *malloc(size_t size);
|
||||||
void *calloc(size_t sz);
|
void *malloc(size_t size, memory_region::memory_region_type type);
|
||||||
void *realloc(void *data, size_t sz);
|
void *calloc(size_t size);
|
||||||
void free(void *p);
|
void *calloc(size_t size, memory_region::memory_region_type type);
|
||||||
|
void *realloc(void *mem, size_t size);
|
||||||
|
void *realloc(void *mem, size_t size,
|
||||||
|
memory_region::memory_region_type type);
|
||||||
|
void free(void *mem);
|
||||||
|
void free(void *mem, memory_region::memory_region_type type);
|
||||||
|
|
||||||
void send_message(rust_message *message);
|
void send_message(rust_message *message);
|
||||||
void drain_incoming_message_queue();
|
void drain_incoming_message_queue();
|
||||||
|
|||||||
@@ -173,25 +173,7 @@ check_null(rust_dom *dom, T value, char const *expr,
|
|||||||
|
|
||||||
#define CHECK_NULL(dom, e) (check_null(dom, e, #e, __FILE__, __LINE__))
|
#define CHECK_NULL(dom, e) (check_null(dom, e, #e, __FILE__, __LINE__))
|
||||||
|
|
||||||
inline void *operator new(size_t sz, void *mem) {
|
#include "memory.h"
|
||||||
return mem;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void *operator new(size_t sz, rust_dom *dom) {
|
|
||||||
return dom->malloc(sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void *operator new[](size_t sz, rust_dom *dom) {
|
|
||||||
return dom->malloc(sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void *operator new(size_t sz, rust_dom &dom) {
|
|
||||||
return dom.malloc(sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void *operator new[](size_t sz, rust_dom &dom) {
|
|
||||||
return dom.malloc(sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct
|
struct
|
||||||
rust_timer
|
rust_timer
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
rust_message::
|
rust_message::
|
||||||
rust_message(const char* label, rust_task *source, rust_task *target) :
|
rust_message(const char* label, rust_task *source, rust_task *target) :
|
||||||
dom(target->dom), label(label),
|
label(label),
|
||||||
|
_dom(target->dom),
|
||||||
_source(source),
|
_source(source),
|
||||||
_target(target) {
|
_target(target) {
|
||||||
}
|
}
|
||||||
@@ -12,12 +13,12 @@ rust_message::~rust_message() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void rust_message::process() {
|
void rust_message::process() {
|
||||||
I(dom, false);
|
I(_dom, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
rust_proxy<rust_task> *
|
rust_proxy<rust_task> *
|
||||||
rust_message::get_source_proxy() {
|
rust_message::get_source_proxy() {
|
||||||
return dom->get_task_proxy(_source);
|
return _dom->get_task_proxy(_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
notify_message::
|
notify_message::
|
||||||
@@ -50,8 +51,9 @@ send(notification_type type, const char* label, rust_task *source,
|
|||||||
rust_proxy<rust_task> *target) {
|
rust_proxy<rust_task> *target) {
|
||||||
rust_task *target_task = target->delegate();
|
rust_task *target_task = target->delegate();
|
||||||
rust_dom *target_domain = target_task->dom;
|
rust_dom *target_domain = target_task->dom;
|
||||||
notify_message *message = new (target_domain)
|
notify_message *message =
|
||||||
notify_message(type, label, source, target_task);
|
new (target_domain, memory_region::SYNCHRONIZED) notify_message(type,
|
||||||
|
label, source, target_task);
|
||||||
target_domain->send_message(message);
|
target_domain->send_message(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +85,8 @@ send(uint8_t *buffer, size_t buffer_sz, const char* label, rust_task *source,
|
|||||||
rust_task *target_task = target->delegate();
|
rust_task *target_task = target->delegate();
|
||||||
rust_port *target_port = port->delegate();
|
rust_port *target_port = port->delegate();
|
||||||
rust_dom *target_domain = target_task->dom;
|
rust_dom *target_domain = target_task->dom;
|
||||||
data_message *message = new (target_domain)
|
data_message *message =
|
||||||
|
new (target_domain, memory_region::SYNCHRONIZED)
|
||||||
data_message(buffer, buffer_sz, label, source,
|
data_message(buffer, buffer_sz, label, source,
|
||||||
target_task, target_port);
|
target_task, target_port);
|
||||||
target_domain->send_message(message);
|
target_domain->send_message(message);
|
||||||
|
|||||||
@@ -9,12 +9,11 @@
|
|||||||
/**
|
/**
|
||||||
* Abstract base class for all message types.
|
* Abstract base class for all message types.
|
||||||
*/
|
*/
|
||||||
class rust_message : public lock_free_queue_node,
|
class rust_message : public lock_free_queue_node {
|
||||||
public dom_owned<rust_message> {
|
|
||||||
public:
|
public:
|
||||||
rust_dom *dom;
|
|
||||||
const char* label;
|
const char* label;
|
||||||
private:
|
private:
|
||||||
|
rust_dom *_dom;
|
||||||
rust_task *_source;
|
rust_task *_source;
|
||||||
protected:
|
protected:
|
||||||
rust_task *_target;
|
rust_task *_target;
|
||||||
@@ -70,7 +69,7 @@ public:
|
|||||||
|
|
||||||
data_message(uint8_t *buffer, size_t buffer_sz, const char* label,
|
data_message(uint8_t *buffer, size_t buffer_sz, const char* label,
|
||||||
rust_task *source, rust_task *target, rust_port *port);
|
rust_task *source, rust_task *target, rust_port *port);
|
||||||
~data_message();
|
virtual ~data_message();
|
||||||
void process();
|
void process();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -5,72 +5,31 @@
|
|||||||
#include "rust_internal.h"
|
#include "rust_internal.h"
|
||||||
#include "rust_srv.h"
|
#include "rust_srv.h"
|
||||||
|
|
||||||
#define TRACK_ALLOCATIONS
|
rust_srv::rust_srv() :
|
||||||
|
local_region(this, false),
|
||||||
rust_srv::rust_srv() : _live_allocations(0) {
|
synchronized_region(this, true) {
|
||||||
// Nop.
|
// Nop.
|
||||||
}
|
}
|
||||||
|
|
||||||
rust_srv::~rust_srv() {
|
rust_srv::~rust_srv() {
|
||||||
if (_live_allocations != 0) {
|
// Nop.
|
||||||
char msg[128];
|
|
||||||
snprintf(msg, sizeof(msg),
|
|
||||||
"leaked memory in rust main loop (%" PRIuPTR " objects)",
|
|
||||||
_live_allocations);
|
|
||||||
#ifdef TRACK_ALLOCATIONS
|
|
||||||
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
|
|
||||||
fatal(msg, __FILE__, __LINE__, "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
rust_srv::malloc(size_t bytes) {
|
|
||||||
++_live_allocations;
|
|
||||||
void * val = ::malloc(bytes);
|
|
||||||
#ifdef TRACK_ALLOCATIONS
|
|
||||||
_allocation_list.append(val);
|
|
||||||
#endif
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
rust_srv::realloc(void *p, size_t bytes) {
|
|
||||||
if (!p) {
|
|
||||||
_live_allocations++;
|
|
||||||
}
|
|
||||||
void * val = ::realloc(p, bytes);
|
|
||||||
#ifdef TRACK_ALLOCATIONS
|
|
||||||
if (_allocation_list.replace(p, val) == false) {
|
|
||||||
printf("realloc: ptr 0x%" PRIxPTR " is not in allocation_list\n",
|
|
||||||
(uintptr_t) p);
|
|
||||||
fatal("not in allocation_list", __FILE__, __LINE__, "");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rust_srv::free(void *p) {
|
rust_srv::free(void *p) {
|
||||||
#ifdef TRACK_ALLOCATIONS
|
|
||||||
if (_allocation_list.replace(p, NULL) == false) {
|
|
||||||
printf("free: ptr 0x%" PRIxPTR " is not in allocation_list\n",
|
|
||||||
(uintptr_t) p);
|
|
||||||
fatal("not in allocation_list", __FILE__, __LINE__, "");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (_live_allocations < 1) {
|
|
||||||
fatal("live_allocs < 1", __FILE__, __LINE__, "");
|
|
||||||
}
|
|
||||||
_live_allocations--;
|
|
||||||
::free(p);
|
::free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
rust_srv::malloc(size_t bytes) {
|
||||||
|
return ::malloc(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
rust_srv::realloc(void *p, size_t bytes) {
|
||||||
|
return ::realloc(p, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rust_srv::log(char const *msg) {
|
rust_srv::log(char const *msg) {
|
||||||
printf("rt: %s\n", msg);
|
printf("rt: %s\n", msg);
|
||||||
|
|||||||
@@ -5,11 +5,13 @@
|
|||||||
#ifndef RUST_SRV_H
|
#ifndef RUST_SRV_H
|
||||||
#define RUST_SRV_H
|
#define RUST_SRV_H
|
||||||
|
|
||||||
|
#include "sync/spin_lock.h"
|
||||||
|
#include "memory_region.h"
|
||||||
|
|
||||||
class rust_srv {
|
class rust_srv {
|
||||||
private:
|
|
||||||
size_t _live_allocations;
|
|
||||||
array_list<void *> _allocation_list;
|
|
||||||
public:
|
public:
|
||||||
|
memory_region local_region;
|
||||||
|
memory_region synchronized_region;
|
||||||
virtual void log(char const *msg);
|
virtual void log(char const *msg);
|
||||||
virtual void fatal(char const *expression,
|
virtual void fatal(char const *expression,
|
||||||
char const *file,
|
char const *file,
|
||||||
@@ -21,12 +23,12 @@ public:
|
|||||||
size_t line,
|
size_t line,
|
||||||
char const *format,
|
char const *format,
|
||||||
...);
|
...);
|
||||||
|
virtual void free(void *);
|
||||||
virtual void *malloc(size_t);
|
virtual void *malloc(size_t);
|
||||||
virtual void *realloc(void *, size_t);
|
virtual void *realloc(void *, size_t);
|
||||||
virtual void free(void *);
|
|
||||||
virtual rust_srv *clone();
|
|
||||||
rust_srv();
|
rust_srv();
|
||||||
virtual ~rust_srv();
|
virtual ~rust_srv();
|
||||||
|
virtual rust_srv *clone();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* RUST_SRV_H */
|
#endif /* RUST_SRV_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user