- a_inc(&libc.threads_minus_1);
- ret = __clone(start, stack, 0x7d8f00, new, &new->tid, new, &new->tid);
+ /* Ensure SIGCANCEL is unblocked in new thread. This requires
+ * working with a copy of the set so we can restore the
+ * original mask in the calling thread. */
+ memcpy(&args->sig_mask, &set, sizeof args->sig_mask);
+ args->sig_mask[(SIGCANCEL-1)/8/sizeof(long)] &=
+ ~(1UL<<((SIGCANCEL-1)%(8*sizeof(long))));
+
+ __tl_lock();
+ libc.threads_minus_1++;
+ ret = __clone((c11 ? start_c11 : start), stack, flags, args, &new->tid, TP_ADJ(new), &__thread_list_lock);
+
+ /* All clone failures translate to EAGAIN. If explicit scheduling
+ * was requested, attempt it before unlocking the thread list so
+ * that the failed thread is never exposed and so that we can
+ * clean up all transient resource usage before returning. */
+ if (ret < 0) {
+ ret = -EAGAIN;
+ } else if (attr._a_sched) {
+ ret = __syscall(SYS_sched_setscheduler,
+ new->tid, attr._a_policy, &attr._a_prio);
+ if (a_swap(&args->control, ret ? 3 : 0)==2)
+ __wake(&args->control, 1, 1);
+ if (ret)
+ __wait(&args->control, 0, 3, 0);
+ }