aboutsummaryrefslogtreecommitdiff
path: root/linuxthreads
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2002-12-31 08:00:19 +0000
committerUlrich Drepper <drepper@redhat.com>2002-12-31 08:00:19 +0000
commit416d2de60b8e567ac7cd6a581afba0f5cdfc932e (patch)
treeabd37640e253dae0e65751ea12f20253830bb269 /linuxthreads
parent89d6e4445954aee95d02b84db7af7fa0cca93195 (diff)
downloadglibc-416d2de60b8e567ac7cd6a581afba0f5cdfc932e.tar.xz
glibc-416d2de60b8e567ac7cd6a581afba0f5cdfc932e.zip
Update.
2002-12-30 Ulrich Drepper <drepper@redhat.com> * malloc/thread-m.h (thread_atfork): Define using __register_atfork.
Diffstat (limited to 'linuxthreads')
-rw-r--r--linuxthreads/ChangeLog41
-rw-r--r--linuxthreads/Makeconfig3
-rw-r--r--linuxthreads/Makefile45
-rw-r--r--linuxthreads/internals.h8
-rw-r--r--linuxthreads/old_pthread_atfork.c27
-rw-r--r--linuxthreads/ptfork.c99
-rw-r--r--linuxthreads/pthread.c4
-rw-r--r--linuxthreads/pthread_atfork.c46
-rw-r--r--linuxthreads/ptlongjmp.c17
-rw-r--r--linuxthreads/sysdeps/pthread/list.h116
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/Makefile3
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/Versions5
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/fork.c40
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/fork.h59
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/ia64/fork.h25
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/jmp-unwind.c32
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/register-atfork.c87
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/sparc/fork.h34
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/unregister-atfork.c49
19 files changed, 662 insertions, 78 deletions
diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog
index 6927282eba..16e26d8950 100644
--- a/linuxthreads/ChangeLog
+++ b/linuxthreads/ChangeLog
@@ -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
diff --git a/linuxthreads/Makeconfig b/linuxthreads/Makeconfig
index 4b1c0c3414..2dfd58c99e 100644
--- a/linuxthreads/Makeconfig
+++ b/linuxthreads/Makeconfig
@@ -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
diff --git a/linuxthreads/Makefile b/linuxthreads/Makefile
index a86aae7d53..9a6745fe17 100644
--- a/linuxthreads/Makefile
+++ b/linuxthreads/Makefile
@@ -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
diff --git a/linuxthreads/internals.h b/linuxthreads/internals.h
index 8c4de222b4..872bc5c047 100644
--- a/linuxthreads/internals.h
+++ b/linuxthreads/internals.h
@@ -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);
diff --git a/linuxthreads/old_pthread_atfork.c b/linuxthreads/old_pthread_atfork.c
new file mode 100644
index 0000000000..768e6876c4
--- /dev/null
+++ b/linuxthreads/old_pthread_atfork.c
@@ -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
diff --git a/linuxthreads/ptfork.c b/linuxthreads/ptfork.c
index 564f8d7c75..195ffcd1b0 100644
--- a/linuxthreads/ptfork.c
+++ b/linuxthreads/ptfork.c
@@ -21,96 +21,71 @@
#include "pthread.h"
#include "internals.h"
#include <bits/libc-lock.h>
+#include "fork.h"
-struct handler_list {
- void (*handler)(void);
- struct handler_list * next;
-};
+extern int __libc_fork (void);
-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)();
-}
-
-extern int __libc_fork(void);
-
-pid_t __fork(void)
+pid_t __pthread_fork (struct fork_block *b)
{
pid_t pid;
+ list_t *runp;
+
+ __libc_lock_lock (b->lock);
- pthread_mutex_lock(&pthread_atfork_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);
diff --git a/linuxthreads/pthread.c b/linuxthreads/pthread.c
index 15de7e610f..444c0a0ed2 100644
--- a/linuxthreads/pthread.c
+++ b/linuxthreads/pthread.c
@@ -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
diff --git a/linuxthreads/pthread_atfork.c b/linuxthreads/pthread_atfork.c
new file mode 100644
index 0000000000..dabb26a726
--- /dev/null
+++ b/linuxthreads/pthread_atfork.c
@@ -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
diff --git a/linuxthreads/ptlongjmp.c b/linuxthreads/ptlongjmp.c
index 18592548ed..ece553141f 100644
--- a/linuxthreads/ptlongjmp.c
+++ b/linuxthreads/ptlongjmp.c
@@ -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;
@@ -60,14 +59,12 @@ static void pthread_cleanup_upto(__jmp_buf target)
THREAD_SETMEM(self, p_in_sighandler, NULL);
}
-void siglongjmp(sigjmp_buf env, int val)
+void siglongjmp (sigjmp_buf env, int val)
{
- pthread_cleanup_upto(env->__jmpbuf);
- __libc_siglongjmp(env, val);
+ __libc_siglongjmp (env, val);
}
-void longjmp(jmp_buf env, int val)
+void longjmp (jmp_buf env, int val)
{
- pthread_cleanup_upto(env->__jmpbuf);
- __libc_longjmp(env, val);
+ __libc_longjmp (env, val);
}
diff --git a/linuxthreads/sysdeps/pthread/list.h b/linuxthreads/sysdeps/pthread/list.h
new file mode 100644
index 0000000000..1d6a4cfa65
--- /dev/null
+++ b/linuxthreads/sysdeps/pthread/list.h
@@ -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>