1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-29 11:41:21 +03:00

Get rid of nptl/sysdeps/ entirely!

This commit is contained in:
Roland McGrath
2014-07-07 09:28:38 -07:00
parent 96baf6ffc5
commit 08192659bb
84 changed files with 528 additions and 664 deletions

147
ChangeLog
View File

@ -1,3 +1,150 @@
2014-07-07 Roland McGrath <roland@hack.frob.com>
* nptl/Makefile (routines): Add libc_pthread_init,
libc_multiple_threads, register-atfork and unregister-atfork.
(libpthread-routines): Add pthread_mutex_cond_lock and pt-fork here.
(gen-as-const-headers): Add lowlevelcond.sym, lowlevelrwlock.sym,
lowlevelbarrier.sym, unwindbuf.sym, lowlevelrobustlock.sym,
pthread-pi-defines.sym, structsem.sym.
* sysdeps/unix/sysv/linux/Makefile [$(subdir) = posix]
(CFLAGS-fork.c, CFLAGS-getpid.o, CFLAGS-getpid.os): New variables.
[$(subdir) = nptl] (tests): Add tst-setgetname.
* nptl/sysdeps/unix/sysv/linux/Makefile: File removed.
* sysdeps/unix/sysv/linux/sigaction.c: Just include
<nptl/sigaction.c> directly here, instead of WRAPPER_INCLUDE.
[!LIBC_SIGACTION]: Remove aliases.
* sysdeps/unix/sysv/linux/aarch64/sigaction.c: Likewise.
* sysdeps/unix/sysv/linux/arm/sigaction.c: Likewise.
* sysdeps/unix/sysv/linux/i386/sigaction.c: Likewise.
* sysdeps/unix/sysv/linux/ia64/sigaction.c: Likewise.
* sysdeps/unix/sysv/linux/mips/sigaction.c: Likewise.
* sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c: Likewise.
* sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c: Likewise.
* sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c: Likewise.
* sysdeps/unix/sysv/linux/x86_64/sigaction.c: Likewise.
* nptl/Versions (libc: GLIBC_2.3.2): Add __register_atfork.
(libc: GLIBC_PRIVATE): Add __libc_pthread_init,
__libc_current_sigrtmin_private, __libc_current_sigrtmax_private,
__libc_allocate_rtsig_private.
* nptl/sysdeps/unix/sysv/linux/Versions: File removed.
* sysdeps/unix/sysv/linux/sigtimedwait.c: Include <nptl/pthreadP.h>.
* sysdeps/unix/sysv/linux/sigwait.c: Likewise.
* sysdeps/unix/sysv/linux/sigwaitinfo.c: Likewise.
* sysdeps/unix/sysv/linux/sleep.c: Likewise.
* nptl/sysdeps/unix/sysv/linux/sigwait.c: File removed.
* nptl/sysdeps/unix/sysv/linux/sigtimedwait.c: File removed.
* nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c: File removed.
* nptl/sysdeps/unix/sysv/linux/sleep.c: File removed.
* nptl/sysdeps/unix/sysv/linux/createthread.c: File removed.
* sysdeps/unix/sysv/linux/ia64/fork.S: File removed.
* nptl/sysdeps/unix/sysv/linux/internaltypes.h: Moved ...
* nptl/internaltypes.h: ... here.
* nptl/sysdeps/unix/sysv/linux/jmp-unwind.c: Moved ...
* sysdeps/nptl/jmp-unwind.c: ... here.
* nptl/sysdeps/unix/sysv/linux/libc-lowlevellock.c: Moved ...
* nptl/libc-lowlevellock.c: ... here.
* nptl/sysdeps/unix/sysv/linux/libc_multiple_threads.c: Moved ...
* nptl/libc_multiple_threads.c: ... here.
* nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c: Moved ...
* nptl/libc_pthread_init.c: ... here.
* nptl/sysdeps/unix/sysv/linux/lowlevelbarrier.sym: Moved ...
* nptl/lowlevelbarrier.sym: ... here.
* nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym: Moved ...
* nptl/lowlevelcond.sym: ... here.
* nptl/sysdeps/unix/sysv/linux/lowlevellock.c: Moved ...
* nptl/lowlevellock.c: ... here.
* nptl/lowlevellock.h: Moved ...
* sysdeps/nptl/lowlevellock.h: ... here.
* nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c: Moved ...
* nptl/lowlevelrobustlock.c: ... here.
* nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.sym: Moved ...
* nptl/lowlevelrobustlock.sym: ... here.
* nptl/sysdeps/unix/sysv/linux/lowlevelrwlock.sym: Moved ...
* nptl/lowlevelrwlock.sym: ... here.
* nptl/sysdeps/unix/sysv/linux/pt-fork.c: Moved ...
* nptl/pt-fork.c: ... here.
* nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym: Moved ...
* nptl/pthread-pi-defines.sym: ... here.
* nptl/sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c: Moved ...
* nptl/pthread_attr_getaffinity.c: ... here.
* nptl/sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c: Moved ...
* nptl/pthread_attr_setaffinity.c: ... here.
* nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c: Moved ...
* nptl/pthread_mutex_cond_lock.c: ... here.
* sysdeps/unix/sysv/linux/s390/pthread_mutex_cond_lock.c:
Update #include.
* sysdeps/unix/sysv/linux/x86/pthread_mutex_cond_lock.c: Likewise.
* nptl/sysdeps/unix/sysv/linux/pthread_once.c: Moved ...
* nptl/pthread_once.c: ... here, replacing old file.
* nptl/sysdeps/unix/sysv/linux/pthread_yield.c: Moved ...
* nptl/pthread_yield.c: ... here.
* nptl/sysdeps/unix/sysv/linux/register-atfork.c: Moved ...
* nptl/register-atfork.c: ... here.
* nptl/sysdeps/unix/sysv/linux/sem_post.c: Moved ...
* nptl/sem_post.c: ... here.
* sysdeps/unix/sysv/linux/alpha/sem_post.c: Update #include.
* nptl/sysdeps/unix/sysv/linux/sem_timedwait.c: Moved ...
* nptl/sem_timedwait.c: ... here.
* nptl/sysdeps/unix/sysv/linux/sem_trywait.c: Moved ...
* nptl/sem_trywait.c: ... here.
* sysdeps/sparc/sparc32/sparcv9/sem_trywait.c: Update #include.
* nptl/sysdeps/unix/sysv/linux/sem_wait.c: Moved ...
* nptl/sem_wait.c: ... here.
* nptl/sysdeps/unix/sysv/linux/structsem.sym: Moved ...
* nptl/structsem.sym: ... here.
* nptl/sysdeps/unix/sysv/linux/mq_notify.c: Moved ...
* sysdeps/unix/sysv/linux/mq_notify.c: ... here, replacing old file.
* nptl/sysdeps/unix/sysv/linux/unregister-atfork.c: Moved ...
* nptl/unregister-atfork.c: ... here.
* nptl/sysdeps/unix/sysv/linux/unwindbuf.sym: Moved ...
* nptl/unwindbuf.sym: ... here.
* nptl/sysdeps/unix/sysv/linux/fork.c: Moved ...
* sysdeps/nptl/fork.c: ... here.
* nptl/sysdeps/unix/sysv/linux/fork.h: Moved ...
* sysdeps/nptl/fork.h: ... here.
* sysdeps/unix/sysv/linux/syscalls.list: Remove fork.
* nptl/sysdeps/unix/sysv/linux/aio_misc.h: Moved ...
* sysdeps/unix/sysv/linux/aio_misc.h: ... here.
* nptl/sysdeps/unix/sysv/linux/allocrtsig.c: Moved ...
* sysdeps/unix/sysv/linux/allocrtsig.c: ... here.
* nptl/sysdeps/unix/sysv/linux/getpid.c: Moved ...
* sysdeps/unix/sysv/linux/getpid.c: ... here.
* nptl/sysdeps/unix/sysv/linux/kernel-posix-timers.h: Moved ...
* sysdeps/unix/sysv/linux/kernel-posix-timers.h: ... here.
* nptl/sysdeps/unix/sysv/linux/pt-raise.c: Moved ...
* sysdeps/unix/sysv/linux/pt-raise.c: ... here.
* nptl/sysdeps/unix/sysv/linux/pthread_getaffinity.c: Moved ...
* sysdeps/unix/sysv/linux/pthread_getaffinity.c: ... here.
* nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c: Moved ...
* sysdeps/unix/sysv/linux/pthread_getcpuclockid.c: ... here.
* nptl/sysdeps/unix/sysv/linux/pthread_getname.c: Moved ...
* sysdeps/unix/sysv/linux/pthread_getname.c: ... here.
* nptl/sysdeps/unix/sysv/linux/pthread_kill.c: Moved ...
* sysdeps/unix/sysv/linux/pthread_kill.c: ... here.
* nptl/sysdeps/unix/sysv/linux/pthread_setaffinity.c: Moved ...
* sysdeps/unix/sysv/linux/pthread_setaffinity.c: ... here.
* nptl/sysdeps/unix/sysv/linux/pthread_setname.c: Moved ...
* sysdeps/unix/sysv/linux/pthread_setname.c: ... here.
* nptl/sysdeps/unix/sysv/linux/pthread_sigqueue.c: Moved ...
* sysdeps/unix/sysv/linux/pthread_sigqueue.c: ... here.
* nptl/sysdeps/unix/sysv/linux/raise.c: Moved ...
* sysdeps/unix/sysv/linux/raise.c: ... here.
* nptl/sysdeps/unix/sysv/linux/timer_create.c: Moved ...
* sysdeps/unix/sysv/linux/timer_create.c: ... here.
* nptl/sysdeps/unix/sysv/linux/timer_delete.c: Moved ...
* sysdeps/unix/sysv/linux/timer_delete.c: ... here.
* nptl/sysdeps/unix/sysv/linux/timer_getoverr.c: Moved ...
* sysdeps/unix/sysv/linux/timer_getoverr.c: ... here.
* nptl/sysdeps/unix/sysv/linux/timer_gettime.c: Moved ...
* sysdeps/unix/sysv/linux/timer_gettime.c: ... here.
* nptl/sysdeps/unix/sysv/linux/timer_routines.c: Moved ...
* sysdeps/unix/sysv/linux/timer_routines.c: ... here.
* nptl/sysdeps/unix/sysv/linux/timer_settime.c: Moved ...
* sysdeps/unix/sysv/linux/timer_settime.c: ... here.
* nptl/sysdeps/unix/sysv/linux/tst-setgetname.c: Moved ...
* sysdeps/unix/sysv/linux/tst-setgetname.c: ... here.
* sysdeps/unix/sysv/linux/s390/jmp-unwind.c: Update #include.
2014-07-04 Siddhesh Poyarekar <siddhesh@redhat.com> 2014-07-04 Siddhesh Poyarekar <siddhesh@redhat.com>
* sysdeps/generic/memcopy.h: Add comment for * sysdeps/generic/memcopy.h: Add comment for

