2005-10-01 Ulrich Drepper <drepper@redhat.com>

Jakub Jelinek  <jakub@redhat.com>

	* descr.h: Define SETXID_BIT and SETXID_BITMASK.  Adjust
	CANCEL_RESTMASK.
	(struct pthread): Move specific_used field to avoid padding.
	Add setxid_futex field.
	* init.c (sighandler_setxid): Reset setxid flag and release the
	setxid futex.
	* allocatestack.c (setxid_signal_thread): New function.  Broken
	out of the bodies of the two loops in __nptl_setxid.  For undetached
	threads check whether they are exiting and if yes, don't send a signal.
	(__nptl_setxid): Simplify loops by using setxid_signal_thread.
	* pthread_create.c (start_thread): For undetached threads, check
	whether setxid bit is set.  If yes, wait until signal has been
	processed.

	* allocatestack.c (STACK_VARIABLES): Initialize them.
	* pthread_create.c (__pthread_create_2_1): Initialize pd.
This commit is contained in:
Ulrich Drepper 2005-10-01 17:20:34 +00:00
parent 2ff89ea46f
commit dff9a7a163
5 changed files with 102 additions and 50 deletions

View File

@ -1,3 +1,23 @@
2005-10-01 Ulrich Drepper <drepper@redhat.com>
Jakub Jelinek <jakub@redhat.com>
* descr.h: Define SETXID_BIT and SETXID_BITMASK. Adjust
CANCEL_RESTMASK.
(struct pthread): Move specific_used field to avoid padding.
Add setxid_futex field.
* init.c (sighandler_setxid): Reset setxid flag and release the
setxid futex.
* allocatestack.c (setxid_signal_thread): New function. Broken
out of the bodies of the two loops in __nptl_setxid. For undetached
threads check whether they are exiting and if yes, don't send a signal.
(__nptl_setxid): Simplify loops by using setxid_signal_thread.
* pthread_create.c (start_thread): For undetached threads, check
whether setxid bit is set. If yes, wait until signal has been
processed.
* allocatestack.c (STACK_VARIABLES): Initialize them.
* pthread_create.c (__pthread_create_2_1): Initialize pd.
2004-09-02 Jakub Jelinek <jakub@redhat.com>
* pthread_cond_destroy.c (__pthread_cond_destroy): If there are

View File

