about summary refs log tree commit diff
path: root/linuxthreads/sysdeps/unix/sysv
diff options
context:
space:
mode:
Diffstat (limited to 'linuxthreads/sysdeps/unix/sysv')
-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
9 files changed, 334 insertions, 0 deletions
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);
+}