View File

@ -29,7 +29,8 @@ extra-libs-others := $(extra-libs)
install-lib-ldscripts := libpthread.so install-lib-ldscripts := libpthread.so
routines = alloca_cutoff forward libc-lowlevellock libc-cancellation \ routines = alloca_cutoff forward libc-lowlevellock libc-cancellation \
libc-cleanup libc-cleanup libc_pthread_init libc_multiple_threads \
register-atfork unregister-atfork
shared-only-routines = forward shared-only-routines = forward
libpthread-routines = nptl-init vars events version \ libpthread-routines = nptl-init vars events version \
@ -54,6 +55,7 @@ libpthread-routines = nptl-init vars events version \
pthread_mutex_init pthread_mutex_destroy \ pthread_mutex_init pthread_mutex_destroy \
pthread_mutex_lock pthread_mutex_trylock \ pthread_mutex_lock pthread_mutex_trylock \
pthread_mutex_timedlock pthread_mutex_unlock \ pthread_mutex_timedlock pthread_mutex_unlock \
pthread_mutex_cond_lock \
pthread_mutexattr_init pthread_mutexattr_destroy \ pthread_mutexattr_init pthread_mutexattr_destroy \
pthread_mutexattr_getpshared \ pthread_mutexattr_getpshared \
pthread_mutexattr_setpshared \ pthread_mutexattr_setpshared \
@ -103,7 +105,7 @@ libpthread-routines = nptl-init vars events version \
pt-longjmp pt-cleanup\ pt-longjmp pt-cleanup\
cancellation \ cancellation \
lowlevellock lowlevelrobustlock \ lowlevellock lowlevelrobustlock \
pt-vfork \ pt-fork pt-vfork \
ptw-write ptw-read ptw-close ptw-fcntl ptw-accept \ ptw-write ptw-read ptw-close ptw-fcntl ptw-accept \
ptw-connect ptw-recv ptw-recvfrom ptw-recvmsg ptw-send \ ptw-connect ptw-recv ptw-recvfrom ptw-recvmsg ptw-send \
ptw-sendmsg ptw-sendto ptw-fsync ptw-lseek ptw-llseek \ ptw-sendmsg ptw-sendto ptw-fsync ptw-lseek ptw-llseek \
@ -277,7 +279,12 @@ test-srcs = tst-oddstacklimit
# Files which must not be linked with libpthread. # Files which must not be linked with libpthread.
tests-nolibpthread = tst-unload tests-nolibpthread = tst-unload
gen-as-const-headers = pthread-errnos.sym gen-as-const-headers = pthread-errnos.sym \
lowlevelcond.sym lowlevelrwlock.sym \
lowlevelbarrier.sym unwindbuf.sym \
lowlevelrobustlock.sym pthread-pi-defines.sym \
structsem.sym
LDFLAGS-pthread.so = -Wl,--enable-new-dtags,-z,nodelete,-z,initfirst LDFLAGS-pthread.so = -Wl,--enable-new-dtags,-z,nodelete,-z,initfirst

