Ticket #13111: fork-heap-locks-handling-3.patch

File fork-heap-locks-handling-3.patch, 7.5 KB (added by korli, 7 years ago)

updated patch

  • headers/private/libroot/libroot_private.h

    diff --git a/headers/private/libroot/libroot_private.h b/headers/private/libroot/libroot_private.h
    index d0676a6..79ec524 100644
    a b void __init_env(const struct user_space_program_args *args);  
    3636void __init_env_post_heap(void);
    3737status_t __init_heap(void);
    3838void __heap_terminate_after(void);
     39void __heap_before_fork(void);
     40void __heap_after_fork_child(void);
     41void __heap_after_fork_parent(void);
    3942
    4043void __init_time(addr_t commPageTable);
    4144void __arch_init_time(struct real_time_data *data, bool setDefaults);
  • headers/private/libroot/user_thread.h

    diff --git a/headers/private/libroot/user_thread.h b/headers/private/libroot/user_thread.h
    index 5c234fe..3f1a210 100644
    a b  
    1212#include <user_thread_defs.h>
    1313
    1414
    15 static inline user_thread*
     15static inline struct user_thread*
    1616get_user_thread()
    1717{
    18     return (user_thread*)tls_get(TLS_USER_THREAD_SLOT);
     18    return (struct user_thread*)tls_get(TLS_USER_THREAD_SLOT);
    1919}
    2020
    2121
    defer_signals()  
    2929static void inline
    3030undefer_signals()
    3131{
    32     user_thread* thread = get_user_thread();
     32    struct user_thread* thread = get_user_thread();
    3333    if (--thread->defer_signals == 0 && thread->pending_signals != 0) {
    3434        // signals shall no longer be deferred -- call a dummy syscall to handle
    3535        // the pending ones
  • src/system/libroot/posix/malloc/arch-specific.cpp

    diff --git a/src/system/libroot/posix/malloc/arch-specific.cpp b/src/system/libroot/posix/malloc/arch-specific.cpp
    index 4167f04..7ac64c2 100644
    a b static size_t sFreeHeapSize, sHeapAreaSize;  
    6767static free_chunk *sFreeChunks;
    6868
    6969
    70 static void
    71 init_after_fork(void)
     70void
     71__init_after_fork(void)
    7272{
    7373    // find the heap area
    7474    sHeapArea = area_for((void*)sFreeHeapBase);
    __init_heap(void)  
    110110
    111111    hoardLockInit(sHeapLock, "heap");
    112112
    113     atfork(&init_after_fork);
    114         // Note: Needs malloc(). Hence we need to be fully initialized.
    115         // TODO: We should actually also install a hook that is called before
    116         // fork() is being executed. In a multithreaded app it would need to
    117         // acquire *all* allocator locks, so that we don't fork() an
    118         // inconsistent state.
    119 
    120113    return B_OK;
    121114}
    122115
  • src/system/libroot/posix/malloc/heap.cpp

    diff --git a/src/system/libroot/posix/malloc/heap.cpp b/src/system/libroot/posix/malloc/heap.cpp
    index 99aba54..e2cc553 100644
    a b hoardHeap::hoardHeap(void)  
    132132    , _magic(HEAP_MAGIC)
    133133#endif
    134134{
    135     // Initialize the per-heap lock.
    136     hoardLockInit(_lock, "hoard heap");
     135    initLock();
    137136
    138137    for (int i = 0; i < SUPERBLOCK_FULLNESS_GROUP; i++) {
    139138        for (int j = 0; j < SIZE_CLASSES; j++) {
  • src/system/libroot/posix/malloc/heap.h

    diff --git a/src/system/libroot/posix/malloc/heap.h b/src/system/libroot/posix/malloc/heap.h
    index f42962e..42e9eb4 100644
    a b class hoardHeap {  
    115115        // Unlock this heap.
    116116        inline void unlock(void);
    117117
     118        // Init this heap lock.
     119        inline void initLock(void);
     120
    118121        // Set our index number (which heap we are).
    119122        inline void setIndex(int i);
    120123
    hoardHeap::unlock(void)  
    444447}
    445448
    446449
     450void
     451hoardHeap::initLock(void)
     452{
     453    // Initialize the per-heap lock.
     454    hoardLockInit(_lock, "hoard heap");
     455}
     456
     457
    447458size_t
    448459hoardHeap::align(const size_t sz)
    449460{
  • src/system/libroot/posix/malloc/processheap.h

    diff --git a/src/system/libroot/posix/malloc/processheap.h b/src/system/libroot/posix/malloc/processheap.h
    index f222289..2c94af9 100644
    a b class processHeap : public hoardHeap {  
    6767        // Get a thread heap index.
    6868        inline int getHeapIndex(void);
    6969
     70        // Get thread heap max.
     71        inline int getMaxThreadHeaps(void);
     72
    7073        // Get the thread heap with index i.
    7174        inline HEAPTYPE & getHeap(int i);
    7275
    processHeap::getHeapIndex(void)  
    199202}
    200203
    201204
     205// Return the maximum number of heaps.
     206
     207int
     208processHeap::getMaxThreadHeaps(void)
     209{
     210    return fMaxThreadHeaps;
     211}
     212
     213
    202214superblock *
    203215processHeap::acquire(const int sizeclass, hoardHeap * dest)
    204216{
  • src/system/libroot/posix/malloc/wrapper.cpp

    diff --git a/src/system/libroot/posix/malloc/wrapper.cpp b/src/system/libroot/posix/malloc/wrapper.cpp
    index c83336a..38c4125 100644
    a b getAllocator(void)  
    256256}
    257257
    258258
     259extern "C" void
     260__heap_before_fork(void)
     261{
     262    static processHeap *pHeap = getAllocator();
     263    for (int i = 0; i < pHeap->getMaxThreadHeaps(); i++)
     264        pHeap->getHeap(i).lock();
     265}
     266
     267void __init_after_fork(void);
     268
     269extern "C" void
     270__heap_after_fork_child(void)
     271{
     272    __init_after_fork();
     273    static processHeap *pHeap = getAllocator();
     274    for (int i = 0; i < pHeap->getMaxThreadHeaps(); i++)
     275        pHeap->getHeap(i).initLock();
     276}
     277
     278
     279extern "C" void
     280__heap_after_fork_parent(void)
     281{
     282    static processHeap *pHeap = getAllocator();
     283    for (int i = 0; i < pHeap->getMaxThreadHeaps(); i++)
     284        pHeap->getHeap(i).unlock();
     285}
     286
     287
    259288//  #pragma mark - public functions
    260289
    261290
  • src/system/libroot/posix/malloc_debug/malloc_debug_api.cpp

    diff --git a/src/system/libroot/posix/malloc_debug/malloc_debug_api.cpp b/src/system/libroot/posix/malloc_debug/malloc_debug_api.cpp
    index 3d3b062..bf38d4c 100644
    a b __heap_terminate_after()  
    202202}
    203203
    204204
     205extern "C" void
     206__heap_before_fork(void)
     207{
     208}
     209
     210
     211extern "C" void
     212__heap_after_fork_child(void)
     213{
     214}
     215
     216
     217extern "C" void
     218__heap_after_fork_parent(void)
     219{
     220}
     221
     222
    205223// #pragma mark - Public API
    206224
    207225
  • src/system/libroot/posix/unistd/fork.c

    diff --git a/src/system/libroot/posix/unistd/fork.c b/src/system/libroot/posix/unistd/fork.c
    index 8d8a963..0316750 100644
    a b  
    1616#include <pthread_private.h>
    1717#include <runtime_loader.h>
    1818#include <syscalls.h>
     19#include <user_thread.h>
    1920
    2021
    2122typedef struct fork_hook {
    call_fork_hooks(fork_hook *hook)  
    105106status_t
    106107__register_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void))
    107108{
     109    defer_signals();
     110
    108111    status_t status = mutex_lock(&sForkLock);
    109     if (status != B_OK)
     112    if (status != B_OK) {
     113        undefer_signals();
    110114        return status;
     115    }
    111116
    112117    if (prepare)
    113118        status = add_fork_hook(&sPrepareHooks, NULL, prepare);
    __register_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(voi  
    119124        status = add_fork_hook(&sChildHooks, &sLastChildHook, child);
    120125
    121126    mutex_unlock(&sForkLock);
     127
     128    undefer_signals();
     129
    122130    return status;
    123131}
    124132
    fork(void)  
    129137    thread_id thread;
    130138    status_t status;
    131139
     140    defer_signals();
     141
    132142    status = mutex_lock(&sForkLock);
    133     if (status != B_OK)
     143    if (status != B_OK) {
     144        undefer_signals();
    134145        return status;
     146    }
    135147
    136148    // call preparation hooks
    137149    call_fork_hooks(sPrepareHooks);
     150    __heap_before_fork();
    138151
    139152    thread = _kern_fork();
    140153    if (thread < 0) {
    141154        // something went wrong
     155        undefer_signals();
    142156        mutex_unlock(&sForkLock);
    143157        __set_errno(thread);
    144158        return -1;
    fork(void)  
    155169            // process we should make sure that it is in a consistent state when
    156170            // calling the kernel.
    157171        __gRuntimeLoader->reinit_after_fork();
     172        __heap_after_fork_child();
    158173        __reinit_pwd_backend_after_fork();
    159174
    160175        call_fork_hooks(sChildHooks);
    161176    } else {
    162177        // we are the parent
     178        __heap_after_fork_parent();
    163179        call_fork_hooks(sParentHooks);
    164180        mutex_unlock(&sForkLock);
    165181    }
    166182
     183    undefer_signals();
     184
    167185    return thread;
    168186}
    169187