Implement sigtimedwait and sigwaitinfo syscalls.
authorDavid Xu <davidxu@dragonflybsd.org>
Sun, 20 Feb 2005 01:17:44 +0000 (01:17 +0000)
committerDavid Xu <davidxu@dragonflybsd.org>
Sun, 20 Feb 2005 01:17:44 +0000 (01:17 +0000)
Reviewed by: dillon

sys/kern/init_sysent.c
sys/kern/kern_sig.c
sys/kern/syscalls.c
sys/kern/syscalls.master
sys/sys/syscall-args
sys/sys/syscall-hide.h
sys/sys/syscall.h
sys/sys/syscall.mk
sys/sys/sysproto.h
sys/sys/sysunion.h

index fc0f368..117d08c 100644 (file)
@@ -2,7 +2,7 @@
  * System call switch table.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $DragonFly: src/sys/kern/init_sysent.c,v 1.23 2005/01/31 17:38:30 joerg Exp $
+ * $DragonFly: src/sys/kern/init_sysent.c,v 1.24 2005/02/20 01:17:44 davidxu Exp $
  * created from DragonFly: src/sys/kern/syscalls.master,v 1.18 2005/01/31 17:35:35 joerg Exp 
  */
 
@@ -367,8 +367,8 @@ struct sysent sysent[] = {
        { AS(sigaction_args), (sy_call_t *)sigaction }, /* 342 = sigaction */
        { AS(sigpending_args), (sy_call_t *)sigpending },       /* 343 = sigpending */
        { AS(sigreturn_args), (sy_call_t *)sigreturn }, /* 344 = sigreturn */
-       { 0, (sy_call_t *)nosys },                      /* 345 = sigtimedwait */
-       { 0, (sy_call_t *)nosys },                      /* 346 = sigwaitinfo */
+       { AS(sigtimedwait_args), (sy_call_t *)sigtimedwait },   /* 345 = sigtimedwait */
+       { AS(sigwaitinfo_args), (sy_call_t *)sigwaitinfo },     /* 346 = sigwaitinfo */
        { AS(__acl_get_file_args), (sy_call_t *)__acl_get_file },       /* 347 = __acl_get_file */
        { AS(__acl_set_file_args), (sy_call_t *)__acl_set_file },       /* 348 = __acl_set_file */
        { AS(__acl_get_fd_args), (sy_call_t *)__acl_get_fd },   /* 349 = __acl_get_fd */
index 8057504..7e36567 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)kern_sig.c  8.7 (Berkeley) 4/18/94
  * $FreeBSD: src/sys/kern/kern_sig.c,v 1.72.2.17 2003/05/16 16:34:34 obrien Exp $
- * $DragonFly: src/sys/kern/kern_sig.c,v 1.33 2004/11/23 06:32:32 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_sig.c,v 1.34 2005/02/20 01:17:44 davidxu Exp $
  */
 
 #include "opt_ktrace.h"
@@ -80,6 +80,8 @@ static void   stop(struct proc *);
 #ifdef SMP
 static void    signotify_remote(void *arg);
 #endif
+static int     kern_sigtimedwait(sigset_t set, siginfo_t *info,
+                   struct timespec *timeout);
 
 static int     filt_sigattach(struct knote *kn);
 static void    filt_sigdetach(struct knote *kn);
@@ -1019,6 +1021,158 @@ signotify_remote(void *arg)
 
 #endif
 
