aboutsummaryrefslogtreecommitdiff
path: root/src/thread_posix.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/thread_posix.c')
-rw-r--r--src/thread_posix.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/src/thread_posix.c b/src/thread_posix.c
index 2898644..84e8e09 100644
--- a/src/thread_posix.c
+++ b/src/thread_posix.c
@@ -4,9 +4,15 @@
static void *bh_thread_run(void *arg)
{
+ bh_tls_t *tls;
bh_task_t *task;
+
+ /* Fetch thread data */
task = (bh_task_t *)arg;
+ /* Setup TLS */
+ tls = bh_tls_fetch();
+
/* Do the task, mark as done, and if required free it */
task->func(task->data);
task->flags |= BH_THREAD_DONE;
@@ -14,6 +20,9 @@ static void *bh_thread_run(void *arg)
if (task->flags & BH_THREAD_CLEANUP)
bh_task_free(task);
+ /* Destroy TLS */
+ bh_tls_cleanup();
+
return NULL;
}
@@ -283,3 +292,100 @@ bh_thread_pool_t *bh_thread_pool_new(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)
+{
+ /* TODO: Check on other OS and compilers */
+#if defined(__clang__) || defined(__GNUC__)
+ while (__sync_lock_test_and_set(&lock->handle, 1));
+ return BH_OK;
+#else
+#error "Spinlocks are not supported"
+ return BH_NO_IMPL;
+#endif
+}
+
+int bh_spinlock_unlock(bh_spinlock_t *lock)
+{
+ /* TODO: Check on other OS and compilers */
+#if defined(__clang__) || defined(__GNUC__)
+ if (__sync_lock_test_and_set(&lock->handle, 0))
+ return BH_OK;
+ return BH_ERROR;
+#else
+#error "Spinlocks are not supported"
+ return BH_NO_IMPL;
+#endif
+}
+
+int bh_spinlock_try_lock(bh_spinlock_t *lock)
+{
+ /* TODO: Check on other OSs and compilers */
+#if defined(__clang__) || defined(__GNUC__)
+ if (__sync_lock_test_and_set(&lock->handle, 1))
+ return BH_ERROR;
+ return BH_OK;
+#else
+#error "Spinlocks are not supported"
+ return BH_NO_IMPL;
+#endif
+}
+
+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 int tls_ready = 0;
+ static pthread_key_t tls_key;
+
+ bh_tls_t *tls;
+
+ /* Protect pthread key by spinlock */
+ bh_spinlock_lock(&tls_lock);
+
+ /* Allocate pthread key if it's not allocated */
+ if (tls_ready == 0)
+ {
+ pthread_key_create(&tls_key, NULL);
+ tls_ready = 1;
+ }
+
+ /* Unlock spinlock */
+ bh_spinlock_unlock(&tls_lock);
+
+ /* Get TLS pointer and setup TLS if neccesery */
+ tls = (bh_tls_t *)pthread_getspecific(tls_key);
+ 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 (pthread_setspecific(tls_key, tls))
+ abort();
+ }
+
+ /* Return TLS */
+ return tls;
+} \ No newline at end of file