-/* Copyright (C) 2002-2007, 2009, 2010 Free Software Foundation, Inc.
+/* 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.
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, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include <assert.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/param.h>
#include <dl-sysdep.h>
+#include <dl-tls.h>
#include <tls.h>
+#include <list.h>
#include <lowlevellock.h>
#include <kernel-features.h>
return NULL;
}
+ /* Don't allow setxid until cloned. */
+ result->setxid_futex = -1;
+
/* Dequeue the entry. */
stack_list_del (&result->list);
/* Clear the DTV. */
dtv_t *dtv = GET_DTV (TLS_TPADJ (result));
- memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t));
+ _dl_clear_dtv (dtv);
/* Re-initialize the TLS. */
_dl_allocate_tls_init (TLS_TPADJ (result));
}
+/* Returns a usable stack for a new thread either by allocating a
+ new stack or reusing a cached stack of sufficient size.
+ ATTR must be non-NULL and point to a valid pthread_attr.
+ PDP must be non-NULL. */
static int
allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
ALLOCATE_STACK_PARMS)
size_t pagesize_m1 = __getpagesize () - 1;
void *stacktop;
- assert (attr != NULL);
assert (powerof2 (pagesize_m1 + 1));
assert (TCB_ALIGNMENT >= STACK_ALIGN);
/* Get the stack size from the attribute if it is set. Otherwise we
use the default we determined at start time. */
- size = attr->stacksize ?: __default_stacksize;
+ if (attr->stacksize != 0)
+ size = attr->stacksize;
+ else
+ {
+ lll_lock (__default_pthread_attr_lock, LLL_PRIVATE);
+ size = __default_pthread_attr.stacksize;
+ lll_unlock (__default_pthread_attr_lock, LLL_PRIVATE);
+ }
/* Get memory for the stack. */
if (__builtin_expect (attr->flags & ATTR_FLAG_STACKADDR, 0))
/* The process ID is also the same as that of the caller. */
pd->pid = THREAD_GETMEM (THREAD_SELF, pid);
+ /* Don't allow setxid until cloned. */
+ pd->setxid_futex = -1;
+
/* Allocate the DTV for this thread. */
if (_dl_allocate_tls (TLS_TPADJ (pd)) == NULL)
{
/* Something went wrong. */
assert (errno == ENOMEM);
- return EAGAIN;
+ return errno;
}
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
if (__builtin_expect (mem == MAP_FAILED, 0))
- {
- if (errno == ENOMEM)
- __set_errno (EAGAIN);
-
- return errno;
- }
+ return errno;
/* SIZE is guaranteed to be greater than zero.
So we can never get a null pointer back from mmap. */
THREAD_SYSINFO(pd) = THREAD_SELF_SYSINFO;
#endif
+ /* Don't allow setxid until cloned. */
+ pd->setxid_futex = -1;
+
/* The process ID is also the same as that of the caller. */
pd->pid = THREAD_GETMEM (THREAD_SELF, pid);
/* Free the stack memory we just allocated. */
(void) munmap (mem, size);
- return EAGAIN;
+ return errno;
}
#endif
if (mprotect (guard, guardsize, PROT_NONE) != 0)
{
- int err;
mprot_error:
- err = errno;
-
lll_lock (stack_cache_lock, LLL_PRIVATE);
/* Remove the thread from the list. */
is nothing we could do. */
(void) munmap (mem, size);
- return err;
+ return errno;
}
pd->guardsize = guardsize;
if (in_flight_stack != 0)
{
bool add_p = in_flight_stack & 1;
- list_t *elem = (list_t *) (in_flight_stack & ~UINTMAX_C (1));
+ list_t *elem = (list_t *) (in_flight_stack & ~(uintptr_t) 1);
if (add_p)
{
in_flight_stack = 0;
- /* Initialize the lock. */
+ /* Initialize locks. */
stack_cache_lock = LLL_LOCK_INITIALIZER;
+ __default_pthread_attr_lock = LLL_LOCK_INITIALIZER;
}
/* If the thread is exiting right now, ignore it. */
if ((ch & EXITING_BITMASK) != 0)
- return;
+ {
+ /* Release the futex if there is no other setxid in
+ progress. */
+ if ((ch & SETXID_BITMASK) == 0)
+ {
+ t->setxid_futex = 1;
+ lll_futex_wake (&t->setxid_futex, 1, LLL_PRIVATE);
+ }
+ return;
+ }
}
while (atomic_compare_and_exchange_bool_acq (&t->cancelhandling,
ch | SETXID_BITMASK, ch));
int val;
INTERNAL_SYSCALL_DECL (err);
-#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 this failed, it must have had not started yet or else exited. */
if (!INTERNAL_SYSCALL_ERROR_P (val, err))