Modify os_cond_reltimedwait to support long time wait (#461)

Modify the argument of os_cond_reltimedwait to uint64 type to support long time wait, and handle possible integer overflow.
This commit is contained in:
Wenyong Huang 2020-12-07 17:37:53 +08:00 committed by GitHub
parent a84d51271c
commit 388530c738
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 121 additions and 58 deletions

View File

@ -42,17 +42,18 @@ wasm_timer_callback(timer_id_t id, unsigned int mod_id)
void * thread_modulers_timer_check(void * arg)
{
int ms_to_expiry;
uint32 ms_to_expiry;
uint64 us_to_wait;
while (timer_thread_run) {
ms_to_expiry = -1;
ms_to_expiry = (uint32)-1;
os_mutex_lock(&g_timer_ctx_list_mutex);
timer_ctx_node_t* elem = (timer_ctx_node_t*)
bh_list_first_elem(&g_timer_ctx_list);
while (elem) {
int next = check_app_timers(elem->timer_ctx);
if (next != -1) {
if (ms_to_expiry == -1 || ms_to_expiry > next)
uint32 next = check_app_timers(elem->timer_ctx);
if (next != (uint32)-1) {
if (ms_to_expiry == (uint32)-1 || ms_to_expiry > next)
ms_to_expiry = next;
}
@ -60,11 +61,13 @@ void * thread_modulers_timer_check(void * arg)
}
os_mutex_unlock(&g_timer_ctx_list_mutex);
if (ms_to_expiry == -1)
ms_to_expiry = 60 * 1000;
if (ms_to_expiry == (uint32)-1)
us_to_wait = BHT_WAIT_FOREVER;
else
us_to_wait = (uint64)ms_to_expiry * 1000;
os_mutex_lock(&g_timer_ctx_list_mutex);
os_cond_reltimedwait(&g_timer_ctx_list_cond, &g_timer_ctx_list_mutex,
ms_to_expiry * 1000);
us_to_wait);
os_mutex_unlock(&g_timer_ctx_list_mutex);
}

View File

@ -848,7 +848,7 @@ pthread_cond_wait_wrapper(wasm_exec_env_t exec_env, uint32 *cond, uint32 *mutex)
*/
static int32
pthread_cond_timedwait_wrapper(wasm_exec_env_t exec_env, uint32 *cond,
uint32 *mutex, uint32 useconds)
uint32 *mutex, uint64 useconds)
{
ThreadInfoNode *cond_info_node, *mutex_info_node;
@ -1014,7 +1014,7 @@ static NativeSymbol native_symbols_lib_pthread[] = {
REG_NATIVE_FUNC(pthread_mutex_destroy, "(*)i"),
REG_NATIVE_FUNC(pthread_cond_init, "(**)i"),
REG_NATIVE_FUNC(pthread_cond_wait, "(**)i"),
REG_NATIVE_FUNC(pthread_cond_timedwait, "(**i)i"),
REG_NATIVE_FUNC(pthread_cond_timedwait, "(**I)i"),
REG_NATIVE_FUNC(pthread_cond_signal, "(*)i"),
REG_NATIVE_FUNC(pthread_cond_destroy, "(*)i"),
REG_NATIVE_FUNC(pthread_key_create, "(*i)i"),

View File

@ -273,7 +273,7 @@ os_cond_destroy(korp_cond *cond)
static int
os_cond_wait_internal(korp_cond *cond, korp_mutex *mutex,
bool timed, int mills)
bool timed, uint32 mills)
{
os_thread_wait_node *node = &thread_data_current()->wait_node;
@ -319,12 +319,25 @@ os_cond_wait(korp_cond *cond, korp_mutex *mutex)
}
int
os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int useconds)
os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds)
{
if (useconds == BHT_WAIT_FOREVER)
if (useconds == BHT_WAIT_FOREVER) {
return os_cond_wait_internal(cond, mutex, false, 0);
else
return os_cond_wait_internal(cond, mutex, true, useconds / 1000);
}
else {
uint64 mills_64 = useconds / 1000;
uint32 mills;
if (mills_64 < (uint64)(UINT32_MAX - 1)) {
mills = (uint64)mills_64;
}
else {
mills = UINT32_MAX - 1;
os_printf("Warning: os_cond_reltimedwait exceeds limit, "
"set to max timeout instead\n");
}
return os_cond_wait_internal(cond, mutex, true, mills);
}
}
int

View File

