struct start_args {
void *(*start_func)(void *);
void *start_arg;
- pthread_attr_t *attr;
- volatile int *perr;
+ volatile int control;
unsigned long sig_mask[_NSIG/8/sizeof(long)];
};
static int start(void *p)
{
struct start_args *args = p;
- if (args->attr) {
- pthread_t self = __pthread_self();
- int ret = -__syscall(SYS_sched_setscheduler, self->tid,
- args->attr->_a_policy, &args->attr->_a_prio);
- if (a_swap(args->perr, ret)==-2)
- __wake(args->perr, 1, 1);
- if (ret) {
- self->detach_state = DT_DETACHED;
+ int state = args->control;
+ if (state) {
+ if (a_cas(&args->control, 1, 2)==1)
+ __wait(&args->control, 0, 2, 1);
+ if (args->control) {
+ __pthread_self()->detach_state = DT_DETACHED;
__pthread_exit(0);
}
}
| CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_DETACHED;
pthread_attr_t attr = { 0 };
sigset_t set;
- volatile int err = -1;
if (!libc.can_do_threads) return ENOSYS;
self = __pthread_self();
struct start_args *args = (void *)stack;
args->start_func = entry;
args->start_arg = arg;
- if (attr._a_sched) {
- args->attr = &attr;
- args->perr = &err;
- } else {
- args->attr = 0;
- args->perr = 0;
- }
+ args->control = attr._a_sched ? 1 : 0;
/* Application signals (but not the synccall signal) must be
* blocked before the thread list lock can be taken, to ensure
}
if (attr._a_sched) {
- if (a_cas(&err, -1, -2)==-1)
- __wait(&err, 0, -2, 1);
- ret = err;
+ int 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) return ret;
}