diff options
Diffstat (limited to 'libpthread/linuxthreads/ptfork.c')
-rw-r--r-- | libpthread/linuxthreads/ptfork.c | 173 |
1 files changed, 49 insertions, 124 deletions
diff --git a/libpthread/linuxthreads/ptfork.c b/libpthread/linuxthreads/ptfork.c index 6f1e2d3c9..71404acf1 100644 --- a/libpthread/linuxthreads/ptfork.c +++ b/libpthread/linuxthreads/ptfork.c @@ -12,156 +12,81 @@ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU Library General Public License for more details. */ -/* mods for uClibc: removed strong alias and defined funcs properly */ - /* The "atfork" stuff */ #include <errno.h> - -#ifdef __ARCH_USE_MMU__ - -#include <bits/uClibc_mutex.h> #include <stddef.h> #include <stdlib.h> #include <unistd.h> #include "pthread.h" #include "internals.h" +#include <bits/libc-lock.h> +#include "fork.h" -struct handler_list { - void (*handler)(void); - struct handler_list * next; -}; - -static pthread_mutex_t pthread_atfork_lock = PTHREAD_MUTEX_INITIALIZER; -static struct handler_list * pthread_atfork_prepare = NULL; -static struct handler_list * pthread_atfork_parent = NULL; -static struct handler_list * pthread_atfork_child = NULL; - -#ifdef __MALLOC__ -__UCLIBC_MUTEX_EXTERN(__malloc_heap_lock); -__UCLIBC_MUTEX_EXTERN(__malloc_sbrk_lock); -#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ -__UCLIBC_MUTEX_EXTERN(__malloc_mmb_heap_lock); -#endif -#elif defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__) -__UCLIBC_MUTEX_EXTERN(__malloc_lock); -#endif - -static void pthread_insert_list(struct handler_list ** list, - void (*handler)(void), - struct handler_list * newlist, - int at_end) -{ - if (handler == NULL) return; - if (at_end) { - while(*list != NULL) list = &((*list)->next); - } - newlist->handler = handler; - newlist->next = *list; - *list = newlist; -} - -struct handler_list_block { - struct handler_list prepare, parent, child; -}; - -int pthread_atfork(void (*prepare)(void), - void (*parent)(void), - void (*child)(void)) -{ - struct handler_list_block * block = - (struct handler_list_block *) malloc(sizeof(struct handler_list_block)); - if (block == NULL) return ENOMEM; - __pthread_mutex_lock(&pthread_atfork_lock); - /* "prepare" handlers are called in LIFO */ - pthread_insert_list(&pthread_atfork_prepare, prepare, &block->prepare, 0); - /* "parent" handlers are called in FIFO */ - pthread_insert_list(&pthread_atfork_parent, parent, &block->parent, 1); - /* "child" handlers are called in FIFO */ - pthread_insert_list(&pthread_atfork_child, child, &block->child, 1); - __pthread_mutex_unlock(&pthread_atfork_lock); - return 0; -} -/*strong_alias (__pthread_atfork, pthread_atfork)*/ - -static __inline__ void pthread_call_handlers(struct handler_list * list) -{ - for (/*nothing*/; list != NULL; list = list->next) (list->handler)(); -} - -void __pthread_once_fork_prepare(void); -void __pthread_once_fork_child(void); -void __pthread_once_fork_parent(void); - -static pid_t __fork(void) +pid_t __pthread_fork (struct fork_block *b) { pid_t pid; - struct handler_list * prepare, * child, * parent; + list_t *runp; - __pthread_mutex_lock(&pthread_atfork_lock); - prepare = pthread_atfork_prepare; - child = pthread_atfork_child; - parent = pthread_atfork_parent; - pthread_call_handlers(prepare); + __libc_lock_lock (b->lock); + + /* Run all the registered preparation handlers. In reverse order. */ + list_for_each_prev (runp, &b->prepare_list) + { + struct fork_handler *curp; + curp = list_entry (runp, struct fork_handler, list); + curp->handler (); + } __pthread_once_fork_prepare(); -#ifdef __MALLOC__ - __pthread_mutex_lock(&__malloc_sbrk_lock); - __pthread_mutex_lock(&__malloc_heap_lock); -#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ - __pthread_mutex_lock(&__malloc_mmb_heap_lock); -#endif -#elif defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__) - __pthread_mutex_lock(&__malloc_lock); -#endif + __flockfilelist(); + + pid = ARCH_FORK (); - pid = __libc_fork(); if (pid == 0) { -#if defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__) - __libc_lock_init_recursive(__malloc_lock); -#elif defined(__MALLOC__) -#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ - __libc_lock_init_adaptive(__malloc_mmb_heap_lock); -#endif - __libc_lock_init_adaptive(__malloc_heap_lock); - __libc_lock_init(__malloc_sbrk_lock); -#endif - __libc_lock_init_adaptive(pthread_atfork_lock); __pthread_reset_main_thread(); + __fresetlockfiles(); __pthread_once_fork_child(); - pthread_call_handlers(child); + + /* Run the handlers registered for the child. */ + list_for_each (runp, &b->child_list) + { + struct fork_handler *curp; + curp = list_entry (runp, struct fork_handler, list); + curp->handler (); + } + + __libc_lock_init (b->lock); } else { -#if defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__) - __pthread_mutex_unlock(&__malloc_lock); -#elif defined(__MALLOC__) -#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ - __pthread_mutex_unlock(&__malloc_mmb_heap_lock); -#endif - __pthread_mutex_unlock(&__malloc_heap_lock); - __pthread_mutex_unlock(&__malloc_sbrk_lock); -#endif - __pthread_mutex_unlock(&pthread_atfork_lock); + __funlockfilelist(); __pthread_once_fork_parent(); - pthread_call_handlers(parent); + + /* Run the handlers registered for the parent. */ + list_for_each (runp, &b->parent_list) + { + struct fork_handler *curp; + curp = list_entry (runp, struct fork_handler, list); + curp->handler (); + } + + __libc_lock_unlock (b->lock); } + return pid; } -strong_alias(__fork,fork) -strong_alias(__fork,vfork) - -#else -/* We can't support pthread_atfork without MMU, since we don't have - fork(), and we can't offer the correct semantics for vfork(). */ -int pthread_atfork(void (*prepare)(void), - void (*parent)(void), - void (*child)(void)) +/* psm: have no idea why these are here, sjhill? */ +#if 0 /*def SHARED*/ +pid_t __fork (void) { - /* ENOMEM is probably pushing it a little bit. - Take it as `no *virtual* memory' :-) */ - errno = ENOMEM; - return -1; + return __libc_fork (); } +weak_alias (__fork, fork) +pid_t __vfork(void) +{ + return __libc_fork (); +} +weak_alias (__vfork, vfork) #endif |