2016-12-09 07:18:27 +00:00
|
|
|
/* Support functionality for using threads.
|
2022-01-01 18:54:23 +00:00
|
|
|
Copyright (C) 2016-2022 Free Software Foundation, Inc.
|
2016-12-09 07:18:27 +00:00
|
|
|
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
|
Prefer https to http for gnu.org and fsf.org URLs
Also, change sources.redhat.com to sourceware.org.
This patch was automatically generated by running the following shell
script, which uses GNU sed, and which avoids modifying files imported
from upstream:
sed -ri '
s,(http|ftp)(://(.*\.)?(gnu|fsf|sourceware)\.org($|[^.]|\.[^a-z])),https\2,g
s,(http|ftp)(://(.*\.)?)sources\.redhat\.com($|[^.]|\.[^a-z]),https\2sourceware.org\4,g
' \
$(find $(git ls-files) -prune -type f \
! -name '*.po' \
! -name 'ChangeLog*' \
! -path COPYING ! -path COPYING.LIB \
! -path manual/fdl-1.3.texi ! -path manual/lgpl-2.1.texi \
! -path manual/texinfo.tex ! -path scripts/config.guess \
! -path scripts/config.sub ! -path scripts/install-sh \
! -path scripts/mkinstalldirs ! -path scripts/move-if-change \
! -path INSTALL ! -path locale/programs/charmap-kw.h \
! -path po/libc.pot ! -path sysdeps/gnu/errlist.c \
! '(' -name configure \
-execdir test -f configure.ac -o -f configure.in ';' ')' \
! '(' -name preconfigure \
-execdir test -f preconfigure.ac ';' ')' \
-print)
and then by running 'make dist-prepare' to regenerate files built
from the altered files, and then executing the following to cleanup:
chmod a+x sysdeps/unix/sysv/linux/riscv/configure
# Omit irrelevant whitespace and comment-only changes,
# perhaps from a slightly-different Autoconf version.
git checkout -f \
sysdeps/csky/configure \
sysdeps/hppa/configure \
sysdeps/riscv/configure \
sysdeps/unix/sysv/linux/csky/configure
# Omit changes that caused a pre-commit check to fail like this:
# remote: *** error: sysdeps/powerpc/powerpc64/ppc-mcount.S: trailing lines
git checkout -f \
sysdeps/powerpc/powerpc64/ppc-mcount.S \
sysdeps/unix/sysv/linux/s390/s390-64/syscall.S
# Omit change that caused a pre-commit check to fail like this:
# remote: *** error: sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S: last line does not end in newline
git checkout -f sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S
2019-09-07 05:40:42 +00:00
|
|
|
<https://www.gnu.org/licenses/>. */
|
2016-12-09 07:18:27 +00:00
|
|
|
|
|
|
|
#ifndef SUPPORT_THREAD_H
|
|
|
|
#define SUPPORT_THREAD_H
|
|
|
|
|
|
|
|
#include <pthread.h>
|
|
|
|
#include <sys/cdefs.h>
|
2021-08-11 18:16:51 +00:00
|
|
|
#include <stdbool.h>
|
2016-12-09 07:18:27 +00:00
|
|
|
|
|
|
|
__BEGIN_DECLS
|
|
|
|
|
|
|
|
/* Terminate the process (with exit status 0) after SECONDS have
|
|
|
|
elapsed, from a helper thread. The process is terminated with the
|
|
|
|
exit function, so atexit handlers are executed. */
|
|
|
|
void delayed_exit (int seconds);
|
|
|
|
|
2021-08-11 18:16:51 +00:00
|
|
|
/* Returns true if Priority Inheritance support CLOCK_MONOTONIC. */
|
|
|
|
bool support_mutex_pi_monotonic (void);
|
|
|
|
|
2016-12-09 07:18:27 +00:00
|
|
|
/* Terminate the process (with exit status 1) if VALUE is not zero.
|
|
|
|
In that case, print a failure message to standard output mentioning
|
|
|
|
FUNCTION. The process is terminated with the exit function, so
|
|
|
|
atexit handlers are executed. */
|
|
|
|
void xpthread_check_return (const char *function, int value);
|
|
|
|
|
|
|
|
/* The following functions call the corresponding libpthread functions
|
|
|
|
and terminate the process on error. */
|
|
|
|
|
|
|
|
void xpthread_barrier_init (pthread_barrier_t *barrier,
|
|
|
|
pthread_barrierattr_t *attr, unsigned int count);
|
|
|
|
void xpthread_barrier_destroy (pthread_barrier_t *barrier);
|
2018-05-29 08:48:46 +00:00
|
|
|
void xpthread_barrierattr_destroy (pthread_barrierattr_t *);
|
|
|
|
void xpthread_barrierattr_init (pthread_barrierattr_t *);
|
|
|
|
void xpthread_barrierattr_setpshared (pthread_barrierattr_t *, int pshared);
|
2017-01-27 05:53:19 +00:00
|
|
|
void xpthread_mutexattr_destroy (pthread_mutexattr_t *);
|
|
|
|
void xpthread_mutexattr_init (pthread_mutexattr_t *);
|
|
|
|
void xpthread_mutexattr_setprotocol (pthread_mutexattr_t *, int);
|
|
|
|
void xpthread_mutexattr_setpshared (pthread_mutexattr_t *, int);
|
|
|
|
void xpthread_mutexattr_setrobust (pthread_mutexattr_t *, int);
|
|
|
|
void xpthread_mutexattr_settype (pthread_mutexattr_t *, int);
|
|
|
|
void xpthread_mutex_init (pthread_mutex_t *, const pthread_mutexattr_t *);
|
|
|
|
void xpthread_mutex_destroy (pthread_mutex_t *);
|
2016-12-09 07:18:27 +00:00
|
|
|
void xpthread_mutex_lock (pthread_mutex_t *mutex);
|
|
|
|
void xpthread_mutex_unlock (pthread_mutex_t *mutex);
|
2017-01-27 05:53:19 +00:00
|
|
|
void xpthread_mutex_consistent (pthread_mutex_t *);
|
2016-12-09 07:18:27 +00:00
|
|
|
void xpthread_spin_lock (pthread_spinlock_t *lock);
|
|
|
|
void xpthread_spin_unlock (pthread_spinlock_t *lock);
|
|
|
|
void xpthread_cond_wait (pthread_cond_t * cond, pthread_mutex_t * mutex);
|
|
|
|
pthread_t xpthread_create (pthread_attr_t *attr,
|
|
|
|
void *(*thread_func) (void *), void *closure);
|
|
|
|
void xpthread_detach (pthread_t thr);
|
|
|
|
void xpthread_cancel (pthread_t thr);
|
|
|
|
void *xpthread_join (pthread_t thr);
|
2016-12-31 13:06:16 +00:00
|
|
|
void xpthread_once (pthread_once_t *guard, void (*func) (void));
|
2017-01-29 00:13:34 +00:00
|
|
|
void xpthread_attr_destroy (pthread_attr_t *attr);
|
|
|
|
void xpthread_attr_init (pthread_attr_t *attr);
|
2021-05-28 19:00:19 +00:00
|
|
|
#ifdef __linux__
|
2021-05-21 18:09:43 +00:00
|
|
|
void xpthread_attr_setaffinity_np (pthread_attr_t *attr,
|
|
|
|
size_t cpusetsize,
|
|
|
|
const cpu_set_t *cpuset);
|
2021-05-28 19:00:19 +00:00
|
|
|
#endif
|
2017-01-29 00:13:34 +00:00
|
|
|
void xpthread_attr_setdetachstate (pthread_attr_t *attr,
|
|
|
|
int detachstate);
|
2019-02-06 08:06:34 +00:00
|
|
|
void xpthread_attr_setstack (pthread_attr_t *attr, void *stackaddr,
|
|
|
|
size_t stacksize);
|
2017-01-29 00:13:34 +00:00
|
|
|
void xpthread_attr_setstacksize (pthread_attr_t *attr,
|
|
|
|
size_t stacksize);
|
nptl: Invert the mmap/mprotect logic on allocated stacks (BZ#18988)
Current allocate_stack logic for create stacks is to first mmap all
the required memory with the desirable memory and then mprotect the
guard area with PROT_NONE if required. Although it works as expected,
it pessimizes the allocation because it requires the kernel to actually
increase commit charge (it counts against the available physical/swap
memory available for the system).
The only issue is to actually check this change since side-effects are
really Linux specific and to actually account them it would require a
kernel specific tests to parse the system wide information. On the kernel
I checked /proc/self/statm does not show any meaningful difference for
vmm and/or rss before and after thread creation. I could only see
really meaningful information checking on system wide /proc/meminfo
between thread creation: MemFree, MemAvailable, and Committed_AS shows
large difference without the patch. I think trying to use these
kind of information on a testcase is fragile.
The BZ#18988 reports shows that the commit pages are easily seen with
mlockall (MCL_FUTURE) (with lock all pages that become mapped in the
process) however a more straighfoward testcase shows that pthread_create
could be faster using this patch:
--
static const int inner_count = 256;
static const int outer_count = 128;
static
void *thread1(void *arg)
{
return NULL;
}
static
void *sleeper(void *arg)
{
pthread_t ts[inner_count];
for (int i = 0; i < inner_count; i++)
pthread_create (&ts[i], &a, thread1, NULL);
for (int i = 0; i < inner_count; i++)
pthread_join (ts[i], NULL);
return NULL;
}
int main(void)
{
pthread_attr_init(&a);
pthread_attr_setguardsize(&a, 1<<20);
pthread_attr_setstacksize(&a, 1134592);
pthread_t ts[outer_count];
for (int i = 0; i < outer_count; i++)
pthread_create(&ts[i], &a, sleeper, NULL);
for (int i = 0; i < outer_count; i++)
pthread_join(ts[i], NULL);
assert(r == 0);
}
return 0;
}
--
On x86_64 (4.4.0-45-generic, gcc 5.4.0) running the small benchtests
I see:
$ time ./test
real 0m3.647s
user 0m0.080s
sys 0m11.836s
While with the patch I see:
$ time ./test
real 0m0.696s
user 0m0.040s
sys 0m1.152s
So I added a pthread_create benchtest (thread_create) which check
the thread creation latency. As for the simple benchtests, I saw
improvements in thread creation on all architectures I tested the
change.
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu,
arm-linux-gnueabihf, powerpc64le-linux-gnu, sparc64-linux-gnu,
and sparcv9-linux-gnu.
[BZ #18988]
* benchtests/thread_create-inputs: New file.
* benchtests/thread_create-source.c: Likewise.
* support/xpthread_attr_setguardsize.c: Likewise.
* support/Makefile (libsupport-routines): Add
xpthread_attr_setguardsize object.
* support/xthread.h: Add xpthread_attr_setguardsize prototype.
* benchtests/Makefile (bench-pthread): Add thread_create.
* nptl/allocatestack.c (allocate_stack): Call mmap with PROT_NONE and
then mprotect the required area.
2017-01-31 20:01:59 +00:00
|
|
|
void xpthread_attr_setguardsize (pthread_attr_t *attr,
|
|
|
|
size_t guardsize);
|
2016-12-09 07:18:27 +00:00
|
|
|
|
2021-01-20 17:32:23 +00:00
|
|
|
void xpthread_kill (pthread_t thr, int signo);
|
|
|
|
|
2020-12-29 14:52:41 +00:00
|
|
|
/* Return the stack size used on support_set_small_thread_stack_size. */
|
|
|
|
size_t support_small_thread_stack_size (void);
|
2019-11-11 08:20:09 +00:00
|
|
|
/* Set the stack size in ATTR to a small value, but still large enough
|
|
|
|
to cover most internal glibc stack usage. */
|
|
|
|
void support_set_small_thread_stack_size (pthread_attr_t *attr);
|
|
|
|
|
|
|
|
/* Return a pointer to a thread attribute which requests a small
|
|
|
|
stack. The caller must not free this pointer. */
|
|
|
|
pthread_attr_t *support_small_stack_thread_attribute (void);
|
|
|
|
|
2016-12-09 07:18:27 +00:00
|
|
|
/* This function returns non-zero if pthread_barrier_wait returned
|
|
|
|
PTHREAD_BARRIER_SERIAL_THREAD. */
|
|
|
|
int xpthread_barrier_wait (pthread_barrier_t *barrier);
|
|
|
|
|
2017-07-28 04:22:44 +00:00
|
|
|
void xpthread_rwlock_init (pthread_rwlock_t *rwlock,
|
|
|
|
const pthread_rwlockattr_t *attr);
|
|
|
|
void xpthread_rwlockattr_init (pthread_rwlockattr_t *attr);
|
|
|
|
void xpthread_rwlockattr_setkind_np (pthread_rwlockattr_t *attr, int pref);
|
|
|
|
void xpthread_rwlock_wrlock (pthread_rwlock_t *rwlock);
|
|
|
|
void xpthread_rwlock_rdlock (pthread_rwlock_t *rwlock);
|
|
|
|
void xpthread_rwlock_unlock (pthread_rwlock_t *rwlock);
|
2019-01-22 03:50:12 +00:00
|
|
|
void xpthread_rwlock_destroy (pthread_rwlock_t *rwlock);
|
2020-04-27 19:40:24 +00:00
|
|
|
pthread_key_t xpthread_key_create (void (*destr_function) (void *));
|
|
|
|
void xpthread_key_delete (pthread_key_t key);
|
2017-07-28 04:22:44 +00:00
|
|
|
|
2016-12-09 07:18:27 +00:00
|
|
|
__END_DECLS
|
|
|
|
|
|
|
|
#endif /* SUPPORT_THREAD_H */
|