int dcethread_create(dcethread** _thread, dcethread_attr* attr, void *(*start_routine)(void *), void *arg) { dcethread_start_args *start_args; dcethread* thread; int detachstate; start_args = (dcethread_start_args *) malloc(sizeof(*start_args)); if (start_args == NULL) { return dcethread__set_errno(ENOMEM); } start_args->start = start_routine; start_args->data = arg; start_args->self = thread = dcethread__new(); /* Record if this thread was created joinably */ if (!attr || (pthread_attr_getdetachstate(attr, &detachstate), detachstate == PTHREAD_CREATE_JOINABLE)) { thread->flag.joinable = 1; } /* If thread is joinable, give it an extra reference */ if (thread->flag.joinable) { thread->refs++; } if (dcethread__set_errno(pthread_create((pthread_t*) &thread->pthread, attr, proxy_start, start_args))) { dcethread__delete(thread); free(start_args); return -1; } DCETHREAD_TRACE("Thread %p: created (pthread %lu)", thread, (unsigned long) thread->pthread); dcethread__lock(thread); while (thread->state == DCETHREAD_STATE_CREATED) { dcethread__wait(thread); } dcethread__unlock(thread); DCETHREAD_TRACE("Thread %p: started", thread); *_thread = thread; return dcethread__set_errno(0); }
void dcethread__unlock(dcethread* thread) { unsigned int refs; dcethread__sanity(thread); /* Access reference count while thread is still locked in order to avoid race conditions */ refs = thread->refs; thread->flag.locked = 0; if (pthread_mutex_unlock((pthread_mutex_t*) &thread->lock)) DCETHREAD_ERROR("Thread %p: failed to unlock mutex", thread); DCETHREAD_TRACE("Thread %p: unlocked", thread); if (refs == 0) { dcethread__delete(thread); } }