[3/6] Simplify Linux sig{timed}wait{info} implementations
Commit Message
This patch simplifies sig{timed}wait{info} by:
- Assuming __NR_rt_sigtimedwait existence on all architectures due minimum
kernel version requirement.
- Add libc.so private __sigtimedwait symbol.
- Call __sigtimedwait on both sigwait and sigwaitinfo.
Checked on x86_64-linux-gnu.
* sysdeps/unix/sysv/linux/Versions (libc) [GLIBC_PRIVATE]: Add
__sigtimedwait.
* sysdeps/unix/sysv/linux/sigtimedwait.c: Simplify includes and
assume __NR_rt_sigtimedwait.
* sysdeps/unix/sysv/linux/sigwait.c (__sigwait): Call __sigtimedwait.
* sysdeps/unix/sysv/linux/sigwaitinfo.c (__sigwaitinfo): Likewise.
Signed-off-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
---
ChangeLog | 7 ++++
sysdeps/unix/sysv/linux/Versions | 1 +
sysdeps/unix/sysv/linux/sigtimedwait.c | 9 -----
sysdeps/unix/sysv/linux/sigwait.c | 67 ++++------------------------------
sysdeps/unix/sysv/linux/sigwaitinfo.c | 40 ++------------------
5 files changed, 18 insertions(+), 106 deletions(-)
Comments
On Fri, Nov 3, 2017 at 5:40 PM, Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
> This patch simplifies sig{timed}wait{info} by:
>
> - Assuming __NR_rt_sigtimedwait existence on all architectures due minimum
> kernel version requirement.
As with __NR_rt_sigqueueinfo, please document in the commit message
the oldest kernel version that provides __NR_rt_sigtimedwait on all
architectures.
> - Add libc.so private __sigtimedwait symbol.
It is not apparent to me why this is necessary, please explain.
> * sysdeps/unix/sysv/linux/sigwait.c (__sigwait): Call __sigtimedwait.
> * sysdeps/unix/sysv/linux/sigwaitinfo.c (__sigwaitinfo): Likewise.
As with your sigpause/sigsuspend changes, please mention the addition
of LIBC_CANCEL_HANDLED annotations in the ChangeLog and add /*
__sigtimedwait handles cancellation */ comments above the
LIBC_CANCEL_HANDLED lines.
zw
On 05/11/2017 19:36, Zack Weinberg wrote:
> On Fri, Nov 3, 2017 at 5:40 PM, Adhemerval Zanella
> <adhemerval.zanella@linaro.org> wrote:
>> This patch simplifies sig{timed}wait{info} by:
>>
>> - Assuming __NR_rt_sigtimedwait existence on all architectures due minimum
>> kernel version requirement.
>
> As with __NR_rt_sigqueueinfo, please document in the commit message
> the oldest kernel version that provides __NR_rt_sigtimedwait on all
> architectures.
Ack, as for __NR_rt_sigqueueinfo I will state Linux 2.6.
>
>> - Add libc.so private __sigtimedwait symbol.
>
> It is not apparent to me why this is necessary, please explain.
Now that sigwait is based on a internal sigtimedwait call and it is
present of both libc.so and libpthread.so we need to add an external
private definition for libpthread.so call.
>
>> * sysdeps/unix/sysv/linux/sigwait.c (__sigwait): Call __sigtimedwait.
>> * sysdeps/unix/sysv/linux/sigwaitinfo.c (__sigwaitinfo): Likewise.
>
> As with your sigpause/sigsuspend changes, please mention the addition
> of LIBC_CANCEL_HANDLED annotations in the ChangeLog and add /*
> __sigtimedwait handles cancellation */ comments above the
> LIBC_CANCEL_HANDLED lines.
>
> zw
>
Ack.
@@ -172,6 +172,7 @@ libc {
__open_nocancel;
__read_nocancel;
__close_nocancel;
+ __sigtimedwait;
# functions used by nscd
__netlink_assert_response;
}
@@ -17,13 +17,7 @@
#include <errno.h>
#include <signal.h>
-#include <string.h>
-
-#include <nptl/pthreadP.h>
#include <sysdep-cancel.h>
-#include <sys/syscall.h>
-
-#ifdef __NR_rt_sigtimedwait
int
__sigtimedwait (const sigset_t *set, siginfo_t *info,
@@ -44,6 +38,3 @@ __sigtimedwait (const sigset_t *set, siginfo_t *info,
}
libc_hidden_def (__sigtimedwait)
weak_alias (__sigtimedwait, sigtimedwait)
-#else
-# include <signal/sigtimedwait.c>
-#endif
@@ -15,73 +15,20 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <errno.h>
#include <signal.h>
-#define __need_NULL
-#include <stddef.h>
-#include <string.h>
-
-#include <nptl/pthreadP.h>
#include <sysdep-cancel.h>
-#include <sys/syscall.h>
-
-#ifdef __NR_rt_sigtimedwait
-
-/* Return any pending signal or wait for one for the given time. */
-static int
-do_sigwait (const sigset_t *set, int *sig)
-{
- int ret;
-
- /* XXX The size argument hopefully will have to be changed to the
- real size of the user-level sigset_t. */
-#ifdef INTERNAL_SYSCALL
- INTERNAL_SYSCALL_DECL (err);
- do
- ret = INTERNAL_SYSCALL (rt_sigtimedwait, err, 4, set,
- NULL, NULL, _NSIG / 8);
- while (INTERNAL_SYSCALL_ERROR_P (ret, err)
- && INTERNAL_SYSCALL_ERRNO (ret, err) == EINTR);
- if (! INTERNAL_SYSCALL_ERROR_P (ret, err))
- {
- *sig = ret;
- ret = 0;
- }
- else
- ret = INTERNAL_SYSCALL_ERRNO (ret, err);
-#else
- do
- ret = INLINE_SYSCALL (rt_sigtimedwait, 4, set, NULL, NULL, _NSIG / 8);
- while (ret == -1 && errno == EINTR);
- if (ret != -1)
- {
- *sig = ret;
- ret = 0;
- }
- else
- ret = errno;
-#endif
-
- return ret;
-}
int
__sigwait (const sigset_t *set, int *sig)
{
- if (SINGLE_THREAD_P)
- return do_sigwait (set, sig);
-
- int oldtype = LIBC_CANCEL_ASYNC ();
-
- int result = do_sigwait (set, sig);
-
- LIBC_CANCEL_RESET (oldtype);
-
- return result;
+ siginfo_t si;
+ if (__sigtimedwait (set, &si, 0) < 0)
+ return -1;
+ *sig = si.si_signo;
+ return 0;
}
libc_hidden_def (__sigwait)
weak_alias (__sigwait, sigwait)
-#else
-# include <sysdeps/posix/sigwait.c>
-#endif
strong_alias (__sigwait, __libc_sigwait)
+
+LIBC_CANCEL_HANDLED ();
@@ -15,52 +15,18 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <errno.h>
#include <signal.h>
-#define __need_NULL
-#include <stddef.h>
-#include <string.h>
-
-#include <nptl/pthreadP.h>
#include <sysdep-cancel.h>
-#include <sys/syscall.h>
-
-#ifdef __NR_rt_sigtimedwait
/* Return any pending signal or wait for one for the given time. */
int
__sigwaitinfo (const sigset_t *set, siginfo_t *info)
{
- sigset_t tmpset;
- if (set != NULL
- && (__builtin_expect (__sigismember (set, SIGCANCEL), 0)
- || __builtin_expect (__sigismember (set, SIGSETXID), 0)))
- {
- /* Create a temporary mask without the bit for SIGCANCEL set. */
- // We are not copying more than we have to.
- memcpy (&tmpset, set, _NSIG / 8);
- __sigdelset (&tmpset, SIGCANCEL);
- __sigdelset (&tmpset, SIGSETXID);
- set = &tmpset;
- }
-
- /* XXX The size argument hopefully will have to be changed to the
- real size of the user-level sigset_t. */
- int result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, NULL, _NSIG / 8);
-
- /* The kernel generates a SI_TKILL code in si_code in case tkill is
- used. tkill is transparently used in raise(). Since having
- SI_TKILL as a code is useful in general we fold the results
- here. */
- if (result != -1 && info != NULL && info->si_code == SI_TKILL)
- info->si_code = SI_USER;
-
- return result;
+ return __sigtimedwait (set, info, 0);
}
libc_hidden_def (__sigwaitinfo)
weak_alias (__sigwaitinfo, sigwaitinfo)
-#else
-# include <signal/sigwaitinfo.c>
-#endif
strong_alias (__sigwaitinfo, __libc_sigwaitinfo)
+
+LIBC_CANCEL_HANDLED ();