+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
-/* 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.
#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
/* 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
}
#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)
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;
-/* 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.
/* 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 \
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;
/* 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;
-/* 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.
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);
}