summaryrefslogtreecommitdiff
path: root/nptl
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2004-09-25 07:55:46 +0000
committerJakub Jelinek <jakub@redhat.com>2004-09-25 07:55:46 +0000
commitbd7c3bed543d02fb01f69b29ea1a736e7a0f618d (patch)
tree7e9bf02d1315ce177dd95075686ba769057d04b2 /nptl
parent338cc5101b59b64358bab982e1311604fdb64651 (diff)
Updated to fedora-glibc-20040925T0738
Diffstat (limited to 'nptl')
-rw-r--r--nptl/ChangeLog22
-rw-r--r--nptl/descr.h3
-rw-r--r--nptl/pthread_create.c25
-rw-r--r--nptl/sysdeps/pthread/createthread.c24
4 files changed, 63 insertions, 11 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index b06743dcb7..2aff8c8dbb 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,25 @@
+2004-09-25 Ulrich Drepper <drepper@redhat.com>
+
+ * descr.h (struct pthread): Add stopped_start field.
+ * sysdeps/pthread/createthread.c (create_thread): Set
+ start_stopped flag in descriptor for new thread appropriately.
+ * pthread_create.c (start_thread): Only take lock to be stopped on
+ startup if stopped_start flag says so.
+
+2004-09-24 Ulrich Drepper <drepper@redhat.com>
+
+ * pthread_create.c (__pthread_create_2_1): Remember whether thread
+ is created detached and if yes, do not try to free the stack in case
+ the thread creation failed.
+ * sysdeps/pthread/createthread.c (do_clone): Free stack here if clone
+ call fails. Don't depend on INTERNAL_SYSCALL_ERRNO return zero in
+ case there has been no error. [BZ #405]
+
+ * pthread_create.c (start_thread): Don't wait for scheduler data
+ etc to be set at the beginning of the function. The cancellation
+ infrastructure must have been set up. And enable async
+ cancellation before potentially going to sleep. [BZ #401]
+
2004-09-20 Ulrich Drepper <drepper@redhat.com>
* Versions: Remove exports for pthread_set*id_np functions.
diff --git a/nptl/descr.h b/nptl/descr.h
index 89bfbd25ad..7ef4221e83 100644
--- a/nptl/descr.h
+++ b/nptl/descr.h
@@ -201,6 +201,9 @@ struct pthread
/* True if the user provided the stack. */
bool user_stack;
+ /* True if thread must stop at startup time. */
+ bool stopped_start;
+
/* Lock to synchronize access to the descriptor. */
lll_lock_t lock;
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
index 160656863d..1bab72d1e9 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -227,11 +227,6 @@ start_thread (void *arg)
struct pthread *pd = (struct pthread *) arg;
- /* Get the lock the parent locked to force synchronization. */
- lll_lock (pd->lock);
- /* And give it up right away. */
- lll_unlock (pd->lock);
-
#if HP_TIMING_AVAIL
/* Remember the time when the thread was started. */
hp_timing_t now;
@@ -257,6 +252,18 @@ start_thread (void *arg)
/* Store the new cleanup handler info. */
THREAD_SETMEM (pd, cleanup_jmp_buf, &unwind_buf);
+ if (__builtin_expect (pd->stopped_start, 0))
+ {
+ int oldtype = CANCEL_ASYNC ();
+
+ /* Get the lock the parent locked to force synchronization. */
+ lll_lock (pd->lock);
+ /* And give it up right away. */
+ lll_unlock (pd->lock);
+
+ CANCEL_RESET (oldtype);
+ }
+
/* Run the code the user provided. */
#ifdef CALL_THREAD_FCT
THREAD_SETMEM (pd, result, CALL_THREAD_FCT (pd));
@@ -443,13 +450,19 @@ __pthread_create_2_1 (newthread, attr, start_routine, arg)
/* Pass the descriptor to the caller. */
*newthread = (pthread_t) pd;
+ /* Remember whether the thread is detached or not. In case of an
+ error we have to free the stacks of non-detached stillborn
+ threads. */
+ bool is_detached = IS_DETACHED (pd);
+
/* Start the thread. */
err = create_thread (pd, iattr, STACK_VARIABLES_ARGS);
if (err != 0)
{
errout:
/* Something went wrong. Free the resources. */
- __deallocate_stack (pd);
+ if (!is_detached)
+ __deallocate_stack (pd);
return err;
}
diff --git a/nptl/sysdeps/pthread/createthread.c b/nptl/sysdeps/pthread/createthread.c
index 49383cf769..8620519887 100644
--- a/nptl/sysdeps/pthread/createthread.c
+++ b/nptl/sysdeps/pthread/createthread.c
@@ -66,8 +66,16 @@ do_clone (struct pthread *pd, const struct pthread_attr *attr,
if (ARCH_CLONE (fct, STACK_VARIABLES_ARGS, clone_flags,
pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
- /* Failed. */
- return errno;
+ {
+ /* Failed. If the thread is detached, remove the TCB here since
+ the caller cannot do this. The caller remembered the thread
+ as detached and cannot reverify that it is not since it must
+ not access the thread descriptor again. */
+ if (IS_DETACHED (pd))
+ __deallocate_stack (pd);
+
+ return errno;
+ }
/* Now we have the possibility to set scheduling parameters etc. */
if (__builtin_expect (stopped != 0, 0))
@@ -95,7 +103,9 @@ do_clone (struct pthread *pd, const struct pthread_attr *attr,
(void) INTERNAL_SYSCALL (tkill, err2, 2, pd->tid, SIGCANCEL);
#endif
- return INTERNAL_SYSCALL_ERRNO (res, err);
+ return (INTERNAL_SYSCALL_ERROR_P (res, err)
+ ? INTERNAL_SYSCALL_ERRNO (res, err)
+ : 0);
}
}
@@ -176,6 +186,9 @@ create_thread (struct pthread *pd, const struct pthread_attr *attr,
if ((_mask & (__nptl_threads_events.event_bits[_idx]
| pd->eventbuf.eventmask.event_bits[_idx])) != 0)
{
+ /* We always must have the thread start stopped. */
+ pd->stopped_start = true;
+
/* Create the thread. We always create the thread stopped
so that it does not get far before we tell the debugger. */
int res = do_clone (pd, attr, clone_flags, start_thread,
@@ -214,10 +227,11 @@ create_thread (struct pthread *pd, const struct pthread_attr *attr,
/* Determine whether the newly created threads has to be started
stopped since we have to set the scheduling parameters or set the
affinity. */
- int stopped = 0;
+ bool stopped = false;
if (attr != NULL && (attr->cpuset != NULL
|| (attr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0))
- stopped = 1;
+ stopped = true;
+ pd->stopped_start = stopped;
/* Actually create the thread. */
int res = do_clone (pd, attr, clone_flags, start_thread,