From bf7839d0f0a23cbbb9a24649af5211a3316bc5ff Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 11 Nov 2017 12:37:47 -0600 Subject: [PATCH] libc/signal: Add support for sigwait(). --- TODO | 26 ++++------ include/signal.h | 3 +- libc/signal/Make.defs | 4 +- libc/signal/sigwait.c | 110 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 123 insertions(+), 20 deletions(-) create mode 100644 libc/signal/sigwait.c diff --git a/TODO b/TODO index 1061679f52..49b788217c 100644 --- a/TODO +++ b/TODO @@ -557,36 +557,28 @@ o pthreads (sched/pthreads) exceptions as noted: accept() mq_timedsend() NA putpmsg() sigtimedwait() - 04 aio_suspend() NA msgrcv() pwrite() NA sigwait() + aio_suspend() NA msgrcv() pwrite() sigwait() NA clock_nanosleep() NA msgsnd() read() sigwaitinfo() - close() NA msync() NA readv() 01 sleep() - connect() nanosleep() recv() 02 system() + close() NA msync() readv() sleep() + connect() nanosleep() recv() 01 system() -- creat() open() recvfrom() tcdrain() - fcntl() pause() NA recvmsg() 01 usleep() + fcntl() pause() NA recvmsg() usleep() NA fdatasync() poll() select() -- wait() fsync() pread() sem_timedwait() waitid() NA getmsg() NA pselect() sem_wait() waitpid() NA getpmsg() pthread_cond_timedwait() send() write() - NA lockf() pthread_cond_wait() NA sendmsg() NA writev() + NA lockf() pthread_cond_wait() NA sendmsg() writev() mq_receive() pthread_join() sendto() - mq_send() pthread_testcancel() 03 sigpause() + mq_send() pthread_testcancel() sigpause() mq_timedreceive() NA putmsg() sigsuspend() NA Not supported -- Doesn't need instrumentation. Handled by lower level calls. nn See note nn - NOTE 01: sleep() and usleep() are user-space functions in the C library and cannot - serve as cancellation points. They are, however, simple wrappers around nanosleep - which is a true cancellation point. - NOTE 02: system() is actually implemented in apps/ as part of NSH. It cannot be - a cancellation point. - NOTE 03: sigpause() is a user-space function in the C library and cannot serve as - cancellation points. It is, however, a simple wrapper around sigsuspend() - which is a true cancellation point. - NOTE 04: aio_suspend() is a user-space function in the C library and cannot serve as - cancellation points. It does call around sigtimedwait() which is a true cancellation - point. + NOTE 01: system() is actually implemented in apps/ as part of NSH. It cannot be + a cancellation point but probably will cause a cancellation due to lower level + system calls. Status: Not really open. This is just the way it is. Priority: Nothing additional is planned. diff --git a/include/signal.h b/include/signal.h index 02e1e20122..b790c8dc16 100644 --- a/include/signal.h +++ b/include/signal.h @@ -1,7 +1,7 @@ /******************************************************************************** * include/signal.h * - * Copyright (C) 2007-2009, 2011, 2013-2016 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009, 2011, 2013-2017 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -308,6 +308,7 @@ int sigqueue(int pid, int signo, FAR void *sival_ptr); #endif int sigrelse(int signo); _sa_handler_t sigset(int signo, _sa_handler_t func); +int sigwait(FAR const sigset_t *set, FAR int *sig); int sigtimedwait(FAR const sigset_t *set, FAR struct siginfo *value, FAR const struct timespec *timeout); int sigsuspend(FAR const sigset_t *sigmask); diff --git a/libc/signal/Make.defs b/libc/signal/Make.defs index bedee1895e..7fdb9cbd1d 100644 --- a/libc/signal/Make.defs +++ b/libc/signal/Make.defs @@ -1,7 +1,7 @@ ############################################################################ # libc/signal/Make.defs # -# Copyright (C) 2011-2012, 2016 Gregory Nutt. All rights reserved. +# Copyright (C) 2011-2012, 2016-2017 Gregory Nutt. All rights reserved. # Author: Gregory Nutt # # Redistribution and use in source and binary forms, with or without @@ -39,7 +39,7 @@ ifneq ($(CONFIG_DISABLE_SIGNALS),y) CSRCS += sig_addset.c sig_delset.c sig_emptyset.c sig_fillset.c CSRCS += sig_hold.c sig_ignore.c sig_ismember.c sig_pause.c sig_raise.c -CSRCS += sig_relse.c sig_set.c signal.c +CSRCS += sig_relse.c sig_set.c signal.c sigwait.c # Add the signal directory to the build diff --git a/libc/signal/sigwait.c b/libc/signal/sigwait.c new file mode 100644 index 0000000000..8a3eeb0375 --- /dev/null +++ b/libc/signal/sigwait.c @@ -0,0 +1,110 @@ +/**************************************************************************** + * libc/signal/sigwait.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sigwait + * + * Description: + * The sigwait() function selects a pending signal from set, atomically + * clears it from the system's set of pending signals, and returns that + * signal number in the location referenced by sig. If prior to the call + * to sigwait() there are multiple pending instances of a single signal + * number, it is implementation-dependent whether upon successful return + * there are any remaining pending signals for that signal number. If the + * implementation supports queued signals and there are multiple signals + * queued for the signal number selected, the first such queued signal + * causes a return from sigwait() and the remainder remain queued. If no + * signal in set is pending at the time of the call, the thread is + * suspended until one or more becomes pending. The signals defined by set + * will been blocked at the time of the call to sigwait(); otherwise the + * behavior is undefined. The effect of sigwait() on the signal actions + * for the signals in set is unspecified. + * + * If more than one thread is using sigwait() to wait for the same + * signal, no more than one of these threads will return from sigwait() + * with the signal number. Which thread returns from sigwait() if more + * than a single thread is waiting is unspecified. + * + * Should any of the multiple pending signals in the range SIGRTMIN to + * SIGRTMAX be selected, it shall be the lowest numbered one. The selection + * order between realtime and non-realtime signals, or between multiple + * pending non-realtime signals, is unspecified. + * + * Input Parameters: + * set - The set of pending signals to wait for + * sig - The location in which to return the pending signal number. + * + * Returned Value: + * Upon successful completion, sigwait() stores the signal number of the + * received signal at the location referenced by sig and returns zero. + * Otherwise, an error number is returned to indicate the error. + * + ****************************************************************************/ + +int sigwait(FAR const sigset_t *set, FAR int *sig) +{ + int signo; + + DEBUGASSERT(set != NULL && sig != NULL); + + /* The standard sigwait() function behaves that same as sigwainfo() with + * the info argument set to NULL. + */ + + signo = sigwaitinfo(set, NULL); + if (signo < 0) + { + /* If sigwaitinfo() fails, return the error number */ + + return get_errno(); + } + + /* Return the signal number in the user provided location */ + + *sig = signo; + return OK; +}