#include <tls.h>
#include <ucontext.h>
-#include <sys/segments.h>
#include <sys/stack.h>
#include <sys/stack.h>
#include <sys/regset.h>
-#include <sys/segments.h>
+#include <sys/lwp.h>
#include <inline-syscall.h>
-#include <sched_priv.h>
+#include <schedP.h>
#include <createthread_arch.c>
DECLARE_INLINE_SYSCALL (int, lwp_create, ucontext_t *ucp, int flags,
if (errval != 0)
return errval;
+ /* Threads inherit the parent's sigmask. */
+ pthread_sigmask (SIG_SETMASK, NULL, &ctx.uc_sigmask);
+
/* One more thread. We cannot have the thread do this itself, since it
might exist but not have been scheduled yet by the time we've returned
and need to check the value to behave correctly. We must do it before
/* We set the thread to be initially suspended so that we can set
scheduling magic. */
int lwp_flags =
- ((attr->flags & ATTR_FLAG_DAEMON) ? THR_DAEMON : 0) |
- ((attr->flags & ATTR_FLAG_DETACHSTATE) ? THR_DETACHED : 0);
+ ((attr->flags & ATTR_FLAG_DAEMON) ? LWP_DAEMON : 0) |
+ ((attr->flags & ATTR_FLAG_DETACHSTATE) ? LWP_DETACHED : 0);
if ((attr->flags & ATTR_FLAG_THR_CREATE) == 0)
- lwp_flags |= THR_SUSPENDED;
+ lwp_flags |= LWP_SUSPENDED;
errval = INLINE_SYSCALL (lwp_create, 3, &ctx, lwp_flags, &pd->tid);
if (errval == 0 && (attr->flags & ATTR_FLAG_THR_CREATE) == 0)
{
errval = EPERM;
}
- /* Resume thread if requested. */
- if (errval == 0)
+ if (errval == 0 && !(attr->flags & ATTR_FLAG_SUSPENDED))
{
- if (!(attr->flags & ATTR_FLAG_SUSPENDED))
- errval = INLINE_SYSCALL (lwp_continue, 1, pd->tid);
+ errval = INLINE_SYSCALL (lwp_continue, 1, pd->tid);
}
+ else if (errval != 0)
+ {
+ pd->flags |= ATTR_FLAG_CREATE_FAILED;
+ INLINE_SYSCALL (lwp_continue, 1, pd->tid);
+
+ if (!IS_DETACHED (pd))
+ {
+ int result;
+ lll_wait_tid (pd->tid);
+ }
- /* Kill the thread if we didn't succeed above. */
- if (errval != 0)
- INLINE_SYSCALL (lwp_kill, 2, pd->tid, SIGKILL);
+ /* Note: if the thread is detached, start_thread will free pd;
+ otherwise the caller of create_thread will free pd. */
+ }
}
- if (errval != 0)
+ if (errval == 0)
+ {
+ /* We now have for sure more than one thread. The main thread might
+ not yet have the flag set. No need to set the global variable
+ again if this is what we use. */
+ THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1);
+ }
+ else
{
atomic_decrement (&__nptl_nthreads); /* Oops, we lied for a second. */
-
- /* 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 errval;