@ -404,12 +404,25 @@ int os_cond_wait(korp_cond *cond, korp_mutex *mutex)
return os_cond_wait_internal(cond, mutex, false, 0);
}
int os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int useconds)
int os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds)
{
if (useconds == BHT_WAIT_FOREVER)
if (useconds == BHT_WAIT_FOREVER) {
return os_cond_wait_internal(cond, mutex, false, 0);
else
return os_cond_wait_internal(cond, mutex, true, useconds / 1000);
}
else {
uint64 mills_64 = useconds / 1000;
int32 mills;
if (mills_64 < (uint64)INT32_MAX) {
mills = (int32)mills_64;
}
else {
mills = INT32_MAX;
os_printf("Warning: os_cond_reltimedwait exceeds limit, "
"set to max timeout instead\n");
}
return os_cond_wait_internal(cond, mutex, true, mills);
}
}
int os_cond_signal(korp_cond *cond)

View File

@ -163,27 +163,48 @@ int os_cond_wait(korp_cond *cond, korp_mutex *mutex)
return BHT_OK;
}
static void msec_nsec_to_abstime(struct timespec *ts, int usec)
static void msec_nsec_to_abstime(struct timespec *ts, uint64 usec)
{
struct timeval tv;
long int tv_sec_new, tv_nsec_new;
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);
tv_sec_new = (long int)(tv.tv_sec + usec / 1000000);
if (tv_sec_new >= tv.tv_sec) {
ts->tv_sec = tv_sec_new;
}
else {
/* integer overflow */
ts->tv_sec = LONG_MAX;
os_printf("Warning: os_cond_reltimedwait exceeds limit, "
"set to max timeout instead\n");
}
if (ts->tv_nsec >= 1000000000L) {
tv_nsec_new = (long int)(tv.tv_usec * 1000 + (usec % 1000000) * 1000);
if (tv.tv_usec * 1000 >= tv.tv_usec
&& tv_nsec_new >= tv.tv_usec * 1000) {
ts->tv_nsec = tv_nsec_new;
}
else {
/* integer overflow */
ts->tv_nsec = LONG_MAX;
os_printf("Warning: os_cond_reltimedwait exceeds limit, "
"set to max timeout instead\n");
}
if (ts->tv_nsec >= 1000000000L && ts->tv_sec < LONG_MAX) {
ts->tv_sec++;
ts->tv_nsec -= 1000000000L;
}
}
int os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int useconds)
int os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds)
{
int ret;
struct timespec abstime;
if (useconds == (int)BHT_WAIT_FOREVER)
if (useconds == BHT_WAIT_FOREVER)
ret = pthread_cond_wait(cond, mutex);
else {
msec_nsec_to_abstime(&abstime, useconds);
@ -290,7 +311,6 @@ mask_signals(int how)
__attribute__((noreturn)) static void
signal_callback(int sig_num, siginfo_t *sig_info, void *sig_ucontext)
{
int i;
void *sig_addr = sig_info->si_addr;
mask_signals(SIG_BLOCK);
@ -314,12 +334,7 @@ signal_callback(int sig_num, siginfo_t *sig_info, void *sig_ucontext)
break;
}
/* divived by 0 to make it abort */
i = os_printf(" ");
os_printf("%d\n", i / (i - 1));
/* access NULL ptr to make it abort */
os_printf("%d\n", *(uint32*)(uintptr_t)(i - 1));
exit(1);
abort();
}
int

View File

@ -138,7 +138,7 @@ int os_cond_wait(korp_cond *cond, korp_mutex *mutex);
*
* @return 0 if success
*/
int os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int useconds);
int os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds);
/**
* Signals the condition variable

View File

@ -19,8 +19,7 @@ extern "C" {
#define BHT_TIMED_OUT (1)
#define BHT_OK (0)
#define BHT_NO_WAIT 0x00000000
#define BHT_WAIT_FOREVER 0xFFFFFFFF
#define BHT_WAIT_FOREVER ((uint64)-1LL)
#define BH_KB (1024)
#define BH_MB ((BH_KB)*1024)

View File

@ -129,7 +129,7 @@ int os_cond_wait(korp_cond *cond, korp_mutex *mutex)
return BHT_OK;
}
int os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int useconds)
int os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds)
{
os_printf("warning: SGX pthread_cond_timedwait isn't supported, "
"calling pthread_cond_wait instead!\n");

View File

@ -399,11 +399,10 @@ os_cond_wait(korp_cond *cond, korp_mutex *mutex)
}
int
os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int useconds)
os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds)
{
uint64 useconds64 = (uint64) useconds;
return os_cond_wait_internal(cond, mutex,
(useconds64 != BHT_WAIT_FOREVER), useconds64);
(useconds != BHT_WAIT_FOREVER), useconds);
}
int

View File

@ -125,7 +125,7 @@ static void msec_nsec_to_abstime(struct timespec *ts, int usec)
}
}
int os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int useconds)
int os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds)
{
return BHT_OK;
}

View File

@ -420,13 +420,26 @@ int os_cond_wait(korp_cond *cond, korp_mutex *mutex)
return os_cond_wait_internal(cond, mutex, false, 0);
}
int os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int useconds)
int os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds)
{
if (useconds == BHT_WAIT_FOREVER)
if (useconds == BHT_WAIT_FOREVER) {
return os_cond_wait_internal(cond, mutex, false, 0);
else
return os_cond_wait_internal(cond, mutex, true, useconds / 1000);
}
else {
uint64 mills_64 = useconds / 1000;
int32 mills;
if (mills_64 < (uint64)INT32_MAX) {
mills = (int32)mills_64;
}
else {
mills = INT32_MAX;
os_printf("Warning: os_cond_reltimedwait exceeds limit, "
"set to max timeout instead\n");
}
return os_cond_wait_internal(cond, mutex, true, mills);
}
}
int os_cond_signal(korp_cond *cond)

View File

@ -171,7 +171,7 @@ void bh_free_msg(bh_queue_node *msg)
bh_queue_free(msg);
}
bh_message_t bh_get_msg(bh_queue *queue, int timeout)
bh_message_t bh_get_msg(bh_queue *queue, uint64 timeout_us)
{
bh_queue_node *msg = NULL;
bh_queue_mutex_lock(&queue->queue_lock);
@ -180,13 +180,13 @@ bh_message_t bh_get_msg(bh_queue *queue, int timeout)
bh_assert(queue->head == NULL);
bh_assert(queue->tail == NULL);
if (timeout == 0) {
if (timeout_us == 0) {
bh_queue_mutex_unlock(&queue->queue_lock);
return NULL;
}
bh_queue_cond_timedwait(&queue->queue_wait_cond, &queue->queue_lock,
timeout);
timeout_us);
}
if (queue->cnt == 0) {
@ -226,7 +226,7 @@ void bh_queue_enter_loop_run(bh_queue *queue,
return;
while (!queue->exit_loop_run) {
bh_queue_node * message = bh_get_msg(queue, (int)BHT_WAIT_FOREVER);
bh_queue_node * message = bh_get_msg(queue, BHT_WAIT_FOREVER);
if (message) {
handle_cb(message, arg);

View File

@ -56,7 +56,7 @@ bool bh_post_msg(bh_queue *queue, unsigned short tag, void *body,
unsigned int len);
bool bh_post_msg2(bh_queue *queue, bh_message_t msg);
bh_message_t bh_get_msg(bh_queue *queue, int timeout);
bh_message_t bh_get_msg(bh_queue *queue, uint64 timeout_us);
unsigned
bh_queue_get_message_count(bh_queue *queue);

View File

@ -396,7 +396,6 @@ handle_expired_timers(timer_ctx_t ctx, app_timer_t *expired)
if (t->is_periodic) {
/* if it is repeating, then reschedule it; */
reschedule_timer(ctx, t);
}
else {
/* else move it to idle list */
@ -423,10 +422,10 @@ get_expiry_ms(timer_ctx_t ctx)
return ms_to_next_expiry;
}
int
uint32
check_app_timers(timer_ctx_t ctx)
{
app_timer_t *t, *expired = NULL;
app_timer_t *t, *expired = NULL, *expired_end = NULL;
uint64 now = bh_get_tick_ms();
os_mutex_lock(&ctx->mutex);
@ -436,8 +435,15 @@ check_app_timers(timer_ctx_t ctx)
if (now >= t->expiry) {
ctx->app_timers = t->next;
t->next = expired;
expired = t;
/* append t to the end of expired list */
t->next = NULL;
if (!expired_end) {
expired = expired_end = t;
}
else {
expired_end->next = t;
expired_end = t;
}
t = ctx->app_timers;
}

View File

@ -32,7 +32,7 @@ bool sys_timer_destroy(timer_ctx_t ctx, uint32 timer_id);
bool sys_timer_cancel(timer_ctx_t ctx, uint32 timer_id);
bool sys_timer_restart(timer_ctx_t ctx, uint32 timer_id, int interval);
void cleanup_app_timers(timer_ctx_t ctx);
int check_app_timers(timer_ctx_t ctx);
uint32 check_app_timers(timer_ctx_t ctx);
uint32 get_expiry_ms(timer_ctx_t ctx);
#ifdef __cplusplus

View File

@ -6,6 +6,8 @@
#ifndef _WAMR_LIB_PTHREAD_H
#define _WAMR_LIB_PTHREAD_H
#include <stdint.h>
/* Data type define of pthread, mutex, cond and key */
typedef unsigned int pthread_t;
typedef unsigned int pthread_mutex_t;
@ -41,7 +43,7 @@ int pthread_cond_init(pthread_cond_t *cond, const void *attr);
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
unsigned int useconds);
uint64_t useconds);
int pthread_cond_signal(pthread_cond_t *cond);