Allow the kernel to be compile without KTRACE option.
[dragonfly.git] / sys / kern / sys_generic.c
index d88fd33..5403dec 100644 (file)
@@ -68,7 +68,9 @@
 #endif
 #include <vm/vm.h>
 #include <vm/vm_page.h>
+
 #include <sys/file2.h>
+#include <sys/mplock2.h>
 
 #include <machine/limits.h>
 
@@ -250,10 +252,10 @@ kern_preadv(int fd, struct uio *auio, int flags, size_t *res)
 static int
 dofileread(int fd, struct file *fp, struct uio *auio, int flags, size_t *res)
 {
-       struct thread *td = curthread;
        int error;
        size_t len;
 #ifdef KTRACE
+       struct thread *td = curthread;
        struct iovec *ktriov = NULL;
        struct uio ktruio;
 #endif
@@ -513,12 +515,18 @@ dofilewrite(int fd, struct file *fp, struct uio *auio, int flags, size_t *res)
 
 /*
  * Ioctl system call
+ *
+ * MPALMOSTSAFE
  */
-/* ARGSUSED */
 int
 sys_ioctl(struct ioctl_args *uap)
 {
-       return(mapped_ioctl(uap->fd, uap->com, uap->data, NULL, &uap->sysmsg));
+       int error;
+
+       get_mplock();
+       error = mapped_ioctl(uap->fd, uap->com, uap->data, NULL, &uap->sysmsg);
+       rel_mplock();
+       return (error);
 }
 
 struct ioctl_map_entry {
@@ -553,7 +561,7 @@ mapped_ioctl(int fd, u_long com, caddr_t uspc_data, struct ioctl_map *map,
        } ubuf;
 
        KKASSERT(p);
-       cred = p->p_ucred;
+       cred = td->td_ucred;
 
        fp = holdfp(p->p_fd, fd, FREAD|FWRITE);
        if (fp == NULL)
@@ -751,6 +759,8 @@ SYSCTL_INT(_kern, OID_AUTO, nselcoll, CTLFLAG_RD, &nselcoll, 0, "");
 
 /*
  * Select system call.
+ *
+ * MPALMOSTSAFE
  */
 int
 sys_select(struct select_args *uap)
@@ -777,8 +787,10 @@ sys_select(struct select_args *uap)
        /*
         * Do real work.
         */
+       get_mplock();
        error = doselect(uap->nd, uap->in, uap->ou, uap->ex, ktvp,
                        &uap->sysmsg_result);
+       rel_mplock();
 
        return (error);
 }
@@ -786,6 +798,8 @@ sys_select(struct select_args *uap)
 
 /*
  * Pselect system call.
+ *
+ * MPALMOSTSAFE
  */
 int
 sys_pselect(struct pselect_args *uap)
@@ -823,9 +837,12 @@ sys_pselect(struct pselect_args *uap)
                error = copyin(uap->sigmask, &sigmask, sizeof(sigmask));
                if (error)
                        return (error);
+               get_mplock();
                lp->lwp_oldsigmask = lp->lwp_sigmask;
                SIG_CANTMASK(sigmask);
                lp->lwp_sigmask = sigmask;
+       } else {
+               get_mplock();
        }
 
        /*
@@ -852,6 +869,7 @@ sys_pselect(struct pselect_args *uap)
                        lp->lwp_sigmask = lp->lwp_oldsigmask;
                }
        }
+       rel_mplock();
 
        return (error);
 }
@@ -956,15 +974,15 @@ retry:
                    24 * 60 * 60 * hz : tvtohz_high(&ttv);
        }
        crit_enter();
+       tsleep_interlock(&selwait, PCATCH);
        if ((lp->lwp_flag & LWP_SELECT) == 0 || nselcoll != ncoll) {
                crit_exit();
                goto retry;
        }
        lp->lwp_flag &= ~LWP_SELECT;
-
-       error = tsleep((caddr_t)&selwait, PCATCH, "select", timo);
-       
+       error = tsleep(&selwait, PCATCH | PINTERLOCKED, "select", timo);
        crit_exit();
+
        if (error == 0)
                goto retry;
 done:
@@ -1027,6 +1045,8 @@ selscan(struct proc *p, fd_mask **ibits, fd_mask **obits, int nfd, int *res)
 
 /*
  * Poll system call.
+ *
+ * MPALMOSTSAFE
  */
 int
 sys_poll(struct poll_args *uap)
