Implement Windows thread/mutex/cond APIs to support multi-thread (#627)
Implement Windows thread/mutex/cond related APIs to support Windows multi-thread feature Change Windows HW boundary check implementation for multi-thread: change SEH to VEH Fix wasm-c-api issue of getting AOTFunctionInstance by index, fix wasm-c-api compile warnings Enable to build invokeNative_general.c with cmake variable Fix several issues in lib-pthread Disable two LLVM passes in multi-thread mode to reserve volatile semantic Update docker script and document to build iwasm with Docker image Signed-off-by: Wenyong Huang <wenyong.huang@intel.com>
This commit is contained in:
@ -11,22 +11,30 @@
|
||||
|
||||
typedef struct {
|
||||
thread_start_routine_t start;
|
||||
void* stack;
|
||||
uint32 stack_size;
|
||||
void* arg;
|
||||
} thread_wrapper_arg;
|
||||
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
static int os_thread_signal_init();
|
||||
static void os_thread_signal_destroy();
|
||||
#endif
|
||||
|
||||
static void *os_thread_wrapper(void *arg)
|
||||
{
|
||||
thread_wrapper_arg * targ = arg;
|
||||
thread_wrapper_arg *targ = arg;
|
||||
thread_start_routine_t start_func = targ->start;
|
||||
void *thread_arg = targ->arg;
|
||||
os_printf("THREAD CREATED %p\n", &targ);
|
||||
targ->stack = (void *)((uintptr_t)(&arg) & (uintptr_t)~0xfff);
|
||||
|
||||
os_printf("THREAD CREATED %p\n", pthread_self());
|
||||
BH_FREE(targ);
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
if (os_thread_signal_init() != 0)
|
||||
return NULL;
|
||||
#endif
|
||||
start_func(thread_arg);
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
os_thread_destroy_stack_guard_pages();
|
||||
os_thread_signal_destroy();
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
@ -58,7 +66,6 @@ int os_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start,
|
||||
|
||||
targ->start = start;
|
||||
targ->arg = arg;
|
||||
targ->stack_size = stack_size;
|
||||
|
||||
if (pthread_create(tid, &tattr, os_thread_wrapper, targ) != 0) {
|
||||
pthread_attr_destroy(&tattr);
|
||||
@ -244,6 +251,7 @@ void os_thread_exit(void *retval)
|
||||
{
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
os_thread_destroy_stack_guard_pages();
|
||||
os_thread_signal_destroy();
|
||||
#endif
|
||||
return pthread_exit(retval);
|
||||
}
|
||||
@ -309,7 +317,7 @@ uint8 *os_thread_get_stack_boundary()
|
||||
static os_thread_local_attribute bool stack_guard_pages_inited = false;
|
||||
|
||||
/* The signal alternate stack base addr */
|
||||
static uint8 *sigalt_stack_base_addr;
|
||||
static os_thread_local_attribute uint8 *sigalt_stack_base_addr;
|
||||
|
||||
/* The signal handler passed to os_signal_init() */
|
||||
static os_signal_handler signal_handler;
|
||||
@ -419,7 +427,7 @@ os_signal_init(os_signal_handler handler)
|
||||
uint32 map_size = SIG_ALT_STACK_SIZE;
|
||||
uint8 *map_addr;
|
||||
|
||||
/* Initialize memory for signal alternate stack */
|
||||
/* Initialize memory for signal alternate stack of current thread */
|
||||
if (!(map_addr = os_mmap(NULL, map_size,
|
||||
MMAP_PROT_READ | MMAP_PROT_WRITE,
|
||||
MMAP_MAP_NONE))) {
|
||||
@ -473,6 +481,20 @@ os_signal_destroy()
|
||||
os_munmap(sigalt_stack_base_addr, SIG_ALT_STACK_SIZE);
|
||||
}
|
||||
|
||||
static int
|
||||
os_thread_signal_init()
|
||||
{
|
||||
assert(signal_handler);
|
||||
/* Use the global signal handler registered previously */
|
||||
return os_signal_init(signal_handler);
|
||||
}
|
||||
|
||||
static void
|
||||
os_thread_signal_destroy()
|
||||
{
|
||||
os_signal_destroy();
|
||||
}
|
||||
|
||||
void
|
||||
os_signal_unmask()
|
||||
{
|
||||
|
||||
@ -5,15 +5,22 @@
|
||||
|
||||
#include "platform_api_vmcore.h"
|
||||
|
||||
int
|
||||
os_thread_sys_init();
|
||||
|
||||
void
|
||||
os_thread_sys_destroy();
|
||||
|
||||
int
|
||||
bh_platform_init()
|
||||
{
|
||||
return 0;
|
||||
return os_thread_sys_init();
|
||||
}
|
||||
|
||||
void
|
||||
bh_platform_destroy()
|
||||
{
|
||||
os_thread_sys_destroy();
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <stdint.h>
|
||||
#include <malloc.h>
|
||||
#include <process.h>
|
||||
#include <Windows.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -40,14 +41,16 @@ extern "C" {
|
||||
/* Default thread priority */
|
||||
#define BH_THREAD_DEFAULT_PRIORITY 0
|
||||
|
||||
typedef void *korp_thread;
|
||||
typedef void *korp_tid;
|
||||
typedef void *korp_mutex;
|
||||
typedef void *korp_sem;
|
||||
typedef void *korp_thread;
|
||||
|
||||
typedef struct {
|
||||
korp_sem s;
|
||||
unsigned int waiting_count;
|
||||
struct os_thread_wait_node;
|
||||
typedef struct os_thread_wait_node *os_thread_wait_list;
|
||||
typedef struct korp_cond {
|
||||
korp_mutex wait_list_lock;
|
||||
os_thread_wait_list thread_wait_list;
|
||||
} korp_cond;
|
||||
|
||||
unsigned os_getpagesize();
|
||||
|
||||
@ -3,155 +3,499 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#include "platform_api_vmcore.h"
|
||||
#include "platform_api_extension.h"
|
||||
|
||||
typedef struct {
|
||||
thread_start_routine_t start;
|
||||
void* stack;
|
||||
uint32 stack_size;
|
||||
void* arg;
|
||||
} thread_wrapper_arg;
|
||||
#define bh_assert(v) assert(v)
|
||||
|
||||
static void *os_thread_wrapper(void *arg)
|
||||
{
|
||||
thread_wrapper_arg * targ = arg;
|
||||
thread_start_routine_t start_func = targ->start;
|
||||
void *thread_arg = targ->arg;
|
||||
os_printf("THREAD CREATED %p\n", &targ);
|
||||
targ->stack = (void *)((uintptr_t)(&arg) & (uintptr_t)~0xfff);
|
||||
BH_FREE(targ);
|
||||
start_func(thread_arg);
|
||||
return NULL;
|
||||
}
|
||||
#define BH_SEM_COUNT_MAX 0xFFFF
|
||||
|
||||
int os_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start,
|
||||
void *arg, unsigned int stack_size, int prio)
|
||||
struct os_thread_data;
|
||||
|
||||
typedef struct os_thread_wait_node {
|
||||
korp_sem sem;
|
||||
void *retval;
|
||||
os_thread_wait_list next;
|
||||
} os_thread_wait_node;
|
||||
|
||||
typedef struct os_thread_data {
|
||||
/* Next thread data */
|
||||
struct os_thread_data *next;
|
||||
/* Thread data of parent thread */
|
||||
struct os_thread_data *parent;
|
||||
/* Thread Id */
|
||||
DWORD thread_id;
|
||||
/* Thread start routine */
|
||||
thread_start_routine_t start_routine;
|
||||
/* Thread start routine argument */
|
||||
void *arg;
|
||||
/* Wait node of current thread */
|
||||
os_thread_wait_node wait_node;
|
||||
/* Wait cond */
|
||||
korp_cond wait_cond;
|
||||
/* Wait lock */
|
||||
korp_mutex wait_lock;
|
||||
/* Waiting list of other threads who are joining this thread */
|
||||
os_thread_wait_list thread_wait_list;
|
||||
} os_thread_data;
|
||||
|
||||
static bool is_thread_sys_inited = false;
|
||||
|
||||
/* Thread data of supervisor thread */
|
||||
static os_thread_data supervisor_thread_data;
|
||||
|
||||
/* Thread data key */
|
||||
static DWORD thread_data_key;
|
||||
|
||||
int os_sem_init(korp_sem* sem);
|
||||
int os_sem_destroy(korp_sem* sem);
|
||||
int os_sem_wait(korp_sem* sem);
|
||||
int os_sem_reltimed_wait(korp_sem* sem, uint64 useconds);
|
||||
int os_sem_signal(korp_sem* sem);
|
||||
|
||||
int
|
||||
os_thread_sys_init()
|
||||
{
|
||||
if (is_thread_sys_inited)
|
||||
return BHT_OK;
|
||||
|
||||
if ((thread_data_key = TlsAlloc()) == TLS_OUT_OF_INDEXES)
|
||||
return BHT_ERROR;
|
||||
|
||||
/* Initialize supervisor thread data */
|
||||
memset(&supervisor_thread_data, 0, sizeof(os_thread_data));
|
||||
|
||||
supervisor_thread_data.thread_id = GetCurrentThreadId();
|
||||
|
||||
if (os_sem_init(&supervisor_thread_data.wait_node.sem) != BHT_OK)
|
||||
goto fail1;
|
||||
|
||||
if (os_mutex_init(&supervisor_thread_data.wait_lock) != BHT_OK)
|
||||
goto fail2;
|
||||
|
||||
if (os_cond_init(&supervisor_thread_data.wait_cond) != BHT_OK)
|
||||
goto fail3;
|
||||
|
||||
if (!TlsSetValue(thread_data_key, &supervisor_thread_data))
|
||||
goto fail4;
|
||||
|
||||
is_thread_sys_inited = true;
|
||||
return BHT_OK;
|
||||
|
||||
fail4:
|
||||
os_cond_destroy(&supervisor_thread_data.wait_cond);
|
||||
fail3:
|
||||
os_mutex_destroy(&supervisor_thread_data.wait_lock);
|
||||
fail2:
|
||||
os_sem_destroy(&supervisor_thread_data.wait_node.sem);
|
||||
fail1:
|
||||
TlsFree(thread_data_key);
|
||||
return BHT_ERROR;
|
||||
}
|
||||
|
||||
int os_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg,
|
||||
unsigned int stack_size)
|
||||
void
|
||||
os_thread_sys_destroy()
|
||||
{
|
||||
if (is_thread_sys_inited) {
|
||||
os_cond_destroy(&supervisor_thread_data.wait_cond);
|
||||
os_mutex_destroy(&supervisor_thread_data.wait_lock);
|
||||
os_sem_destroy(&supervisor_thread_data.wait_node.sem);
|
||||
memset(&supervisor_thread_data, 0, sizeof(os_thread_data));
|
||||
TlsFree(thread_data_key);
|
||||
thread_data_key = 0;
|
||||
is_thread_sys_inited = false;
|
||||
}
|
||||
}
|
||||
|
||||
static os_thread_data *
|
||||
thread_data_current()
|
||||
{
|
||||
return (os_thread_data *)TlsGetValue(thread_data_key);
|
||||
}
|
||||
|
||||
static void
|
||||
os_thread_cleanup(void *retval)
|
||||
{
|
||||
os_thread_data *thread_data = thread_data_current();
|
||||
|
||||
bh_assert(thread_data != NULL);
|
||||
|
||||
os_mutex_lock(&thread_data->wait_lock);
|
||||
if (thread_data->thread_wait_list) {
|
||||
/* Signal each joining thread */
|
||||
os_thread_wait_list head = thread_data->thread_wait_list;
|
||||
while (head) {
|
||||
os_thread_wait_list next = head->next;
|
||||
head->retval = retval;
|
||||
os_sem_signal(&head->sem);
|
||||
head = next;
|
||||
}
|
||||
thread_data->thread_wait_list = NULL;
|
||||
}
|
||||
os_mutex_unlock(&thread_data->wait_lock);
|
||||
|
||||
/* Destroy resources */
|
||||
os_cond_destroy(&thread_data->wait_cond);
|
||||
os_sem_destroy(&thread_data->wait_node.sem);
|
||||
os_mutex_destroy(&thread_data->wait_lock);
|
||||
BH_FREE(thread_data);
|
||||
}
|
||||
|
||||
static unsigned
|
||||
os_thread_wrapper(void *arg)
|
||||
{
|
||||
os_thread_data *thread_data = arg;
|
||||
os_thread_data *parent = thread_data->parent;
|
||||
void *retval;
|
||||
bool result;
|
||||
|
||||
os_printf("THREAD CREATED %p\n", thread_data);
|
||||
|
||||
os_mutex_lock(&parent->wait_lock);
|
||||
thread_data->thread_id = GetCurrentThreadId();
|
||||
result = TlsSetValue(thread_data_key, thread_data);
|
||||
/* Notify parent thread */
|
||||
os_cond_signal(&parent->wait_cond);
|
||||
os_mutex_unlock(&parent->wait_lock);
|
||||
|
||||
if (!result)
|
||||
return -1;
|
||||
|
||||
retval = thread_data->start_routine(thread_data->arg);
|
||||
|
||||
os_thread_cleanup(retval);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
os_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start,
|
||||
void *arg, unsigned int stack_size, int prio)
|
||||
{
|
||||
os_thread_data *parent = thread_data_current();
|
||||
os_thread_data *thread_data;
|
||||
|
||||
if (!p_tid || !start)
|
||||
return BHT_ERROR;
|
||||
|
||||
if (stack_size < BH_APPLET_PRESERVED_STACK_SIZE)
|
||||
stack_size = BH_APPLET_PRESERVED_STACK_SIZE;
|
||||
|
||||
if (!(thread_data = BH_MALLOC(sizeof(os_thread_data))))
|
||||
return BHT_ERROR;
|
||||
|
||||
memset(thread_data, 0, sizeof(os_thread_data));
|
||||
thread_data->parent = parent;
|
||||
thread_data->start_routine = start;
|
||||
thread_data->arg = arg;
|
||||
|
||||
if (os_sem_init(&thread_data->wait_node.sem) != BHT_OK)
|
||||
goto fail1;
|
||||
|
||||
if (os_mutex_init(&thread_data->wait_lock) != BHT_OK)
|
||||
goto fail2;
|
||||
|
||||
if (os_cond_init(&thread_data->wait_cond) != BHT_OK)
|
||||
goto fail3;
|
||||
|
||||
os_mutex_lock(&parent->wait_lock);
|
||||
if (!_beginthreadex(NULL, stack_size,
|
||||
os_thread_wrapper, thread_data,
|
||||
0, NULL)) {
|
||||
os_mutex_unlock(&parent->wait_lock);
|
||||
goto fail4;
|
||||
}
|
||||
/* Wait for the thread routine to set thread_data's tid
|
||||
and add thread_data to thread data list */
|
||||
os_cond_wait(&parent->wait_cond, &parent->wait_lock);
|
||||
os_mutex_unlock(&parent->wait_lock);
|
||||
|
||||
*p_tid = (korp_tid)thread_data;
|
||||
return BHT_OK;
|
||||
|
||||
fail4:
|
||||
os_cond_destroy(&thread_data->wait_cond);
|
||||
fail3:
|
||||
os_mutex_destroy(&thread_data->wait_lock);
|
||||
fail2:
|
||||
os_sem_destroy(&thread_data->wait_node.sem);
|
||||
fail1:
|
||||
BH_FREE(thread_data);
|
||||
return BHT_ERROR;
|
||||
}
|
||||
|
||||
int
|
||||
os_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg,
|
||||
unsigned int stack_size)
|
||||
{
|
||||
return os_thread_create_with_prio(tid, start, arg, stack_size,
|
||||
BH_THREAD_DEFAULT_PRIORITY);
|
||||
}
|
||||
|
||||
korp_tid os_self_thread()
|
||||
korp_tid
|
||||
os_self_thread()
|
||||
{
|
||||
return NULL;
|
||||
return (korp_tid)TlsGetValue(thread_data_key);
|
||||
}
|
||||
|
||||
int os_mutex_init(korp_mutex *mutex)
|
||||
int
|
||||
os_thread_join(korp_tid thread, void **p_retval)
|
||||
{
|
||||
os_thread_data *thread_data, *curr_thread_data;
|
||||
|
||||
/* Get thread data of current thread */
|
||||
curr_thread_data = thread_data_current();
|
||||
curr_thread_data->wait_node.next = NULL;
|
||||
|
||||
/* Get thread data of thread to join */
|
||||
thread_data = (os_thread_data *)thread;
|
||||
bh_assert(thread_data);
|
||||
|
||||
os_mutex_lock(&thread_data->wait_lock);
|
||||
if (!thread_data->thread_wait_list)
|
||||
thread_data->thread_wait_list = &curr_thread_data->wait_node;
|
||||
else {
|
||||
/* Add to end of waiting list */
|
||||
os_thread_wait_node *p = thread_data->thread_wait_list;
|
||||
while (p->next)
|
||||
p = p->next;
|
||||
p->next = &curr_thread_data->wait_node;
|
||||
}
|
||||
os_mutex_unlock(&thread_data->wait_lock);
|
||||
|
||||
/* Wait the sem */
|
||||
os_sem_wait(&curr_thread_data->wait_node.sem);
|
||||
if (p_retval)
|
||||
*p_retval = curr_thread_data->wait_node.retval;
|
||||
return BHT_OK;
|
||||
}
|
||||
|
||||
int os_recursive_mutex_init(korp_mutex *mutex)
|
||||
int
|
||||
os_thread_detach(korp_tid thread)
|
||||
{
|
||||
/* Do nothing */
|
||||
return BHT_OK;
|
||||
(void)thread;
|
||||
}
|
||||
|
||||
void
|
||||
os_thread_exit(void *retval)
|
||||
{
|
||||
os_thread_cleanup(retval);
|
||||
_endthreadex(0);
|
||||
}
|
||||
|
||||
int
|
||||
os_sem_init(korp_sem *sem)
|
||||
{
|
||||
bh_assert(sem);
|
||||
*sem = CreateSemaphore(NULL, 0, BH_SEM_COUNT_MAX, NULL);
|
||||
return (*sem != NULL) ? BHT_OK : BHT_ERROR;
|
||||
}
|
||||
|
||||
int
|
||||
os_sem_destroy(korp_sem *sem)
|
||||
{
|
||||
bh_assert(sem);
|
||||
CloseHandle(*sem);
|
||||
return BHT_OK;
|
||||
}
|
||||
|
||||
int os_mutex_destroy(korp_mutex *mutex)
|
||||
int
|
||||
os_sem_wait(korp_sem *sem)
|
||||
{
|
||||
DWORD ret;
|
||||
|
||||
bh_assert(sem);
|
||||
|
||||
ret = WaitForSingleObject(*sem, INFINITE);
|
||||
|
||||
if (ret == WAIT_OBJECT_0)
|
||||
return BHT_OK;
|
||||
else if(ret == WAIT_TIMEOUT)
|
||||
return (int)WAIT_TIMEOUT;
|
||||
else /* WAIT_FAILED or others */
|
||||
return BHT_ERROR;
|
||||
}
|
||||
|
||||
int
|
||||
os_sem_reltimed_wait(korp_sem *sem, uint64 useconds)
|
||||
{
|
||||
uint64 mseconds_64;
|
||||
DWORD ret, mseconds;
|
||||
|
||||
bh_assert(sem);
|
||||
|
||||
if (useconds == BHT_WAIT_FOREVER)
|
||||
mseconds = INFINITE;
|
||||
else {
|
||||
mseconds_64 = useconds / 1000;
|
||||
|
||||
if (mseconds_64 < (uint64)(UINT32_MAX - 1)) {
|
||||
mseconds = (uint32)mseconds_64;
|
||||
}
|
||||
else {
|
||||
mseconds = UINT32_MAX - 1;
|
||||
os_printf("Warning: os_sem_reltimed_wait exceeds limit, "
|
||||
"set to max timeout instead\n");
|
||||
}
|
||||
}
|
||||
|
||||
ret = WaitForSingleObject(*sem, mseconds);
|
||||
|
||||
if (ret == WAIT_OBJECT_0)
|
||||
return BHT_OK;
|
||||
else if(ret == WAIT_TIMEOUT)
|
||||
return (int)WAIT_TIMEOUT;
|
||||
else /* WAIT_FAILED or others */
|
||||
return BHT_ERROR;
|
||||
}
|
||||
|
||||
int
|
||||
os_sem_signal(korp_sem *sem)
|
||||
{
|
||||
bh_assert(sem);
|
||||
return ReleaseSemaphore(*sem, 1, NULL) != FALSE
|
||||
? BHT_OK: BHT_ERROR;
|
||||
}
|
||||
|
||||
int
|
||||
os_mutex_init(korp_mutex *mutex)
|
||||
{
|
||||
bh_assert(mutex);
|
||||
*mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
return (*mutex != NULL) ? BHT_OK : BHT_ERROR;
|
||||
}
|
||||
|
||||
int
|
||||
os_recursive_mutex_init(korp_mutex *mutex)
|
||||
{
|
||||
bh_assert(mutex);
|
||||
*mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
return (*mutex != NULL) ? BHT_OK : BHT_ERROR;
|
||||
}
|
||||
|
||||
int
|
||||
os_mutex_destroy(korp_mutex *mutex)
|
||||
{
|
||||
assert(mutex);
|
||||
return CloseHandle(*mutex) ? BHT_OK : BHT_ERROR;
|
||||
}
|
||||
|
||||
int
|
||||
os_mutex_lock(korp_mutex *mutex)
|
||||
{
|
||||
int ret;
|
||||
|
||||
assert(mutex);
|
||||
ret = WaitForSingleObject(*mutex, INFINITE);
|
||||
return ret != WAIT_FAILED ? BHT_OK : BHT_ERROR;
|
||||
}
|
||||
|
||||
int
|
||||
os_mutex_unlock(korp_mutex *mutex)
|
||||
{
|
||||
bh_assert(mutex);
|
||||
return ReleaseMutex(*mutex) ? BHT_OK : BHT_ERROR;
|
||||
}
|
||||
|
||||
int
|
||||
os_cond_init(korp_cond *cond)
|
||||
{
|
||||
bh_assert(cond);
|
||||
if (os_mutex_init(&cond->wait_list_lock) != BHT_OK)
|
||||
return BHT_ERROR;
|
||||
|
||||
cond->thread_wait_list = NULL;
|
||||
return BHT_OK;
|
||||
}
|
||||
|
||||
int os_mutex_lock(korp_mutex *mutex)
|
||||
{
|
||||
return BHT_ERROR;
|
||||
}
|
||||
|
||||
int os_mutex_unlock(korp_mutex *mutex)
|
||||
int
|
||||
os_cond_destroy(korp_cond *cond)
|
||||
{
|
||||
bh_assert(cond);
|
||||
os_mutex_destroy(&cond->wait_list_lock);
|
||||
return BHT_OK;
|
||||
}
|
||||
|
||||
int os_cond_init(korp_cond *cond)
|
||||
static int
|
||||
os_cond_wait_internal(korp_cond *cond, korp_mutex *mutex,
|
||||
bool timed, uint64 useconds)
|
||||
{
|
||||
os_thread_wait_node *node = &thread_data_current()->wait_node;
|
||||
|
||||
node->next = NULL;
|
||||
|
||||
bh_assert(cond);
|
||||
bh_assert(mutex);
|
||||
os_mutex_lock(&cond->wait_list_lock);
|
||||
if (!cond->thread_wait_list)
|
||||
cond->thread_wait_list = node;
|
||||
else {
|
||||
/* Add to end of wait list */
|
||||
os_thread_wait_node *p = cond->thread_wait_list;
|
||||
while (p->next)
|
||||
p = p->next;
|
||||
p->next = node;
|
||||
}
|
||||
os_mutex_unlock(&cond->wait_list_lock);
|
||||
|
||||
/* Unlock mutex, wait sem and lock mutex again */
|
||||
os_mutex_unlock(mutex);
|
||||
if (timed)
|
||||
os_sem_reltimed_wait(&node->sem, useconds);
|
||||
else
|
||||
os_sem_wait(&node->sem);
|
||||
os_mutex_lock(mutex);
|
||||
|
||||
/* Remove wait node from wait list */
|
||||
os_mutex_lock(&cond->wait_list_lock);
|
||||
if (cond->thread_wait_list == node)
|
||||
cond->thread_wait_list = node->next;
|
||||
else {
|
||||
/* Remove from the wait list */
|
||||
os_thread_wait_node *p = cond->thread_wait_list;
|
||||
while (p->next != node)
|
||||
p = p->next;
|
||||
p->next = node->next;
|
||||
}
|
||||
os_mutex_unlock(&cond->wait_list_lock);
|
||||
|
||||
return BHT_OK;
|
||||
}
|
||||
|
||||
int os_cond_destroy(korp_cond *cond)
|
||||
int
|
||||
os_cond_wait(korp_cond *cond, korp_mutex *mutex)
|
||||
{
|
||||
return BHT_OK;
|
||||
return os_cond_wait_internal(cond, mutex, false, 0);
|
||||
}
|
||||
|
||||
int os_cond_wait(korp_cond *cond, korp_mutex *mutex)
|
||||
int
|
||||
os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds)
|
||||
{
|
||||
return BHT_OK;
|
||||
}
|
||||
|
||||
|
||||
int gettimeofday(struct timeval * tp, struct timezone * tzp)
|
||||
{
|
||||
/* Note: some broken versions only have 8 trailing zero's,
|
||||
the correct epoch has 9 trailing zero's
|
||||
This magic number is the number of 100 nanosecond intervals
|
||||
since January 1, 1601 (UTC) until 00:00:00 January 1, 1970 */
|
||||
static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL);
|
||||
|
||||
SYSTEMTIME system_time;
|
||||
FILETIME file_time;
|
||||
uint64_t time;
|
||||
|
||||
GetSystemTime(&system_time);
|
||||
SystemTimeToFileTime(&system_time, &file_time);
|
||||
time = ((uint64_t)file_time.dwLowDateTime);
|
||||
time += ((uint64_t)file_time.dwHighDateTime) << 32;
|
||||
|
||||
tp->tv_sec = (long)((time - EPOCH) / 10000000L);
|
||||
tp->tv_usec = (long)(system_time.wMilliseconds * 1000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void msec_nsec_to_abstime(struct timespec *ts, int usec)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
ts->tv_sec = (long int)(tv.tv_sec + usec / 1000000);
|
||||
ts->tv_nsec = (long int)(tv.tv_usec * 1000 + (usec % 1000000) * 1000);
|
||||
|
||||
if (ts->tv_nsec >= 1000000000L) {
|
||||
ts->tv_sec++;
|
||||
ts->tv_nsec -= 1000000000L;
|
||||
if (useconds == BHT_WAIT_FOREVER) {
|
||||
return os_cond_wait_internal(cond, mutex, false, 0);
|
||||
}
|
||||
else {
|
||||
return os_cond_wait_internal(cond, mutex, true, useconds);
|
||||
}
|
||||
}
|
||||
|
||||
int os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds)
|
||||
int
|
||||
os_cond_signal(korp_cond *cond)
|
||||
{
|
||||
return BHT_OK;
|
||||
}
|
||||
/* Signal the head wait node of wait list */
|
||||
os_mutex_lock(&cond->wait_list_lock);
|
||||
if (cond->thread_wait_list)
|
||||
os_sem_signal(&cond->thread_wait_list->sem);
|
||||
os_mutex_unlock(&cond->wait_list_lock);
|
||||
|
||||
int os_cond_signal(korp_cond *cond)
|
||||
{
|
||||
return BHT_OK;
|
||||
}
|
||||
|
||||
int os_thread_join(korp_tid thread, void **value_ptr)
|
||||
{
|
||||
return BHT_OK;
|
||||
}
|
||||
|
||||
int os_thread_detach(korp_tid thread)
|
||||
{
|
||||
return BHT_OK;
|
||||
}
|
||||
|
||||
void os_thread_exit(void *retval)
|
||||
{
|
||||
}
|
||||
|
||||
static os_thread_local_attribute uint8 *thread_stack_boundary = NULL;
|
||||
|
||||
uint8 *os_thread_get_stack_boundary()
|
||||
uint8 *
|
||||
os_thread_get_stack_boundary()
|
||||
{
|
||||
ULONG_PTR low_limit = 0, high_limit = 0;
|
||||
uint32 page_size;
|
||||
@ -167,10 +511,21 @@ uint8 *os_thread_get_stack_boundary()
|
||||
return thread_stack_boundary;
|
||||
}
|
||||
|
||||
static os_thread_local_attribute bool stack_guard_pages_inited = false;
|
||||
|
||||
bool
|
||||
os_thread_init_stack_guard_pages()
|
||||
{
|
||||
return true;
|
||||
ULONG StackSizeInBytes = 16 * 1024;
|
||||
bool ret;
|
||||
|
||||
if (stack_guard_pages_inited)
|
||||
return true;
|
||||
|
||||
ret = SetThreadStackGuarantee(&StackSizeInBytes);
|
||||
if (ret)
|
||||
stack_guard_pages_inited = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Reference in New Issue
Block a user