View File

@ -21,6 +21,8 @@ libc {
pthread_attr_init; pthread_attr_init;
} }
GLIBC_2.3.2 { GLIBC_2.3.2 {
__register_atfork;
# Changed pthread_cond_t. # Changed pthread_cond_t.
pthread_cond_init; pthread_cond_destroy; pthread_cond_init; pthread_cond_destroy;
pthread_cond_wait; pthread_cond_signal; pthread_cond_wait; pthread_cond_signal;
@ -31,6 +33,9 @@ libc {
# Internal libc interface to libpthread # Internal libc interface to libpthread
__libc_dl_error_tsd; __libc_dl_error_tsd;
__libc_vfork; __libc_vfork;
__libc_pthread_init;
__libc_current_sigrtmin_private; __libc_current_sigrtmax_private;
__libc_allocate_rtsig_private;
} }
} }

View File

@ -1,6 +1,6 @@
/* Copyright (C) 2002-2014 Free Software Foundation, Inc. /* Copyright (C) 2003-2014 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
@ -9,7 +9,7 @@
The GNU C Library is distributed in the hope that it will be useful, The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details. Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
@ -18,37 +18,114 @@
#include "pthreadP.h" #include "pthreadP.h"
#include <lowlevellock.h> #include <lowlevellock.h>
#include <atomic.h>
unsigned long int __fork_generation attribute_hidden;
static int once_lock = LLL_LOCK_INITIALIZER;
static void
clear_once_control (void *arg)
{
pthread_once_t *once_control = (pthread_once_t *) arg;
/* Reset to the uninitialized state here. We don't need a stronger memory
order because we do not need to make any other of our writes visible to
other threads that see this value: This function will be called if we
get interrupted (see __pthread_once), so all we need to relay to other
threads is the state being reset again. */
*once_control = 0;
lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
}
/* This is similar to a lock implementation, but we distinguish between three
states: not yet initialized (0), initialization finished (2), and
initialization in progress (__fork_generation | 1). If in the first state,
threads will try to run the initialization by moving to the second state;
the first thread to do so via a CAS on once_control runs init_routine,
other threads block.
When forking the process, some threads can be interrupted during the second
state; they won't be present in the forked child, so we need to restart
initialization in the child. To distinguish an in-progress initialization
from an interrupted initialization (in which case we need to reclaim the
lock), we look at the fork generation that's part of the second state: We
can reclaim iff it differs from the current fork generation.
XXX: This algorithm has an ABA issue on the fork generation: If an
initialization is interrupted, we then fork 2^30 times (30 bits of
once_control are used for the fork generation), and try to initialize
again, we can deadlock because we can't distinguish the in-progress and
interrupted cases anymore. */
int int
__pthread_once (once_control, init_routine) __pthread_once (once_control, init_routine)
pthread_once_t *once_control; pthread_once_t *once_control;
void (*init_routine) (void); void (*init_routine) (void);
{ {
/* XXX Depending on whether the LOCK_IN_ONCE_T is defined use a while (1)
global lock variable or one which is part of the pthread_once_t
object. */
if (*once_control == PTHREAD_ONCE_INIT)
{ {
lll_lock (once_lock, LLL_PRIVATE); int oldval, val, newval;
/* XXX This implementation is not complete. It doesn't take /* We need acquire memory order for this load because if the value
cancelation and fork into account. */ signals that initialization has finished, we need to be see any
if (*once_control == PTHREAD_ONCE_INIT) data modifications done during initialization. */
val = *once_control;
atomic_read_barrier();
do
{ {
init_routine (); /* Check if the initialization has already been done. */
if (__glibc_likely ((val & 2) != 0))
return 0;
*once_control = !PTHREAD_ONCE_INIT; oldval = val;
/* We try to set the state to in-progress and having the current
fork generation. We don't need atomic accesses for the fork
generation because it's immutable in a particular process, and
forked child processes start with a single thread that modified
the generation. */
newval = __fork_generation | 1;
/* We need acquire memory order here for the same reason as for the
load from once_control above. */
val = atomic_compare_and_exchange_val_acq (once_control, newval,
oldval);
}
while (__glibc_unlikely (val != oldval));
/* Check if another thread already runs the initializer. */
if ((oldval & 1) != 0)
{
/* Check whether the initializer execution was interrupted by a
fork. We know that for both values, bit 0 is set and bit 1 is
not. */
if (oldval == newval)
{
/* Same generation, some other thread was faster. Wait. */
lll_futex_wait (once_control, newval, LLL_PRIVATE);
continue;
}
} }
lll_unlock (once_lock, LLL_PRIVATE); /* This thread is the first here. Do the initialization.
Register a cleanup handler so that in case the thread gets
interrupted the initialization can be restarted. */
pthread_cleanup_push (clear_once_control, once_control);
init_routine ();
pthread_cleanup_pop (0);
/* Mark *once_control as having finished the initialization. We need
release memory order here because we need to synchronize with other
threads that want to use the initialized data. */
atomic_write_barrier();
*once_control = 2;
/* Wake up all other threads. */
lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
break;
} }
return 0; return 0;
} }
strong_alias (__pthread_once, pthread_once) weak_alias (__pthread_once, pthread_once)
hidden_def (__pthread_once) hidden_def (__pthread_once)

