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); }
int dcethread_attr_create(dcethread_attr *attr) { if (dcethread__set_errno(pthread_attr_init(attr))) { return -1; } if (dcethread__set_errno(pthread_attr_setdetachstate(attr, PTHREAD_CREATE_JOINABLE))) { pthread_attr_destroy(attr); return -1; } return 0; }
int dcethread_atfork(void *user_state, void (*pre_fork)(void *), void (*parent_fork)(void *), void (*child_fork)(void *)) { dcethread_atfork_handler handler; dcethread_atfork_init(); pthread_rwlock_wrlock(&atfork_lock); if (atfork_handlers_len >= ATFORK_MAX_HANDLERS) { pthread_rwlock_unlock(&atfork_lock); return dcethread__set_errno(ENOMEM); } /* Fill in struct */ handler.user_state = user_state; handler.pre_fork = pre_fork; handler.child_fork = child_fork; handler.parent_fork = parent_fork; #ifndef AVOID_PTHREAD_ATFORK /* If no handlers have been registered yet, register our proxy functions exactly once with the real pthread_atfork */ if (atfork_handlers_len == 0) { if (dcethread__set_errno(pthread_atfork(__dcethread_pre_fork, __dcethread_parent_fork, __dcethread_child_fork))) { pthread_rwlock_unlock(&atfork_lock); return -1; } } #endif /* Add handler to array */ atfork_handlers[atfork_handlers_len++] = handler; pthread_rwlock_unlock(&atfork_lock); return dcethread__set_errno(0); }
int dcethread_mutex_lock(dcethread_mutex *mutex) { int res = pthread_mutex_lock((pthread_mutex_t*) &mutex->mutex); if (res == 0) { mutex->owner = pthread_self(); } return dcethread__set_errno(res); }
int dcethread_enableasync(int on) { dcethread* thread = dcethread__self(); int old; dcethread__lock(thread); old = thread->flag.async; thread->flag.async = on; dcethread__unlock(thread); (void) dcethread__set_errno(0); return old; }
ssize_t dcethread_attr_getstacksize(dcethread_attr* attr) { size_t stacksize; if (dcethread__set_errno(pthread_attr_getstacksize(attr, &stacksize))) { return -1; } else { return (ssize_t)stacksize; } }
int dcethread_attr_getprio(dcethread_attr* attr) { struct sched_param sp; if (dcethread__set_errno(pthread_attr_getschedparam(attr, &sp))) { return -1; } else { return sp.sched_priority; } }
int dcethread_mutex_trylock(dcethread_mutex *mutex) { int ret; ret = pthread_mutex_trylock((pthread_mutex_t*) &mutex->mutex); if (ret == 0) { mutex->owner = pthread_self(); return 1; } else if (ret == EBUSY) { return 0; } else { return dcethread__set_errno(ret); } }
int dcethread_attr_setsched(dcethread_attr *attr, int sched) { return dcethread__set_errno(pthread_attr_setschedpolicy(attr, sched)); }
int dcethread_keycreate(dcethread_key *key, void (*destructor)(void *value)) { return dcethread__set_errno(pthread_key_create(key, destructor)); }
int dcethread_cond_broadcast(dcethread_cond *cond) { return dcethread__set_errno(pthread_cond_broadcast(cond)); }
int dcethread_mutex_init(dcethread_mutex *mutex, dcethread_mutexattr* attr) { mutex->owner = (pthread_t) -1; return dcethread__set_errno(pthread_mutex_init((pthread_mutex_t*) &mutex->mutex, attr)); }
int dcethread_mutexattr_delete(dcethread_mutexattr *attr) { return dcethread__set_errno(pthread_mutexattr_destroy(attr)); }
int dcethread_mutexattr_setkind(dcethread_mutexattr *attr, int kind) { return dcethread__set_errno(pthread_mutexattr_settype(attr, kind)); }
int dcethread_mutexattr_create(dcethread_mutexattr *attr) { return dcethread__set_errno(pthread_mutexattr_init(attr)); }
int dcethread_mutex_destroy(dcethread_mutex *mutex) { return dcethread__set_errno(pthread_mutex_destroy((pthread_mutex_t*) &mutex->mutex)); }