@ -1,4 +1,5 @@
/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
/* Copyright (C) 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@ -33,7 +34,7 @@
#ifndef NEED_SEPARATE_REGISTER_STACK
/* Most architectures have exactly one stack pointer. Some have more. */
# define STACK_VARIABLES void *stackaddr
# define STACK_VARIABLES void *stackaddr = NULL
/* How to pass the values to the 'create_thread' function. */
# define STACK_VARIABLES_ARGS stackaddr
@ -52,7 +53,7 @@
/* We need two stacks. The kernel will place them but we have to tell
the kernel about the size of the reserved address space. */
# define STACK_VARIABLES void *stackaddr; size_t stacksize
# define STACK_VARIABLES void *stackaddr = NULL; size_t stacksize = 0
/* How to pass the values to the 'create_thread' function. */
# define STACK_VARIABLES_ARGS stackaddr, stacksize
@ -817,6 +818,45 @@ __find_thread_by_id (pid_t tid)
}
#endif
static void
internal_function
setxid_signal_thread (struct xid_command *cmdp, struct pthread *t)
{
if (! IS_DETACHED (t))
{
int ch;
do
{
ch = t->cancelhandling;
/* If the thread is exiting right now, ignore it. */
if ((ch & EXITING_BITMASK) != 0)
return;
}
while (atomic_compare_and_exchange_val_acq (&t->cancelhandling,
ch | SETXID_BITMASK, ch));
}
int val;
#if __ASSUME_TGKILL
val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid),
t->tid, SIGSETXID);
#else
# ifdef __NR_tgkill
val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid),
t->tid, SIGSETXID);
if (INTERNAL_SYSCALL_ERROR_P (val, err)
&& INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS)
# endif
val = INTERNAL_SYSCALL (tkill, err, 2, t->tid, SIGSETXID);
#endif
if (!INTERNAL_SYSCALL_ERROR_P (val, err))
atomic_increment (&cmdp->cntr);
}
int
attribute_hidden
__nptl_setxid (struct xid_command *cmdp)
@ -836,54 +876,20 @@ __nptl_setxid (struct xid_command *cmdp)
list_for_each (runp, &stack_used)
{
struct pthread *t = list_entry (runp, struct pthread, list);
if (t != self)
{
int val;
#if __ASSUME_TGKILL
val = INTERNAL_SYSCALL (tgkill, err, 3,
THREAD_GETMEM (THREAD_SELF, pid),
t->tid, SIGSETXID);
#else
# ifdef __NR_tgkill
val = INTERNAL_SYSCALL (tgkill, err, 3,
THREAD_GETMEM (THREAD_SELF, pid),
t->tid, SIGSETXID);
if (INTERNAL_SYSCALL_ERROR_P (val, err)
&& INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS)
# endif
val = INTERNAL_SYSCALL (tkill, err, 2, t->tid, SIGSETXID);
#endif
if (t == self)
continue;
if (!INTERNAL_SYSCALL_ERROR_P (val, err))
atomic_increment (&cmdp->cntr);
}
setxid_signal_thread (cmdp, t);
}
/* Now the list with threads using user-allocated stacks. */
list_for_each (runp, &__stack_user)
{
struct pthread *t = list_entry (runp, struct pthread, list);
if (t != self)
{
int val;
#if __ASSUME_TGKILL
val = INTERNAL_SYSCALL (tgkill, err, 3,
THREAD_GETMEM (THREAD_SELF, pid),
t->tid, SIGSETXID);
#else
# ifdef __NR_tgkill
val = INTERNAL_SYSCALL (tgkill, err, 3,
THREAD_GETMEM (THREAD_SELF, pid),
t->tid, SIGSETXID);
if (INTERNAL_SYSCALL_ERROR_P (val, err)
&& INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS)
# endif
val = INTERNAL_SYSCALL (tkill, err, 2, t->tid, SIGSETXID);
#endif
if (t == self)
continue;
if (!INTERNAL_SYSCALL_ERROR_P (val, err))
atomic_increment (&cmdp->cntr);
}
setxid_signal_thread (cmdp, t);
}
int cur = cmdp->cntr;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@ -161,8 +161,11 @@ struct pthread
/* Bit set if thread terminated and TCB is freed. */
#define TERMINATED_BIT 5
#define TERMINATED_BITMASK 0x20
/* Bit set if thread is supposed to change XID. */
#define SETXID_BIT 6
#define SETXID_BITMASK 0x40
/* Mask for the rest. Helps the compiler to optimize. */
#define CANCEL_RESTMASK 0xffffffc0
#define CANCEL_RESTMASK 0xffffff80
#define CANCEL_ENABLED_AND_CANCELED(value) \
(((value) & (CANCELSTATE_BITMASK | CANCELED_BITMASK | EXITING_BITMASK \
@ -185,12 +188,12 @@ struct pthread
void *data;
} specific_1stblock[PTHREAD_KEY_2NDLEVEL_SIZE];
/* Flag which is set when specific data is set. */
bool specific_used;
/* Two-level array for the thread-specific data. */
struct pthread_key_data *specific[PTHREAD_KEY_1STLEVEL_SIZE];
/* Flag which is set when specific data is set. */
bool specific_used;
/* True if events must be reported. */
bool report_events;
@ -203,6 +206,9 @@ struct pthread
/* Lock to synchronize access to the descriptor. */
lll_lock_t lock;
/* Lock for synchronizing setxid calls. */
lll_lock_t setxid_futex;
#if HP_TIMING_AVAIL
/* Offset of the CPU clock at start thread start time. */
hp_timing_t cpuclock_offset;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@ -211,6 +211,15 @@ sighandler_setxid (int sig, siginfo_t *si, void *ctx)
if (atomic_decrement_val (&__xidcmd->cntr) == 0)
lll_futex_wake (&__xidcmd->cntr, 1);
/* Reset the SETXID flag. */
struct pthread *self = THREAD_SELF;
int flags = THREAD_GETMEM (self, cancelhandling);
THREAD_SETMEM (self, cancelhandling, flags & ~SETXID_BITMASK);
/* And release the futex. */
self->setxid_futex = 1;
lll_futex_wake (&self->setxid_futex, 1);
}

View File

@ -314,6 +314,17 @@ start_thread (void *arg)
if (IS_DETACHED (pd))
/* Free the TCB. */
__free_tcb (pd);
else if (__builtin_expect (pd->cancelhandling & SETXID_BITMASK, 0))
{
/* Some other thread might call any of the setXid functions and expect
us to reply. In this case wait until we did that. */
do
lll_futex_wait (&pd->setxid_futex, 0);
while (pd->cancelhandling & SETXID_BITMASK);
/* Reset the value so that the stack can be reused. */
pd->setxid_futex = 0;
}
/* We cannot call '_exit' here. '_exit' will terminate the process.
@ -354,7 +365,7 @@ __pthread_create_2_1 (newthread, attr, start_routine, arg)
accessing far-away memory. */
iattr = &default_attr;
struct pthread *pd;
struct pthread *pd = NULL;
int err = ALLOCATE_STACK (iattr, &pd);
if (__builtin_expect (err != 0, 0))
/* Something went wrong. Maybe a parameter of the attributes is