libs/libc/wqueue/work_usrthread.c: Revise commit 49e725625a. Use sigprocmask() so tht we do not lose a signal, not sched_lock() which will not do the job in SMP mode.

This commit is contained in:
Gregory Nutt 2018-09-14 09:02:03 -06:00
parent 49e725625a
commit dc48263a6a
2 changed files with 25 additions and 15 deletions

View File

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

View File

@ -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.
*/