Message ID | 87ef5lezyp.fsf@oldenburg2.str.redhat.com |
---|---|
State | New |
Headers | show |
Series | misc: Add twalk_r function | expand |
On 4/29/19 8:51 AM, Florian Weimer wrote: > The twalk function is very difficult to use in a multi-threaded > program because there is no way to pass external state to the > iterator function. I like *_r variants of existing functions. Thanks for adding this. OK with typo fix in manual (see below s/threat/thread/g). For a new API though I'd like to see one more reviewer, can you track down someone else? Reviewed-by: Carlos O'Donell <carlos@redhat.com> > (I expect to use this new function in sem_close and > __gconv_release_shlib, but the function is generally useful.) > > 2019-04-29 Florian Weimer <fweimer@redhat.com> > > misc: Add twalk_r function. > * include/search.h (__twalk_r): Declare. > * manual/examples/twalk.c: New file. > * manual/search.texi (Tree Search Function): Document twalk_r. > * misc/Versions (2.30): Export twalk_r. > (GLIBC_PRIVATE): Export __twalk_r. > * misc/search.h [__USE_GNU] (twalk_r): Declare. > * misc/tsearch.c (trecurse_r, __twalk_r): New functions. > (twalk_r): Add weak alias. > * misc/tst-tsearch.c (struct walk_trace_element): Define. > (walk_trace): New variable. > (struct twalk_with_twalk_r_closure): Define. > (twalk_with_twalk_r_action): New function. > (twalk_with_twalk_r): Likewise. > (walk_action): Call walk_trace_add. > (walk_tree_with): Rename from walk_tree. Add walk argument. > (walk_tree): New function. > * sysdeps/mach/hurd/i386/libc.abilist (GLIBC_2.30): Add twalk_r. > * sysdeps/unix/sysv/linux/aarch64/libc.abilist (GLIBC_2.30): > Likewise. > * sysdeps/unix/sysv/linux/alpha/libc.abilist (GLIBC_2.30): > Likewise. > * sysdeps/unix/sysv/linux/arm/libc.abilist (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/csky/libc.abilist (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/hppa/libc.abilist (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/i386/libc.abilist (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/ia64/libc.abilist (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist (GLIBC_2.30): > Likewise. > * sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist (GLIBC_2.30): > Likewise. > * sysdeps/unix/sysv/linux/microblaze/libc.abilist (GLIBC_2.30): > Likewise. > * sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist > (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist > (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist > (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist > (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/nios2/libc.abilist (GLIBC_2.30): > Likewise. > * sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist > (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist > (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist > (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist > (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist (GLIBC_2.30): > Likewise. > * sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist (GLIBC_2.30): > Likewise. > * sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist (GLIBC_2.30): > Likewise. > * sysdeps/unix/sysv/linux/sh/libc.abilist (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist (GLIBC_2.30): > Likewise. > * sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist (GLIBC_2.30): > Likewise. > * sysdeps/unix/sysv/linux/x86_64/64/libc.abilist (GLIBC_2.30): > Likewise. > * sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist (GLIBC_2.30): > Likewise. > > diff --git a/NEWS b/NEWS > index 792ffb1ec8..a32bcbd7a4 100644 > --- a/NEWS > +++ b/NEWS > @@ -16,6 +16,8 @@ Major new features: > * The dynamic linker accepts the --preload argument to preload shared > objects, in addition to the LD_PRELOAD environment variable. > > +* The twalk_r function has been added. OK. > + > * On Linux, the gettid function has been added. > > * Minguo (Republic of China) calendar support has been added as an > diff --git a/include/search.h b/include/search.h > index e17693022d..72fbc94476 100644 > --- a/include/search.h > +++ b/include/search.h > @@ -23,6 +23,8 @@ extern void *__tdelete (const void *__key, void **__rootp, > libc_hidden_proto (__tdelete) > extern void __twalk (const void *__root, __action_fn_t action); > libc_hidden_proto (__twalk) > +extern __typeof__ (twalk_r) __twalk_r; > +libc_hidden_proto (__twalk_r) OK. > extern void __tdestroy (void *__root, __free_fn_t freefct); > libc_hidden_proto (__tdestroy) > #endif > diff --git a/manual/examples/twalk.c b/manual/examples/twalk.c > new file mode 100644 > index 0000000000..04e32731d6 > --- /dev/null > +++ b/manual/examples/twalk.c > @@ -0,0 +1,56 @@ > +/* Implement twalk using twalk_r. OK. > + Copyright (C) 2019 Free Software Foundation, Inc. > + > + 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 General Public License > + along with this program; if not, see <http://www.gnu.org/licenses/>. > +*/ > + > +#include <search.h> > + > +struct twalk_with_twalk_r_closure > +{ > + void (*action) (const void *, VISIT, int); > + int depth; > +}; OK. Closure. > + > +static void > +twalk_with_twalk_r_action (const void *nodep, VISIT which, void *closure0) > +{ > + struct twalk_with_twalk_r_closure *closure = closure0; > + > + switch (which) > + { > + case leaf: > + closure->action (nodep, which, closure->depth); > + break; > + case preorder: > + closure->action (nodep, which, closure->depth); > + ++closure->depth; > + break; > + case postorder: > + /* The preorder action incremented the depth. */ > + closure->action (nodep, which, closure->depth - 1); > + break; > + case endorder: > + --closure->depth; > + closure->action (nodep, which, closure->depth); > + break; > + } > +} OK. Call a specific function, with depth, and take action. Good example. > + > +void > +twalk (const void *root, void (*action) (const void *, VISIT, int)) > +{ > + struct twalk_with_twalk_r_closure closure = { action, 0 }; > + twalk_r (root, twalk_with_twalk_r_action, &closure); > +} OK. > diff --git a/manual/search.texi b/manual/search.texi > index 1574c96562..26f2ceeb55 100644 > --- a/manual/search.texi > +++ b/manual/search.texi > @@ -618,5 +618,28 @@ Since the functions used for the @var{action} parameter to @code{twalk} > must not modify the tree data, it is safe to run @code{twalk} in more > than one thread at the same time, working on the same tree. It is also > safe to call @code{tfind} in parallel. Functions which modify the tree > -must not be used, otherwise the behavior is undefined. > +must not be used, otherwise the behavior is undefined. However, it is > +difficult to pass data external to the tree to the callback function > +without resorting to global variables (and threat safety issues), so s/threat/thread/g > +see the @code{twalk_r} function below. > +@end deftypefun > + > +@deftypefun void twalk_r (const void *@var{root}, void (*@var{action}) (const void *@var{key}, VISIT @var{which}, void *@var{closure}), void *@var{closure}) > +@standards{GNU, search.h} > +@safety{@prelim{}@mtsafe{@mtsrace{:root}}@assafe{}@acsafe{}} > +For each node in the tree with a node pointed to by @var{root}, the > +@code{twalk_r} function calls the function provided by the parameter > +@var{action}. For leaf nodes the function is called exactly once with > +@var{value} set to @code{leaf}. For internal nodes the function is > +called three times, setting the @var{value} parameter or @var{action} to > +the appropriate value. The @var{closure} parameter is passed down to > +each call of the @var{action} function, unmodified. > + OK. > +It is possible to implement the @code{twalk} function on top of the > +@code{twalk_r} function, which is why there is no separate level > +parameter. OK. > + > +@smallexample > +@include twalk.c.texi > +@end smallexample > @end deftypefun > diff --git a/misc/Versions b/misc/Versions > index 900e4ffb79..e749582369 100644 > --- a/misc/Versions > +++ b/misc/Versions > @@ -158,11 +158,14 @@ libc { > GLIBC_2.26 { > preadv2; preadv64v2; pwritev2; pwritev64v2; > } > + GLIBC_2.30 { > + twalk_r; OK. > + } > GLIBC_PRIVATE { > __madvise; > __mktemp; > __libc_ifunc_impl_list; > - __tdelete; __tfind; __tsearch; __twalk; > + __tdelete; __tfind; __tsearch; __twalk; __twalk_r; OK. > __mmap; __munmap; __mprotect; > __sched_get_priority_min; __sched_get_priority_max; > __libc_allocate_once_slow; > diff --git a/misc/search.h b/misc/search.h > index 47e8a43436..be3cc25ef9 100644 > --- a/misc/search.h > +++ b/misc/search.h > @@ -150,6 +150,12 @@ typedef void (*__action_fn_t) (const void *__nodep, VISIT __value, > extern void twalk (const void *__root, __action_fn_t __action); > > #ifdef __USE_GNU > +/* Like twalk, but pass down an additional closure parameter. */ > +extern void twalk_r (const void *__root, > + void (*) (const void *__nodep, VISIT __value, > + void *__closure), > + void *__closure); > + OK. > /* Callback type for function to free a tree node. If the keys are atomic > data this function should do nothing. */ > typedef void (*__free_fn_t) (void *__nodep); > diff --git a/misc/tsearch.c b/misc/tsearch.c > index 5c19082a59..24d8d69de3 100644 > --- a/misc/tsearch.c > +++ b/misc/tsearch.c > @@ -719,7 +719,41 @@ __twalk (const void *vroot, __action_fn_t action) > libc_hidden_def (__twalk) > weak_alias (__twalk, twalk) > > +/* twalk_r is the same as twalk, but with an additional closure > + parameter. */ > +static void > +trecurse_r (const void *vroot, void (*action) (const void *, VISIT, void *), > + void *closure) > +{ > + const_node root = (const_node) vroot; > > + if (LEFT(root) == NULL && RIGHT(root) == NULL) > + (*action) (root, leaf, closure); > + else > + { > + (*action) (root, preorder, closure); > + if (LEFT(root) != NULL) > + trecurse_r (LEFT(root), action, closure); > + (*action) (root, postorder, closure); > + if (RIGHT(root) != NULL) > + trecurse_r (RIGHT(root), action, closure); > + (*action) (root, endorder, closure); > + } > +} OK. Pass closure to all calls. > + > +void > +__twalk_r (const void *vroot, void (*action) (const void *, VISIT, void *), > + void *closure) > +{ > + const_node root = (const_node) vroot; > + > + CHECK_TREE ((node) root); > + > + if (root != NULL && action != NULL) > + trecurse_r (root, action, closure); > +} OK. > +libc_hidden_def (__twalk_r) > +weak_alias (__twalk_r, twalk_r) > > /* The standardized functions miss an important functionality: the > tree cannot be removed easily. We provide a function to do this. */ > diff --git a/misc/tst-tsearch.c b/misc/tst-tsearch.c > index 5803a456e0..9a570dd6c9 100644 > --- a/misc/tst-tsearch.c > +++ b/misc/tst-tsearch.c > @@ -25,6 +25,7 @@ > #include <string.h> > #include <search.h> > #include <tst-stack-align.h> > +#include <support/check.h> > > #define SEED 0 > #define BALANCED 1 > @@ -74,6 +75,20 @@ static int max_depth; > > static int stack_align_check[2]; > > +/* Used to compare walk traces between the two implementations. */ > +struct walk_trace_element > +{ > + const void *key; > + VISIT which; > + int depth; > +}; OK. > +#define DYNARRAY_STRUCT walk_trace_list > +#define DYNARRAY_ELEMENT struct walk_trace_element > +#define DYNARRAY_PREFIX walk_trace_ > +#define DYNARRAY_INITIAL_SIZE 0 > +#include <malloc/dynarray-skeleton.c> > +static struct walk_trace_list walk_trace; > + > /* Compare two keys. */ > static int > cmp_fn (const void *a, const void *b) > @@ -102,11 +117,54 @@ memfry (int *string) > } > } > > +struct twalk_with_twalk_r_closure > +{ > + void (*action) (const void *, VISIT, int); > + int depth; > +}; OK. > + > +static void > +twalk_with_twalk_r_action (const void *nodep, VISIT which, void *closure0) > +{ > + struct twalk_with_twalk_r_closure *closure = closure0; > + > + switch (which) > + { > + case leaf: > + closure->action (nodep, which, closure->depth); > + break; > + case preorder: > + closure->action (nodep, which, closure->depth); > + ++closure->depth; > + break; > + case postorder: > + /* The preorder action incremented the depth. */ > + closure->action (nodep, which, closure->depth - 1); > + break; > + case endorder: > + --closure->depth; > + closure->action (nodep, which, closure->depth); > + break; > + } > +} OK. > + > +static void > +twalk_with_twalk_r (const void *root, > + void (*action) (const void *, VISIT, int)) > +{ > + struct twalk_with_twalk_r_closure closure = { action, 0 }; > + twalk_r (root, twalk_with_twalk_r_action, &closure); > + TEST_COMPARE (closure.depth, 0); > +} OK. > + > static void > walk_action (const void *nodep, const VISIT which, const int depth) > { > int key = **(int **) nodep; > > + walk_trace_add (&walk_trace, > + (struct walk_trace_element) { nodep, which, depth }); > + OK. > if (!stack_align_check[1]) > stack_align_check[1] = TEST_STACK_ALIGN () ? -1 : 1; > > @@ -128,14 +186,16 @@ walk_action (const void *nodep, const VISIT which, const int depth) > } > > static void > -walk_tree (void *root, int expected_count) > +walk_tree_with (void *root, int expected_count, > + void (*walk) (const void *, > + void (*) (const void *, VISIT, int))) OK. > { > int i; > > memset (z, 0, sizeof z); > max_depth = 0; > > - twalk (root, walk_action); > + walk (root, walk_action); OK. > for (i = 0; i < expected_count; ++i) > if (z[i] != 1) > { > @@ -154,6 +214,31 @@ walk_tree (void *root, int expected_count) > } > } > > +static void > +walk_tree (void *root, int expected_count) > +{ > + walk_trace_clear (&walk_trace); > + walk_tree_with (root, expected_count, twalk); > + TEST_VERIFY (!walk_trace_has_failed (&walk_trace)); > + size_t first_list_size; > + struct walk_trace_element *first_list > + = walk_trace_finalize (&walk_trace, &first_list_size); > + > + walk_tree_with (root, expected_count, twalk_with_twalk_r); > + > + /* Compare the two traces. */ > + TEST_COMPARE (first_list_size, walk_trace_size (&walk_trace)); > + for (size_t i = 0; i < first_list_size && i < walk_trace_size (&walk_trace); > + ++i) > + { > + TEST_VERIFY (first_list[i].key == walk_trace_at (&walk_trace, i)->key); > + TEST_COMPARE (first_list[i].which, walk_trace_at (&walk_trace, i)->which); > + TEST_COMPARE (first_list[i].depth, walk_trace_at (&walk_trace, i)->depth); > + } > + > + walk_trace_free (&walk_trace); > +} OK. > + > /* Perform an operation on a tree. */ > static void > mangle_tree (enum order how, enum action what, void **root, int lag) > diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist > index dd3cf6f9f2..1fc7ab2433 100644 > --- a/sysdeps/mach/hurd/i386/libc.abilist > +++ b/sysdeps/mach/hurd/i386/libc.abilist > @@ -2175,6 +2175,7 @@ GLIBC_2.3.4 setipv4sourcefilter F > GLIBC_2.3.4 setsourcefilter F > GLIBC_2.3.4 xdr_quad_t F > GLIBC_2.3.4 xdr_u_quad_t F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist > index f3b44d723f..b7283ad486 100644 > --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist > @@ -2142,3 +2142,4 @@ GLIBC_2.29 getcpu F > GLIBC_2.29 posix_spawn_file_actions_addchdir_np F > GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist > index fd81fc4ad0..a817e683a4 100644 > --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist > +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist > @@ -2217,6 +2217,7 @@ GLIBC_2.30 __nldbl_vwarnx F > GLIBC_2.30 __nldbl_warn F > GLIBC_2.30 __nldbl_warnx F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist > index f451fefac9..97b6cbf903 100644 > --- a/sysdeps/unix/sysv/linux/arm/libc.abilist > +++ b/sysdeps/unix/sysv/linux/arm/libc.abilist > @@ -127,6 +127,7 @@ GLIBC_2.29 getcpu F > GLIBC_2.29 posix_spawn_file_actions_addchdir_np F > GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 _Exit F > GLIBC_2.4 _IO_2_1_stderr_ D 0xa0 > GLIBC_2.4 _IO_2_1_stdin_ D 0xa0 > diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist > index 018d02b414..796e622a6d 100644 > --- a/sysdeps/unix/sysv/linux/csky/libc.abilist > +++ b/sysdeps/unix/sysv/linux/csky/libc.abilist > @@ -2086,3 +2086,4 @@ GLIBC_2.29 xencrypt F > GLIBC_2.29 xprt_register F > GLIBC_2.29 xprt_unregister F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist > index fc3c5d5c27..4e7d71d112 100644 > --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist > +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist > @@ -2038,6 +2038,7 @@ GLIBC_2.3.4 setsourcefilter F > GLIBC_2.3.4 xdr_quad_t F > GLIBC_2.3.4 xdr_u_quad_t F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist > index f2b04dbbff..11bd8c601a 100644 > --- a/sysdeps/unix/sysv/linux/i386/libc.abilist > +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist > @@ -2204,6 +2204,7 @@ GLIBC_2.3.4 vm86 F > GLIBC_2.3.4 xdr_quad_t F > GLIBC_2.3.4 xdr_u_quad_t F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist > index 10ecf2e47c..589cce5b8d 100644 > --- a/sysdeps/unix/sysv/linux/ia64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist > @@ -2070,6 +2070,7 @@ GLIBC_2.3.4 setsourcefilter F > GLIBC_2.3.4 xdr_quad_t F > GLIBC_2.3.4 xdr_u_quad_t F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist > index 814e81b9d2..4b3727a91d 100644 > --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist > +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist > @@ -128,6 +128,7 @@ GLIBC_2.29 getcpu F > GLIBC_2.29 posix_spawn_file_actions_addchdir_np F > GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 _Exit F > GLIBC_2.4 _IO_2_1_stderr_ D 0x98 > GLIBC_2.4 _IO_2_1_stdin_ D 0x98 > diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist > index 68e80372e7..4be30c0339 100644 > --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist > +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist > @@ -2147,6 +2147,7 @@ GLIBC_2.3.4 setsourcefilter F > GLIBC_2.3.4 xdr_quad_t F > GLIBC_2.3.4 xdr_u_quad_t F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist > index 31178e4f54..e0010965a8 100644 > --- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist > +++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist > @@ -2134,3 +2134,4 @@ GLIBC_2.29 getcpu F > GLIBC_2.29 posix_spawn_file_actions_addchdir_np F > GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist > index 7074573638..2a62f67741 100644 > --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist > +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist > @@ -2121,6 +2121,7 @@ GLIBC_2.3.4 setsourcefilter F > GLIBC_2.3.4 xdr_quad_t F > GLIBC_2.3.4 xdr_u_quad_t F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist > index 154f9c77fc..5a23f11fc9 100644 > --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist > +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist > @@ -2119,6 +2119,7 @@ GLIBC_2.3.4 setsourcefilter F > GLIBC_2.3.4 xdr_quad_t F > GLIBC_2.3.4 xdr_u_quad_t F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist > index 97b8f42d5c..32532a19da 100644 > --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist > +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist > @@ -2127,6 +2127,7 @@ GLIBC_2.3.4 setsourcefilter F > GLIBC_2.3.4 xdr_quad_t F > GLIBC_2.3.4 xdr_u_quad_t F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist > index 5b3e85de93..882f5cb5bf 100644 > --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist > @@ -2121,6 +2121,7 @@ GLIBC_2.3.4 setsourcefilter F > GLIBC_2.3.4 xdr_quad_t F > GLIBC_2.3.4 xdr_u_quad_t F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist > index 04a130a81c..c99a299bab 100644 > --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist > +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist > @@ -2175,3 +2175,4 @@ GLIBC_2.29 getcpu F > GLIBC_2.29 posix_spawn_file_actions_addchdir_np F > GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist > index a701584422..d5f4364197 100644 > --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist > +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist > @@ -2177,6 +2177,7 @@ GLIBC_2.30 __nldbl_vwarnx F > GLIBC_2.30 __nldbl_warn F > GLIBC_2.30 __nldbl_warnx F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist > index bbb647cd98..581fd10290 100644 > --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist > +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist > @@ -2210,6 +2210,7 @@ GLIBC_2.30 __nldbl_vwarnx F > GLIBC_2.30 __nldbl_warn F > GLIBC_2.30 __nldbl_warnx F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist > index bb23bf61a8..ce10e0436e 100644 > --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist > +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist > @@ -2040,6 +2040,7 @@ GLIBC_2.30 __nldbl_vwarnx F > GLIBC_2.30 __nldbl_warn F > GLIBC_2.30 __nldbl_warnx F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist > index 7921dda979..1cc729da7f 100644 > --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist > +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist > @@ -2244,3 +2244,4 @@ GLIBC_2.30 __nldbl_vwarnx F > GLIBC_2.30 __nldbl_warn F > GLIBC_2.30 __nldbl_warnx F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist > index da123d3867..2bda5692f4 100644 > --- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist > @@ -2104,3 +2104,4 @@ GLIBC_2.29 getcpu F > GLIBC_2.29 posix_spawn_file_actions_addchdir_np F > GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist > index 2aed339af4..dddc138a1e 100644 > --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist > +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist > @@ -2172,6 +2172,7 @@ GLIBC_2.30 __nldbl_vwarnx F > GLIBC_2.30 __nldbl_warn F > GLIBC_2.30 __nldbl_warnx F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist > index e46feb56e5..b2c75a48a8 100644 > --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist > @@ -2076,6 +2076,7 @@ GLIBC_2.30 __nldbl_vwarnx F > GLIBC_2.30 __nldbl_warn F > GLIBC_2.30 __nldbl_warnx F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist > index 24a8f934cb..8b83449b16 100644 > --- a/sysdeps/unix/sysv/linux/sh/libc.abilist > +++ b/sysdeps/unix/sysv/linux/sh/libc.abilist > @@ -2042,6 +2042,7 @@ GLIBC_2.3.4 setsourcefilter F > GLIBC_2.3.4 xdr_quad_t F > GLIBC_2.3.4 xdr_u_quad_t F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist > index ebdbd2c5ae..a237be9d93 100644 > --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist > +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist > @@ -2166,6 +2166,7 @@ GLIBC_2.30 __nldbl_vwarnx F > GLIBC_2.30 __nldbl_warn F > GLIBC_2.30 __nldbl_warnx F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist > index 0992349b06..b850694434 100644 > --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist > @@ -2093,6 +2093,7 @@ GLIBC_2.3.4 setsourcefilter F > GLIBC_2.3.4 xdr_quad_t F > GLIBC_2.3.4 xdr_u_quad_t F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist > index af004fcff6..c6f22f0c7b 100644 > --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist > @@ -2051,6 +2051,7 @@ GLIBC_2.3.4 setsourcefilter F > GLIBC_2.3.4 xdr_quad_t F > GLIBC_2.3.4 xdr_u_quad_t F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist > index 84015f0a57..1184385bce 100644 > --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist > +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist > @@ -2150,3 +2150,4 @@ GLIBC_2.29 getcpu F > GLIBC_2.29 posix_spawn_file_actions_addchdir_np F > GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > OK.
* Carlos O'Donell: >> diff --git a/manual/search.texi b/manual/search.texi >> index 1574c96562..26f2ceeb55 100644 >> --- a/manual/search.texi >> +++ b/manual/search.texi >> @@ -618,5 +618,28 @@ Since the functions used for the @var{action} parameter to @code{twalk} >> must not modify the tree data, it is safe to run @code{twalk} in more >> than one thread at the same time, working on the same tree. It is also >> safe to call @code{tfind} in parallel. Functions which modify the tree >> -must not be used, otherwise the behavior is undefined. >> +must not be used, otherwise the behavior is undefined. However, it is >> +difficult to pass data external to the tree to the callback function >> +without resorting to global variables (and threat safety issues), so > > s/threat/thread/g Oops, thanks. There's also a whitespace issue. Fixed and pushed to the fw/twalk_r branch. diff --git a/manual/search.texi b/manual/search.texi index 26f2ceeb55..979732f027 100644 --- a/manual/search.texi +++ b/manual/search.texi @@ -618,9 +618,9 @@ Since the functions used for the @var{action} parameter to @code{twalk} must not modify the tree data, it is safe to run @code{twalk} in more than one thread at the same time, working on the same tree. It is also safe to call @code{tfind} in parallel. Functions which modify the tree -must not be used, otherwise the behavior is undefined. However, it is +must not be used, otherwise the behavior is undefined. However, it is difficult to pass data external to the tree to the callback function -without resorting to global variables (and threat safety issues), so +without resorting to global variables (and thread safety issues), so see the @code{twalk_r} function below. @end deftypefun I will wait for a second review before pushing this to master. Florian
On 29/04/2019 09:51, Florian Weimer wrote: > The twalk function is very difficult to use in a multi-threaded > program because there is no way to pass external state to the > iterator function. LGTM as well, with some nits below (the whitespace you seems to fixed already). > > (I expect to use this new function in sem_close and > __gconv_release_shlib, but the function is generally useful.) As a side note I worked on a sem_open/sem_close refactor some time ago that uses dynarray and the char array derived structure, aimed to remove both the twalk and alloca internal usage. It turned to be a slight simpler implementation as well and I will try to send it upstream. Reviewed-by: Carlos O'Donell <carlos@redhat.com> > > 2019-04-29 Florian Weimer <fweimer@redhat.com> > > misc: Add twalk_r function. > * include/search.h (__twalk_r): Declare. > * manual/examples/twalk.c: New file. > * manual/search.texi (Tree Search Function): Document twalk_r. > * misc/Versions (2.30): Export twalk_r. > (GLIBC_PRIVATE): Export __twalk_r. > * misc/search.h [__USE_GNU] (twalk_r): Declare. > * misc/tsearch.c (trecurse_r, __twalk_r): New functions. > (twalk_r): Add weak alias. > * misc/tst-tsearch.c (struct walk_trace_element): Define. > (walk_trace): New variable. > (struct twalk_with_twalk_r_closure): Define. > (twalk_with_twalk_r_action): New function. > (twalk_with_twalk_r): Likewise. > (walk_action): Call walk_trace_add. > (walk_tree_with): Rename from walk_tree. Add walk argument. > (walk_tree): New function. > * sysdeps/mach/hurd/i386/libc.abilist (GLIBC_2.30): Add twalk_r. > * sysdeps/unix/sysv/linux/aarch64/libc.abilist (GLIBC_2.30): > Likewise. > * sysdeps/unix/sysv/linux/alpha/libc.abilist (GLIBC_2.30): > Likewise. > * sysdeps/unix/sysv/linux/arm/libc.abilist (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/csky/libc.abilist (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/hppa/libc.abilist (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/i386/libc.abilist (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/ia64/libc.abilist (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist (GLIBC_2.30): > Likewise. > * sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist (GLIBC_2.30): > Likewise. > * sysdeps/unix/sysv/linux/microblaze/libc.abilist (GLIBC_2.30): > Likewise. > * sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist > (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist > (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist > (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist > (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/nios2/libc.abilist (GLIBC_2.30): > Likewise. > * sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist > (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist > (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist > (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist > (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist (GLIBC_2.30): > Likewise. > * sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist (GLIBC_2.30): > Likewise. > * sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist (GLIBC_2.30): > Likewise. > * sysdeps/unix/sysv/linux/sh/libc.abilist (GLIBC_2.30): Likewise. > * sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist (GLIBC_2.30): > Likewise. > * sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist (GLIBC_2.30): > Likewise. > * sysdeps/unix/sysv/linux/x86_64/64/libc.abilist (GLIBC_2.30): > Likewise. > * sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist (GLIBC_2.30): > Likewise. > > diff --git a/NEWS b/NEWS > index 792ffb1ec8..a32bcbd7a4 100644 > --- a/NEWS > +++ b/NEWS > @@ -16,6 +16,8 @@ Major new features: > * The dynamic linker accepts the --preload argument to preload shared > objects, in addition to the LD_PRELOAD environment variable. > > +* The twalk_r function has been added. > + I think we can extend it description a bit by adding it is a GNU extension that behaves like twalk but with an addional parameter to be passed in callback action function (like qsort_r). > * On Linux, the gettid function has been added. > > * Minguo (Republic of China) calendar support has been added as an > diff --git a/include/search.h b/include/search.h > index e17693022d..72fbc94476 100644 > --- a/include/search.h > +++ b/include/search.h > @@ -23,6 +23,8 @@ extern void *__tdelete (const void *__key, void **__rootp, > libc_hidden_proto (__tdelete) > extern void __twalk (const void *__root, __action_fn_t action); > libc_hidden_proto (__twalk) > +extern __typeof__ (twalk_r) __twalk_r; > +libc_hidden_proto (__twalk_r) > extern void __tdestroy (void *__root, __free_fn_t freefct); > libc_hidden_proto (__tdestroy) > #endif Ok. > diff --git a/manual/examples/twalk.c b/manual/examples/twalk.c > new file mode 100644 > index 0000000000..04e32731d6 > --- /dev/null > +++ b/manual/examples/twalk.c > @@ -0,0 +1,56 @@ > +/* Implement twalk using twalk_r. > + Copyright (C) 2019 Free Software Foundation, Inc. > + > + 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 General Public License > + along with this program; if not, see <http://www.gnu.org/licenses/>. > +*/ > + > +#include <search.h> > + > +struct twalk_with_twalk_r_closure > +{ > + void (*action) (const void *, VISIT, int); > + int depth; > +}; > + > +static void > +twalk_with_twalk_r_action (const void *nodep, VISIT which, void *closure0) > +{ > + struct twalk_with_twalk_r_closure *closure = closure0; > + > + switch (which) > + { > + case leaf: > + closure->action (nodep, which, closure->depth); > + break; > + case preorder: > + closure->action (nodep, which, closure->depth); > + ++closure->depth; > + break; > + case postorder: > + /* The preorder action incremented the depth. */ > + closure->action (nodep, which, closure->depth - 1); > + break; > + case endorder: > + --closure->depth; > + closure->action (nodep, which, closure->depth); > + break; > + } > +} > + > +void > +twalk (const void *root, void (*action) (const void *, VISIT, int)) > +{ > + struct twalk_with_twalk_r_closure closure = { action, 0 }; > + twalk_r (root, twalk_with_twalk_r_action, &closure); > +} Ok. > diff --git a/manual/search.texi b/manual/search.texi > index 1574c96562..26f2ceeb55 100644 > --- a/manual/search.texi > +++ b/manual/search.texi > @@ -618,5 +618,28 @@ Since the functions used for the @var{action} parameter to @code{twalk} > must not modify the tree data, it is safe to run @code{twalk} in more > than one thread at the same time, working on the same tree. It is also > safe to call @code{tfind} in parallel. Functions which modify the tree > -must not be used, otherwise the behavior is undefined. > +must not be used, otherwise the behavior is undefined. However, it is I think it is missing two spaces after period. > +difficult to pass data external to the tree to the callback function > +without resorting to global variables (and threat safety issues), so > +see the @code{twalk_r} function below. > +@end deftypefun > + > +@deftypefun void twalk_r (const void *@var{root}, void (*@var{action}) (const void *@var{key}, VISIT @var{which}, void *@var{closure}), void *@var{closure}) > +@standards{GNU, search.h} > +@safety{@prelim{}@mtsafe{@mtsrace{:root}}@assafe{}@acsafe{}} > +For each node in the tree with a node pointed to by @var{root}, the > +@code{twalk_r} function calls the function provided by the parameter > +@var{action}. For leaf nodes the function is called exactly once with > +@var{value} set to @code{leaf}. For internal nodes the function is > +called three times, setting the @var{value} parameter or @var{action} to > +the appropriate value. The @var{closure} parameter is passed down to > +each call of the @var{action} function, unmodified. > + > +It is possible to implement the @code{twalk} function on top of the > +@code{twalk_r} function, which is why there is no separate level > +parameter. > + > +@smallexample > +@include twalk.c.texi > +@end smallexample > @end deftypefun Ok. > diff --git a/misc/Versions b/misc/Versions > index 900e4ffb79..e749582369 100644 > --- a/misc/Versions > +++ b/misc/Versions > @@ -158,11 +158,14 @@ libc { > GLIBC_2.26 { > preadv2; preadv64v2; pwritev2; pwritev64v2; > } > + GLIBC_2.30 { > + twalk_r; > + } > GLIBC_PRIVATE { > __madvise; > __mktemp; > __libc_ifunc_impl_list; > - __tdelete; __tfind; __tsearch; __twalk; > + __tdelete; __tfind; __tsearch; __twalk; __twalk_r; > __mmap; __munmap; __mprotect; > __sched_get_priority_min; __sched_get_priority_max; > __libc_allocate_once_slow; Ok. > diff --git a/misc/search.h b/misc/search.h > index 47e8a43436..be3cc25ef9 100644 > --- a/misc/search.h > +++ b/misc/search.h > @@ -150,6 +150,12 @@ typedef void (*__action_fn_t) (const void *__nodep, VISIT __value, > extern void twalk (const void *__root, __action_fn_t __action); > > #ifdef __USE_GNU > +/* Like twalk, but pass down an additional closure parameter. */ > +extern void twalk_r (const void *__root, > + void (*) (const void *__nodep, VISIT __value, > + void *__closure), > + void *__closure); > + > /* Callback type for function to free a tree node. If the keys are atomic > data this function should do nothing. */ > typedef void (*__free_fn_t) (void *__nodep); Ok. > diff --git a/misc/tsearch.c b/misc/tsearch.c > index 5c19082a59..24d8d69de3 100644 > --- a/misc/tsearch.c > +++ b/misc/tsearch.c > @@ -719,7 +719,41 @@ __twalk (const void *vroot, __action_fn_t action) > libc_hidden_def (__twalk) > weak_alias (__twalk, twalk) > > +/* twalk_r is the same as twalk, but with an additional closure > + parameter. */ > +static void > +trecurse_r (const void *vroot, void (*action) (const void *, VISIT, void *), > + void *closure) > +{ > + const_node root = (const_node) vroot; > > + if (LEFT(root) == NULL && RIGHT(root) == NULL) > + (*action) (root, leaf, closure); > + else > + { > + (*action) (root, preorder, closure); > + if (LEFT(root) != NULL) > + trecurse_r (LEFT(root), action, closure); > + (*action) (root, postorder, closure); > + if (RIGHT(root) != NULL) > + trecurse_r (RIGHT(root), action, closure); > + (*action) (root, endorder, closure); > + } > +} > + > +void > +__twalk_r (const void *vroot, void (*action) (const void *, VISIT, void *), > + void *closure) > +{ > + const_node root = (const_node) vroot; > + > + CHECK_TREE ((node) root); > + > + if (root != NULL && action != NULL) > + trecurse_r (root, action, closure); > +} > +libc_hidden_def (__twalk_r) > +weak_alias (__twalk_r, twalk_r) > > /* The standardized functions miss an important functionality: the > tree cannot be removed easily. We provide a function to do this. */ Ok. > diff --git a/misc/tst-tsearch.c b/misc/tst-tsearch.c > index 5803a456e0..9a570dd6c9 100644 > --- a/misc/tst-tsearch.c > +++ b/misc/tst-tsearch.c > @@ -25,6 +25,7 @@ > #include <string.h> > #include <search.h> > #include <tst-stack-align.h> > +#include <support/check.h> > > #define SEED 0 > #define BALANCED 1 > @@ -74,6 +75,20 @@ static int max_depth; > > static int stack_align_check[2]; > > +/* Used to compare walk traces between the two implementations. */ > +struct walk_trace_element > +{ > + const void *key; > + VISIT which; > + int depth; > +}; > +#define DYNARRAY_STRUCT walk_trace_list > +#define DYNARRAY_ELEMENT struct walk_trace_element > +#define DYNARRAY_PREFIX walk_trace_ > +#define DYNARRAY_INITIAL_SIZE 0 > +#include <malloc/dynarray-skeleton.c> > +static struct walk_trace_list walk_trace; > + > /* Compare two keys. */ > static int > cmp_fn (const void *a, const void *b) > @@ -102,11 +117,54 @@ memfry (int *string) > } > } > > +struct twalk_with_twalk_r_closure > +{ > + void (*action) (const void *, VISIT, int); > + int depth; > +}; > + > +static void > +twalk_with_twalk_r_action (const void *nodep, VISIT which, void *closure0) > +{ > + struct twalk_with_twalk_r_closure *closure = closure0; > + > + switch (which) > + { > + case leaf: > + closure->action (nodep, which, closure->depth); > + break; > + case preorder: > + closure->action (nodep, which, closure->depth); > + ++closure->depth; > + break; > + case postorder: > + /* The preorder action incremented the depth. */ > + closure->action (nodep, which, closure->depth - 1); > + break; > + case endorder: > + --closure->depth; > + closure->action (nodep, which, closure->depth); > + break; > + } > +} > + > +static void > +twalk_with_twalk_r (const void *root, > + void (*action) (const void *, VISIT, int)) > +{ > + struct twalk_with_twalk_r_closure closure = { action, 0 }; > + twalk_r (root, twalk_with_twalk_r_action, &closure); > + TEST_COMPARE (closure.depth, 0); > +} > + Ok. > static void > walk_action (const void *nodep, const VISIT which, const int depth) > { > int key = **(int **) nodep; > > + walk_trace_add (&walk_trace, > + (struct walk_trace_element) { nodep, which, depth }); > + > if (!stack_align_check[1]) > stack_align_check[1] = TEST_STACK_ALIGN () ? -1 : 1; Ok. > > @@ -128,14 +186,16 @@ walk_action (const void *nodep, const VISIT which, const int depth) > } > > static void > -walk_tree (void *root, int expected_count) > +walk_tree_with (void *root, int expected_count, > + void (*walk) (const void *, > + void (*) (const void *, VISIT, int))) > { > int i; > > memset (z, 0, sizeof z); > max_depth = 0; > > - twalk (root, walk_action); > + walk (root, walk_action); > for (i = 0; i < expected_count; ++i) > if (z[i] != 1) > { > @@ -154,6 +214,31 @@ walk_tree (void *root, int expected_count) > } > } > Ok. > +static void > +walk_tree (void *root, int expected_count) > +{ > + walk_trace_clear (&walk_trace); > + walk_tree_with (root, expected_count, twalk); > + TEST_VERIFY (!walk_trace_has_failed (&walk_trace)); > + size_t first_list_size; > + struct walk_trace_element *first_list > + = walk_trace_finalize (&walk_trace, &first_list_size); > + > + walk_tree_with (root, expected_count, twalk_with_twalk_r); > + > + /* Compare the two traces. */ > + TEST_COMPARE (first_list_size, walk_trace_size (&walk_trace)); > + for (size_t i = 0; i < first_list_size && i < walk_trace_size (&walk_trace); > + ++i) > + { > + TEST_VERIFY (first_list[i].key == walk_trace_at (&walk_trace, i)->key); > + TEST_COMPARE (first_list[i].which, walk_trace_at (&walk_trace, i)->which); > + TEST_COMPARE (first_list[i].depth, walk_trace_at (&walk_trace, i)->depth); > + } > + > + walk_trace_free (&walk_trace); > +} > + > /* Perform an operation on a tree. */ > static void > mangle_tree (enum order how, enum action what, void **root, int lag) Ok. > diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist > index dd3cf6f9f2..1fc7ab2433 100644 > --- a/sysdeps/mach/hurd/i386/libc.abilist > +++ b/sysdeps/mach/hurd/i386/libc.abilist > @@ -2175,6 +2175,7 @@ GLIBC_2.3.4 setipv4sourcefilter F > GLIBC_2.3.4 setsourcefilter F > GLIBC_2.3.4 xdr_quad_t F > GLIBC_2.3.4 xdr_u_quad_t F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist > index f3b44d723f..b7283ad486 100644 > --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist > @@ -2142,3 +2142,4 @@ GLIBC_2.29 getcpu F > GLIBC_2.29 posix_spawn_file_actions_addchdir_np F > GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist > index fd81fc4ad0..a817e683a4 100644 > --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist > +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist > @@ -2217,6 +2217,7 @@ GLIBC_2.30 __nldbl_vwarnx F > GLIBC_2.30 __nldbl_warn F > GLIBC_2.30 __nldbl_warnx F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist > index f451fefac9..97b6cbf903 100644 > --- a/sysdeps/unix/sysv/linux/arm/libc.abilist > +++ b/sysdeps/unix/sysv/linux/arm/libc.abilist > @@ -127,6 +127,7 @@ GLIBC_2.29 getcpu F > GLIBC_2.29 posix_spawn_file_actions_addchdir_np F > GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 _Exit F > GLIBC_2.4 _IO_2_1_stderr_ D 0xa0 > GLIBC_2.4 _IO_2_1_stdin_ D 0xa0 > diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist > index 018d02b414..796e622a6d 100644 > --- a/sysdeps/unix/sysv/linux/csky/libc.abilist > +++ b/sysdeps/unix/sysv/linux/csky/libc.abilist > @@ -2086,3 +2086,4 @@ GLIBC_2.29 xencrypt F > GLIBC_2.29 xprt_register F > GLIBC_2.29 xprt_unregister F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist > index fc3c5d5c27..4e7d71d112 100644 > --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist > +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist > @@ -2038,6 +2038,7 @@ GLIBC_2.3.4 setsourcefilter F > GLIBC_2.3.4 xdr_quad_t F > GLIBC_2.3.4 xdr_u_quad_t F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist > index f2b04dbbff..11bd8c601a 100644 > --- a/sysdeps/unix/sysv/linux/i386/libc.abilist > +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist > @@ -2204,6 +2204,7 @@ GLIBC_2.3.4 vm86 F > GLIBC_2.3.4 xdr_quad_t F > GLIBC_2.3.4 xdr_u_quad_t F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist > index 10ecf2e47c..589cce5b8d 100644 > --- a/sysdeps/unix/sysv/linux/ia64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist > @@ -2070,6 +2070,7 @@ GLIBC_2.3.4 setsourcefilter F > GLIBC_2.3.4 xdr_quad_t F > GLIBC_2.3.4 xdr_u_quad_t F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist > index 814e81b9d2..4b3727a91d 100644 > --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist > +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist > @@ -128,6 +128,7 @@ GLIBC_2.29 getcpu F > GLIBC_2.29 posix_spawn_file_actions_addchdir_np F > GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 _Exit F > GLIBC_2.4 _IO_2_1_stderr_ D 0x98 > GLIBC_2.4 _IO_2_1_stdin_ D 0x98 > diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist > index 68e80372e7..4be30c0339 100644 > --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist > +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist > @@ -2147,6 +2147,7 @@ GLIBC_2.3.4 setsourcefilter F > GLIBC_2.3.4 xdr_quad_t F > GLIBC_2.3.4 xdr_u_quad_t F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist > index 31178e4f54..e0010965a8 100644 > --- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist > +++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist > @@ -2134,3 +2134,4 @@ GLIBC_2.29 getcpu F > GLIBC_2.29 posix_spawn_file_actions_addchdir_np F > GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist > index 7074573638..2a62f67741 100644 > --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist > +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist > @@ -2121,6 +2121,7 @@ GLIBC_2.3.4 setsourcefilter F > GLIBC_2.3.4 xdr_quad_t F > GLIBC_2.3.4 xdr_u_quad_t F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist > index 154f9c77fc..5a23f11fc9 100644 > --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist > +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist > @@ -2119,6 +2119,7 @@ GLIBC_2.3.4 setsourcefilter F > GLIBC_2.3.4 xdr_quad_t F > GLIBC_2.3.4 xdr_u_quad_t F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist > index 97b8f42d5c..32532a19da 100644 > --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist > +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist > @@ -2127,6 +2127,7 @@ GLIBC_2.3.4 setsourcefilter F > GLIBC_2.3.4 xdr_quad_t F > GLIBC_2.3.4 xdr_u_quad_t F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist > index 5b3e85de93..882f5cb5bf 100644 > --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist > @@ -2121,6 +2121,7 @@ GLIBC_2.3.4 setsourcefilter F > GLIBC_2.3.4 xdr_quad_t F > GLIBC_2.3.4 xdr_u_quad_t F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist > index 04a130a81c..c99a299bab 100644 > --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist > +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist > @@ -2175,3 +2175,4 @@ GLIBC_2.29 getcpu F > GLIBC_2.29 posix_spawn_file_actions_addchdir_np F > GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist > index a701584422..d5f4364197 100644 > --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist > +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist > @@ -2177,6 +2177,7 @@ GLIBC_2.30 __nldbl_vwarnx F > GLIBC_2.30 __nldbl_warn F > GLIBC_2.30 __nldbl_warnx F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist > index bbb647cd98..581fd10290 100644 > --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist > +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist > @@ -2210,6 +2210,7 @@ GLIBC_2.30 __nldbl_vwarnx F > GLIBC_2.30 __nldbl_warn F > GLIBC_2.30 __nldbl_warnx F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist > index bb23bf61a8..ce10e0436e 100644 > --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist > +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist > @@ -2040,6 +2040,7 @@ GLIBC_2.30 __nldbl_vwarnx F > GLIBC_2.30 __nldbl_warn F > GLIBC_2.30 __nldbl_warnx F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist > index 7921dda979..1cc729da7f 100644 > --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist > +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist > @@ -2244,3 +2244,4 @@ GLIBC_2.30 __nldbl_vwarnx F > GLIBC_2.30 __nldbl_warn F > GLIBC_2.30 __nldbl_warnx F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist > index da123d3867..2bda5692f4 100644 > --- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist > @@ -2104,3 +2104,4 @@ GLIBC_2.29 getcpu F > GLIBC_2.29 posix_spawn_file_actions_addchdir_np F > GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist > index 2aed339af4..dddc138a1e 100644 > --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist > +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist > @@ -2172,6 +2172,7 @@ GLIBC_2.30 __nldbl_vwarnx F > GLIBC_2.30 __nldbl_warn F > GLIBC_2.30 __nldbl_warnx F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist > index e46feb56e5..b2c75a48a8 100644 > --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist > @@ -2076,6 +2076,7 @@ GLIBC_2.30 __nldbl_vwarnx F > GLIBC_2.30 __nldbl_warn F > GLIBC_2.30 __nldbl_warnx F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist > index 24a8f934cb..8b83449b16 100644 > --- a/sysdeps/unix/sysv/linux/sh/libc.abilist > +++ b/sysdeps/unix/sysv/linux/sh/libc.abilist > @@ -2042,6 +2042,7 @@ GLIBC_2.3.4 setsourcefilter F > GLIBC_2.3.4 xdr_quad_t F > GLIBC_2.3.4 xdr_u_quad_t F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist > index ebdbd2c5ae..a237be9d93 100644 > --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist > +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist > @@ -2166,6 +2166,7 @@ GLIBC_2.30 __nldbl_vwarnx F > GLIBC_2.30 __nldbl_warn F > GLIBC_2.30 __nldbl_warnx F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist > index 0992349b06..b850694434 100644 > --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist > @@ -2093,6 +2093,7 @@ GLIBC_2.3.4 setsourcefilter F > GLIBC_2.3.4 xdr_quad_t F > GLIBC_2.3.4 xdr_u_quad_t F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist > index af004fcff6..c6f22f0c7b 100644 > --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist > @@ -2051,6 +2051,7 @@ GLIBC_2.3.4 setsourcefilter F > GLIBC_2.3.4 xdr_quad_t F > GLIBC_2.3.4 xdr_u_quad_t F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist > index 84015f0a57..1184385bce 100644 > --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist > +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist > @@ -2150,3 +2150,4 @@ GLIBC_2.29 getcpu F > GLIBC_2.29 posix_spawn_file_actions_addchdir_np F > GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F > GLIBC_2.30 gettid F > +GLIBC_2.30 twalk_r F > Ok.
* Adhemerval Zanella: > On 29/04/2019 09:51, Florian Weimer wrote: >> The twalk function is very difficult to use in a multi-threaded >> program because there is no way to pass external state to the >> iterator function. > > LGTM as well, with some nits below (the whitespace you seems to > fixed already). > >> >> (I expect to use this new function in sem_close and >> __gconv_release_shlib, but the function is generally useful.) > > As a side note I worked on a sem_open/sem_close refactor some time ago > that uses dynarray and the char array derived structure, aimed to remove > both the twalk and alloca internal usage. It turned to be a slight simpler > implementation as well and I will try to send it upstream. > > Reviewed-by: Carlos O'Donell <carlos@redhat.com> I assume this should be your Reviewed-by? >> diff --git a/NEWS b/NEWS >> index 792ffb1ec8..a32bcbd7a4 100644 >> --- a/NEWS >> +++ b/NEWS >> @@ -16,6 +16,8 @@ Major new features: >> * The dynamic linker accepts the --preload argument to preload shared >> objects, in addition to the LD_PRELOAD environment variable. >> >> +* The twalk_r function has been added. >> + > > I think we can extend it description a bit by adding it is a GNU extension > that behaves like twalk but with an addional parameter to be passed in > callback action function (like qsort_r). “The twalk_r function has been added. It is similar to the existing twalk function, but it passes an additional caller-supplied argument to the callback function.” Thanks, Florian
> Il giorno 1 mag 2019, alle ore 03:11, Florian Weimer <fweimer@redhat.com> ha scritto: > > * Adhemerval Zanella: > >>> On 29/04/2019 09:51, Florian Weimer wrote: >>> The twalk function is very difficult to use in a multi-threaded >>> program because there is no way to pass external state to the >>> iterator function. >> >> LGTM as well, with some nits below (the whitespace you seems to >> fixed already). >> >>> >>> (I expect to use this new function in sem_close and >>> __gconv_release_shlib, but the function is generally useful.) >> >> As a side note I worked on a sem_open/sem_close refactor some time ago >> that uses dynarray and the char array derived structure, aimed to remove >> both the twalk and alloca internal usage. It turned to be a slight simpler >> implementation as well and I will try to send it upstream. >> >> Reviewed-by: Carlos O'Donell <carlos@redhat.com> > > I assume this should be your Reviewed-by? Oops, indeed. > >>> diff --git a/NEWS b/NEWS >>> index 792ffb1ec8..a32bcbd7a4 100644 >>> --- a/NEWS >>> +++ b/NEWS >>> @@ -16,6 +16,8 @@ Major new features: >>> * The dynamic linker accepts the --preload argument to preload shared >>> objects, in addition to the LD_PRELOAD environment variable. >>> >>> +* The twalk_r function has been added. >>> + >> >> I think we can extend it description a bit by adding it is a GNU extension >> that behaves like twalk but with an addional parameter to be passed in >> callback action function (like qsort_r). > > “The twalk_r function has been added. It is similar to the existing > twalk function, but it passes an additional caller-supplied argument to > the callback function.” > LGTM. > Thanks, > Florian
I'm seeing (at least with GCC 8): tst-tsearch.c: In function 'walk_tree.constprop': tst-tsearch.c:231:3: error: 'first_list_size' may be used uninitialized in this function [-Werror=maybe-uninitialized] for (size_t i = 0; i < first_list_size && i < walk_trace_size (&walk_trace); ^~~ https://sourceware.org/ml/libc-testresults/2019-q2/msg00121.html
* Joseph Myers: > I'm seeing (at least with GCC 8): > > tst-tsearch.c: In function 'walk_tree.constprop': > tst-tsearch.c:231:3: error: 'first_list_size' may be used uninitialized in this function [-Werror=maybe-uninitialized] > for (size_t i = 0; i < first_list_size && i < walk_trace_size (&walk_trace); > ^~~ Huh. Sorry about that. I don't get this error, with a GCC 8.3-based compiler. It's arguably a test bug. Does this patch fix it for you? diff --git a/misc/tst-tsearch.c b/misc/tst-tsearch.c index 9a570dd6c9..07d13622b1 100644 --- a/misc/tst-tsearch.c +++ b/misc/tst-tsearch.c @@ -223,6 +223,7 @@ walk_tree (void *root, int expected_count) size_t first_list_size; struct walk_trace_element *first_list = walk_trace_finalize (&walk_trace, &first_list_size); + TEST_VERIFY_EXIT (first_list != NULL); walk_tree_with (root, expected_count, twalk_with_twalk_r); It assumes that the tree is not empty, but I think this is true in this test. Thanks, Florian
On Thu, 2 May 2019, Florian Weimer wrote:
> It's arguably a test bug. Does this patch fix it for you?
Yes, this fixes the testsuite build.
* Joseph Myers: > On Thu, 2 May 2019, Florian Weimer wrote: > >> It's arguably a test bug. Does this patch fix it for you? > > Yes, this fixes the testsuite build. Thanks, this is what I pushed to master. Florian misc/tst-tsearch: Additional explicit error checking This avoids an undefined variable warning with certain GCC versions. 2019-05-03 Florian Weimer <fweimer@redhat.com> * misc/tst-tsearch.c (walk_tree): Add more error checking. diff --git a/misc/tst-tsearch.c b/misc/tst-tsearch.c index 9a570dd6c9..44895d4c0a 100644 --- a/misc/tst-tsearch.c +++ b/misc/tst-tsearch.c @@ -223,8 +223,10 @@ walk_tree (void *root, int expected_count) size_t first_list_size; struct walk_trace_element *first_list = walk_trace_finalize (&walk_trace, &first_list_size); + TEST_VERIFY_EXIT (first_list != NULL); walk_tree_with (root, expected_count, twalk_with_twalk_r); + TEST_VERIFY (!walk_trace_has_failed (&walk_trace)); /* Compare the two traces. */ TEST_COMPARE (first_list_size, walk_trace_size (&walk_trace));
diff --git a/NEWS b/NEWS index 792ffb1ec8..a32bcbd7a4 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,8 @@ Major new features: * The dynamic linker accepts the --preload argument to preload shared objects, in addition to the LD_PRELOAD environment variable. +* The twalk_r function has been added. + * On Linux, the gettid function has been added. * Minguo (Republic of China) calendar support has been added as an diff --git a/include/search.h b/include/search.h index e17693022d..72fbc94476 100644 --- a/include/search.h +++ b/include/search.h @@ -23,6 +23,8 @@ extern void *__tdelete (const void *__key, void **__rootp, libc_hidden_proto (__tdelete) extern void __twalk (const void *__root, __action_fn_t action); libc_hidden_proto (__twalk) +extern __typeof__ (twalk_r) __twalk_r; +libc_hidden_proto (__twalk_r) extern void __tdestroy (void *__root, __free_fn_t freefct); libc_hidden_proto (__tdestroy) #endif diff --git a/manual/examples/twalk.c b/manual/examples/twalk.c new file mode 100644 index 0000000000..04e32731d6 --- /dev/null +++ b/manual/examples/twalk.c @@ -0,0 +1,56 @@ +/* Implement twalk using twalk_r. + Copyright (C) 2019 Free Software Foundation, Inc. + + 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 General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include <search.h> + +struct twalk_with_twalk_r_closure +{ + void (*action) (const void *, VISIT, int); + int depth; +}; + +static void +twalk_with_twalk_r_action (const void *nodep, VISIT which, void *closure0) +{ + struct twalk_with_twalk_r_closure *closure = closure0; + + switch (which) + { + case leaf: + closure->action (nodep, which, closure->depth); + break; + case preorder: + closure->action (nodep, which, closure->depth); + ++closure->depth; + break; + case postorder: + /* The preorder action incremented the depth. */ + closure->action (nodep, which, closure->depth - 1); + break; + case endorder: + --closure->depth; + closure->action (nodep, which, closure->depth); + break; + } +} + +void +twalk (const void *root, void (*action) (const void *, VISIT, int)) +{ + struct twalk_with_twalk_r_closure closure = { action, 0 }; + twalk_r (root, twalk_with_twalk_r_action, &closure); +} diff --git a/manual/search.texi b/manual/search.texi index 1574c96562..26f2ceeb55 100644 --- a/manual/search.texi +++ b/manual/search.texi @@ -618,5 +618,28 @@ Since the functions used for the @var{action} parameter to @code{twalk} must not modify the tree data, it is safe to run @code{twalk} in more than one thread at the same time, working on the same tree. It is also safe to call @code{tfind} in parallel. Functions which modify the tree -must not be used, otherwise the behavior is undefined. +must not be used, otherwise the behavior is undefined. However, it is +difficult to pass data external to the tree to the callback function +without resorting to global variables (and threat safety issues), so +see the @code{twalk_r} function below. +@end deftypefun + +@deftypefun void twalk_r (const void *@var{root}, void (*@var{action}) (const void *@var{key}, VISIT @var{which}, void *@var{closure}), void *@var{closure}) +@standards{GNU, search.h} +@safety{@prelim{}@mtsafe{@mtsrace{:root}}@assafe{}@acsafe{}} +For each node in the tree with a node pointed to by @var{root}, the +@code{twalk_r} function calls the function provided by the parameter +@var{action}. For leaf nodes the function is called exactly once with +@var{value} set to @code{leaf}. For internal nodes the function is +called three times, setting the @var{value} parameter or @var{action} to +the appropriate value. The @var{closure} parameter is passed down to +each call of the @var{action} function, unmodified. + +It is possible to implement the @code{twalk} function on top of the +@code{twalk_r} function, which is why there is no separate level +parameter. + +@smallexample +@include twalk.c.texi +@end smallexample @end deftypefun diff --git a/misc/Versions b/misc/Versions index 900e4ffb79..e749582369 100644 --- a/misc/Versions +++ b/misc/Versions @@ -158,11 +158,14 @@ libc { GLIBC_2.26 { preadv2; preadv64v2; pwritev2; pwritev64v2; } + GLIBC_2.30 { + twalk_r; + } GLIBC_PRIVATE { __madvise; __mktemp; __libc_ifunc_impl_list; - __tdelete; __tfind; __tsearch; __twalk; + __tdelete; __tfind; __tsearch; __twalk; __twalk_r; __mmap; __munmap; __mprotect; __sched_get_priority_min; __sched_get_priority_max; __libc_allocate_once_slow; diff --git a/misc/search.h b/misc/search.h index 47e8a43436..be3cc25ef9 100644 --- a/misc/search.h +++ b/misc/search.h @@ -150,6 +150,12 @@ typedef void (*__action_fn_t) (const void *__nodep, VISIT __value, extern void twalk (const void *__root, __action_fn_t __action); #ifdef __USE_GNU +/* Like twalk, but pass down an additional closure parameter. */ +extern void twalk_r (const void *__root, + void (*) (const void *__nodep, VISIT __value, + void *__closure), + void *__closure); + /* Callback type for function to free a tree node. If the keys are atomic data this function should do nothing. */ typedef void (*__free_fn_t) (void *__nodep); diff --git a/misc/tsearch.c b/misc/tsearch.c index 5c19082a59..24d8d69de3 100644 --- a/misc/tsearch.c +++ b/misc/tsearch.c @@ -719,7 +719,41 @@ __twalk (const void *vroot, __action_fn_t action) libc_hidden_def (__twalk) weak_alias (__twalk, twalk) +/* twalk_r is the same as twalk, but with an additional closure + parameter. */ +static void +trecurse_r (const void *vroot, void (*action) (const void *, VISIT, void *), + void *closure) +{ + const_node root = (const_node) vroot; + if (LEFT(root) == NULL && RIGHT(root) == NULL) + (*action) (root, leaf, closure); + else + { + (*action) (root, preorder, closure); + if (LEFT(root) != NULL) + trecurse_r (LEFT(root), action, closure); + (*action) (root, postorder, closure); + if (RIGHT(root) != NULL) + trecurse_r (RIGHT(root), action, closure); + (*action) (root, endorder, closure); + } +} + +void +__twalk_r (const void *vroot, void (*action) (const void *, VISIT, void *), + void *closure) +{ + const_node root = (const_node) vroot; + + CHECK_TREE ((node) root); + + if (root != NULL && action != NULL) + trecurse_r (root, action, closure); +} +libc_hidden_def (__twalk_r) +weak_alias (__twalk_r, twalk_r) /* The standardized functions miss an important functionality: the tree cannot be removed easily. We provide a function to do this. */ diff --git a/misc/tst-tsearch.c b/misc/tst-tsearch.c index 5803a456e0..9a570dd6c9 100644 --- a/misc/tst-tsearch.c +++ b/misc/tst-tsearch.c @@ -25,6 +25,7 @@ #include <string.h> #include <search.h> #include <tst-stack-align.h> +#include <support/check.h> #define SEED 0 #define BALANCED 1 @@ -74,6 +75,20 @@ static int max_depth; static int stack_align_check[2]; +/* Used to compare walk traces between the two implementations. */ +struct walk_trace_element +{ + const void *key; + VISIT which; + int depth; +}; +#define DYNARRAY_STRUCT walk_trace_list +#define DYNARRAY_ELEMENT struct walk_trace_element +#define DYNARRAY_PREFIX walk_trace_ +#define DYNARRAY_INITIAL_SIZE 0 +#include <malloc/dynarray-skeleton.c> +static struct walk_trace_list walk_trace; + /* Compare two keys. */ static int cmp_fn (const void *a, const void *b) @@ -102,11 +117,54 @@ memfry (int *string) } } +struct twalk_with_twalk_r_closure +{ + void (*action) (const void *, VISIT, int); + int depth; +}; + +static void +twalk_with_twalk_r_action (const void *nodep, VISIT which, void *closure0) +{ + struct twalk_with_twalk_r_closure *closure = closure0; + + switch (which) + { + case leaf: + closure->action (nodep, which, closure->depth); + break; + case preorder: + closure->action (nodep, which, closure->depth); + ++closure->depth; + break; + case postorder: + /* The preorder action incremented the depth. */ + closure->action (nodep, which, closure->depth - 1); + break; + case endorder: + --closure->depth; + closure->action (nodep, which, closure->depth); + break; + } +} + +static void +twalk_with_twalk_r (const void *root, + void (*action) (const void *, VISIT, int)) +{ + struct twalk_with_twalk_r_closure closure = { action, 0 }; + twalk_r (root, twalk_with_twalk_r_action, &closure); + TEST_COMPARE (closure.depth, 0); +} + static void walk_action (const void *nodep, const VISIT which, const int depth) { int key = **(int **) nodep; + walk_trace_add (&walk_trace, + (struct walk_trace_element) { nodep, which, depth }); + if (!stack_align_check[1]) stack_align_check[1] = TEST_STACK_ALIGN () ? -1 : 1; @@ -128,14 +186,16 @@ walk_action (const void *nodep, const VISIT which, const int depth) } static void -walk_tree (void *root, int expected_count) +walk_tree_with (void *root, int expected_count, + void (*walk) (const void *, + void (*) (const void *, VISIT, int))) { int i; memset (z, 0, sizeof z); max_depth = 0; - twalk (root, walk_action); + walk (root, walk_action); for (i = 0; i < expected_count; ++i) if (z[i] != 1) { @@ -154,6 +214,31 @@ walk_tree (void *root, int expected_count) } } +static void +walk_tree (void *root, int expected_count) +{ + walk_trace_clear (&walk_trace); + walk_tree_with (root, expected_count, twalk); + TEST_VERIFY (!walk_trace_has_failed (&walk_trace)); + size_t first_list_size; + struct walk_trace_element *first_list + = walk_trace_finalize (&walk_trace, &first_list_size); + + walk_tree_with (root, expected_count, twalk_with_twalk_r); + + /* Compare the two traces. */ + TEST_COMPARE (first_list_size, walk_trace_size (&walk_trace)); + for (size_t i = 0; i < first_list_size && i < walk_trace_size (&walk_trace); + ++i) + { + TEST_VERIFY (first_list[i].key == walk_trace_at (&walk_trace, i)->key); + TEST_COMPARE (first_list[i].which, walk_trace_at (&walk_trace, i)->which); + TEST_COMPARE (first_list[i].depth, walk_trace_at (&walk_trace, i)->depth); + } + + walk_trace_free (&walk_trace); +} + /* Perform an operation on a tree. */ static void mangle_tree (enum order how, enum action what, void **root, int lag) diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist index dd3cf6f9f2..1fc7ab2433 100644 --- a/sysdeps/mach/hurd/i386/libc.abilist +++ b/sysdeps/mach/hurd/i386/libc.abilist @@ -2175,6 +2175,7 @@ GLIBC_2.3.4 setipv4sourcefilter F GLIBC_2.3.4 setsourcefilter F GLIBC_2.3.4 xdr_quad_t F GLIBC_2.3.4 xdr_u_quad_t F +GLIBC_2.30 twalk_r F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist index f3b44d723f..b7283ad486 100644 --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist @@ -2142,3 +2142,4 @@ GLIBC_2.29 getcpu F GLIBC_2.29 posix_spawn_file_actions_addchdir_np F GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist index fd81fc4ad0..a817e683a4 100644 --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist @@ -2217,6 +2217,7 @@ GLIBC_2.30 __nldbl_vwarnx F GLIBC_2.30 __nldbl_warn F GLIBC_2.30 __nldbl_warnx F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F GLIBC_2.4 _IO_fprintf F GLIBC_2.4 _IO_printf F GLIBC_2.4 _IO_sprintf F diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist index f451fefac9..97b6cbf903 100644 --- a/sysdeps/unix/sysv/linux/arm/libc.abilist +++ b/sysdeps/unix/sysv/linux/arm/libc.abilist @@ -127,6 +127,7 @@ GLIBC_2.29 getcpu F GLIBC_2.29 posix_spawn_file_actions_addchdir_np F GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F GLIBC_2.4 _Exit F GLIBC_2.4 _IO_2_1_stderr_ D 0xa0 GLIBC_2.4 _IO_2_1_stdin_ D 0xa0 diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist index 018d02b414..796e622a6d 100644 --- a/sysdeps/unix/sysv/linux/csky/libc.abilist +++ b/sysdeps/unix/sysv/linux/csky/libc.abilist @@ -2086,3 +2086,4 @@ GLIBC_2.29 xencrypt F GLIBC_2.29 xprt_register F GLIBC_2.29 xprt_unregister F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist index fc3c5d5c27..4e7d71d112 100644 --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist @@ -2038,6 +2038,7 @@ GLIBC_2.3.4 setsourcefilter F GLIBC_2.3.4 xdr_quad_t F GLIBC_2.3.4 xdr_u_quad_t F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist index f2b04dbbff..11bd8c601a 100644 --- a/sysdeps/unix/sysv/linux/i386/libc.abilist +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist @@ -2204,6 +2204,7 @@ GLIBC_2.3.4 vm86 F GLIBC_2.3.4 xdr_quad_t F GLIBC_2.3.4 xdr_u_quad_t F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist index 10ecf2e47c..589cce5b8d 100644 --- a/sysdeps/unix/sysv/linux/ia64/libc.abilist +++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist @@ -2070,6 +2070,7 @@ GLIBC_2.3.4 setsourcefilter F GLIBC_2.3.4 xdr_quad_t F GLIBC_2.3.4 xdr_u_quad_t F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist index 814e81b9d2..4b3727a91d 100644 --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist @@ -128,6 +128,7 @@ GLIBC_2.29 getcpu F GLIBC_2.29 posix_spawn_file_actions_addchdir_np F GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F GLIBC_2.4 _Exit F GLIBC_2.4 _IO_2_1_stderr_ D 0x98 GLIBC_2.4 _IO_2_1_stdin_ D 0x98 diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist index 68e80372e7..4be30c0339 100644 --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist @@ -2147,6 +2147,7 @@ GLIBC_2.3.4 setsourcefilter F GLIBC_2.3.4 xdr_quad_t F GLIBC_2.3.4 xdr_u_quad_t F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist index 31178e4f54..e0010965a8 100644 --- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist +++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist @@ -2134,3 +2134,4 @@ GLIBC_2.29 getcpu F GLIBC_2.29 posix_spawn_file_actions_addchdir_np F GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist index 7074573638..2a62f67741 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist @@ -2121,6 +2121,7 @@ GLIBC_2.3.4 setsourcefilter F GLIBC_2.3.4 xdr_quad_t F GLIBC_2.3.4 xdr_u_quad_t F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist index 154f9c77fc..5a23f11fc9 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist @@ -2119,6 +2119,7 @@ GLIBC_2.3.4 setsourcefilter F GLIBC_2.3.4 xdr_quad_t F GLIBC_2.3.4 xdr_u_quad_t F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist index 97b8f42d5c..32532a19da 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist @@ -2127,6 +2127,7 @@ GLIBC_2.3.4 setsourcefilter F GLIBC_2.3.4 xdr_quad_t F GLIBC_2.3.4 xdr_u_quad_t F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist index 5b3e85de93..882f5cb5bf 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist @@ -2121,6 +2121,7 @@ GLIBC_2.3.4 setsourcefilter F GLIBC_2.3.4 xdr_quad_t F GLIBC_2.3.4 xdr_u_quad_t F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist index 04a130a81c..c99a299bab 100644 --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist @@ -2175,3 +2175,4 @@ GLIBC_2.29 getcpu F GLIBC_2.29 posix_spawn_file_actions_addchdir_np F GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist index a701584422..d5f4364197 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist @@ -2177,6 +2177,7 @@ GLIBC_2.30 __nldbl_vwarnx F GLIBC_2.30 __nldbl_warn F GLIBC_2.30 __nldbl_warnx F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F GLIBC_2.4 _IO_fprintf F GLIBC_2.4 _IO_printf F GLIBC_2.4 _IO_sprintf F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist index bbb647cd98..581fd10290 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist @@ -2210,6 +2210,7 @@ GLIBC_2.30 __nldbl_vwarnx F GLIBC_2.30 __nldbl_warn F GLIBC_2.30 __nldbl_warnx F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F GLIBC_2.4 _IO_fprintf F GLIBC_2.4 _IO_printf F GLIBC_2.4 _IO_sprintf F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist index bb23bf61a8..ce10e0436e 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist @@ -2040,6 +2040,7 @@ GLIBC_2.30 __nldbl_vwarnx F GLIBC_2.30 __nldbl_warn F GLIBC_2.30 __nldbl_warnx F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F GLIBC_2.4 _IO_fprintf F GLIBC_2.4 _IO_printf F GLIBC_2.4 _IO_sprintf F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist index 7921dda979..1cc729da7f 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist @@ -2244,3 +2244,4 @@ GLIBC_2.30 __nldbl_vwarnx F GLIBC_2.30 __nldbl_warn F GLIBC_2.30 __nldbl_warnx F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist index da123d3867..2bda5692f4 100644 --- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist +++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist @@ -2104,3 +2104,4 @@ GLIBC_2.29 getcpu F GLIBC_2.29 posix_spawn_file_actions_addchdir_np F GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist index 2aed339af4..dddc138a1e 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist @@ -2172,6 +2172,7 @@ GLIBC_2.30 __nldbl_vwarnx F GLIBC_2.30 __nldbl_warn F GLIBC_2.30 __nldbl_warnx F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F GLIBC_2.4 _IO_fprintf F GLIBC_2.4 _IO_printf F GLIBC_2.4 _IO_sprintf F diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist index e46feb56e5..b2c75a48a8 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist @@ -2076,6 +2076,7 @@ GLIBC_2.30 __nldbl_vwarnx F GLIBC_2.30 __nldbl_warn F GLIBC_2.30 __nldbl_warnx F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F GLIBC_2.4 _IO_fprintf F GLIBC_2.4 _IO_printf F GLIBC_2.4 _IO_sprintf F diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist index 24a8f934cb..8b83449b16 100644 --- a/sysdeps/unix/sysv/linux/sh/libc.abilist +++ b/sysdeps/unix/sysv/linux/sh/libc.abilist @@ -2042,6 +2042,7 @@ GLIBC_2.3.4 setsourcefilter F GLIBC_2.3.4 xdr_quad_t F GLIBC_2.3.4 xdr_u_quad_t F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist index ebdbd2c5ae..a237be9d93 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist @@ -2166,6 +2166,7 @@ GLIBC_2.30 __nldbl_vwarnx F GLIBC_2.30 __nldbl_warn F GLIBC_2.30 __nldbl_warnx F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F GLIBC_2.4 _IO_fprintf F GLIBC_2.4 _IO_printf F GLIBC_2.4 _IO_sprintf F diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist index 0992349b06..b850694434 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist @@ -2093,6 +2093,7 @@ GLIBC_2.3.4 setsourcefilter F GLIBC_2.3.4 xdr_quad_t F GLIBC_2.3.4 xdr_u_quad_t F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist index af004fcff6..c6f22f0c7b 100644 --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist @@ -2051,6 +2051,7 @@ GLIBC_2.3.4 setsourcefilter F GLIBC_2.3.4 xdr_quad_t F GLIBC_2.3.4 xdr_u_quad_t F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist index 84015f0a57..1184385bce 100644 --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist @@ -2150,3 +2150,4 @@ GLIBC_2.29 getcpu F GLIBC_2.29 posix_spawn_file_actions_addchdir_np F GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F GLIBC_2.30 gettid F +GLIBC_2.30 twalk_r F