Kaynağa Gözat

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.
Wenyong Huang 5 yıl önce
ebeveyn
işleme
388530c738

+ 11 - 8
core/app-framework/base/native/timer_wrapper.c

@@ -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);
     }
 

+ 3 - 3
core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c

@@ -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"),
@@ -1028,4 +1028,4 @@ get_lib_pthread_export_apis(NativeSymbol **p_lib_pthread_apis)
 {
     *p_lib_pthread_apis = native_symbols_lib_pthread;
     return sizeof(native_symbols_lib_pthread) / sizeof(NativeSymbol);
-}
+}

+ 18 - 5
core/shared/platform/alios/alios_thread.c

@@ -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

+ 17 - 4
core/shared/platform/common/freertos/freertos_thread.c

@@ -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)

+ 28 - 13
core/shared/platform/common/posix/posix_thread.c

@@ -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");
+    }
+
+    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) {
+    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

+ 1 - 1
core/shared/platform/include/platform_api_extension.h

@@ -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

+ 1 - 2
core/shared/platform/include/platform_common.h

@@ -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)

+ 1 - 1
core/shared/platform/linux-sgx/sgx_thread.c

@@ -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");

+ 2 - 3
core/shared/platform/riot/riot_thread.c

@@ -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

+ 1 - 1
core/shared/platform/windows/win_thread.c

@@ -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;
 }

+ 17 - 4
core/shared/platform/zephyr/zephyr_thread.c

@@ -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)

+ 4 - 4
core/shared/utils/bh_queue.c

@@ -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);

+ 1 - 1
core/shared/utils/bh_queue.h

@@ -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);

+ 11 - 5
core/shared/utils/runtime_timer.c

@@ -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;
         }

+ 1 - 1
core/shared/utils/runtime_timer.h

@@ -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

+ 4 - 2
wamr-sdk/app/libc-builtin-sysroot/include/pthread.h

@@ -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);
 
@@ -56,4 +58,4 @@ void *pthread_getspecific(pthread_key_t key);
 
 int pthread_key_delete(pthread_key_t key);
 
-#endif /* end of _WAMR_LIB_PTHREAD_H */
+#endif /* end of _WAMR_LIB_PTHREAD_H */