Update.
2002-12-30 Ulrich Drepper <drepper@redhat.com> * malloc/thread-m.h (thread_atfork): Define using __register_atfork.
This commit is contained in:
parent
89d6e44459
commit
416d2de60b
|
@ -1,3 +1,7 @@
|
|||
2002-12-30 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* malloc/thread-m.h (thread_atfork): Define using __register_atfork.
|
||||
|
||||
2002-12-30 Roland McGrath <roland@redhat.com>
|
||||
|
||||
* Rules (generated): Target removed.
|
||||
|
|
|
@ -1,3 +1,44 @@
|
|||
2002-12-31 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* sysdeps/pthread/list.h: New file.
|
||||
* sysdeps/unix/sysv/linux/jmp-unwind.c: New file.
|
||||
* sysdeps/unix/sysv/linux/fork.c: New file.
|
||||
* sysdeps/unix/sysv/linux/fork.h: New file.
|
||||
* sysdeps/unix/sysv/linux/ia64/fork.h: New file.
|
||||
* sysdeps/unix/sysv/linux/sparc/fork.h: New file.
|
||||
* sysdeps/unix/sysv/linux/register-atfork.c: New file.
|
||||
* sysdeps/unix/sysv/linux/unregister-atfork.c: New file.
|
||||
* sysdeps/unix/sysv/linux/Makefile: New file.
|
||||
* sysdeps/unix/sysv/linux/Versions: New file.
|
||||
* ptlongjmp.c (pthread_cleanup_upto): Rename to...
|
||||
(__pthread_cleanup_upto): ...this. Add targetframe argument,
|
||||
use it instead of currentframe. No longer static.
|
||||
(siglongjmp, longjmp): Remove pthread_cleanup_upto calls.
|
||||
* internals.h (__pthread_cleanup_upto, __pthread_fork): New prototypes.
|
||||
(struct pthread_functions): Add ptr_pthread_fork,
|
||||
ptr_pthread_cleanup_upto.
|
||||
* pthread.c (pthread_functions): Initialize ptr_pthread_fork and
|
||||
ptr_pthread_cleanup_upto.
|
||||
* ptfork.c: Include fork.h.
|
||||
(struct handler_list, struct handler_list_block): Remove.
|
||||
(pthread_atfork_lock, pthread_atfork_prepare, pthread_atfork_parent,
|
||||
pthread_atfork_child): Remove.
|
||||
(pthread_insert_list, __pthread_atfork, pthread_call_handlers): Remove.
|
||||
(__pthread_fork): New function.
|
||||
(__fork, __vfork): Call __libc_fork.
|
||||
* Makefile (libpthread-routines): Add old_pthread_atfork.
|
||||
(libpthread-nonshared): Add pthread_atfork.
|
||||
(others): Depend on $(objpfx)libpthread_nonshared.a.
|
||||
($(objpfx)libpthread_nonshared.a): New rule.
|
||||
(install): Depend on $(inst_libdir)/libpthread.so.
|
||||
($(inst_libdir)/libpthread.so, $(inst_libdir)/libpthread_nonshared.a):
|
||||
New rules.
|
||||
(tests): Depend on libpthread_nonshared.a too.
|
||||
* old_pthread_atfork.c: New file.
|
||||
* pthread_atfork.c: New file.
|
||||
* Makeconfig (shared-thread-library): Include libpthread_nonshared.a
|
||||
too.
|
||||
|
||||
2002-12-30 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* forward.c: Make all functions available by default again. It
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
|
||||
have-thread-library = yes
|
||||
|
||||
shared-thread-library = $(common-objpfx)linuxthreads/libpthread.so
|
||||
shared-thread-library = $(common-objpfx)linuxthreads/libpthread.so \
|
||||
$(common-objpfx)linuxthreads/libpthread_nonshared.a
|
||||
static-thread-library = $(common-objpfx)linuxthreads/libpthread.a
|
||||
bounded-thread-library = $(common-objpfx)linuxthreads/libpthread_b.a
|
||||
|
||||
|
|
|
@ -46,12 +46,14 @@ libpthread-routines := attr cancel condvar join manager mutex ptfork \
|
|||
ptw-lseek64 ptw-llseek ptw-msync ptw-nanosleep \
|
||||
ptw-open ptw-open64 ptw-pause ptw-pread ptw-pread64 \
|
||||
ptw-pwrite ptw-pwrite64 ptw-tcdrain ptw-wait \
|
||||
ptw-waitpid pt-system
|
||||
ptw-waitpid pt-system old_pthread_atfork
|
||||
# Don't generate deps for calls with no sources. See sysdeps/unix/Makefile.
|
||||
omit-deps = $(unix-syscalls:%=ptw-%)
|
||||
|
||||
libpthread-shared-only-routines = pt-allocrtsig
|
||||
|
||||
libpthread-nonshared = pthread_atfork
|
||||
|
||||
nodelete-yes = -Wl,--enable-new-dtags,-z,nodelete
|
||||
initfirst-yes = -Wl,--enable-new-dtags,-z,initfirst
|
||||
LDFLAGS-pthread.so = $(nodelete-$(have-z-nodelete)) \
|
||||
|
@ -65,6 +67,14 @@ CFLAGS-tst-cancel.c = -fno-inline -fno-inline-functions
|
|||
include ../Makeconfig
|
||||
|
||||
ifeq ($(build-shared),yes)
|
||||
others: $(objpfx)libpthread_nonshared.a
|
||||
endif
|
||||
|
||||
$(objpfx)libpthread_nonshared.a: $(addprefix $(objpfx),$(addsuffix .os,$(libpthread-nonshared)))
|
||||
$(AR) $(ARFLAGS) $@ $^
|
||||
|
||||
ifeq ($(build-shared),yes)
|
||||
|
||||
extra-objs += crti.o crtn.o
|
||||
omit-deps += crti crtn
|
||||
|
||||
|
@ -92,6 +102,31 @@ endif
|
|||
|
||||
include ../Rules
|
||||
|
||||
# What we install as libpthread.so for programs to link against is in fact a
|
||||
# link script. It contains references for the various libraries we need.
|
||||
# The libpthread.so object is not complete since some functions are only defined
|
||||
# in libpthread_nonshared.a.
|
||||
# We need to use absolute paths since otherwise local copies (if they exist)
|
||||
# of the files are taken by the linker.
|
||||
install: $(inst_libdir)/libpthread.so
|
||||
$(inst_libdir)/libpthread.so: $(common-objpfx)format.lds \
|
||||
$(objpfx)libpthread.so$(libpthread.so-version) \
|
||||
$(inst_libdir)/$(patsubst %,$(libtype.oS),\
|
||||
$(libprefix)pthread) \
|
||||
$(+force)
|
||||
(echo '/* GNU ld script';\
|
||||
echo ' Use the shared library, but some functions are only in';\
|
||||
echo ' the static library, so try that secondarily. */';\
|
||||
cat $<; \
|
||||
echo 'GROUP ( $(slibdir)/libpthread.so$(libpthread.so-version)' \
|
||||
'$(libdir)/$(patsubst %,$(libtype.oS),$(libprefix)pthread)'\
|
||||
')' \
|
||||
) > $@.new
|
||||
mv -f $@.new $@
|
||||
$(inst_libdir)/libpthread_nonshared.a: $(objpfx)libpthread_nonshared.a
|
||||
$(do-install)
|
||||
|
||||
|
||||
extra-B-pthread.so = -B$(common-objpfx)linuxthreads/
|
||||
$(objpfx)libpthread.so: $(objpfx)crti.o $(objpfx)crtn.o
|
||||
$(objpfx)libpthread.so: +preinit += $(objpfx)crti.o
|
||||
|
@ -154,14 +189,16 @@ $(objpfx)libpthread.so: $(libc-link.so) $(common-objpfx)libc_nonshared.a
|
|||
ifeq ($(build-shared),yes)
|
||||
$(addprefix $(objpfx), \
|
||||
$(filter-out $(tests-static) $(tests-reverse) unload, \
|
||||
$(tests) $(test-srcs))): $(objpfx)libpthread.so
|
||||
$(tests) $(test-srcs))): $(objpfx)libpthread.so \
|
||||
$(objpfx)libpthread_nonshared.a
|
||||
# $(objpfx)../libc.so is used instead of $(common-objpfx)libc.so,
|
||||
# since otherwise libpthread.so comes before libc.so when linking.
|
||||
$(addprefix $(objpfx), $(tests-reverse)): \
|
||||
$(objpfx)../libc.so $(objpfx)libpthread.so
|
||||
$(objpfx)../libc.so $(objpfx)libpthread.so \
|
||||
$(objpfx)libpthread_nonshared.a
|
||||
$(addprefix $(objpfx),$(librt-tests)): $(common-objpfx)rt/librt.so
|
||||
$(objpfx)unload: $(common-objpfx)dlfcn/libdl.so
|
||||
$(objpfx)unload.out: $(objpfx)libpthread.so
|
||||
$(objpfx)unload.out: $(objpfx)libpthread.so $(objpfx)libpthread_nonshared.a
|
||||
else
|
||||
$(addprefix $(objpfx),$(tests) $(test-srcs)): $(objpfx)libpthread.a
|
||||
$(addprefix $(objpfx),$(librt-tests)): $(common-objpfx)rt/librt.a
|
||||
|
|
|
@ -463,6 +463,11 @@ extern int __libc_enable_asynccancel (void) attribute_hidden;
|
|||
extern void __libc_disable_asynccancel (int oldtype)
|
||||
internal_function attribute_hidden;
|
||||
|
||||
extern void __pthread_cleanup_upto (__jmp_buf target,
|
||||
char *targetframe) attribute_hidden;
|
||||
struct fork_block;
|
||||
extern pid_t __pthread_fork (struct fork_block *b) attribute_hidden;
|
||||
|
||||
#if !defined NOT_IN_libc
|
||||
# define LIBC_CANCEL_ASYNC() \
|
||||
__libc_enable_asynccancel ()
|
||||
|
@ -482,6 +487,7 @@ extern void __libc_disable_asynccancel (int oldtype)
|
|||
the thread functions. */
|
||||
struct pthread_functions
|
||||
{
|
||||
pid_t (*ptr_pthread_fork) (struct fork_block *);
|
||||
int (*ptr_pthread_attr_destroy) (pthread_attr_t *);
|
||||
int (*ptr___pthread_attr_init_2_0) (pthread_attr_t *);
|
||||
int (*ptr___pthread_attr_init_2_1) (pthread_attr_t *);
|
||||
|
@ -519,6 +525,8 @@ struct pthread_functions
|
|||
int (*ptr_pthread_setcancelstate) (int, int *);
|
||||
int (*ptr_pthread_setcanceltype) (int, int *);
|
||||
void (*ptr_pthread_do_exit) (void *retval, char *currentframe);
|
||||
void (*ptr_pthread_cleanup_upto) (__jmp_buf target,
|
||||
char *targetframe);
|
||||
pthread_descr (*ptr_pthread_thread_self) (void);
|
||||
int (*ptr_pthread_internal_tsd_set) (int key, const void * pointer);
|
||||
void * (*ptr_pthread_internal_tsd_get) (int key);
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <shlib-compat.h>
|
||||
|
||||
#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_3)
|
||||
# define __pthread_atfork __dyn_pthread_atfork
|
||||
# include "pthread_atfork.c"
|
||||
# undef __pthread_atfork
|
||||
compat_symbol (libpthread, __dyn_pthread_atfork, pthread_atfork, GLIBC_2_0);
|
||||
#endif
|
|
@ -21,96 +21,71 @@
|
|||
#include "pthread.h"
|
||||
#include "internals.h"
|
||||
#include <bits/libc-lock.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;
|
||||
|
||||
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)();
|
||||
}
|
||||
#include "fork.h"
|
||||
|
||||
extern int __libc_fork (void);
|
||||
|
||||
pid_t __fork(void)
|
||||
pid_t __pthread_fork (struct fork_block *b)
|
||||
{
|
||||
pid_t pid;
|
||||
list_t *runp;
|
||||
|
||||
pthread_mutex_lock(&pthread_atfork_lock);
|
||||
__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_call_handlers(pthread_atfork_prepare);
|
||||
__pthread_once_fork_prepare();
|
||||
__flockfilelist();
|
||||
|
||||
pid = __libc_fork();
|
||||
pid = ARCH_FORK ();
|
||||
|
||||
if (pid == 0) {
|
||||
__pthread_reset_main_thread();
|
||||
|
||||
__fresetlockfiles();
|
||||
__pthread_once_fork_child();
|
||||
pthread_call_handlers(pthread_atfork_child);
|
||||
|
||||
pthread_mutex_init(&pthread_atfork_lock, NULL);
|
||||
/* 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 {
|
||||
__funlockfilelist();
|
||||
__pthread_once_fork_parent();
|
||||
pthread_call_handlers(pthread_atfork_parent);
|
||||
|
||||
pthread_mutex_unlock(&pthread_atfork_lock);
|
||||
/* 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;
|
||||
}
|
||||
|
||||
pid_t __fork (void)
|
||||
{
|
||||
return __libc_fork ();
|
||||
}
|
||||
weak_alias (__fork, fork);
|
||||
|
||||
pid_t __vfork(void)
|
||||
{
|
||||
return __fork();
|
||||
return __libc_fork ();
|
||||
}
|
||||
weak_alias (__vfork, vfork);
|
||||
|
|
|
@ -238,6 +238,7 @@ static struct pthread_functions pthread_functions =
|
|||
.ptr_pthread_internal_tsd_get = __pthread_internal_tsd_get,
|
||||
.ptr_pthread_internal_tsd_address = __pthread_internal_tsd_address,
|
||||
#endif
|
||||
.ptr_pthread_fork = __pthread_fork,
|
||||
.ptr_pthread_attr_destroy = __pthread_attr_destroy,
|
||||
#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
|
||||
.ptr___pthread_attr_init_2_0 = __pthread_attr_init_2_0,
|
||||
|
@ -273,7 +274,8 @@ static struct pthread_functions pthread_functions =
|
|||
.ptr_pthread_setcancelstate = __pthread_setcancelstate,
|
||||
.ptr_pthread_setcanceltype = __pthread_setcanceltype,
|
||||
.ptr_pthread_do_exit = __pthread_do_exit,
|
||||
.ptr_pthread_thread_self = __pthread_thread_self
|
||||
.ptr_pthread_thread_self = __pthread_thread_self,
|
||||
.ptr_pthread_cleanup_upto = __pthread_cleanup_upto
|
||||
};
|
||||
# define ptr_pthread_functions &pthread_functions
|
||||
#else
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include "internals.h"
|
||||
#include <fork.h>
|
||||
|
||||
/* This is defined by newer gcc version unique for each module. */
|
||||
extern void *__dso_handle __attribute__ ((__weak__));
|
||||
|
||||
|
||||
/* Hide the symbol so that no definition but the one locally in the
|
||||
executable or DSO is used. */
|
||||
int
|
||||
#ifndef __pthread_atfork
|
||||
/* Don't mark the compatibility function as hidden. */
|
||||
attribute_hidden
|
||||
#endif
|
||||
__pthread_atfork (prepare, parent, child)
|
||||
void (*prepare) (void);
|
||||
void (*parent) (void);
|
||||
void (*child) (void);
|
||||
{
|
||||
return __register_atfork (prepare, parent, child,
|
||||
&__dso_handle == NULL ? NULL : __dso_handle);
|
||||
}
|
||||
#ifndef __pthread_atfork
|
||||
extern int pthread_atfork (void (*prepare) (void), void (*parent) (void),
|
||||
void (*child) (void)) attribute_hidden;
|
||||
strong_alias (__pthread_atfork, pthread_atfork)
|
||||
#endif
|
|
@ -27,24 +27,23 @@ extern void __libc_longjmp (sigjmp_buf env, int val)
|
|||
__attribute__ ((noreturn));
|
||||
|
||||
|
||||
static void pthread_cleanup_upto(__jmp_buf target)
|
||||
void __pthread_cleanup_upto (__jmp_buf target, char *targetframe)
|
||||
{
|
||||
pthread_descr self = thread_self();
|
||||
struct _pthread_cleanup_buffer * c;
|
||||
char *currentframe = CURRENT_STACK_FRAME;
|
||||
|
||||
for (c = THREAD_GETMEM(self, p_cleanup);
|
||||
c != NULL && _JMPBUF_UNWINDS(target, c);
|
||||
c = c->__prev)
|
||||
{
|
||||
#if _STACK_GROWS_DOWN
|
||||
if ((char *) c <= currentframe)
|
||||
if ((char *) c <= targetframe)
|
||||
{
|
||||
c = NULL;
|
||||
break;
|
||||
}
|
||||
#elif _STACK_GROWS_UP
|
||||
if ((char *) c >= currentframe)
|
||||
if ((char *) c >= targetframe)
|
||||
{
|
||||
c = NULL;
|
||||
break;
|
||||
|
@ -62,12 +61,10 @@ static void pthread_cleanup_upto(__jmp_buf target)
|
|||
|
||||
void siglongjmp (sigjmp_buf env, int val)
|
||||
{
|
||||
pthread_cleanup_upto(env->__jmpbuf);
|
||||
__libc_siglongjmp (env, val);
|
||||
}
|
||||
|
||||
void longjmp (jmp_buf env, int val)
|
||||
{
|
||||
pthread_cleanup_upto(env->__jmpbuf);
|
||||
__libc_longjmp (env, val);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
/* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#ifndef _LIST_H
|
||||
#define _LIST_H 1
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/* The definitions of this file are adopted from those which can be
|
||||
found in the Linux kernel headers to enable people familiar with
|
||||
the latter find their way in these sources as well. */
|
||||
|
||||
|
||||
/* Basic type for the double-link list. */
|
||||
typedef struct list_head
|
||||
{
|
||||
struct list_head *next;
|
||||
struct list_head *prev;
|
||||
} list_t;
|
||||
|
||||
|
||||
/* Define a variable with the head and tail of the list. */
|
||||
#define LIST_HEAD(name) \
|
||||
list_t name = { &(name), &(name) }
|
||||
|
||||
/* Initialize a new list head. */
|
||||
#define INIT_LIST_HEAD(ptr) \
|
||||
(ptr)->next = (ptr)->prev = (ptr)
|
||||
|
||||
|
||||
/* Add new element at the head of the list. */
|
||||
static inline void
|
||||
list_add (list_t *newp, list_t *head)
|
||||
{
|
||||
head->next->prev = newp;
|
||||
newp->next = head->next;
|
||||
newp->prev = head;
|
||||
head->next = newp;
|
||||
}
|
||||
|
||||
|
||||
/* Add new element at the tail of the list. */
|
||||
static inline void
|
||||
list_add_tail (list_t *newp, list_t *head)
|
||||
{
|
||||
head->prev->next = newp;
|
||||
newp->next = head;
|
||||
newp->prev = head->prev;
|
||||
head->prev = newp;
|
||||
}
|
||||
|
||||
|
||||
/* Remove element from list. */
|
||||
static inline void
|
||||
list_del (list_t *elem)
|
||||
{
|
||||
elem->next->prev = elem->prev;
|
||||
elem->prev->next = elem->next;
|
||||
}
|
||||
|
||||
|
||||
/* Join two lists. */
|
||||
static inline void
|
||||
list_splice (list_t *add, list_t *head)
|
||||
{
|
||||
/* Do nothing if the list which gets added is empty. */
|
||||
if (add != add->next)
|
||||
{
|
||||
add->next->prev = head;
|
||||
add->prev->next = head->next;
|
||||
head->next->prev = add->prev;
|
||||
head->next = add->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Get typed element from list at a given position. */
|
||||
#define list_entry(ptr, type, member) \
|
||||
((type *) ((char *) (ptr) - (unsigned long) (&((type *) 0)->member)))
|
||||
|
||||
|
||||
|
||||
/* Iterate forward over the elements of the list. */
|
||||
#define list_for_each(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||
|
||||
|
||||
/* Iterate forward over the elements of the list. */
|
||||
#define list_for_each_prev(pos, head) \
|
||||
for (pos = (head)->prev; pos != (head); pos = pos->prev)
|
||||
|
||||
|
||||
/* Iterate backwards over the elements list. The list elements can be
|
||||
removed from the list while doing this. */
|
||||
#define list_for_each_prev_safe(pos, p, head) \
|
||||
for (pos = (head)->prev, p = pos->prev; \
|
||||
pos != (head); \
|
||||
pos = p, p = pos->prev)
|
||||
|
||||
#endif /* list.h */
|
|
@ -0,0 +1,3 @@
|
|||
ifeq ($(subdir),linuxthreads)
|
||||
sysdep_routines += register-atfork unregister-atfork
|
||||
endif
|
|
@ -0,0 +1,5 @@
|
|||
libc {
|
||||
GLIBC_2.3.2 {
|
||||
__register_atfork;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <errno.h>
|
||||
#include "fork.h"
|
||||
#include <bits/libc-lock.h>
|
||||
|
||||
weak_extern (__pthread_fork);
|
||||
|
||||
struct fork_block __fork_block =
|
||||
{
|
||||
.lock = PTHREAD_MUTEX_INITIALIZER,
|
||||
.prepare_list = { &__fork_block.prepare_list, &__fork_block.prepare_list },
|
||||
.parent_list = { &__fork_block.parent_list, &__fork_block.parent_list },
|
||||
.child_list = { &__fork_block.child_list, &__fork_block.child_list }
|
||||
};
|
||||
|
||||
pid_t
|
||||
__libc_fork (void)
|
||||
{
|
||||
return __libc_maybe_call2 (pthread_fork, (&__fork_block), ARCH_FORK ());
|
||||
}
|
||||
weak_alias (__libc_fork, __fork)
|
||||
weak_alias (__libc_fork, fork)
|
|
@ -0,0 +1,59 @@
|
|||
/* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <list.h>
|
||||
#include <bits/libc-lock.h>
|
||||
#include <sysdep.h>
|
||||
|
||||
struct fork_block
|
||||
{
|
||||
/* Lock to protect handling of fork handlers. */
|
||||
__libc_lock_define (, lock);
|
||||
|
||||
/* Lists of registered fork handlers. */
|
||||
list_t prepare_list;
|
||||
list_t parent_list;
|
||||
list_t child_list;
|
||||
};
|
||||
|
||||
extern struct fork_block __fork_block attribute_hidden;
|
||||
|
||||
/* Elements of the fork handler lists. */
|
||||
struct fork_handler
|
||||
{
|
||||
list_t list;
|
||||
void (*handler) (void);
|
||||
void *dso_handle;
|
||||
};
|
||||
|
||||
|
||||
/* Function to call to unregister fork handlers. */
|
||||
extern void __unregister_atfork (void *dso_handle) attribute_hidden;
|
||||
#define UNREGISTER_ATFORK(dso_handle) __unregister_atfork (dso_handle)
|
||||
|
||||
|
||||
/* C library side function to register new fork handlers. */
|
||||
extern int __register_atfork (void (*__prepare) (void),
|
||||
void (*__parent) (void),
|
||||
void (*__child) (void),
|
||||
void *dso_handle);
|
||||
|
||||
#ifndef ARCH_FORK
|
||||
# define ARCH_FORK() INLINE_SYSCALL (fork, 0)
|
||||
#endif
|
|
@ -0,0 +1,25 @@
|
|||
/* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <signal.h>
|
||||
#include <sysdep.h>
|
||||
|
||||
#define ARCH_FORK() INLINE_SYSCALL (clone, 2, SIGCHLD, 0)
|
||||
|
||||
#include_next <fork.h>
|
|
@ -0,0 +1,32 @@
|
|||
/* _longjmp_unwind -- Clean up stack frames unwound by longjmp.
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <stddef.h>
|
||||
#include <bits/libc-lock.h>
|
||||
|
||||
weak_extern (__pthread_cleanup_upto);
|
||||
|
||||
void
|
||||
_longjmp_unwind (jmp_buf env, int val)
|
||||
{
|
||||
__libc_maybe_call2 (pthread_cleanup_upto,
|
||||
(env->__jmpbuf, __builtin_frame_address (0)),
|
||||
(void) 0);
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include "fork.h"
|
||||
|
||||
|
||||
int
|
||||
__register_atfork (prepare, parent, child, dso_handle)
|
||||
void (*prepare) (void);
|
||||
void (*parent) (void);
|
||||
void (*child) (void);
|
||||
void *dso_handle;
|
||||
{
|
||||
struct fork_handler *new_prepare = NULL;
|
||||
struct fork_handler *new_parent = NULL;
|
||||
struct fork_handler *new_child = NULL;
|
||||
|
||||
if (prepare != NULL)
|
||||
{
|
||||
new_prepare = (struct fork_handler *) malloc (sizeof (*new_prepare));
|
||||
if (new_prepare == NULL)
|
||||
goto out1;
|
||||
|
||||
new_prepare->handler = prepare;
|
||||
new_prepare->dso_handle = dso_handle;
|
||||
}
|
||||
|
||||
if (parent != NULL)
|
||||
{
|
||||
new_parent = (struct fork_handler *) malloc (sizeof (*new_parent));
|
||||
if (new_parent == NULL)
|
||||
goto out2;
|
||||
|
||||
new_parent->handler = parent;
|
||||
new_parent->dso_handle = dso_handle;
|
||||
}
|
||||
|
||||
if (child != NULL)
|
||||
{
|
||||
new_child = (struct fork_handler *) malloc (sizeof (*new_child));
|
||||
if (new_child == NULL)
|
||||
{
|
||||
free (new_parent);
|
||||
out2:
|
||||
free (new_prepare);
|
||||
out1:
|
||||
return errno;
|
||||
}
|
||||
|
||||
new_child->handler = child;
|
||||
new_child->dso_handle = dso_handle;
|
||||
}
|
||||
|
||||
/* Get the lock to not conflict with running forks. */
|
||||
__libc_lock_lock (__fork_block.lock);
|
||||
|
||||
/* Now that we have all the handlers allocate enqueue them. */
|
||||
if (new_prepare != NULL)
|
||||
list_add_tail (&new_prepare->list, &__fork_block.prepare_list);
|
||||
if (new_parent != NULL)
|
||||
list_add_tail (&new_parent->list, &__fork_block.parent_list);
|
||||
if (new_child != NULL)
|
||||
list_add_tail (&new_child->list, &__fork_block.child_list);
|
||||
|
||||
/* Release the lock. */
|
||||
__libc_lock_unlock (__fork_block.lock);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <sysdep.h>
|
||||
|
||||
#define ARCH_FORK() \
|
||||
({ \
|
||||
register long __o0 __asm__ ("o0"); \
|
||||
register long __o1 __asm__ ("o1"); \
|
||||
register long __g1 __asm__ ("g1") = __NR_fork; \
|
||||
__asm __volatile (__SYSCALL_STRING \
|
||||
: "=r" (__g1), "=r" (__o0), "=r" (__o1) \
|
||||
: "0" (__g1) \
|
||||
: __SYSCALL_CLOBBERS); \
|
||||
__o0 == -1 ? __o0 : (__o0 & (__o1 - 1)); \
|
||||
})
|
||||
|
||||
#include_next <fork.h>
|
|
@ -0,0 +1,49 @@
|
|||
/* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include "fork.h"
|
||||
|
||||
|
||||
void
|
||||
__unregister_atfork (dso_handle)
|
||||
void *dso_handle;
|
||||
{
|
||||
/* Get the lock to not conflict with running forks. */
|
||||
__libc_lock_lock (__fork_block.lock);
|
||||
|
||||
list_t *runp;
|
||||
list_t *prevp;
|
||||
|
||||
list_for_each_prev_safe (runp, prevp, &__fork_block.prepare_list)
|
||||
if (list_entry (runp, struct fork_handler, list)->dso_handle == dso_handle)
|
||||
list_del (runp);
|
||||
|
||||
list_for_each_prev_safe (runp, prevp, &__fork_block.parent_list)
|
||||
if (list_entry (runp, struct fork_handler, list)->dso_handle == dso_handle)
|
||||
list_del (runp);
|
||||
|
||||
list_for_each_prev_safe (runp, prevp, &__fork_block.child_list)
|
||||
if (list_entry (runp, struct fork_handler, list)->dso_handle == dso_handle)
|
||||
list_del (runp);
|
||||
|
||||
/* Release the lock. */
|
||||
__libc_lock_unlock (__fork_block.lock);
|
||||
}
|
|
@ -72,8 +72,14 @@ __libc_lock_define (typedef, mutex_t)
|
|||
|
||||
#endif
|
||||
|
||||
/* This is defined by newer gcc version unique for each module. */
|
||||
extern void *__dso_handle __attribute__ ((__weak__));
|
||||
|
||||
#include <fork.h>
|
||||
|
||||
#define thread_atfork(prepare, parent, child) \
|
||||
(__pthread_atfork != NULL ? __pthread_atfork(prepare, parent, child) : 0)
|
||||
__register_atfork (prepare, parent, child, \
|
||||
&__dso_handle == NULL ? NULL : __dso_handle)
|
||||
|
||||
#elif defined(MUTEX_INITIALIZER)
|
||||
/* Assume hurd, with cthreads */
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
2002-12-30 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* sysdeps/pthread/pt-initfini.c (call_initialize_minimal): Mark
|
||||
__pthread_initialize_minimal as hidden.
|
||||
|
||||
* init.c (__pthread_initialize_minimal_internal): Don't mark as
|
||||
constructor.
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Special .init and .fini section support. Linuxthread version.
|
||||
Copyright (C) 1995, 1996, 1997, 2000, 2001 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995,1996,1997,2000,2001,2002 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it
|
||||
|
@ -65,7 +65,8 @@ asm ("\n/*@_init_PROLOG_BEGINS*/");
|
|||
static void
|
||||
call_initialize_minimal (void)
|
||||
{
|
||||
extern void __pthread_initialize_minimal (void);
|
||||
extern void __pthread_initialize_minimal (void)
|
||||
__attribute ((visibility ("hidden")));
|
||||
|
||||
__pthread_initialize_minimal ();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue