diff options
author | Florian Weimer <fweimer@redhat.com> | 2020-11-16 19:33:30 +0100 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2020-11-16 19:33:30 +0100 |
commit | 1daccf403b1bd86370eb94edca794dc106d02039 (patch) | |
tree | e54bc8ee71eb92b7114df79e2f378a477c470029 /sysdeps/nptl | |
parent | aac0f62c47beee5b546bacc330acc2dd21cda0dc (diff) | |
download | glibc-1daccf403b1bd86370eb94edca794dc106d02039.zip glibc-1daccf403b1bd86370eb94edca794dc106d02039.tar.gz glibc-1daccf403b1bd86370eb94edca794dc106d02039.tar.bz2 |
nptl: Move stack list variables into _rtld_global
Now __thread_gscope_wait (the function behind THREAD_GSCOPE_WAIT,
formerly __wait_lookup_done) can be implemented directly in ld.so,
eliminating the unprotected GL (dl_wait_lookup_done) function
pointer.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Diffstat (limited to 'sysdeps/nptl')
-rw-r--r-- | sysdeps/nptl/dl-thread_gscope_wait.c | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/sysdeps/nptl/dl-thread_gscope_wait.c b/sysdeps/nptl/dl-thread_gscope_wait.c new file mode 100644 index 0000000..a9bfbee --- /dev/null +++ b/sysdeps/nptl/dl-thread_gscope_wait.c @@ -0,0 +1,80 @@ +/* Out-of-line notification function for the GSCOPE locking mechanism. + Copyright (C) 2007-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <nptl/descr.h> +#include <futex-internal.h> +#include <ldsodefs.h> +#include <list.h> +#include <lowlevellock.h> + +void +__thread_gscope_wait (void) +{ + lll_lock (GL (dl_stack_cache_lock), LLL_PRIVATE); + + struct pthread *self = THREAD_SELF; + + /* Iterate over the list with system-allocated threads first. */ + list_t *runp; + list_for_each (runp, &GL (dl_stack_used)) + { + struct pthread *t = list_entry (runp, struct pthread, list); + if (t == self || t->header.gscope_flag == THREAD_GSCOPE_FLAG_UNUSED) + continue; + + int *const gscope_flagp = &t->header.gscope_flag; + + /* We have to wait until this thread is done with the global + scope. First tell the thread that we are waiting and + possibly have to be woken. */ + if (atomic_compare_and_exchange_bool_acq (gscope_flagp, + THREAD_GSCOPE_FLAG_WAIT, + THREAD_GSCOPE_FLAG_USED)) + continue; + + do + futex_wait_simple ((unsigned int *) gscope_flagp, + THREAD_GSCOPE_FLAG_WAIT, FUTEX_PRIVATE); + while (*gscope_flagp == THREAD_GSCOPE_FLAG_WAIT); + } + + /* Now the list with threads using user-allocated stacks. */ + list_for_each (runp, &GL (dl_stack_user)) + { + struct pthread *t = list_entry (runp, struct pthread, list); + if (t == self || t->header.gscope_flag == THREAD_GSCOPE_FLAG_UNUSED) + continue; + + int *const gscope_flagp = &t->header.gscope_flag; + + /* We have to wait until this thread is done with the global + scope. First tell the thread that we are waiting and + possibly have to be woken. */ + if (atomic_compare_and_exchange_bool_acq (gscope_flagp, + THREAD_GSCOPE_FLAG_WAIT, + THREAD_GSCOPE_FLAG_USED)) + continue; + + do + futex_wait_simple ((unsigned int *) gscope_flagp, + THREAD_GSCOPE_FLAG_WAIT, FUTEX_PRIVATE); + while (*gscope_flagp == THREAD_GSCOPE_FLAG_WAIT); + } + + lll_unlock (GL (dl_stack_cache_lock), LLL_PRIVATE); +} |