diff options
| author | Mikhail Zakharov | 2019-01-02 10:44:52 -0500 |
|---|---|---|
| committer | Damien George | 2019-01-27 12:40:10 +1100 |
| commit | 18723e9889626a0700c2defaeba82e86b0b6f08a (patch) | |
| tree | 388f55ced3696a5f4eefa98ebf038f69d56bbc42 | |
| parent | 1e7b4222268d49c6a0e7b5a0033d3b25061653a7 (diff) | |
unix/mpthreadport: Remove busy wait loop in thread garbage collection.
One can't use pthread calls in a signal handler because they are not
async-signal-safe (see man signal-safety). Instead, sem_post can be used
to post from within a signal handler and this should be more efficient than
using a busy wait loop, waiting on a volatile variable.
| -rw-r--r-- | ports/unix/mpthreadport.c | 11 |
1 files changed, 5 insertions, 6 deletions
diff --git a/ports/unix/mpthreadport.c b/ports/unix/mpthreadport.c index 4efa5925b..29f2efe75 100644 --- a/ports/unix/mpthreadport.c +++ b/ports/unix/mpthreadport.c @@ -36,6 +36,7 @@ #include <signal.h> #include <sched.h> +#include <semaphore.h> // this structure forms a linked list, one node per active thread typedef struct _thread_t { @@ -53,7 +54,7 @@ STATIC thread_t *thread; // this is used to synchronise the signal handler of the thread // it's needed because we can't use any pthread calls in a signal handler -STATIC volatile int thread_signal_done; +STATIC sem_t thread_signal_done; // this signal handler is used to scan the regs and stack of a thread STATIC void mp_thread_gc(int signo, siginfo_t *info, void *context) { @@ -70,7 +71,7 @@ STATIC void mp_thread_gc(int signo, siginfo_t *info, void *context) { void **ptrs = (void**)(void*)MP_STATE_THREAD(pystack_start); gc_collect_root(ptrs, (MP_STATE_THREAD(pystack_cur) - MP_STATE_THREAD(pystack_start)) / sizeof(void*)); #endif - thread_signal_done = 1; + sem_post(&thread_signal_done); } } @@ -84,6 +85,7 @@ void mp_thread_init(void) { thread->ready = 1; thread->arg = NULL; thread->next = NULL; + sem_init(&thread_signal_done, 0, 0); // enable signal handler for garbage collection struct sigaction sa; @@ -122,11 +124,8 @@ void mp_thread_gc_others(void) { if (!th->ready) { continue; } - thread_signal_done = 0; pthread_kill(th->id, SIGUSR1); - while (thread_signal_done == 0) { - sched_yield(); - } + sem_wait(&thread_signal_done); } pthread_mutex_unlock(&thread_mutex); } |
