]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
posix: Consolidate register-atfork
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>
Mon, 18 Jan 2021 18:10:02 +0000 (15:10 -0300)
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>
Fri, 12 Mar 2021 13:19:22 +0000 (10:19 -0300)
Both htl and nptl uses a different data structure to implement atfork
handlers.  The nptl one was refactored by 27761a1042d to use a dynarray
which simplifies the code.

This patch moves the nptl one to be the generic implementation and
replace Hurd linked one.  Different than previous NPTL, Hurd also uses
a global lock, so performance should be similar.

Checked on x86_64-linux-gnu, i686-linux-gnu, and with a build for
i686-gnu.

htl/Makefile
htl/register-atfork.c [deleted file]
include/register-atfork.h [moved from sysdeps/htl/fork.h with 54% similarity]
nptl/Makefile
posix/Makefile
posix/register-atfork.c [moved from nptl/register-atfork.c with 97% similarity]
sysdeps/generic/fork.h
sysdeps/htl/pt-atfork.c
sysdeps/mach/hurd/fork.c
sysdeps/nptl/fork.h

index c15c1b194eaf93dd6a9ac6fb9319454a318fe41b..895a6f777c8a599dc3861f41eb86e4eb59b5e197 100644 (file)
@@ -165,7 +165,7 @@ headers :=                          \
 
 distribute :=
 
-routines := forward libc_pthread_init alloca_cutoff register-atfork pt-atfork
+routines := forward libc_pthread_init alloca_cutoff pt-atfork
 shared-only-routines = forward
 static-only-routines = pt-atfork
 
