From 2283536b276fa8d8c625426925eecb5e5ee1d4ba Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Mon, 10 Dec 2012 11:20:15 +0100 Subject: [PATCH] base: avoid deadlock in sliced_heap It happens that ram_session and rm_session itself are invoking alloc respectively free on the very same sliced heap inside core. Lock only the sliced_heap list implementation and let the session locking to the session implementation of rm_session and ram_session. The ram_session and rm_session must take care to proper lock since inside both implementations already the session handling thread and the service thread are running parallel. --- base/src/base/heap/sliced_heap.cc | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/base/src/base/heap/sliced_heap.cc b/base/src/base/heap/sliced_heap.cc index a05b06cf89..649bffaffd 100644 --- a/base/src/base/heap/sliced_heap.cc +++ b/base/src/base/heap/sliced_heap.cc @@ -70,9 +70,6 @@ Sliced_heap::~Sliced_heap() bool Sliced_heap::alloc(size_t size, void **out_addr) { - /* serialize access to block list */ - Lock::Guard lock_guard(_lock); - /* allocation includes space for block meta data and is page-aligned */ size = align_addr(size + sizeof(Block), 12); @@ -91,6 +88,9 @@ bool Sliced_heap::alloc(size_t size, void **out_addr) return false; } + /* serialize access to block list */ + Lock::Guard lock_guard(_lock); + Block *b = new(local_addr) Block(ds_cap, size); _consumed += size; _block_list.insert(b); @@ -101,15 +101,21 @@ bool Sliced_heap::alloc(size_t size, void **out_addr) void Sliced_heap::free(void *addr, size_t size) { - /* serialize access to block list */ - Lock::Guard lock_guard(_lock); + Ram_dataspace_capability ds_cap; + void * local_addr; + { + /* serialize access to block list */ + Lock::Guard lock_guard(_lock); - Block *b = Block::block(addr); - _block_list.remove(b); - _consumed -= b->size(); - Ram_dataspace_capability ds_cap = b->ds_cap(); - delete b; - _rm_session->detach(b); + Block *b = Block::block(addr); + _block_list.remove(b); + _consumed -= b->size(); + ds_cap = b->ds_cap(); + local_addr = b; + delete b; + } + + _rm_session->detach(local_addr); _ram_session->free(ds_cap); }