summaryrefslogtreecommitdiff
path: root/pthread/pt-create.c
diff options
context:
space:
mode:
Diffstat (limited to 'pthread/pt-create.c')
-rw-r--r--pthread/pt-create.c69
1 files changed, 32 insertions, 37 deletions
diff --git a/pthread/pt-create.c b/pthread/pt-create.c
index fd6800f..99d1b47 100644
--- a/pthread/pt-create.c
+++ b/pthread/pt-create.c
@@ -103,47 +103,30 @@ __pthread_create_internal (struct __pthread **thread,
pthread->state = (setup->detachstate == PTHREAD_CREATE_DETACHED
? PTHREAD_DETACHED : PTHREAD_JOINABLE);
- /* If the user supplied a stack, it is not our responsibility to
- setup a stack guard. */
if (setup->stackaddr)
- pthread->guardsize = 0;
- else
- pthread->guardsize = (setup->guardsize <= setup->stacksize
- ? setup->guardsize : setup->stacksize);
-
- /* Find a stack. There are several scenarios: if a detached thread
- kills itself, it has no way to deallocate its stack, thus it
- leaves PTHREAD->stack set to true. We try to reuse it here,
- however, if the user supplied a stack or changes the size,
- we cannot use the old one. Right now, we simply deallocate it. */
- if (pthread->stack)
{
- if ((setup->stackaddr && setup->stackaddr != pthread->stackaddr)
- || (setup->stacksize != pthread->stacksize))
- {
- __pthread_stack_dealloc (pthread->stackaddr,
- pthread->stacksize);
- pthread->stackaddr = setup->stackaddr;
- pthread->stacksize = setup->stacksize;
- }
+ pthread->stackaddr = setup->stackaddr;
+
+ /* If the user supplied a stack, it is not our responsibility to
+ setup a stack guard. */
+ pthread->guardsize = 0;
+ pthread->stack = 0;
}
else
{
- pthread->stacksize = setup->stacksize;
-
- if (setup->stackaddr)
- pthread->stackaddr = setup->stackaddr;
- else
- {
- err = __pthread_stack_alloc (&pthread->stackaddr,
- setup->stacksize);
- if (err)
- goto failed_stack_alloc;
-
- pthread->stack = 1;
- }
+ /* Allocate a stack. */
+ err = __pthread_stack_alloc (&pthread->stackaddr,
+ setup->stacksize);
+ if (err)
+ goto failed_stack_alloc;
+
+ pthread->guardsize = (setup->guardsize <= setup->stacksize
+ ? setup->guardsize : setup->stacksize);
+ pthread->stack = 1;
}
+ pthread->stacksize = setup->stacksize;
+
/* Allocate the kernel thread and other required resources. */
err = __pthread_thread_alloc (pthread);
if (err)
@@ -169,6 +152,10 @@ __pthread_create_internal (struct __pthread **thread,
if (err)
goto failed_sigstate;
+ /* If the new thread is joinable, add a reference for the caller. */
+ if (pthread->state == PTHREAD_JOINABLE)
+ pthread->nr_refs++;
+
/* Set the new thread's signal mask and set the pending signals to
empty. POSIX says: "The signal mask shall be inherited from the
creating thread. The set of signals pending for the new thread
@@ -216,6 +203,10 @@ __pthread_create_internal (struct __pthread **thread,
return 0;
failed_starting:
+ /* If joinable, a reference was added for the caller. */
+ if (pthread->state == PTHREAD_JOINABLE)
+ __pthread_dealloc (pthread);
+
__pthread_setid (pthread->thread, NULL);
__atomic_dec (&__pthread_total);
failed_sigstate:
@@ -227,10 +218,14 @@ __pthread_create_internal (struct __pthread **thread,
failed_thread_tls_alloc:
#endif /* ENABLE_TLS */
__pthread_thread_dealloc (pthread);
- __pthread_thread_halt (pthread);
+ __pthread_thread_terminate (pthread);
+
+ /* __pthread_thread_terminate has taken care of deallocating the stack and
+ the thread structure. */
+ goto failed;
failed_thread_alloc:
- __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize);
- pthread->stack = 0;
+ if (pthread->stack)
+ __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize);
failed_stack_alloc:
__pthread_dealloc (pthread);
failed: