diff options
Diffstat (limited to 'src/thread_win.c')
| -rw-r--r-- | src/thread_win.c | 90 |
1 files changed, 88 insertions, 2 deletions
diff --git a/src/thread_win.c b/src/thread_win.c index bb14774..92a5bb4 100644 --- a/src/thread_win.c +++ b/src/thread_win.c @@ -2,12 +2,16 @@ static unsigned __stdcall bh_thread_run(void *arg) { + bh_tls_t *tls; bh_thread_data_t data; /* Fetch thread data, store it on stack and free from heap */ data = *(bh_thread_data_t *)arg; free(arg); + /* Setup TLS */ + tls = bh_tls_fetch(); + /* Do the task, mark as done, and if required free it */ data.task->func(data.task->data); data.task->flags |= BH_THREAD_DONE; @@ -15,8 +19,12 @@ static unsigned __stdcall bh_thread_run(void *arg) if (data.task->flags & BH_THREAD_CLEANUP) bh_task_free(data.task); - /* Call thread specific end function (deallocate TLS) */ + /* Destroy our TLS */ + bh_tls_cleanup(); + + /* Call thread specific end function (deallocate libc TLS) */ data.end(0); + return 0; } @@ -58,7 +66,7 @@ bh_thread_t *bh_thread_new_base(bh_task_t *task, /* Allocate thread object */ result = malloc(sizeof(*result)); - if (result && !bh_thread_init_base(result, task, begin, end)) + if (result && bh_thread_init_base(result, task, begin, end)) { free(result); result = NULL; @@ -439,3 +447,81 @@ bh_thread_pool_t *bh_thread_pool_new_base(size_t size, return result; } +void bh_spinlock_init(bh_spinlock_t *lock) +{ + lock->handle = 0; +} + +void bh_spinlock_destroy(bh_spinlock_t *lock) +{ + (void)lock; +} + +int bh_spinlock_lock(bh_spinlock_t *lock) +{ + while (InterlockedExchange(&lock->handle, 1)); + return BH_OK; +} + +int bh_spinlock_unlock(bh_spinlock_t *lock) +{ + if (InterlockedExchange(&lock->handle, 0)) + return BH_OK; + return BH_ERROR; +} + +int bh_spinlock_try_lock(bh_spinlock_t *lock) +{ + if (InterlockedExchange(&lock->handle, 1)) + return BH_ERROR; + return BH_OK; +} + +bh_tls_info_t *bh_tls_info(void) +{ + static bh_tls_info_t info = {0, 0}; + + return &info; +} + +bh_tls_t *bh_tls_fetch(void) +{ + static bh_spinlock_t tls_lock = {0}; + static DWORD tls_index = TLS_OUT_OF_INDEXES; + + bh_tls_t *tls; + + /* Protect TLS index by spinlock */ + bh_spinlock_lock(&tls_lock); + + /* Allocate TLS index if it's not allocated */ + if (tls_index == TLS_OUT_OF_INDEXES) + tls_index = TlsAlloc(); + + /* Unlock spinlock */ + bh_spinlock_unlock(&tls_lock); + + /* Check that TLS index is valid */ + if (tls_index == TLS_OUT_OF_INDEXES) + abort(); + + /* Get TLS pointer and setup TLS if neccesery */ + tls = (bh_tls_t *)TlsGetValue(tls_index); + if (tls == NULL) + { + /* Allocate space for TLS */ + tls = malloc(sizeof(*tls)); + if (!tls) + abort(); + + /* Zero out TLS */ + memset(tls, 0, sizeof(*tls)); + + /* Set TLS value */ + if (!TlsSetValue(tls_index, tls)) + abort(); + } + + /* Return TLS */ + return tls; +} |
