about summary refs log tree commit diff
path: root/linuxthreads/sysdeps
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/sysdeps
parent89d6e4445954aee95d02b84db7af7fa0cca93195 (diff)
downloadglibc-416d2de60b8e567ac7cd6a581afba0f5cdfc932e.tar.gz
glibc-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/sysdeps')
-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
10 files changed, 450 insertions, 0 deletions
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>
+
+/* 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 */
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/Makefile b/linuxthreads/sysdeps/unix/sysv/linux/Makefile
new file mode 100644
index 0000000000..38c6cbc1af
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/Makefile
@@ -0,0 +1,3 @@
+ifeq ($(subdir),linuxthreads)
+sysdep_routines += register-atfork unregister-atfork
+endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/Versions b/linuxthreads/sysdeps/unix/sysv/linux/Versions
new file mode 100644
index 0000000000..6cd3dbe372
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/Versions
@@ -0,0 +1,5 @@
+libc {
+  GLIBC_2.3.2 {
+    __register_atfork;
+  }
+}
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/fork.c b/linuxthreads/sysdeps/unix/sysv/linux/fork.c
new file mode 100644
index 0000000000..c519fa0677
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/fork.c
@@ -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)
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/fork.h b/linuxthreads/sysdeps/unix/sysv/linux/fork.h
new file mode 100644
index 0000000000..e84119a2ef
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/fork.h
@@ -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
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/ia64/fork.h b/linuxthreads/sysdeps/unix/sysv/linux/ia64/fork.h
new file mode 100644
index 0000000000..30a0cc1918
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/ia64/fork.h
@@ -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>
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/jmp-unwind.c b/linuxthreads/sysdeps/unix/sysv/linux/jmp-unwind.c
new file mode 100644
index 0000000000..37cc4c2c0b
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/jmp-unwind.c
@@ -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);
+}
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/register-atfork.c b/linuxthreads/sysdeps/unix/sysv/linux/register-atfork.c
new file mode 100644
index 0000000000..2dce262a38
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/register-atfork.c
@@ -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;
+}
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sparc/fork.h b/linuxthreads/sysdeps/unix/sysv/linux/sparc/fork.h
new file mode 100644
index 0000000000..793cb1d5f9
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/sparc/fork.h
@@ -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>
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/unregister-atfork.c b/linuxthreads/sysdeps/unix/sysv/linux/unregister-atfork.c
new file mode 100644
index 0000000000..dad273fdf5
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/unregister-atfork.c
@@ -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);
+}