View File

@ -1,39 +0,0 @@
# Copyright (C) 2002-2014 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
# 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
# <http://www.gnu.org/licenses/>.
ifeq ($(subdir),nptl)
sysdep_routines += register-atfork unregister-atfork libc_pthread_init \
libc_multiple_threads
libpthread-sysdep_routines += pt-fork pthread_mutex_cond_lock
gen-as-const-headers += lowlevelcond.sym lowlevelrwlock.sym \
lowlevelbarrier.sym unwindbuf.sym \
lowlevelrobustlock.sym pthread-pi-defines.sym \
structsem.sym
tests += tst-setgetname
endif
ifeq ($(subdir),posix)
CFLAGS-fork.c = $(libio-mtsafe)
CFLAGS-getpid.o = -fomit-frame-pointer
CFLAGS-getpid.os = -fomit-frame-pointer
endif
# Needed in both the signal and nptl subdir.
CFLAGS-sigaction.c = -DWRAPPER_INCLUDE='<nptl/sigaction.c>'

View File

@ -1,15 +0,0 @@
libc {
GLIBC_2.3.2 {
__register_atfork;
}
GLIBC_PRIVATE {
__libc_pthread_init;
__libc_current_sigrtmin_private; __libc_current_sigrtmax_private;
__libc_allocate_rtsig_private;
}
}
libpthread {
GLIBC_2.0 {
fork; __fork;
}
}

View File

@ -1,23 +0,0 @@
/* Copyright (C) 2003-2014 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>.
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
<http://www.gnu.org/licenses/>. */
/* Value passed to 'clone' for initialization of the thread register. */
#define TLS_VALUE pd
/* Get the real implementation. */
#include <nptl/createthread.c>

View File

@ -1,282 +0,0 @@
/* Copyright (C) 2004-2014 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contribute by Ulrich Drepper <drepper@redhat.com>, 2004.
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
<http://www.gnu.org/licenses/>. */
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <mqueue.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sysdep.h>
#include <unistd.h>
#include <sys/socket.h>
#include <not-cancel.h>
#include <nptl/pthreadP.h>
#ifdef __NR_mq_notify
/* Defined in the kernel headers: */
#define NOTIFY_COOKIE_LEN 32 /* Length of the cookie used. */
#define NOTIFY_WOKENUP 1 /* Code for notifcation. */
#define NOTIFY_REMOVED 2 /* Code for closed message queue
of de-notifcation. */
/* Data structure for the queued notification requests. */
union notify_data
{
struct
{
void (*fct) (union sigval); /* The function to run. */
union sigval param; /* The parameter to pass. */
pthread_attr_t *attr; /* Attributes to create the thread with. */
/* NB: on 64-bit machines the struct as a size of 24 bytes. Which means
byte 31 can still be used for returning the status. */
};
char raw[NOTIFY_COOKIE_LEN];
};
/* Keep track of the initialization. */
static pthread_once_t once = PTHREAD_ONCE_INIT;
/* The netlink socket. */
static int netlink_socket = -1;
/* Barrier used to make sure data passed to the new thread is not
resused by the parent. */
static pthread_barrier_t notify_barrier;
/* Modify the signal mask. We move this into a separate function so
that the stack space needed for sigset_t is not deducted from what
the thread can use. */
static int
__attribute__ ((noinline))
change_sigmask (int how, sigset_t *oss)
{
sigset_t ss;
sigfillset (&ss);
return pthread_sigmask (how, &ss, oss);
}
/* The function used for the notification. */
static void *
notification_function (void *arg)
{
/* Copy the function and parameter so that the parent thread can go
on with its life. */
volatile union notify_data *data = (volatile union notify_data *) arg;
void (*fct) (union sigval) = data->fct;
union sigval param = data->param;
/* Let the parent go. */
(void) pthread_barrier_wait (&notify_barrier);
/* Make the thread detached. */
(void) pthread_detach (pthread_self ());
/* The parent thread has all signals blocked. This is probably a
bit surprising for this thread. So we unblock all of them. */
(void) change_sigmask (SIG_UNBLOCK, NULL);
/* Now run the user code. */
fct (param);
/* And we are done. */
return NULL;
}
/* Helper thread. */
static void *
helper_thread (void *arg)
{
while (1)
{
union notify_data data;
ssize_t n = recv (netlink_socket, &data, sizeof (data),
MSG_NOSIGNAL | MSG_WAITALL);
if (n < NOTIFY_COOKIE_LEN)
continue;
if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_WOKENUP)
{
/* Just create the thread as instructed. There is no way to
report a problem with creating a thread. */
pthread_t th;
if (__builtin_expect (pthread_create (&th, data.attr,
notification_function, &data)
== 0, 0))
/* Since we passed a pointer to DATA to the new thread we have
to wait until it is done with it. */
(void) pthread_barrier_wait (&notify_barrier);
}
else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED)
/* The only state we keep is the copy of the thread attributes. */
free (data.attr);
}
return NULL;
}
static void
reset_once (void)
{
once = PTHREAD_ONCE_INIT;
}
static void
init_mq_netlink (void)
{
/* This code might be called a second time after fork(). The file
descriptor is inherited from the parent. */
if (netlink_socket == -1)
{
/* Just a normal netlink socket, not bound. */
netlink_socket = socket (AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, 0);
/* No need to do more if we have no socket. */
if (netlink_socket == -1)
return;
}
int err = 1;
/* Initialize the barrier. */
if (__builtin_expect (pthread_barrier_init (&notify_barrier, NULL, 2) == 0,
0))
{
/* Create the helper thread. */
pthread_attr_t attr;
(void) pthread_attr_init (&attr);
(void) pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
/* We do not need much stack space, the bare minimum will be enough. */
(void) pthread_attr_setstacksize (&attr, __pthread_get_minstack (&attr));
/* Temporarily block all signals so that the newly created
thread inherits the mask. */
sigset_t oss;
int have_no_oss = change_sigmask (SIG_BLOCK, &oss);
pthread_t th;
err = pthread_create (&th, &attr, helper_thread, NULL);
/* Reset the signal mask. */
if (!have_no_oss)
pthread_sigmask (SIG_SETMASK, &oss, NULL);
(void) pthread_attr_destroy (&attr);
if (err == 0)
{
static int added_atfork;
if (added_atfork == 0
&& pthread_atfork (NULL, NULL, reset_once) != 0)
{
/* The child thread will call recv() which is a
cancellation point. */
(void) pthread_cancel (th);
err = 1;
}
else
added_atfork = 1;
}
}
if (err != 0)
{
close_not_cancel_no_status (netlink_socket);
netlink_socket = -1;
}
}
/* Register notification upon message arrival to an empty message queue
MQDES. */
int
mq_notify (mqd_t mqdes, const struct sigevent *notification)
{
/* Make sure the type is correctly defined. */
assert (sizeof (union notify_data) == NOTIFY_COOKIE_LEN);
/* Special treatment needed for SIGEV_THREAD. */
if (notification == NULL || notification->sigev_notify != SIGEV_THREAD)
return INLINE_SYSCALL (mq_notify, 2, mqdes, notification);
/* The kernel cannot directly start threads. This will have to be
done at userlevel. Since we cannot start threads from signal
handlers we have to create a dedicated thread which waits for
notifications for arriving messages and creates threads in
response. */
/* Initialize only once. */
pthread_once (&once, init_mq_netlink);
/* If we cannot create the netlink socket we cannot provide
SIGEV_THREAD support. */
if (__glibc_unlikely (netlink_socket == -1))
{
__set_errno (ENOSYS);
return -1;
}
/* Create the cookie. It will hold almost all the state. */
union notify_data data;
memset (&data, '\0', sizeof (data));
data.fct = notification->sigev_notify_function;
data.param = notification->sigev_value;
if (notification->sigev_notify_attributes != NULL)
{
/* The thread attribute has to be allocated separately. */
data.attr = (pthread_attr_t *) malloc (sizeof (pthread_attr_t));
if (data.attr == NULL)
return -1;
memcpy (data.attr, notification->sigev_notify_attributes,
sizeof (pthread_attr_t));
}
/* Construct the new request. */
struct sigevent se;
se.sigev_notify = SIGEV_THREAD;
se.sigev_signo = netlink_socket;
se.sigev_value.sival_ptr = &data;
/* Tell the kernel. */
int retval = INLINE_SYSCALL (mq_notify, 2, mqdes, &se);
/* If it failed, free the allocated memory. */
if (__glibc_unlikely (retval != 0))
free (data.attr);
return retval;
}
#else
# include <rt/mq_notify.c>
#endif