diff --git a/htl/register-atfork.c b/htl/register-atfork.c
deleted file mode 100644 (file)
index 8be132f..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/* Atfork handling.  Hurd pthread version.
-   Copyright (C) 2002-2021 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, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <errno.h>
-#include <stdlib.h>
-#include <libc-lock.h>
-#include <fork.h>
-
-struct atfork
-{
-  void (*prepare) (void);
-  void (*parent) (void);
-  void (*child) (void);
-  void *dso_handle;
-  struct atfork *prev;
-  struct atfork *next;
-};
-
-/* TODO: better locking */
-__libc_lock_define_initialized (static, atfork_lock);
-static struct atfork *fork_handlers, *fork_last_handler;
-
-static void
-atfork_pthread_prepare (void)
-{
-  struct atfork *handlers, *last_handler;
-
-  __libc_lock_lock (atfork_lock);
-  handlers = fork_handlers;
-  last_handler = fork_last_handler;
-  __libc_lock_unlock (atfork_lock);
-
-  if (last_handler == NULL)
-    return;
-
-  while (1)
-    {
-      if (last_handler->prepare != NULL)
-       last_handler->prepare ();
-      if (last_handler == handlers)
-       break;
-      last_handler = last_handler->prev;
-    }
-}
-text_set_element (_hurd_atfork_prepare_hook, atfork_pthread_prepare);
-
-static void
-atfork_pthread_parent (void)
-{
-  struct atfork *handlers;
-
-  __libc_lock_lock (atfork_lock);
-  handlers = fork_handlers;
-  __libc_lock_unlock (atfork_lock);
-
-  while (handlers != NULL)
-    {
-      if (handlers->parent != NULL)
-       handlers->parent ();
-      handlers = handlers->next;
-    }
-}
-text_set_element (_hurd_atfork_parent_hook, atfork_pthread_parent);
-
-static void
-atfork_pthread_child (void)
-{
-  struct atfork *handlers;
-
-  __libc_lock_lock (atfork_lock);
-  handlers = fork_handlers;
-  __libc_lock_unlock (atfork_lock);
-
-  while (handlers != NULL)
-    {
-      if (handlers->child != NULL)
-       handlers->child ();
-      handlers = handlers->next;
-    }
-}
-text_set_element (_hurd_atfork_child_hook, atfork_pthread_child);
-
-int
-__register_atfork (void (*prepare) (void),
-                  void (*parent) (void),
-                  void (*child) (void),
-                  void *dso_handle)
-{
-  struct atfork *new = malloc (sizeof (*new));
-  if (new == NULL)
-    return errno;
-
-  new->prepare = prepare;
-  new->parent = parent;
-  new->child = child;
-  new->dso_handle = dso_handle;
-  new->next = NULL;
-
-  __libc_lock_lock (atfork_lock);
-  new->prev = fork_last_handler;
-  if (fork_last_handler != NULL)
-    fork_last_handler->next = new;
-  if (fork_handlers == NULL)
-    fork_handlers = new;
-  fork_last_handler = new;
-  __libc_lock_unlock (atfork_lock);
-
-  return 0;
-}
-libc_hidden_def (__register_atfork)
-
-void
-__unregister_atfork (void *dso_handle)
-{
-  struct atfork **handlers, *prev = NULL, *next;
-  __libc_lock_lock (atfork_lock);
-  handlers = &fork_handlers;
-  while (*handlers != NULL)
-    {
-      if ((*handlers)->dso_handle == dso_handle)
-       {
-         /* Drop this handler from the list.  */
-         if (*handlers == fork_last_handler)
-           {
-             /* Was last, new last is prev, if any.  */
-             fork_last_handler = prev;
-           }
-
-         next = (*handlers)->next;
-         if (next != NULL)
-           next->prev = prev;
-         *handlers = next;
-       }
-      else
-       {
-         /* Just proceed to next handler.  */
-         prev = *handlers;
-         handlers = &prev->next;
-       }
-    }
-  __libc_lock_unlock (atfork_lock);
-}
similarity index 54%
rename from sysdeps/htl/fork.h
rename to include/register-atfork.h
index 0fccc309f86553c46d6dd139703d652785831372..fadde14700947ac6bf6597a4feb2e94691b0953b 100644 (file)
@@ -1,5 +1,5 @@
-/* Register fork handlers.  Generic version.
-   Copyright (C) 2002-2021 Free Software Foundation, Inc.
+/* Internal pthread_atfork definitions.
+   Copyright (C) 2021 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
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
+#ifndef _REGISTER_ATFORK_H
+#define _REGISTER_ATFORK_H
+
+/* Elements of the fork handler lists.  */
+struct fork_handler
+{
+  void (*prepare_handler) (void);
+  void (*parent_handler) (void);
+  void (*child_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)
 
+enum __run_fork_handler_type
+{
+  atfork_run_prepare,
+  atfork_run_child,
+  atfork_run_parent
+};
+
+/* Run the atfork handlers and lock/unlock the internal lock depending
+   of the WHO argument:
+
+   - atfork_run_prepare: run all the PREPARE_HANDLER in reverse order of
+                        insertion and locks the internal lock.
+   - atfork_run_child: run all the CHILD_HANDLER and unlocks the internal
+                      lock.
+   - atfork_run_parent: run all the PARENT_HANDLER and unlocks the internal
+                       lock.
+
+   Perform locking only if DO_LOCKING.  */
+extern void __run_fork_handlers (enum __run_fork_handler_type who,
+                                _Bool do_locking) attribute_hidden;
 
 /* C library side function to register new fork handlers.  */
 extern int __register_atfork (void (*__prepare) (void),
@@ -27,3 +59,5 @@ extern int __register_atfork (void (*__prepare) (void),
                              void (*__child) (void),
                              void *dso_handle);
 libc_hidden_proto (__register_atfork)
+
+#endif
index 33766eaf7a4630151e1e2322a852b86daddee968..e5d69e885824eba2e26d63277c0828f60bb05721 100644 (file)
@@ -74,7 +74,6 @@ routines = \
   pthread_self \
   pthread_setschedparam \
   pthread_sigmask \
-  register-atfork \
 
 shared-only-routines = forward
 static-only-routines = pthread_atfork
index 305ec757cd797f1b47fc12b9d17f418f8b74b421..be0c72f0bbfdaa20b327302570e5599ac7a2e763 100644 (file)
@@ -39,7 +39,7 @@ routines :=                                                                 \
        times                                                                 \
        wait waitpid wait3 wait4 waitid                                       \
        alarm sleep pause nanosleep                                           \
-       fork vfork _exit                                                      \
+       fork vfork _exit register-atfork                                      \
        execve fexecve execv execle execl execvp execlp execvpe               \
        getpid getppid                                                        \
        getuid geteuid getgid getegid getgroups setuid setgid group_member    \
similarity index 97%
rename from nptl/register-atfork.c
rename to posix/register-atfork.c
index 30c16fba40653d8b79fa9a7816bd6246899a48c5..6fd9e4c56aafd7cca710474cd60d5dc0a6b4e78a 100644 (file)
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fork.h>
-#include <atomic.h>
+#include <libc-lock.h>
+#include <stdbool.h>
+#include <register-atfork.h>
 
 #define DYNARRAY_ELEMENT           struct fork_handler
 #define DYNARRAY_STRUCT            fork_handler_list
index 623cae28dfa22d00ed09b8842ca36f44f733942c..6cc842a425d0c36f285933160d0ac9cfaeba9138 100644 (file)
@@ -6,3 +6,22 @@
      parameter which is the DSO handle for the DSO which gets unloaded.
      The function so called has to remove the atfork handlers registered
      by this module.  */
+
+
+/* System specific fork definition.  Generic version.
+   Copyright (C) 2002-2021 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, see
+   <https://www.gnu.org/licenses/>.  */
index 3d115d3819b2140ad4375154ea04e04ddeb7936e..dbb3b8f0cc14c7d91870c24baf6c9fdfbfeda1f6 100644 (file)
@@ -20,6 +20,7 @@
 #include <pt-internal.h>
 #include <fork.h>
 #include <dso_handle.h>
+#include <register-atfork.h>
 
 /* Hide the symbol so that no definition but the one locally in the
    executable or DSO is used.  */
index 2b39f4e8b52d45b2e06670c5ae88c6c6ee1887bd..1c5299e6867ed93f2e42c55e3d3ce8329fe3eb27 100644 (file)
@@ -30,6 +30,7 @@
 #include <malloc/malloc-internal.h>
 #include <nss/nss_database.h>
 #include <unwind-link.h>
+#include <register-atfork.h>
 
 #undef __fork
 
 /* Things that want to be locked while forking.  */
 symbol_set_declare (_hurd_fork_locks)
 
-
-/* Application callbacks registered through pthread_atfork.  */
-DEFINE_HOOK (_hurd_atfork_prepare_hook, (void));
-DEFINE_HOOK (_hurd_atfork_child_hook, (void));
-DEFINE_HOOK (_hurd_atfork_parent_hook, (void));
-
 /* Things that want to be called before we fork, to prepare the parent for
    task_create, when the new child task will inherit our address space.  */
 DEFINE_HOOK (_hurd_fork_prepare_hook, (void));
@@ -72,7 +67,7 @@ __fork (void)
   struct hurd_sigstate *volatile ss;
   struct nss_database_data nss_database_data;
 
-  RUN_HOOK (_hurd_atfork_prepare_hook, ());
+  __run_fork_handlers (atfork_run_prepare, true);
 
   ss = _hurd_self_sigstate ();
   __spin_lock (&ss->critical_section_lock);
@@ -726,10 +721,8 @@ __fork (void)
 
   if (!err)
     {
-      if (pid != 0)
-       RUN_HOOK (_hurd_atfork_parent_hook, ());
-      else
-       RUN_HOOK (_hurd_atfork_child_hook, ());
+      __run_fork_handlers (pid == 0 ? atfork_run_child : atfork_run_parent,
+                          true);
     }
 
   return err ? __hurd_fail (err) : pid;
index 25002287b198f3a74a79716d3e7aed91b34a1453..524675429072122a110d9763b528bb71c74e078d 100644 (file)
    <https://www.gnu.org/licenses/>.  */
 
 #include <lowlevellock.h>
+#include <register-atfork.h>
 
 /* The fork generation counter, defined in libpthread.  */
 extern unsigned long int __fork_generation attribute_hidden;
 
 /* Pointer to the fork generation counter in the thread library.  */
 extern unsigned long int *__fork_generation_pointer attribute_hidden;
-
-/* Elements of the fork handler lists.  */
-struct fork_handler
-{
-  void (*prepare_handler) (void);
-  void (*parent_handler) (void);
-  void (*child_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)
-
-enum __run_fork_handler_type
-{
-  atfork_run_prepare,
-  atfork_run_child,
-  atfork_run_parent
-};
-
-/* Run the atfork handlers and lock/unlock the internal lock depending
-   of the WHO argument:
-
-   - atfork_run_prepare: run all the PREPARE_HANDLER in reverse order of
-                        insertion and locks the internal lock.
-   - atfork_run_child: run all the CHILD_HANDLER and unlocks the internal
-                      lock.
-   - atfork_run_parent: run all the PARENT_HANDLER and unlocks the internal
-                       lock.
-
-   Perform locking only if DO_LOCKING.  */
-extern void __run_fork_handlers (enum __run_fork_handler_type who,
-                                _Bool do_locking) attribute_hidden;
-
-/* 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);
-libc_hidden_proto (__register_atfork)