diff options
-rw-r--r-- | nptl/ChangeLog | 20 | ||||
-rw-r--r-- | nptl/allocatestack.c | 92 | ||||
-rw-r--r-- | nptl/descr.h | 16 | ||||
-rw-r--r-- | nptl/init.c | 11 | ||||
-rw-r--r-- | nptl/pthread_create.c | 13 |
5 files changed, 102 insertions, 50 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog index 8e48cfde66..555df8311d 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -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 diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c index fcb6c6e475..bb27c180e6 100644 --- a/nptl/allocatestack.c +++ b/nptl/allocatestack.c @@ -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; diff --git a/nptl/descr.h b/nptl/descr.h index 77251d5e45..aaef9bc621 100644 --- a/nptl/descr.h +++ b/nptl/descr.h @@ -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; diff --git a/nptl/init.c b/nptl/init.c index 86745af8d1..de704122d1 100644 --- a/nptl/init.c +++ b/nptl/init.c @@ -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); } diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c index 122778bddf..f2f206be5a 100644 --- a/nptl/pthread_create.c +++ b/nptl/pthread_create.c @@ -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 |