View File

@ -1,131 +0,0 @@
/* Copyright (C) 2003-2014 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
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
<http://www.gnu.org/licenses/>. */
#include "pthreadP.h"
#include <lowlevellock.h>
#include <atomic.h>
unsigned long int __fork_generation attribute_hidden;
static void
clear_once_control (void *arg)
{
pthread_once_t *once_control = (pthread_once_t *) arg;
/* Reset to the uninitialized state here. We don't need a stronger memory
order because we do not need to make any other of our writes visible to
other threads that see this value: This function will be called if we
get interrupted (see __pthread_once), so all we need to relay to other
threads is the state being reset again. */
*once_control = 0;
lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
}
/* This is similar to a lock implementation, but we distinguish between three
states: not yet initialized (0), initialization finished (2), and
initialization in progress (__fork_generation | 1). If in the first state,
threads will try to run the initialization by moving to the second state;
the first thread to do so via a CAS on once_control runs init_routine,
other threads block.
When forking the process, some threads can be interrupted during the second
state; they won't be present in the forked child, so we need to restart
initialization in the child. To distinguish an in-progress initialization
from an interrupted initialization (in which case we need to reclaim the
lock), we look at the fork generation that's part of the second state: We
can reclaim iff it differs from the current fork generation.
XXX: This algorithm has an ABA issue on the fork generation: If an
initialization is interrupted, we then fork 2^30 times (30 bits of
once_control are used for the fork generation), and try to initialize
again, we can deadlock because we can't distinguish the in-progress and
interrupted cases anymore. */
int
__pthread_once (once_control, init_routine)
pthread_once_t *once_control;
void (*init_routine) (void);
{
while (1)
{
int oldval, val, newval;
/* We need acquire memory order for this load because if the value
signals that initialization has finished, we need to be see any
data modifications done during initialization. */
val = *once_control;
atomic_read_barrier();
do
{
/* Check if the initialization has already been done. */
if (__glibc_likely ((val & 2) != 0))
return 0;
oldval = val;
/* We try to set the state to in-progress and having the current
fork generation. We don't need atomic accesses for the fork
generation because it's immutable in a particular process, and
forked child processes start with a single thread that modified
the generation. */
newval = __fork_generation | 1;
/* We need acquire memory order here for the same reason as for the
load from once_control above. */
val = atomic_compare_and_exchange_val_acq (once_control, newval,
oldval);
}
while (__glibc_unlikely (val != oldval));
/* Check if another thread already runs the initializer. */
if ((oldval & 1) != 0)
{
/* Check whether the initializer execution was interrupted by a
fork. We know that for both values, bit 0 is set and bit 1 is
not. */
if (oldval == newval)
{
/* Same generation, some other thread was faster. Wait. */
lll_futex_wait (once_control, newval, LLL_PRIVATE);
continue;
}
}
/* This thread is the first here. Do the initialization.
Register a cleanup handler so that in case the thread gets
interrupted the initialization can be restarted. */
pthread_cleanup_push (clear_once_control, once_control);
init_routine ();
pthread_cleanup_pop (0);
/* Mark *once_control as having finished the initialization. We need
release memory order here because we need to synchronize with other
threads that want to use the initialized data. */
atomic_write_barrier();
*once_control = 2;
/* Wake up all other threads. */
lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
break;
}
return 0;
}
weak_alias (__pthread_once, pthread_once)
hidden_def (__pthread_once)

View File

@ -1,2 +0,0 @@
#include <nptl/pthreadP.h>
#include "../../../../../sysdeps/unix/sysv/linux/sigtimedwait.c"

View File

@ -1,2 +0,0 @@
#include <nptl/pthreadP.h>
#include "../../../../../sysdeps/unix/sysv/linux/sigwait.c"

View File

@ -1,2 +0,0 @@
#include <nptl/pthreadP.h>
#include "../../../../../sysdeps/unix/sysv/linux/sigwaitinfo.c"

View File