@@ -1057,13 +1077,13 @@ sys_poll(struct poll_args *uap)
                bits = smallbits;
        error = copyin(uap->fds, bits, ni);
        if (error)
-               goto done;
+               goto done2;
        if (uap->timeout != INFTIM) {
                atv.tv_sec = uap->timeout / 1000;
                atv.tv_usec = (uap->timeout % 1000) * 1000;
                if (itimerfix(&atv)) {
                        error = EINVAL;
-                       goto done;
+                       goto done2;
                }
                getmicrouptime(&rtv);
                timevaladd(&atv, &rtv);
@@ -1072,32 +1092,37 @@ sys_poll(struct poll_args *uap)
                atv.tv_usec = 0;
        }
        timo = 0;
+       get_mplock();
 retry:
        ncoll = nselcoll;
        lp->lwp_flag |= LWP_SELECT;
        error = pollscan(p, bits, nfds, &uap->sysmsg_result);
        if (error || uap->sysmsg_result)
-               goto done;
+               goto done1;
        if (atv.tv_sec || atv.tv_usec) {
                getmicrouptime(&rtv);
                if (timevalcmp(&rtv, &atv, >=))
-                       goto done;
+                       goto done1;
                ttv = atv;
                timevalsub(&ttv, &rtv);
                timo = ttv.tv_sec > 24 * 60 * 60 ?
                    24 * 60 * 60 * hz : tvtohz_high(&ttv);
        } 
        crit_enter();
+       tsleep_interlock(&selwait, PCATCH);
        if ((lp->lwp_flag & LWP_SELECT) == 0 || nselcoll != ncoll) {
                crit_exit();
                goto retry;
        }
        lp->lwp_flag &= ~LWP_SELECT;
-       error = tsleep((caddr_t)&selwait, PCATCH, "poll", timo);
+       error = tsleep(&selwait, PCATCH | PINTERLOCKED, "poll", timo);
        crit_exit();
+
        if (error == 0)
                goto retry;
-done:
+done1:
+       rel_mplock();
+done2:
        lp->lwp_flag &= ~LWP_SELECT;
        /* poll is not restarted after signals... */
        if (error == ERESTART)
@@ -1153,6 +1178,8 @@ pollscan(struct proc *p, struct pollfd *fds, u_int nfd, int *res)
 /*
  * OpenBSD poll system call.
  * XXX this isn't quite a true representation..  OpenBSD uses select ops.
+ *
+ * MPSAFE
  */
 int
 sys_openbsd_poll(struct openbsd_poll_args *uap)
@@ -1217,8 +1244,16 @@ selwakeup(struct selinfo *sip)
        if (lp == NULL)
                return;
 
+       /*
+        * This is a temporary hack until the code can be rewritten.
+        * Check LWP_SELECT before assuming we can setrunnable().
+        * Otherwise we might catch the lwp before it actually goes to
+        * sleep.
+        */
        crit_enter();
-       if (lp->lwp_wchan == (caddr_t)&selwait) {
+       if (lp->lwp_flag & LWP_SELECT) {
+               lp->lwp_flag &= ~LWP_SELECT;
+       } else if (lp->lwp_wchan == (caddr_t)&selwait) {
                /*
                 * Flag the process to break the tsleep when
                 * setrunnable is called, but only call setrunnable
@@ -1227,8 +1262,6 @@ selwakeup(struct selinfo *sip)
                lp->lwp_flag |= LWP_BREAKTSLEEP;
                if (p->p_stat != SSTOP)
                        setrunnable(lp);
-       } else if (lp->lwp_flag & LWP_SELECT) {
-               lp->lwp_flag &= ~LWP_SELECT;
        }
        crit_exit();
 }