Skip to content

Commit

Permalink
Issue plasma-umass#176: avoid recursive call on allocator on library …
Browse files Browse the repository at this point in the history
…initializaton

First, libcoz must provide basic allocator via malloc/calloc (for dlsym)
to avoid clash with user' allocator like jemalloc

Second, libcoz must be preloaded before any other to override any other
allocator implementation

Third, once libcoz is initialized (right before real main) disable
internal allocator and pass requests through
  • Loading branch information
VGubarev committed Nov 2, 2021
1 parent b88a9ac commit 1dea01d
Showing 4 changed files with 72 additions and 1 deletion.
2 changes: 1 addition & 1 deletion coz
Original file line number Diff line number Diff line change
@@ -79,7 +79,7 @@ def _coz_run(args):
sys.exit(1)

if 'LD_PRELOAD' in env:
env['LD_PRELOAD'] += ':' + coz_runtime
env['LD_PRELOAD'] = coz_runtime + ':' + env['LD_PRELOAD']
else:
env['LD_PRELOAD'] = coz_runtime

47 changes: 47 additions & 0 deletions libcoz/libcoz.cpp
Original file line number Diff line number Diff line change
@@ -11,6 +11,8 @@
#include <stdlib.h>
#include <sys/stat.h>

#include <atomic>
#include <cstring>
#include <sstream>
#include <string>
#include <unordered_set>
@@ -225,6 +227,25 @@ static bool is_coz_signal(int signum) {
return signum == SampleSignal || signum == SIGSEGV || signum == SIGABRT;
}

namespace {

template <size_t Size>
class LocalArena {
std::array<char, Size> _data;
std::atomic<char *> _offset{_data.begin()};

public:
void * allocate(size_t bytes_requested) {
char * prev = _offset.fetch_add(bytes_requested, std::memory_order_relaxed);
if (prev + bytes_requested > _data.end()) {
std::abort();
}
return prev;
}
};

}

extern "C" {
/// Pass pthread_create calls to coz so child threads can inherit the parent's delay count
int pthread_create(pthread_t* thread,
@@ -359,6 +380,32 @@ extern "C" {
return real::pthread_rwlock_unlock(rwlock);
}

void * malloc(size_t bytes_requested) throw() {
if (!initialized && !init_in_progress) {
static LocalArena<1 << 22> arena;
return arena.allocate(bytes_requested);
}
return real::malloc(bytes_requested);
}

void * calloc(size_t nmemb, size_t size) throw() {
if (!initialized && !init_in_progress) {
const size_t bytes_requested = nmemb * size;
void * ptr = malloc(bytes_requested);
std::memset(ptr, 0x0, bytes_requested);

return ptr;
}
return real::calloc(nmemb, size);
}

void free(void * ptr) throw() {
if (!initialized && !init_in_progress) {
return;
}
return real::free(ptr);
}

/// Run shutdown before exiting
void __attribute__((noreturn)) exit(int status) throw() {
profiler::get_instance().shutdown();
21 changes: 21 additions & 0 deletions libcoz/real.cpp
Original file line number Diff line number Diff line change
@@ -51,6 +51,23 @@ static void* get_pthread_handle() {
* located function is called.
*/

static void * resolve_calloc(size_t nmemb, size_t size) throw() {
GET_SYMBOL(calloc);
if(real_calloc) return real_calloc(nmemb, size);
return nullptr;
}

static void * resolve_malloc(size_t size) throw() {
GET_SYMBOL(malloc);
if(real_malloc) return real_malloc(size);
return nullptr;
}

static void resolve_free(void * ptr) throw() {
GET_SYMBOL(free);
if(real_free) real_free(ptr);
}

static NORETURN void resolve_exit(int status) throw() {
GET_SYMBOL(exit);
if(real_exit) real_exit(status);
@@ -262,6 +279,10 @@ static int resolve_pthread_rwlock_unlock(pthread_rwlock_t* rwlock) throw() {
* corresponding resolver function.
*/
namespace real {
DEFINE_WRAPPER(malloc);
DEFINE_WRAPPER(calloc);
DEFINE_WRAPPER(free);

DEFINE_WRAPPER(exit);
DEFINE_WRAPPER(_exit);
DEFINE_WRAPPER(_Exit);
3 changes: 3 additions & 0 deletions libcoz/real.h
Original file line number Diff line number Diff line change
@@ -16,6 +16,9 @@
#define DECLARE_WRAPPER(name) extern decltype(::name)* name;

namespace real {
DECLARE_WRAPPER(malloc);
DECLARE_WRAPPER(calloc);
DECLARE_WRAPPER(free);
DECLARE_WRAPPER(exit);
DECLARE_WRAPPER(_exit);
DECLARE_WRAPPER(_Exit);

0 comments on commit 1dea01d

Please sign in to comment.