@ -1,10 +0,0 @@
/* We want an #include_next, but we are the main source file.
So, #include ourselves and in that incarnation we can use #include_next. */
#ifndef INCLUDED_SELF
# define INCLUDED_SELF
# include <sleep.c>
#else
/* This defines the CANCELLATION_P macro, which sleep.c checks for. */
# include <pthreadP.h>
# include_next <sleep.c>
#endif

View File

@ -1 +1 @@
#include <sysdeps/unix/sysv/linux/sem_trywait.c> #include <nptl/sem_trywait.c>

View File

@ -144,6 +144,10 @@ sysdep_headers += bits/initspin.h
sysdep_routines += sched_getcpu sysdep_routines += sched_getcpu
tests += tst-getcpu tests += tst-getcpu
CFLAGS-fork.c = $(libio-mtsafe)
CFLAGS-getpid.o = -fomit-frame-pointer
CFLAGS-getpid.os = -fomit-frame-pointer
endif endif
ifeq ($(subdir),inet) ifeq ($(subdir),inet)
@ -190,3 +194,7 @@ ifeq ($(subdir),nscd)
sysdep-CFLAGS += -DHAVE_EPOLL -DHAVE_SENDFILE -DHAVE_INOTIFY -DHAVE_NETLINK sysdep-CFLAGS += -DHAVE_EPOLL -DHAVE_SENDFILE -DHAVE_INOTIFY -DHAVE_NETLINK
CFLAGS-gai.c += -DNEED_NETLINK CFLAGS-gai.c += -DNEED_NETLINK
endif endif
ifeq ($(subdir),nptl)
tests += tst-setgetname
endif

View File

@ -67,12 +67,4 @@ __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
} }
libc_hidden_def (__libc_sigaction) libc_hidden_def (__libc_sigaction)
#ifdef WRAPPER_INCLUDE #include <nptl/sigaction.c>
# include WRAPPER_INCLUDE
#endif
#ifndef LIBC_SIGACTION
weak_alias (__libc_sigaction, __sigaction)
libc_hidden_weak (__sigaction)
weak_alias (__libc_sigaction, sigaction)
#endif

View File

@ -2,4 +2,4 @@
the acquire/release semantics of atomic_exchange_and_add. And even if the acquire/release semantics of atomic_exchange_and_add. And even if
we don't do this, we should be using atomic_full_barrier or otherwise. */ we don't do this, we should be using atomic_full_barrier or otherwise. */
#define __lll_rel_instr "mb" #define __lll_rel_instr "mb"
#include <nptl/sysdeps/unix/sysv/linux/sem_post.c> #include <nptl/sem_post.c>

View File

@ -84,12 +84,4 @@ __libc_sigaction (sig, act, oact)
} }
libc_hidden_def (__libc_sigaction) libc_hidden_def (__libc_sigaction)
#ifdef WRAPPER_INCLUDE #include <nptl/sigaction.c>
# include WRAPPER_INCLUDE
#endif
#ifndef LIBC_SIGACTION
weak_alias (__libc_sigaction, __sigaction)
libc_hidden_weak (__sigaction)
weak_alias (__libc_sigaction, sigaction)
#endif

View File

@ -84,15 +84,7 @@ __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
} }
libc_hidden_def (__libc_sigaction) libc_hidden_def (__libc_sigaction)
#ifdef WRAPPER_INCLUDE #include <nptl/sigaction.c>
# include WRAPPER_INCLUDE
#endif
#ifndef LIBC_SIGACTION
weak_alias (__libc_sigaction, __sigaction)
libc_hidden_weak (__sigaction)
weak_alias (__libc_sigaction, sigaction)
#endif
/* NOTE: Please think twice before making any changes to the bits of /* NOTE: Please think twice before making any changes to the bits of
code below. GDB needs some intimate knowledge about it to code below. GDB needs some intimate knowledge about it to

View File

@ -1,40 +0,0 @@
/* Copyright (C) 2000-2014 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
<http://www.gnu.org/licenses/>. */
#include <sysdep.h>
#define _SIGNAL_H
#include <bits/signum.h>
/* pid_t fork(void); */
/* Implemented as a clone system call with parameters SIGCHLD and 0 */
ENTRY(__libc_fork)
alloc r2=ar.pfs,0,0,2,0
mov out0=SIGCHLD /* Return SIGCHLD when child finishes */
/* no other clone flags; nothing shared */
mov out1=0 /* Standard sp value. */
;;
DO_CALL (SYS_ify (clone))
cmp.eq p6,p0=-1,r10
(p6) br.cond.spnt.few __syscall_error
ret
PSEUDO_END(__libc_fork)
weak_alias (__libc_fork, __fork)
libc_hidden_def (__fork)
weak_alias (__libc_fork, fork)

View File

@ -45,12 +45,4 @@ __libc_sigaction (sig, act, oact)
} }
libc_hidden_def (__libc_sigaction) libc_hidden_def (__libc_sigaction)
#ifdef WRAPPER_INCLUDE #include <nptl/sigaction.c>
# include WRAPPER_INCLUDE
#endif
#ifndef LIBC_SIGACTION
weak_alias (__libc_sigaction, __sigaction)
libc_hidden_def (__sigaction)
weak_alias (__libc_sigaction, sigaction)
#endif

View File