+static int
+kern_sigtimedwait(sigset_t waitset, siginfo_t *info, struct timespec *timeout)
+{
+       sigset_t savedmask, set;
+       struct proc *p = curproc;
+       int error, sig, hz, timevalid = 0;
+       struct timespec rts, ets, ts;
+       struct timeval tv;
+
+       error = 0;
+       sig = 0;
+       SIG_CANTMASK(waitset);
+       savedmask = p->p_sigmask;
+
+       if (timeout) {
+               if (timeout->tv_sec < 0 || 
+                   (timeout->tv_nsec >= 0 && timeout->tv_nsec < 1000000000)) {
+                       timevalid = 1;
+                       getnanouptime(&rts);
+                       ets = rts;
+                       timespecadd(&ets, timeout);
+               }
+       }
+
+       for (;;) {
+               set = p->p_siglist;
+               SIGSETAND(set, waitset);
+               if ((sig = sig_ffs(&set)) != 0) {
+                       SIGFILLSET(p->p_sigmask);
+                       SIGDELSET(p->p_sigmask, sig);
+                       sig = issignal(p);
+                       /*
+                        * It may be a STOP signal, in the case, issignal
+                        * returns 0, because we may stop there, and new
+                        * signal can come in, we should restart if we got
+                        * nothing.
+                        */
+                       if (sig == 0)
+                               continue;
+                       else
+                               break;
+               }
+
+               /*
+                * Previous checking got nothing, and we retried but still
+                * got nothing, we should return the error status.
+                */
+               if (error)
+                       break;
+
+               /*
+                * POSIX says this must be checked after looking for pending
+                * signals.
+                */
+               if (timeout) {
+                       if (!timevalid) {
+                               error = EINVAL;
+                               break;
+                       }
+                       getnanouptime(&rts);
+                       if (timespeccmp(&rts, &ets, >=)) {
+                               error = EAGAIN;
+                               break;
+                       }
+                       ts = ets;
+                       timespecsub(&ts, &rts);
+                       TIMESPEC_TO_TIMEVAL(&tv, &ts);
+                       hz = tvtohz_high(&tv);
+               } else
+                       hz = 0;
+
+               p->p_sigmask = savedmask;
+               SIGSETNAND(p->p_sigmask, waitset);
+               error = tsleep(&p->p_sigacts, PCATCH, "sigwt", hz);
+               if (timeout) {
+                       if (error == ERESTART) {
+                               /* can not restart a timeout wait. */
+                               error = EINTR;
+                       } else if (error == EAGAIN) {
+                               /* will calculate timeout by ourself. */
+                               error = 0;
+                       }
+               }
+               /* Retry ... */
+       }
+
+       p->p_sigmask = savedmask;
+       if (sig) {
+               error = 0;
+               bzero(info, sizeof(*info));
+               info->si_signo = sig;
+               SIGDELSET(p->p_siglist, sig);   /* take the signal! */
+       }
+       return (error);
+}
+
+int
+sigtimedwait(struct sigtimedwait_args *uap)
+{
+       struct timespec ts;
+       struct timespec *timeout;
+       sigset_t set;
+       siginfo_t info;
+       int error;
+
+       if (uap->timeout) {
+               error = copyin(uap->timeout, &ts, sizeof(ts));
+               if (error)
+                       return (error);
+               timeout = &ts;
+       } else {
+               timeout = NULL;
+       }
+       error = copyin(uap->set, &set, sizeof(set));
+       if (error)
+               return (error);
+       error = kern_sigtimedwait(set, &info, timeout);
+       if (error)
+               return (error);
+       if (uap->info)
+               error = copyout(&info, uap->info, sizeof(info));
+       /* Repost if we got an error. */
+       if (error)
+               psignal(curproc, info.si_signo);
+       else
+               uap->sysmsg_result = info.si_signo;
+       return (error);
+}
+
+int
+sigwaitinfo(struct sigwaitinfo_args *uap)
+{
+       siginfo_t info;
+       sigset_t set;
+       int error;
+
+       error = copyin(uap->set, &set, sizeof(set));
+       if (error)
+               return (error);
+       error = kern_sigtimedwait(set, &info, NULL);
+       if (error)
+               return (error);
+       if (uap->info)
+               error = copyout(&info, uap->info, sizeof(info));
+       /* Repost if we got an error. */
+       if (error)
+               psignal(curproc, info.si_signo);
+       else
+               uap->sysmsg_result = info.si_signo;
+       return (error);
+}
+
 /*
  * If the current process has received a signal that would interrupt a
  * system call, return EINTR or ERESTART as appropriate.
index 8bfe1ac..97a3d3a 100644 (file)
@@ -2,7 +2,7 @@
  * System call names.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $DragonFly: src/sys/kern/syscalls.c,v 1.22 2005/01/31 17:38:30 joerg Exp $
+ * $DragonFly: src/sys/kern/syscalls.c,v 1.23 2005/02/20 01:17:44 davidxu Exp $
  * created from DragonFly: src/sys/kern/syscalls.master,v 1.18 2005/01/31 17:35:35 joerg Exp 
  */
 
