| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392 |
- /*
- * Copyright (C) 2019 Intel Corporation. All rights reserved.
- * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- */
- #include "bh_thread.h"
- #include "bh_assert.h"
- #include "bh_log.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/time.h>
- static bool is_thread_sys_inited = false;
- static korp_mutex thread_list_lock;
- static pthread_key_t thread_local_storage_key[BH_MAX_TLS_NUM];
- int _vm_thread_sys_init()
- {
- unsigned i, j;
- int ret;
- if (is_thread_sys_inited)
- return 0;
- for (i = 0; i < BH_MAX_TLS_NUM; i++) {
- ret = pthread_key_create(&thread_local_storage_key[i], NULL);
- if (ret)
- goto fail;
- }
- ret = vm_mutex_init(&thread_list_lock);
- if (ret)
- goto fail;
- is_thread_sys_inited = true;
- return 0;
- fail: for (j = 0; j < i; j++)
- pthread_key_delete(thread_local_storage_key[j]);
- return -1;
- }
- void vm_thread_sys_destroy(void)
- {
- if (is_thread_sys_inited) {
- unsigned i;
- for (i = 0; i < BH_MAX_TLS_NUM; i++)
- pthread_key_delete(thread_local_storage_key[i]);
- vm_mutex_destroy(&thread_list_lock);
- is_thread_sys_inited = false;
- }
- }
- typedef struct {
- thread_start_routine_t start;
- void* stack;
- uint32 stack_size;
- void* arg;
- } thread_wrapper_arg;
- static void *vm_thread_wrapper(void *arg)
- {
- thread_wrapper_arg * targ = arg;
- LOG_VERBOSE("THREAD CREATE 0x%08x\n", &targ);
- targ->stack = (void *)((uintptr_t)(&arg) & (uintptr_t)~0xfff);
- _vm_tls_put(1, targ);
- targ->start(targ->arg);
- BH_FREE(targ);
- _vm_tls_put(1, NULL);
- return NULL;
- }
- int _vm_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start,
- void *arg, unsigned int stack_size, int prio)
- {
- pthread_attr_t tattr;
- thread_wrapper_arg *targ;
- bh_assert(stack_size > 0);
- bh_assert(tid);
- bh_assert(start);
- *tid = INVALID_THREAD_ID;
- pthread_attr_init(&tattr);
- pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE);
- if (pthread_attr_setstacksize(&tattr, stack_size) != 0) {
- bh_debug("Invalid thread stack size %u. Min stack size on Linux = %u",
- stack_size, PTHREAD_STACK_MIN);
- pthread_attr_destroy(&tattr);
- return BHT_ERROR;
- }
- targ = (thread_wrapper_arg*) BH_MALLOC(sizeof(*targ));
- if (!targ) {
- pthread_attr_destroy(&tattr);
- return BHT_ERROR;
- }
- targ->start = start;
- targ->arg = arg;
- targ->stack_size = stack_size;
- if (pthread_create(tid, &tattr, vm_thread_wrapper, targ) != 0) {
- pthread_attr_destroy(&tattr);
- BH_FREE(targ);
- return BHT_ERROR;
- }
- pthread_attr_destroy(&tattr);
- return BHT_OK;
- }
- int _vm_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg,
- unsigned int stack_size)
- {
- return _vm_thread_create_with_prio(tid, start, arg, stack_size,
- BH_THREAD_DEFAULT_PRIORITY);
- }
- korp_tid _vm_self_thread()
- {
- return (korp_tid) pthread_self();
- }
- void vm_thread_exit(void * code)
- {
- BH_FREE(_vm_tls_get(1));
- _vm_tls_put(1, NULL);
- pthread_exit(code);
- }
- void *_vm_tls_get(unsigned idx)
- {
- bh_assert(idx < BH_MAX_TLS_NUM);
- return pthread_getspecific(thread_local_storage_key[idx]);
- }
- int _vm_tls_put(unsigned idx, void * tls)
- {
- bh_assert(idx < BH_MAX_TLS_NUM);
- pthread_setspecific(thread_local_storage_key[idx], tls);
- return BHT_OK;
- }
- int _vm_mutex_init(korp_mutex *mutex)
- {
- return pthread_mutex_init(mutex, NULL) == 0 ? BHT_OK : BHT_ERROR;
- }
- int _vm_recursive_mutex_init(korp_mutex *mutex)
- {
- int ret;
- pthread_mutexattr_t mattr;
- bh_assert(mutex);
- ret = pthread_mutexattr_init(&mattr);
- if (ret)
- return BHT_ERROR;
- pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE_NP);
- ret = pthread_mutex_init(mutex, &mattr);
- pthread_mutexattr_destroy(&mattr);
- return ret == 0 ? BHT_OK : BHT_ERROR;
- }
- int _vm_mutex_destroy(korp_mutex *mutex)
- {
- int ret;
- bh_assert(mutex);
- ret = pthread_mutex_destroy(mutex);
- return ret == 0 ? BHT_OK : BHT_ERROR;
- }
- /* Returned error (EINVAL, EAGAIN and EDEADLK) from
- locking the mutex indicates some logic error present in
- the program somewhere.
- Don't try to recover error for an existing unknown error.*/
- void vm_mutex_lock(korp_mutex *mutex)
- {
- int ret;
- bh_assert(mutex);
- ret = pthread_mutex_lock(mutex);
- if (0 != ret) {
- printf("vm mutex lock failed (ret=%d)!\n", ret);
- exit(-1);
- }
- }
- int vm_mutex_trylock(korp_mutex *mutex)
- {
- int ret;
- bh_assert(mutex);
- ret = pthread_mutex_trylock(mutex);
- return ret == 0 ? BHT_OK : BHT_ERROR;
- }
- /* Returned error (EINVAL, EAGAIN and EPERM) from
- unlocking the mutex indicates some logic error present
- in the program somewhere.
- Don't try to recover error for an existing unknown error.*/
- void vm_mutex_unlock(korp_mutex *mutex)
- {
- int ret;
- bh_assert(mutex);
- ret = pthread_mutex_unlock(mutex);
- if (0 != ret) {
- printf("vm mutex unlock failed (ret=%d)!\n", ret);
- exit(-1);
- }
- }
- int _vm_sem_init(korp_sem* sem, unsigned int c)
- {
- int ret;
- bh_assert(sem);
- ret = sem_init(sem, 0, c);
- return ret == 0 ? BHT_OK : BHT_ERROR;
- }
- int _vm_sem_destroy(korp_sem *sem)
- {
- int ret;
- bh_assert(sem);
- ret = sem_destroy(sem);
- return ret == 0 ? BHT_OK : BHT_ERROR;
- }
- int _vm_sem_wait(korp_sem *sem)
- {
- int ret;
- bh_assert(sem);
- ret = sem_wait(sem);
- return ret == 0 ? BHT_OK : BHT_ERROR;
- }
- int _vm_sem_reltimedwait(korp_sem *sem, int mills)
- {
- int ret = BHT_OK;
- struct timespec timeout;
- const int mills_per_sec = 1000;
- const int mills_to_nsec = 1E6;
- bh_assert(sem);
- if (mills == (int)BHT_WAIT_FOREVER) {
- ret = sem_wait(sem);
- } else {
- timeout.tv_sec = mills / mills_per_sec;
- timeout.tv_nsec = (mills % mills_per_sec) * mills_to_nsec;
- timeout.tv_sec += time(NULL);
- ret = sem_timedwait(sem, &timeout);
- }
- if (ret != BHT_OK) {
- if (errno == BHT_TIMEDOUT) {
- ret = BHT_TIMEDOUT;
- errno = 0;
- } else {
- bh_debug("Faliure happens when timed wait is called");
- bh_assert(0);
- }
- }
- return ret;
- }
- int _vm_sem_post(korp_sem *sem)
- {
- bh_assert(sem);
- return sem_post(sem) == 0 ? BHT_OK : BHT_ERROR;
- }
- int _vm_cond_init(korp_cond *cond)
- {
- bh_assert(cond);
- if (pthread_cond_init(cond, NULL) != BHT_OK)
- return BHT_ERROR;
- return BHT_OK;
- }
- int _vm_cond_destroy(korp_cond *cond)
- {
- bh_assert(cond);
- if (pthread_cond_destroy(cond) != BHT_OK)
- return BHT_ERROR;
- return BHT_OK;
- }
- int _vm_cond_wait(korp_cond *cond, korp_mutex *mutex)
- {
- bh_assert(cond);
- bh_assert(mutex);
- if (pthread_cond_wait(cond, mutex) != BHT_OK)
- return BHT_ERROR;
- return BHT_OK;
- }
- static void msec_nsec_to_abstime(struct timespec *ts, int64 msec, int32 nsec)
- {
- struct timeval tv;
- gettimeofday(&tv, NULL);
- ts->tv_sec = (long int)(tv.tv_sec + msec / 1000);
- ts->tv_nsec = (long int)(tv.tv_usec * 1000 + (msec % 1000) * 1000000 + nsec);
- if (ts->tv_nsec >= 1000000000L) {
- ts->tv_sec++;
- ts->tv_nsec -= 1000000000L;
- }
- }
- int _vm_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int mills)
- {
- int ret;
- struct timespec abstime;
- if (mills == (int)BHT_WAIT_FOREVER)
- ret = pthread_cond_wait(cond, mutex);
- else {
- msec_nsec_to_abstime(&abstime, mills, 0);
- ret = pthread_cond_timedwait(cond, mutex, &abstime);
- }
- if (ret != BHT_OK && ret != BHT_TIMEDOUT)
- return BHT_ERROR;
- return BHT_OK;
- }
- int _vm_cond_signal(korp_cond *cond)
- {
- bh_assert(cond);
- if (pthread_cond_signal(cond) != BHT_OK)
- return BHT_ERROR;
- return BHT_OK;
- }
- int _vm_cond_broadcast(korp_cond *cond)
- {
- bh_assert(cond);
- if (pthread_cond_broadcast(cond) != BHT_OK)
- return BHT_ERROR;
- return BHT_OK;
- }
- int _vm_thread_cancel(korp_tid thread)
- {
- return pthread_cancel(thread);
- }
- int _vm_thread_join(korp_tid thread, void **value_ptr, int mills)
- {
- return pthread_join(thread, value_ptr);
- }
- int _vm_thread_detach(korp_tid thread)
- {
- return pthread_detach(thread);
- }
|