@ -87,15 +87,8 @@ __libc_sigaction (sig, act, oact)
} }
libc_hidden_def (__libc_sigaction) libc_hidden_def (__libc_sigaction)
#ifdef WRAPPER_INCLUDE #include <nptl/sigaction.c>
# include WRAPPER_INCLUDE
#endif
#ifndef LIBC_SIGACTION
weak_alias (__libc_sigaction, __sigaction)
libc_hidden_weak (__sigaction)
weak_alias (__libc_sigaction, sigaction)
#endif
/* NOTE: Please think twice before making any changes to the bits of /* NOTE: Please think twice before making any changes to the bits of
code below. GDB needs some intimate knowledge about it to code below. GDB needs some intimate knowledge about it to

View File

@ -1,5 +1,6 @@
/* Copyright (C) 2004-2014 Free Software Foundation, Inc. /* Copyright (C) 2004-2014 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contribute by Ulrich Drepper <drepper@redhat.com>, 2004.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
@ -15,27 +16,265 @@
License along with the GNU C Library; if not, see License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
#include <assert.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <mqueue.h> #include <mqueue.h>
#include <stddef.h> #include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sysdep.h> #include <sysdep.h>
#include <unistd.h>
#include <sys/socket.h>
#include <not-cancel.h>
#include <nptl/pthreadP.h>
#ifdef __NR_mq_notify #ifdef __NR_mq_notify
/* Defined in the kernel headers: */
#define NOTIFY_COOKIE_LEN 32 /* Length of the cookie used. */
#define NOTIFY_WOKENUP 1 /* Code for notifcation. */
#define NOTIFY_REMOVED 2 /* Code for closed message queue
of de-notifcation. */
/* Data structure for the queued notification requests. */
union notify_data
{
struct
{
void (*fct) (union sigval); /* The function to run. */
union sigval param; /* The parameter to pass. */
pthread_attr_t *attr; /* Attributes to create the thread with. */
/* NB: on 64-bit machines the struct as a size of 24 bytes. Which means
byte 31 can still be used for returning the status. */
};
char raw[NOTIFY_COOKIE_LEN];
};
/* Keep track of the initialization. */
static pthread_once_t once = PTHREAD_ONCE_INIT;
/* The netlink socket. */
static int netlink_socket = -1;
/* Barrier used to make sure data passed to the new thread is not
resused by the parent. */
static pthread_barrier_t notify_barrier;
/* Modify the signal mask. We move this into a separate function so
that the stack space needed for sigset_t is not deducted from what
the thread can use. */
static int
__attribute__ ((noinline))
change_sigmask (int how, sigset_t *oss)
{
sigset_t ss;
sigfillset (&ss);
return pthread_sigmask (how, &ss, oss);
}
/* The function used for the notification. */
static void *
notification_function (void *arg)
{
/* Copy the function and parameter so that the parent thread can go
on with its life. */
volatile union notify_data *data = (volatile union notify_data *) arg;
void (*fct) (union sigval) = data->fct;
union sigval param = data->param;
/* Let the parent go. */
(void) pthread_barrier_wait (&notify_barrier);
/* Make the thread detached. */
(void) pthread_detach (pthread_self ());
/* The parent thread has all signals blocked. This is probably a
bit surprising for this thread. So we unblock all of them. */
(void) change_sigmask (SIG_UNBLOCK, NULL);
/* Now run the user code. */
fct (param);
/* And we are done. */
return NULL;
}
/* Helper thread. */
static void *
helper_thread (void *arg)
{
while (1)
{
union notify_data data;
ssize_t n = recv (netlink_socket, &data, sizeof (data),
MSG_NOSIGNAL | MSG_WAITALL);
if (n < NOTIFY_COOKIE_LEN)
continue;
if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_WOKENUP)
{
/* Just create the thread as instructed. There is no way to
report a problem with creating a thread. */
pthread_t th;
if (__builtin_expect (pthread_create (&th, data.attr,
notification_function, &data)
== 0, 0))
/* Since we passed a pointer to DATA to the new thread we have
to wait until it is done with it. */
(void) pthread_barrier_wait (&notify_barrier);
}
else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED)
/* The only state we keep is the copy of the thread attributes. */
free (data.attr);
}
return NULL;
}
static void
reset_once (void)
{
once = PTHREAD_ONCE_INIT;
}
static void
init_mq_netlink (void)
{
/* This code might be called a second time after fork(). The file
descriptor is inherited from the parent. */
if (netlink_socket == -1)
{
/* Just a normal netlink socket, not bound. */
netlink_socket = socket (AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, 0);
/* No need to do more if we have no socket. */
if (netlink_socket == -1)
return;
}
int err = 1;
/* Initialize the barrier. */
if (__builtin_expect (pthread_barrier_init (&notify_barrier, NULL, 2) == 0,
0))
{
/* Create the helper thread. */
pthread_attr_t attr;
(void) pthread_attr_init (&attr);
(void) pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
/* We do not need much stack space, the bare minimum will be enough. */
(void) pthread_attr_setstacksize (&attr, __pthread_get_minstack (&attr));
/* Temporarily block all signals so that the newly created
thread inherits the mask. */
sigset_t oss;
int have_no_oss = change_sigmask (SIG_BLOCK, &oss);
pthread_t th;
err = pthread_create (&th, &attr, helper_thread, NULL);
/* Reset the signal mask. */
if (!have_no_oss)
pthread_sigmask (SIG_SETMASK, &oss, NULL);
(void) pthread_attr_destroy (&attr);
if (err == 0)
{
static int added_atfork;
if (added_atfork == 0
&& pthread_atfork (NULL, NULL, reset_once) != 0)
{
/* The child thread will call recv() which is a
cancellation point. */
(void) pthread_cancel (th);
err = 1;
}
else
added_atfork = 1;
}
}
if (err != 0)
{
close_not_cancel_no_status (netlink_socket);
netlink_socket = -1;
}
}
/* Register notification upon message arrival to an empty message queue /* Register notification upon message arrival to an empty message queue
MQDES. */ MQDES. */
int int
mq_notify (mqd_t mqdes, const struct sigevent *notification) mq_notify (mqd_t mqdes, const struct sigevent *notification)
{ {
/* mq_notify which handles SIGEV_THREAD is included in the thread /* Make sure the type is correctly defined. */
add-on. */ assert (sizeof (union notify_data) == NOTIFY_COOKIE_LEN);
if (notification != NULL
&& notification->sigev_notify == SIGEV_THREAD) /* Special treatment needed for SIGEV_THREAD. */
if (notification == NULL || notification->sigev_notify != SIGEV_THREAD)
return INLINE_SYSCALL (mq_notify, 2, mqdes, notification);
/* The kernel cannot directly start threads. This will have to be
done at userlevel. Since we cannot start threads from signal
handlers we have to create a dedicated thread which waits for
notifications for arriving messages and creates threads in
response. */
/* Initialize only once. */
pthread_once (&once, init_mq_netlink);
/* If we cannot create the netlink socket we cannot provide
SIGEV_THREAD support. */
if (__glibc_unlikely (netlink_socket == -1))
{ {
__set_errno (ENOSYS); __set_errno (ENOSYS);
return -1; return -1;
} }
return INLINE_SYSCALL (mq_notify, 2, mqdes, notification);
/* Create the cookie. It will hold almost all the state. */
union notify_data data;
memset (&data, '\0', sizeof (data));
data.fct = notification->sigev_notify_function;
data.param = notification->sigev_value;
if (notification->sigev_notify_attributes != NULL)
{
/* The thread attribute has to be allocated separately. */
data.attr = (pthread_attr_t *) malloc (sizeof (pthread_attr_t));
if (data.attr == NULL)
return -1;
memcpy (data.attr, notification->sigev_notify_attributes,
sizeof (pthread_attr_t));
}
/* Construct the new request. */
struct sigevent se;
se.sigev_notify = SIGEV_THREAD;
se.sigev_signo = netlink_socket;
se.sigev_value.sival_ptr = &data;
/* Tell the kernel. */
int retval = INLINE_SYSCALL (mq_notify, 2, mqdes, &se);
/* If it failed, free the allocated memory. */
if (__glibc_unlikely (retval != 0))
free (data.attr);
return retval;
} }
#else #else