@@ -352,8 +352,8 @@ char *syscallnames[] = {
        "sigaction",                    /* 342 = sigaction */
        "sigpending",                   /* 343 = sigpending */
        "sigreturn",                    /* 344 = sigreturn */
-       "#345",                 /* 345 = sigtimedwait */
-       "#346",                 /* 346 = sigwaitinfo */
+       "sigtimedwait",                 /* 345 = sigtimedwait */
+       "sigwaitinfo",                  /* 346 = sigwaitinfo */
        "__acl_get_file",                       /* 347 = __acl_get_file */
        "__acl_set_file",                       /* 348 = __acl_set_file */
        "__acl_get_fd",                 /* 349 = __acl_get_fd */
index edd4354..49363a3 100644 (file)
@@ -1,4 +1,4 @@
- $DragonFly: src/sys/kern/syscalls.master,v 1.18 2005/01/31 17:35:35 joerg Exp $
+ $DragonFly: src/sys/kern/syscalls.master,v 1.19 2005/02/20 01:17:44 davidxu Exp $
 
 ; @(#)syscalls.master  8.2 (Berkeley) 1/13/94
 ; $FreeBSD: src/sys/kern/syscalls.master,v 1.72.2.10 2002/07/12 08:22:46 alfred Exp $
                            struct sigaction *oact); }
 343    STD     POSIX   { int sigpending(sigset_t *set); }
 344    STD     BSD     { int sigreturn(ucontext_t *sigcntxp); }
