diff options
Diffstat (limited to 'src/thread_win.c')
| -rw-r--r-- | src/thread_win.c | 164 |
1 files changed, 92 insertions, 72 deletions
diff --git a/src/thread_win.c b/src/thread_win.c index 098e7dd..bb14774 100644 --- a/src/thread_win.c +++ b/src/thread_win.c @@ -3,16 +3,19 @@ static unsigned __stdcall bh_thread_run(void *arg) { bh_thread_data_t data; - + + /* Fetch thread data, store it on stack and free from heap */ data = *(bh_thread_data_t *)arg; free(arg); - + + /* Do the task, mark as done, and if required free it */ data.task->func(data.task->data); data.task->flags |= BH_THREAD_DONE; if (data.task->flags & BH_THREAD_CLEANUP) bh_task_free(data.task); - + + /* Call thread specific end function (deallocate TLS) */ data.end(0); return 0; } @@ -23,24 +26,28 @@ int bh_thread_init_base(bh_thread_t *thread, bh_thread_end_cb_t end) { bh_thread_data_t *data; - + + /* Allocate thread specific data */ data = malloc(sizeof(*data)); if (!data) - return -1; - + return BH_OOM; + + /* Setup thread specific data */ data->task = task; data->end = end; - + + /* Create and setup thread (relative to the callers libc) */ thread->allocated = 0; thread->handle = (HANDLE)_beginthreadex(NULL, 0, bh_thread_run, data, 0, NULL); - + + /* Check for errors */ if (!thread->handle) { free(data); - return -1; + return BH_ERROR; } - - return 0; + + return BH_OK; } bh_thread_t *bh_thread_new_base(bh_task_t *task, @@ -48,46 +55,53 @@ bh_thread_t *bh_thread_new_base(bh_task_t *task, bh_thread_end_cb_t end) { bh_thread_t *result; - + + /* Allocate thread object */ result = malloc(sizeof(*result)); if (result && !bh_thread_init_base(result, task, begin, end)) { free(result); result = NULL; } - + + /* Mark thread as allocated for deallocation in join/detach */ if (result) result->allocated = 1; - + return result; } int bh_thread_join(bh_thread_t *thread) { + /* Join the thread */ WaitForSingleObject(thread->handle, INFINITE); CloseHandle(thread->handle); - + + /* If thread is allocated, deallocate it */ if (thread->allocated) free(thread); - - return 0; + + return BH_OK; } int bh_thread_detach(bh_thread_t *thread) { + /* Detach from thread */ CloseHandle(thread->handle); - + + /* If thread is allocated, deallocate it */ if (thread->allocated) free(thread); - - return 0; + + return BH_OK; } int bh_mutex_init(bh_mutex_t *mutex) { + /* TODO: Is this spincount needed or sane? */ if (!InitializeCriticalSectionAndSpinCount(&mutex->handle, 0x400)) - return -1; - return 0; + return BH_ERROR; + return BH_OK; } void bh_mutex_destroy(bh_mutex_t *mutex) @@ -98,29 +112,30 @@ void bh_mutex_destroy(bh_mutex_t *mutex) int bh_mutex_lock(bh_mutex_t *mutex) { EnterCriticalSection(&mutex->handle); - return 0; + return BH_OK; } int bh_mutex_try_lock(bh_mutex_t *mutex) { if (!TryEnterCriticalSection(&mutex->handle)) - return -1; - return 0; + return BH_ERROR; + return BH_OK; } int bh_mutex_unlock(bh_mutex_t *mutex) { LeaveCriticalSection(&mutex->handle); - return 0; + return BH_OK; } int bh_semaphore_init(bh_semaphore_t *semaphore, int count) { + /* Create semaphore with max value of 32767 (to match POSIX) */ semaphore->handle = CreateSemaphore(NULL, count, 0x7FFF, NULL); if (!semaphore->handle) - return -1; - - return 0; + return BH_ERROR; + + return BH_OK; } void bh_semaphore_destroy(bh_semaphore_t *semaphore) @@ -131,37 +146,38 @@ void bh_semaphore_destroy(bh_semaphore_t *semaphore) int bh_semaphore_post(bh_semaphore_t *semaphore) { if (!ReleaseSemaphore(semaphore->handle, 1, NULL)) - return -1; - return 0; + return BH_ERROR; + return BH_OK; } int bh_semaphore_wait(bh_semaphore_t *semaphore) { if (WaitForSingleObject(semaphore->handle, INFINITE)) - return -1; - return 0; + return BH_ERROR; + return BH_OK; } int bh_semaphore_wait_for(bh_semaphore_t *semaphore, unsigned long timeout) { + /* FIXME: Check if we timed out or errored out */ if (WaitForSingleObject(semaphore->handle, timeout)) - return -1; - return 0; + return BH_TIMEOUT; + return BH_ERROR; } int bh_semaphore_try_wait(bh_semaphore_t *semaphore) { if (WaitForSingleObject(semaphore->handle, 0)) - return -1; - return 0; + return BH_ERROR; + return BH_OK; } #if WINVER >= _WIN32_WINNT_VISTA int bh_cond_init(bh_cond_t *cond) { InitializeConditionVariable(&cond->handle); - return 0; + return BH_OK; } void bh_cond_destroy(bh_cond_t *cond) @@ -179,43 +195,46 @@ int bh_cond_wait_for(bh_cond_t *cond, bh_mutex_t *mutex, unsigned long timeout) { + /* FIXME: Check if we timed out or errored out */ if (!SleepConditionVariableCS(&cond->handle, &mutex->handle, timeout)) - return -1; - return 0; + return BH_TIMEOUT; + return BH_OK; } int bh_cond_signal(bh_cond_t *cond) { WakeConditionVariable(&cond->handle); - return 0; + return BH_OK; } int bh_cond_broadcast(bh_cond_t *cond) { WakeAllConditionVariable(&cond->handle); - return 0; + return BH_OK; } #else /* Condition variable implementation based on BeOS article * http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html - */ + * + * Slow, but correct implementation of CVs. + */ int bh_cond_init(bh_cond_t *cond) { if (bh_mutex_init(&cond->lock)) - return -1; - + return BH_ERROR; + if (bh_semaphore_init(&cond->wait, 0)) { bh_mutex_destroy(&cond->lock); - return -1; + return BH_ERROR; } - + if (bh_semaphore_init(&cond->done, 0)) { bh_semaphore_destroy(&cond->wait); bh_mutex_destroy(&cond->lock); - return -1; + return BH_ERROR; } cond->waiting = 0; cond->signals = 0; @@ -234,27 +253,27 @@ int bh_cond_wait(bh_cond_t *cond, bh_mutex_t *mutex) { int retval; - + bh_mutex_lock(&cond->lock); cond->waiting++; bh_mutex_unlock(&cond->lock); bh_mutex_unlock(mutex); - + retval = bh_semaphore_wait(&cond->wait); - + bh_mutex_lock(&cond->lock); if (cond->signals > 0) { if (retval) bh_semaphore_wait(&cond->wait); - + bh_semaphore_post(&cond->done); cond->signals--; } cond->waiting--; - bh_mutex_unlock(&cond->lock); + bh_mutex_unlock(&cond->lock); bh_mutex_lock(mutex); - + return retval; } @@ -263,70 +282,70 @@ int bh_cond_wait_for(bh_cond_t *cond, unsigned long timeout) { int retval; - + bh_mutex_lock(&cond->lock); cond->waiting++; bh_mutex_unlock(&cond->lock); bh_mutex_unlock(mutex); - + retval = bh_semaphore_wait_for(&cond->wait, timeout); - + bh_mutex_lock(&cond->lock); if (cond->signals > 0) { if (retval) bh_semaphore_wait(&cond->wait); - + bh_semaphore_post(&cond->done); cond->signals--; } cond->waiting--; - bh_mutex_unlock(&cond->lock); + bh_mutex_unlock(&cond->lock); bh_mutex_lock(mutex); - + return retval; } int bh_cond_signal(bh_cond_t *cond) { bh_mutex_lock(&cond->lock); - + if (cond->waiting > cond->signals) { cond->signals++; - + bh_semaphore_post(&cond->wait); bh_mutex_unlock(&cond->lock); bh_semaphore_wait(&cond->done); } else bh_mutex_unlock(&cond->lock); - - return 0; + + return BH_OK; } int bh_cond_broadcast(bh_cond_t *cond) { int i, waiting; - + bh_mutex_lock(&cond->lock); if (cond->waiting > cond->signals) { waiting = cond->waiting - cond->signals; cond->signals = cond->waiting; - + for (i = 0; i < waiting; i++) bh_semaphore_post(&cond->wait); - + bh_mutex_unlock(&cond->lock); - + for (i = 0; i < waiting; i++) bh_semaphore_wait(&cond->done); } else bh_mutex_unlock(&cond->lock); - - return 0; + + return BH_OK; } #endif @@ -386,7 +405,7 @@ int bh_thread_pool_init_base(bh_thread_pool_t *pool, } } - return 0; + return BH_OK; queue_fail: free(pool->threads); @@ -401,7 +420,7 @@ task_fail: bh_mutex_destroy(&pool->lock); lock_fail: - return -1; + return BH_ERROR; } bh_thread_pool_t *bh_thread_pool_new_base(size_t size, @@ -409,6 +428,7 @@ bh_thread_pool_t *bh_thread_pool_new_base(size_t size, bh_thread_end_cb_t end) { bh_thread_pool_t *result; + result = malloc(sizeof(*result)); if (result && bh_thread_pool_init_base(result, size, begin, end)) { |