View File

@ -18,7 +18,7 @@
#include <setjmp.h> #include <setjmp.h>
#include <stddef.h> #include <stddef.h>
#include <pthreadP.h> #include <nptl/pthreadP.h>
extern void __pthread_cleanup_upto (__jmp_buf env, char *targetframe); extern void __pthread_cleanup_upto (__jmp_buf env, char *targetframe);
#pragma weak __pthread_cleanup_upto #pragma weak __pthread_cleanup_upto

View File

@ -19,4 +19,4 @@
already elided locks. */ already elided locks. */
#include <elision-conf.h> #include <elision-conf.h>
#include <nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c> #include <nptl/pthread_mutex_cond_lock.c>

View File

@ -43,12 +43,4 @@ __libc_sigaction (sig, act, oact)
} }
libc_hidden_def (__libc_sigaction) libc_hidden_def (__libc_sigaction)
#ifdef WRAPPER_INCLUDE #include <nptl/sigaction.c>
# include WRAPPER_INCLUDE
#endif
#ifndef LIBC_SIGACTION
weak_alias (__libc_sigaction, __sigaction)
libc_hidden_weak (__sigaction)
weak_alias (__libc_sigaction, sigaction)
#endif

View File

@ -69,12 +69,4 @@ __libc_sigaction (sig, act, oact)
} }
libc_hidden_def (__libc_sigaction) libc_hidden_def (__libc_sigaction)
#ifdef WRAPPER_INCLUDE #include <nptl/sigaction.c>
# include WRAPPER_INCLUDE
#endif
#ifndef LIBC_SIGACTION
weak_alias (__libc_sigaction, __sigaction)
libc_hidden_weak (__sigaction)
weak_alias (__libc_sigaction, sigaction)
#endif

View File

@ -19,6 +19,7 @@
#include <signal.h> #include <signal.h>
#include <string.h> #include <string.h>
#include <nptl/pthreadP.h>
#include <sysdep-cancel.h> #include <sysdep-cancel.h>
#include <sys/syscall.h> #include <sys/syscall.h>

View File

@ -21,6 +21,7 @@
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
#include <nptl/pthreadP.h>
#include <sysdep-cancel.h> #include <sysdep-cancel.h>
#include <sys/syscall.h> #include <sys/syscall.h>

View File

@ -21,6 +21,7 @@
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
#include <nptl/pthreadP.h>
#include <sysdep-cancel.h> #include <sysdep-cancel.h>
#include <sys/syscall.h> #include <sys/syscall.h>

View File

@ -23,6 +23,7 @@
#include <string.h> /* For the real memset prototype. */ #include <string.h> /* For the real memset prototype. */
#include <unistd.h> #include <unistd.h>
#include <sys/param.h> #include <sys/param.h>
#include <nptl/pthreadP.h>
#if 0 #if 0

View File

@ -62,15 +62,8 @@ __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
} }
libc_hidden_def (__libc_sigaction) libc_hidden_def (__libc_sigaction)
#ifdef WRAPPER_INCLUDE #include <nptl/sigaction.c>
# include WRAPPER_INCLUDE
#endif
#ifndef LIBC_SIGACTION
weak_alias (__libc_sigaction, __sigaction);
libc_hidden_weak (__sigaction)
weak_alias (__libc_sigaction, sigaction);
#endif
static void static void
__rt_sigreturn_stub (void) __rt_sigreturn_stub (void)

View File

@ -63,15 +63,8 @@ __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
} }
libc_hidden_def (__libc_sigaction) libc_hidden_def (__libc_sigaction)
#ifdef WRAPPER_INCLUDE #include <nptl/sigaction.c>
# include WRAPPER_INCLUDE
#endif
#ifndef LIBC_SIGACTION
weak_alias (__libc_sigaction, __sigaction);
libc_hidden_weak (__sigaction)
weak_alias (__libc_sigaction, sigaction);
#endif
static void static void
__rt_sigreturn_stub (void) __rt_sigreturn_stub (void)

View File

@ -15,7 +15,6 @@ epoll_ctl EXTRA epoll_ctl i:iiip epoll_ctl
epoll_wait EXTRA epoll_wait Ci:ipii epoll_wait epoll_wait EXTRA epoll_wait Ci:ipii epoll_wait
fdatasync - fdatasync Ci:i fdatasync fdatasync - fdatasync Ci:i fdatasync
flock - flock i:ii __flock flock flock - flock i:ii __flock flock
fork - fork i: __libc_fork __fork fork
get_kernel_syms EXTRA get_kernel_syms i:p get_kernel_syms get_kernel_syms EXTRA get_kernel_syms i:p get_kernel_syms
getegid - getegid Ei: __getegid getegid getegid - getegid Ei: __getegid getegid
geteuid - geteuid Ei: __geteuid geteuid geteuid - geteuid Ei: __geteuid geteuid

View File

@ -19,4 +19,4 @@
already elided locks. */ already elided locks. */
#include <elision-conf.h> #include <elision-conf.h>
#include "sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c" #include <nptl/pthread_mutex_cond_lock.c>

View File

@ -73,15 +73,8 @@ __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
} }
libc_hidden_def (__libc_sigaction) libc_hidden_def (__libc_sigaction)
#ifdef WRAPPER_INCLUDE #include <nptl/sigaction.c>
# include WRAPPER_INCLUDE
#endif
#ifndef LIBC_SIGACTION
weak_alias (__libc_sigaction, __sigaction)
libc_hidden_weak (__sigaction)
weak_alias (__libc_sigaction, sigaction)
#endif
/* NOTE: Please think twice before making any changes to the bits of /* NOTE: Please think twice before making any changes to the bits of
code below. GDB needs some intimate knowledge about it to code below. GDB needs some intimate knowledge about it to