aboutsummaryrefslogtreecommitdiff
path: root/src/thread_win.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/thread_win.c')
-rw-r--r--src/thread_win.c90
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;
+}