aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2021-01-18 15:10:02 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2021-03-12 10:19:22 -0300
commit2b47727c68b6329cf8890e56fc9dbaa4e7300961 (patch)
treea6068c64f81fa0221cddd7f96d4a2ed3fbf816a9
parentcdba937662b16fc3685a8115f21e73f21330a44c (diff)
downloadglibc-2b47727c68b6329cf8890e56fc9dbaa4e7300961.tar
glibc-2b47727c68b6329cf8890e56fc9dbaa4e7300961.tar.gz
glibc-2b47727c68b6329cf8890e56fc9dbaa4e7300961.tar.bz2
glibc-2b47727c68b6329cf8890e56fc9dbaa4e7300961.zip
posix: Consolidate register-atfork
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.
-rw-r--r--htl/Makefile2
-rw-r--r--htl/register-atfork.c157
-rw-r--r--include/register-atfork.h (renamed from sysdeps/htl/fork.h)38
-rw-r--r--nptl/Makefile1
-rw-r--r--posix/Makefile2
-rw-r--r--posix/register-atfork.c (renamed from nptl/register-atfork.c)8
-rw-r--r--sysdeps/generic/fork.h19
-rw-r--r--sysdeps/htl/pt-atfork.c1
-rw-r--r--sysdeps/mach/hurd/fork.c15
-rw-r--r--sysdeps/nptl/fork.h42
10 files changed, 66 insertions, 219 deletions
diff --git a/htl/Makefile b/htl/Makefile
index c15c1b194e..895a6f777c 100644
--- a/htl/Makefile
+++ b/htl/Makefile
@@ -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
index 8be132f981..0000000000
--- a/htl/register-atfork.c
+++ /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);
-}
diff --git a/sysdeps/htl/fork.h b/include/register-atfork.h
index 0fccc309f8..fadde14700 100644
--- a/sysdeps/htl/fork.h
+++ b/include/register-atfork.h
@@ -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
@@ -16,10 +16,42 @@
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
diff --git a/nptl/Makefile b/nptl/Makefile
index 33766eaf7a..e5d69e8858 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -74,7 +74,6 @@ routines = \
pthread_self \
pthread_setschedparam \
pthread_sigmask \
- register-atfork \
shared-only-routines = forward
static-only-routines = pthread_atfork
diff --git a/posix/Makefile b/posix/Makefile
index 305ec757cd..be0c72f0bb 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -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 \
diff --git a/nptl/register-atfork.c b/posix/register-atfork.c
index 30c16fba40..6fd9e4c56a 100644
--- a/nptl/register-atfork.c
+++ b/posix/register-atfork.c
@@ -16,11 +16,9 @@
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
diff --git a/sysdeps/generic/fork.h b/sysdeps/generic/fork.h
index 623cae28df..6cc842a425 100644
--- a/sysdeps/generic/fork.h
+++ b/sysdeps/generic/fork.h
@@ -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/>. */
diff --git a/sysdeps/htl/pt-atfork.c b/sysdeps/htl/pt-atfork.c
index 3d115d3819..dbb3b8f0cc 100644
--- a/sysdeps/htl/pt-atfork.c
+++ b/sysdeps/htl/pt-atfork.c
@@ -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. */
diff --git a/sysdeps/mach/hurd/fork.c b/sysdeps/mach/hurd/fork.c
index 2b39f4e8b5..1c5299e686 100644
--- a/sysdeps/mach/hurd/fork.c
+++ b/sysdeps/mach/hurd/fork.c
@@ -30,6 +30,7 @@
#include <malloc/malloc-internal.h>
#include <nss/nss_database.h>
#include <unwind-link.h>
+#include <register-atfork.h>
#undef __fork
@@ -37,12 +38,6 @@
/* 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;
diff --git a/sysdeps/nptl/fork.h b/sysdeps/nptl/fork.h
index 25002287b1..5246754290 100644
--- a/sysdeps/nptl/fork.h
+++ b/sysdeps/nptl/fork.h
@@ -17,50 +17,10 @@
<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)