-345    UNIMPL  NOHIDE  sigtimedwait
-346    UNIMPL  NOHIDE  sigwaitinfo
+345    STD     POSIX   { int sigtimedwait(const sigset_t *set,\
+                            siginfo_t *info, const struct timespec *timeout); }
+346    STD     POSIX   { int sigwaitinfo(const sigset_t *set,\
+                            siginfo_t *info); }
 347    STD     BSD     { int __acl_get_file(const char *path, \
                            acl_type_t type, struct acl *aclp); }
 348    STD     BSD     { int __acl_set_file(const char *path, \
index fa81b57..da43579 100644 (file)
@@ -1,6 +1,6 @@
 # System call argument table.
 # DO NOT EDIT-- this file is automatically generated.
-# $DragonFly: src/sys/sys/Attic/syscall-args,v 1.7 2005/01/31 18:18:21 joerg Exp $
+# $DragonFly: src/sys/sys/Attic/syscall-args,v 1.8 2005/02/20 01:17:43 davidxu Exp $
 
 # Created from DragonFly: src/sys/kern/syscalls.master,v 1.18 2005/01/31 17:35:35 joerg Exp 
 
@@ -219,6 +219,8 @@ int sigsuspend      sigsuspend      sigsuspend_args const sigset_t *        sigmask
 int    sigaction       sigaction       sigaction_args  int     sig     const struct sigaction *        act     struct sigaction *      oact
 int    sigpending      sigpending      sigpending_args sigset_t *      set
 int    sigreturn       sigreturn       sigreturn_args  ucontext_t *    sigcntxp
+int    sigtimedwait    sigtimedwait    sigtimedwait_args       const sigset_t *        set     siginfo_t *     info    const struct timespec * timeout
+int    sigwaitinfo     sigwaitinfo     sigwaitinfo_args        const sigset_t *        set     siginfo_t *     info
 int    __acl_get_file  __acl_get_file  __acl_get_file_args     const char *    path    acl_type_t      type    struct acl *    aclp
 int    __acl_set_file  __acl_set_file  __acl_set_file_args     const char *    path    acl_type_t      type    struct acl *    aclp
 int    __acl_get_fd    __acl_get_fd    __acl_get_fd_args       int     filedes acl_type_t      type    struct acl *    aclp
index 55dd0e2..9ca22c9 100644 (file)
@@ -2,7 +2,7 @@
  * System call hiders.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $DragonFly: src/sys/sys/syscall-hide.h,v 1.24 2005/01/31 17:38:30 joerg Exp $
+ * $DragonFly: src/sys/sys/syscall-hide.h,v 1.25 2005/02/20 01:17:43 davidxu Exp $
  * created from DragonFly: src/sys/kern/syscalls.master,v 1.18 2005/01/31 17:35:35 joerg Exp 
  */
 
@@ -257,6 +257,8 @@ HIDE_POSIX(sigsuspend)
 HIDE_POSIX(sigaction)
 HIDE_POSIX(sigpending)
 HIDE_BSD(sigreturn)
+HIDE_POSIX(sigtimedwait)
+HIDE_POSIX(sigwaitinfo)
 HIDE_BSD(__acl_get_file)
 HIDE_BSD(__acl_set_file)
 HIDE_BSD(__acl_get_fd)
index 421f662..d9302b2 100644 (file)
@@ -2,7 +2,7 @@
  * System call numbers.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $DragonFly: src/sys/sys/syscall.h,v 1.24 2005/01/31 17:38:30 joerg Exp $
+ * $DragonFly: src/sys/sys/syscall.h,v 1.25 2005/02/20 01:17:43 davidxu Exp $
  * created from DragonFly: src/sys/kern/syscalls.master,v 1.18 2005/01/31 17:35:35 joerg Exp 
  */
 
 #define        SYS_sigaction   342
 #define        SYS_sigpending  343
 #define        SYS_sigreturn   344
+#define        SYS_sigtimedwait        345
+#define        SYS_sigwaitinfo 346
 #define        SYS___acl_get_file      347
 #define        SYS___acl_set_file      348
 #define        SYS___acl_get_fd        349
index f631827..8a948eb 100644 (file)
@@ -1,6 +1,6 @@
 # DragonFly system call names.
 # DO NOT EDIT-- this file is automatically generated.
-# $DragonFly: src/sys/sys/syscall.mk,v 1.24 2005/01/31 17:38:30 joerg Exp $
+# $DragonFly: src/sys/sys/syscall.mk,v 1.25 2005/02/20 01:17:43 davidxu Exp $
 # created from DragonFly: src/sys/kern/syscalls.master,v 1.18 2005/01/31 17:35:35 joerg Exp 
 MIASM =  \
        syscall.o \
@@ -218,6 +218,8 @@ MIASM =  \
        sigaction.o \
        sigpending.o \
        sigreturn.o \
+       sigtimedwait.o \
+       sigwaitinfo.o \
        __acl_get_file.o \
        __acl_set_file.o \
        __acl_get_fd.o \
index 610ba42..84757da 100644 (file)
@@ -2,7 +2,7 @@
  * System call prototypes.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $DragonFly: src/sys/sys/sysproto.h,v 1.24 2005/01/31 17:38:30 joerg Exp $
+ * $DragonFly: src/sys/sys/sysproto.h,v 1.25 2005/02/20 01:17:43 davidxu Exp $
  * created from DragonFly: src/sys/kern/syscalls.master,v 1.18 2005/01/31 17:35:35 joerg Exp 
  */
 
@@ -1790,6 +1790,23 @@ struct   sigreturn_args {
        union usrmsg usrmsg;
        ucontext_t *    sigcntxp;       char sigcntxp_[PAD_(ucontext_t *)];
 };
+struct sigtimedwait_args {
+#ifdef _KERNEL
+       struct sysmsg sysmsg;
+#endif
+       union usrmsg usrmsg;
+       const sigset_t *        set;    char set_[PAD_(const sigset_t *)];
+       siginfo_t *     info;   char info_[PAD_(siginfo_t *)];
+       const struct timespec * timeout;        char timeout_[PAD_(const struct timespec *)];
+};
+struct sigwaitinfo_args {
+#ifdef _KERNEL
+       struct sysmsg sysmsg;
+#endif
+       union usrmsg usrmsg;
+       const sigset_t *        set;    char set_[PAD_(const sigset_t *)];
+       siginfo_t *     info;   char info_[PAD_(siginfo_t *)];
+};
 struct __acl_get_file_args {
 #ifdef _KERNEL
        struct sysmsg sysmsg;
@@ -2375,6 +2392,8 @@ int       sigsuspend (struct sigsuspend_args *);
 int    sigaction (struct sigaction_args *);
 int    sigpending (struct sigpending_args *);
 int    sigreturn (struct sigreturn_args *);
+int    sigtimedwait (struct sigtimedwait_args *);
+int    sigwaitinfo (struct sigwaitinfo_args *);
 int    __acl_get_file (struct __acl_get_file_args *);
 int    __acl_set_file (struct __acl_set_file_args *);
 int    __acl_get_fd (struct __acl_get_fd_args *);
index aab879d..05e0621 100644 (file)
@@ -2,7 +2,7 @@
  * Union of syscall args for messaging.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $DragonFly: src/sys/sys/sysunion.h,v 1.21 2005/01/31 17:38:30 joerg Exp $
+ * $DragonFly: src/sys/sys/sysunion.h,v 1.22 2005/02/20 01:17:43 davidxu Exp $
  * created from DragonFly: src/sys/kern/syscalls.master,v 1.18 2005/01/31 17:35:35 joerg Exp 
  */
 
@@ -302,6 +302,8 @@ union sysunion {
        struct  sigaction_args sigaction;
        struct  sigpending_args sigpending;
        struct  sigreturn_args sigreturn;
+       struct  sigtimedwait_args sigtimedwait;
+       struct  sigwaitinfo_args sigwaitinfo;
        struct  __acl_get_file_args __acl_get_file;
        struct  __acl_set_file_args __acl_set_file;
        struct  __acl_get_fd_args __acl_get_fd;