From 2b47727c68b6329cf8890e56fc9dbaa4e7300961 Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Mon, 18 Jan 2021 15:10:02 -0300 Subject: [PATCH] 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. --- htl/Makefile | 2 +- htl/register-atfork.c | 157 ------------------ .../htl/fork.h => include/register-atfork.h | 38 ++++- nptl/Makefile | 1 - posix/Makefile | 2 +- {nptl => posix}/register-atfork.c | 8 +- sysdeps/generic/fork.h | 19 +++ sysdeps/htl/pt-atfork.c | 1 + sysdeps/mach/hurd/fork.c | 15 +- sysdeps/nptl/fork.h | 42 +---- 10 files changed, 66 insertions(+), 219 deletions(-) delete mode 100644 htl/register-atfork.c rename sysdeps/htl/fork.h => include/register-atfork.h (54%) rename {nptl => posix}/register-atfork.c (97%) 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 - . */ - -#include -#include -#include -#include - -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 similarity index 54% rename from sysdeps/htl/fork.h rename to 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 . */ +#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 similarity index 97% rename from nptl/register-atfork.c rename to 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 . */ -#include -#include -#include -#include -#include +#include +#include +#include #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 + . */ 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 #include #include +#include /* 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 #include #include +#include #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 @@ . */ #include +#include /* 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) -- 2.43.5