This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix linuxthreads tst-cancel5


Hi!

The following patch fixes tst-cancel5 by handling fork/__fork and
siglongjmp/longjmp the same between -lpthread -lc and -lc -lpthread.

BTW: Something should still be done about malloc/thread-m.h thread_atfork,
particularly it should call IMHO __register_atfork directly
(both for nptl and linuxthreads).

2002-12-31  Jakub Jelinek  <jakub@redhat.com>

linuxthreads/
	* 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.
nptl/
	* Makefile ($(inst_libdir)/libpthread.so): Depend on
	$(common-objpfx)format.lds, include that into the output script.
	Fix comment.
	(extra-B-pthread.so): Change linuxthreads/ into nptl/.

--- libc/linuxthreads/sysdeps/pthread/list.h.jj	2002-12-30 18:40:56.000000000 +0100
+++ libc/linuxthreads/sysdeps/pthread/list.h	2002-11-26 23:50:31.000000000 +0100
@@ -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 */
--- libc/linuxthreads/sysdeps/unix/sysv/linux/ia64/fork.h.jj	2002-12-31 01:54:46.000000000 +0100
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/ia64/fork.h	2002-12-31 01:56:06.000000000 +0100
@@ -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>
--- libc/linuxthreads/sysdeps/unix/sysv/linux/sparc/fork.h.jj	2002-12-31 01:54:46.000000000 +0100
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/sparc/fork.h	2002-12-31 02:05:33.000000000 +0100
@@ -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>
--- libc/linuxthreads/sysdeps/unix/sysv/linux/jmp-unwind.c.jj	2002-12-30 18:03:32.000000000 +0100
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/jmp-unwind.c	2002-12-30 18:19:13.000000000 +0100
@@ -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);
+}
--- libc/linuxthreads/sysdeps/unix/sysv/linux/fork.c.jj	2002-12-30 18:31:37.000000000 +0100
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/fork.c	2002-12-31 00:04:40.000000000 +0100
@@ -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)
--- libc/linuxthreads/sysdeps/unix/sysv/linux/fork.h.jj	2002-12-30 18:31:41.000000000 +0100
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/fork.h	2002-12-30 19:25:46.000000000 +0100
@@ -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
--- libc/linuxthreads/sysdeps/unix/sysv/linux/register-atfork.c.jj	2002-12-30 18:31:44.000000000 +0100
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/register-atfork.c	2002-12-30 19:07:25.000000000 +0100
@@ -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;
+}
--- libc/linuxthreads/sysdeps/unix/sysv/linux/unregister-atfork.c.jj	2002-12-30 18:31:48.000000000 +0100
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/unregister-atfork.c	2002-12-30 19:07:46.000000000 +0100
@@ -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);
+}
--- libc/linuxthreads/sysdeps/unix/sysv/linux/Makefile.jj	2002-12-30 19:46:42.000000000 +0100
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/Makefile	2002-12-30 19:47:33.000000000 +0100
@@ -0,0 +1,3 @@
+ifeq ($(subdir),linuxthreads)
+sysdep_routines += register-atfork unregister-atfork
+endif
--- libc/linuxthreads/sysdeps/unix/sysv/linux/Versions.jj	2002-12-30 19:47:44.000000000 +0100
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/Versions	2002-12-30 19:49:07.000000000 +0100
@@ -0,0 +1,5 @@
+libc {
+  GLIBC_2.3.2 {
+    __register_atfork;
+  }
+}
--- libc/linuxthreads/ptlongjmp.c.jj	2001-06-17 04:19:16.000000000 +0200
+++ libc/linuxthreads/ptlongjmp.c	2002-12-30 18:20:09.000000000 +0100
@@ -27,24 +27,23 @@ extern void __libc_longjmp (sigjmp_buf e
      __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_b
     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);
 }
--- libc/linuxthreads/internals.h.jj	2002-12-27 21:49:58.000000000 +0100
+++ libc/linuxthreads/internals.h	2002-12-31 00:37:09.000000000 +0100
@@ -463,6 +463,11 @@ extern int __libc_enable_asynccancel (vo
 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 (
    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);
--- libc/linuxthreads/pthread.c.jj	2002-12-30 13:38:46.000000000 +0100
+++ libc/linuxthreads/pthread.c	2002-12-30 19:52:12.000000000 +0100
@@ -238,6 +238,7 @@ static struct pthread_functions pthread_
     .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_
     .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
--- libc/linuxthreads/ptfork.c.jj	2000-12-27 18:16:24.000000000 +0100
+++ libc/linuxthreads/ptfork.c	2002-12-30 20:24:24.000000000 +0100
@@ -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;
-};
-
-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)
+extern int __libc_fork (void);
 
-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;
 
-  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);
--- libc/linuxthreads/Makefile.jj	2002-12-27 19:10:38.000000000 +0100
+++ libc/linuxthreads/Makefile	2002-12-31 01:35:55.000000000 +0100
@@ -46,12 +46,14 @@ libpthread-routines := attr cancel condv
 		       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-i
 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,12 +189,14 @@ $(objpfx)libpthread.so: $(libc-link.so) 
 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
 $(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
--- libc/linuxthreads/old_pthread_atfork.c.jj	2002-12-30 19:44:40.000000000 +0100
+++ libc/linuxthreads/old_pthread_atfork.c	2002-11-26 23:50:00.000000000 +0100
@@ -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
--- libc/linuxthreads/pthread_atfork.c.jj	2002-12-30 19:44:48.000000000 +0100
+++ libc/linuxthreads/pthread_atfork.c	2002-12-30 20:41:48.000000000 +0100
@@ -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
--- libc/linuxthreads/Makeconfig.jj	2001-05-21 08:06:20.000000000 +0200
+++ libc/linuxthreads/Makeconfig	2002-12-30 22:00:09.000000000 +0100
@@ -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
 
--- libc/nptl/Makefile.jj	2002-12-27 12:54:22.000000000 +0100
+++ libc/nptl/Makefile	2002-12-30 19:40:54.000000000 +0100
@@ -175,20 +175,22 @@ tests-reverse += tst-cancel5
 
 include ../Rules
 
-# What we install as libc.so for programs to link against is in fact a
+# 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 libc.so object is not complete since some functions are only defined
-# in libc_nonshared.a.
+# 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: $(objpfx)libpthread.so$(libpthread.so-version) \
+$(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)'\
 	      ')' \
@@ -200,7 +202,7 @@ $(inst_libdir)/libpthread_nonshared.a: $
 
 CFLAGS-tst-unload.c += -DPREFIX=\"$(objpfx)\"
 
-extra-B-pthread.so = -B$(common-objpfx)linuxthreads/
+extra-B-pthread.so = -B$(common-objpfx)nptl/
 $(objpfx)libpthread.so: $(objpfx)crti.o
 $(objpfx)libpthread.so: +preinit += $(objpfx)crti.o
 

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]