[3/6] Simplify Linux sig{timed}wait{info} implementations

Message ID 1509745249-11404-3-git-send-email-adhemerval.zanella@linaro.org
State Dropped
Headers

Commit Message

Adhemerval Zanella Nov. 3, 2017, 9:40 p.m. UTC
  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

Zack Weinberg Nov. 5, 2017, 9:36 p.m. UTC | #1
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
  
Adhemerval Zanella Nov. 6, 2017, 11:03 a.m. UTC | #2
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.
  

Patch

diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions
index 6c9e06f..d3dbcde 100644
--- a/sysdeps/unix/sysv/linux/Versions
+++ b/sysdeps/unix/sysv/linux/Versions
@@ -172,6 +172,7 @@  libc {
     __open_nocancel;
     __read_nocancel;
     __close_nocancel;
+    __sigtimedwait;
     # functions used by nscd
     __netlink_assert_response;
   }
diff --git a/sysdeps/unix/sysv/linux/sigtimedwait.c b/sysdeps/unix/sysv/linux/sigtimedwait.c
index 21e9fca..f74a921 100644
--- a/sysdeps/unix/sysv/linux/sigtimedwait.c
+++ b/sysdeps/unix/sysv/linux/sigtimedwait.c
@@ -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
diff --git a/sysdeps/unix/sysv/linux/sigwait.c b/sysdeps/unix/sysv/linux/sigwait.c
index 18a4485..2e8fa71 100644
--- a/sysdeps/unix/sysv/linux/sigwait.c
+++ b/sysdeps/unix/sysv/linux/sigwait.c
@@ -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 ();
diff --git a/sysdeps/unix/sysv/linux/sigwaitinfo.c b/sysdeps/unix/sysv/linux/sigwaitinfo.c
index 0062d3e..6267425 100644
--- a/sysdeps/unix/sysv/linux/sigwaitinfo.c
+++ b/sysdeps/unix/sysv/linux/sigwaitinfo.c
@@ -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 ();