about summary refs log tree commit diff
path: root/sysdeps/unix/sysv/linux/arch-fork.h
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv/linux/arch-fork.h')
-rw-r--r--sysdeps/unix/sysv/linux/arch-fork.h43
1 files changed, 34 insertions, 9 deletions
diff --git a/sysdeps/unix/sysv/linux/arch-fork.h b/sysdeps/unix/sysv/linux/arch-fork.h
index d5f542924f..3daa9651e5 100644
--- a/sysdeps/unix/sysv/linux/arch-fork.h
+++ b/sysdeps/unix/sysv/linux/arch-fork.h
@@ -1,4 +1,4 @@
-/* ARCH_FORK definition for Linux fork implementation.  Stub version.
+/* arch_fork definition for Linux fork implementation.
    Copyright (C) 2014-2018 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -16,12 +16,37 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-/* This file should define the function-like macro of no arguments
-   ARCH_FORK to an INLINE_SYSCALL invocation of the clone-like system
-   call, passing the CLONE_CHILD_SETTID and CLONE_CHILD_CLEARTID flags
-   and &THREAD_SELF->tid as the TID address.
+#ifndef __ARCH_FORK_H
+#define __ARCH_FORK_H
 
-   Machines that lack an arch-fork.h header file will hit an #error in
-   fork.c; this stub file doesn't contain an #error itself mainly for
-   the transition period of migrating old machine-specific fork.c files
-   to machine-specific arch-fork.h instead.  */
+#include <unistd.h>
+
+/* Call the clone syscall with fork semantic.  The CTID address is used
+   to store the child thread ID at its locationm, to erase it in child memory
+   when the child exits, and do a wakeup on the futex at that address.
+
+   The architecture with non-default kernel abi semantic should correctlly
+   override it with one of the supported calling convention (check generic
+   kernel-features.h for the clone abi variants).  */
+static inline pid_t
+arch_fork (void *ctid)
+{
+  const int flags = CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD;
+  long int ret;
+#ifdef __ASSUME_CLONE_BACKWARDS
+  ret = INLINE_SYSCALL_CALL (clone, flags, 0, NULL, 0, ctid);
+#elif defined(__ASSUME_CLONE_BACKWARDS2)
+  ret = INLINE_SYSCALL_CALL (clone, 0, flags, NULL, ctid, 0);
+#elif defined(__ASSUME_CLONE_BACKWARDS3)
+  ret = INLINE_SYSCALL_CALL (clone, flags, 0, 0, NULL, ctid, 0);
+#elif defined(__ASSUME_CLONE2)
+  ret = INLINE_SYSCALL_CALL (clone2, flags, 0, 0, NULL, ctid, 0);
+#elif defined(__ASSUME_CLONE_DEFAULT)
+  ret = INLINE_SYSCALL_CALL (clone, flags, 0, NULL, ctid, 0);
+#else
+# error "Undefined clone variant"
+#endif
+  return ret;
+}
+
+#endif /* __ARCH_FORK_H  */