diff options
Diffstat (limited to 'src/thread_posix.c')
| -rw-r--r-- | src/thread_posix.c | 106 |
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 |
