From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Wed, 2 Dec 2015 23:37:28 -0500 Subject: [PATCH] switch pthread_atfork handler allocation to mmap Signed-off-by: anupritaisno1 --- libc/bionic/pthread_atfork.cpp | 35 ++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/libc/bionic/pthread_atfork.cpp b/libc/bionic/pthread_atfork.cpp index 0dcabdfb2..6306052ee 100644 --- a/libc/bionic/pthread_atfork.cpp +++ b/libc/bionic/pthread_atfork.cpp @@ -29,6 +29,9 @@ #include #include #include +#include +#include +#include #include "platform/bionic/macros.h" @@ -43,6 +46,8 @@ struct atfork_t { void* dso_handle; }; +static atfork_t* pool; + class atfork_list_t { public: constexpr atfork_list_t() : first_(nullptr), last_(nullptr) {} @@ -101,7 +106,8 @@ class atfork_list_t { last_ = entry->prev; } - free(entry); + entry->next = pool; + pool = entry; } atfork_t* first_; @@ -154,18 +160,35 @@ void __bionic_atfork_run_parent() { // __register_atfork is the name used by glibc extern "C" int __register_atfork(void (*prepare)(void), void (*parent)(void), void(*child)(void), void* dso) { - atfork_t* entry = reinterpret_cast(malloc(sizeof(atfork_t))); - if (entry == nullptr) { - return ENOMEM; + pthread_mutex_lock(&g_atfork_list_mutex); + + if (!pool) { + size_t page_size = getpagesize(); + char* page = static_cast(mmap(NULL, page_size, PROT_READ|PROT_WRITE, + MAP_ANONYMOUS|MAP_PRIVATE, -1, 0)); + if (page == MAP_FAILED) { + pthread_mutex_unlock(&g_atfork_list_mutex); + return ENOMEM; + } + + prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, page, page_size, + "atfork handlers"); + + for (char* it = page; it < page + page_size - sizeof(atfork_t); it += sizeof(atfork_t)) { + atfork_t* node = reinterpret_cast(it); + node->next = pool; + pool = node; + } } + atfork_t* entry = pool; + pool = entry->next; + entry->prepare = prepare; entry->parent = parent; entry->child = child; entry->dso_handle = dso; - pthread_mutex_lock(&g_atfork_list_mutex); - g_atfork_list.push_back(entry); pthread_mutex_unlock(&g_atfork_list_mutex);