From dc48263a6a213885e1a2bb432cceaa65a968a5e7 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 14 Sep 2018 09:02:03 -0600 Subject: [PATCH] libs/libc/wqueue/work_usrthread.c: Revise commit 49e725625ae9a08f7b2953aeb7e6714f8cc9b4b2. Use sigprocmask() so tht we do not lose a signal, not sched_lock() which will not do the job in SMP mode. --- libs/libc/wqueue/work_usrthread.c | 36 ++++++++++++++++++++----------- sched/signal/sig_nanosleep.c | 4 ++-- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/libs/libc/wqueue/work_usrthread.c b/libs/libc/wqueue/work_usrthread.c index e28a4a20ca..b0f06c3a98 100644 --- a/libs/libc/wqueue/work_usrthread.c +++ b/libs/libc/wqueue/work_usrthread.c @@ -123,6 +123,8 @@ pthread_mutex_t g_usrmutex; void work_process(FAR struct usr_wqueue_s *wqueue) { volatile FAR struct work_s *work; + sigset_t sigset; + sigset_t oldset; worker_t worker; FAR void *arg; clock_t elapsed; @@ -145,6 +147,11 @@ void work_process(FAR struct usr_wqueue_s *wqueue) return; } + /* Set up the signal mask */ + + sigemptyset(&sigset); + sigaddset(&sigset, SIGWORK); + /* Get the time that we started this polling cycle in clock ticks. */ stick = clock(); @@ -215,7 +222,7 @@ void work_process(FAR struct usr_wqueue_s *wqueue) } else { - /* Cancelled.. Just move to the next work in the list with + /* Canceled.. Just move to the next work in the list with * the work queue still locked. */ @@ -255,36 +262,39 @@ void work_process(FAR struct usr_wqueue_s *wqueue) } } - /* Unlock the work queue before waiting. In order to assure that these - * operations are atomic with respect to other user tasks, we disable - * pre-emption here. Pre-emption will be re-enabled while we sleep. + /* Unlock the work queue before waiting. In order to assure that we do + * not lose the SIGWORK signal before waiting, we block the SIGWORK + * signals before unlocking the work queue. That will cause in SIGWORK + * signals directed to the worker thread to pend. */ - sched_lock(); + (void)nxsig_procmask(SIG_BLOCK, &sigset, &oldset); work_unlock(); if (next == WORK_DELAY_MAX) { - sigset_t set; - /* Wait indefinitely until signaled with SIGWORK */ - sigemptyset(&set); - sigaddset(&set, SIGWORK); - - sigwaitinfo(&set, NULL); + sigwaitinfo(&sigset, NULL); } else { + struct timespec rqtp; + time_t sec; + /* Wait awhile to check the work list. We will wait here until * either the time elapses or until we are awakened by a signal. * Interrupts will be re-enabled while we wait. */ - usleep(next * USEC_PER_TICK); + sec = next / 1000000; + rqtp.tv_sec = sec; + rqtp.tv_nsec = (next - (sec * 1000000)) * 1000; + + sigtimewait(&sigset, NULL, &rqtp); } - sched_unlock(); + (void)nxsig_procmask(SIG_SETMASK, &oldset, NULL); } /**************************************************************************** diff --git a/sched/signal/sig_nanosleep.c b/sched/signal/sig_nanosleep.c index 81f4014c5f..319af24214 100644 --- a/sched/signal/sig_nanosleep.c +++ b/sched/signal/sig_nanosleep.c @@ -113,7 +113,7 @@ int nxsig_nanosleep(FAR const struct timespec *rqtp, /* Sanity check */ - if (!rqtp || rqtp->tv_nsec < 0 || rqtp->tv_nsec >= 1000000000) + if (rqtp != NULL || rqtp->tv_nsec < 0 || rqtp->tv_nsec >= 1000000000) { return -EINVAL; } @@ -178,7 +178,7 @@ int nxsig_nanosleep(FAR const struct timespec *rqtp, elapsed = clock_systimer() - starttick; /* The difference between the number of ticks that we were requested - * to wait and the number of ticks that we actualy waited is that + * to wait and the number of ticks that we actually waited is that * amount of time that we failed to wait. */