Author: kib
Date: Tue Jul 14 22:52:46 2009
New Revision: 195702
URL: http://svn.freebsd.org/changeset/base/195702

Log:
  Add new msleep(9) flag PBDY that shall be specified together with
  PCATCH, to indicate that thread shall not be stopped upon receipt of
  SIGSTOP until it reaches the kernel->usermode boundary.
  
  Also change thread_single(SINGLE_NO_EXIT) to only stop threads at
  the user boundary unconditionally.
  
  Tested by:    pho
  Reviewed by:  jhb
  Approved by:  re (kensmith)

Modified:
  head/sys/cddl/compat/opensolaris/sys/sig.h
  head/sys/kern/kern_sig.c
  head/sys/kern/kern_synch.c
  head/sys/kern/kern_thread.c
  head/sys/kern/subr_sleepqueue.c
  head/sys/kern/subr_trap.c
  head/sys/sys/param.h
  head/sys/sys/proc.h
  head/sys/sys/signalvar.h
  head/sys/sys/sleepqueue.h

Modified: head/sys/cddl/compat/opensolaris/sys/sig.h
==============================================================================
--- head/sys/cddl/compat/opensolaris/sys/sig.h  Tue Jul 14 22:51:31 2009        
(r195701)
+++ head/sys/cddl/compat/opensolaris/sys/sig.h  Tue Jul 14 22:52:46 2009        
(r195702)
@@ -55,7 +55,7 @@ issig(int why)
                p = td->td_proc;
                PROC_LOCK(p);
                mtx_lock(&p->p_sigacts->ps_mtx);
-               sig = cursig(td);
+               sig = cursig(td, SIG_STOP_ALLOWED);
                mtx_unlock(&p->p_sigacts->ps_mtx);
                PROC_UNLOCK(p);
                if (sig != 0)

Modified: head/sys/kern/kern_sig.c
==============================================================================
--- head/sys/kern/kern_sig.c    Tue Jul 14 22:51:31 2009        (r195701)
+++ head/sys/kern/kern_sig.c    Tue Jul 14 22:52:46 2009        (r195702)
@@ -100,7 +100,7 @@ SDT_PROBE_ARGTYPE(proc, kernel, , signal
 static int     coredump(struct thread *);
 static char    *expand_name(const char *, uid_t, pid_t);
 static int     killpg1(struct thread *td, int sig, int pgid, int all);
-static int     issignal(struct thread *p);
+static int     issignal(struct thread *td, int stop_allowed);
 static int     sigprop(int sig);
 static void    tdsigwakeup(struct thread *, int, sig_t, int);
 static void    sig_suspend_threads(struct thread *, struct proc *, int);
@@ -558,12 +558,14 @@ sigqueue_delete_stopmask_proc(struct pro
  * action, the process stops in issignal().
  */
 int
-cursig(struct thread *td)
+cursig(struct thread *td, int stop_allowed)
 {
        PROC_LOCK_ASSERT(td->td_proc, MA_OWNED);
+       KASSERT(stop_allowed == SIG_STOP_ALLOWED ||
+           stop_allowed == SIG_STOP_NOT_ALLOWED, ("cursig: stop_allowed"));
        mtx_assert(&td->td_proc->p_sigacts->ps_mtx, MA_OWNED);
        THREAD_LOCK_ASSERT(td, MA_NOTOWNED);
-       return (SIGPENDING(td) ? issignal(td) : 0);
+       return (SIGPENDING(td) ? issignal(td, stop_allowed) : 0);
 }
 
 /*
@@ -1191,7 +1193,7 @@ restart:
                SIG_CANTMASK(td->td_sigmask);
                SIGDELSET(td->td_sigmask, i);
                mtx_lock(&ps->ps_mtx);
-               sig = cursig(td);
+               sig = cursig(td, SIG_STOP_ALLOWED);
                mtx_unlock(&ps->ps_mtx);
                if (sig)
                        goto out;
@@ -2310,18 +2312,28 @@ static void
 sig_suspend_threads(struct thread *td, struct proc *p, int sending)
 {
        struct thread *td2;
+       int wakeup_swapper;
 
        PROC_LOCK_ASSERT(p, MA_OWNED);
        PROC_SLOCK_ASSERT(p, MA_OWNED);
 
+       wakeup_swapper = 0;
        FOREACH_THREAD_IN_PROC(p, td2) {
                thread_lock(td2);
                td2->td_flags |= TDF_ASTPENDING | TDF_NEEDSUSPCHK;
                if ((TD_IS_SLEEPING(td2) || TD_IS_SWAPPED(td2)) &&
-                   (td2->td_flags & TDF_SINTR) &&
-                   !TD_IS_SUSPENDED(td2)) {
-                       thread_suspend_one(td2);
-               } else {
+                   (td2->td_flags & TDF_SINTR)) {
+                       if (td2->td_flags & TDF_SBDRY) {
+                               if (TD_IS_SUSPENDED(td2))
+                                       wakeup_swapper |=
+                                           thread_unsuspend_one(td2);
+                               if (TD_ON_SLEEPQ(td2))
+                                       wakeup_swapper |=
+                                           sleepq_abort(td2, ERESTART);
+                       } else if (!TD_IS_SUSPENDED(td2)) {
+                               thread_suspend_one(td2);
+                       }
+               } else if (!TD_IS_SUSPENDED(td2)) {
                        if (sending || td != td2)
                                td2->td_flags |= TDF_ASTPENDING;
 #ifdef SMP
@@ -2331,6 +2343,8 @@ sig_suspend_threads(struct thread *td, s
                }
                thread_unlock(td2);
        }
+       if (wakeup_swapper)
+               kick_proc0();
 }
 
 int
@@ -2387,8 +2401,7 @@ stopme:
  *             postsig(sig);
  */
 static int
-issignal(td)
-       struct thread *td;
+issignal(struct thread *td, int stop_allowed)
 {
        struct proc *p;
        struct sigacts *ps;
@@ -2506,6 +2519,10 @@ issignal(td)
                                    (p->p_pgrp->pg_jobc == 0 &&
                                     prop & SA_TTYSTOP))
                                        break;  /* == ignore */
+
+                               /* Ignore, but do not drop the stop signal. */
+                               if (stop_allowed != SIG_STOP_ALLOWED)
+                                       return (sig);
                                mtx_unlock(&ps->ps_mtx);
                                WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK,
                                    &p->p_mtx.lock_object, "Catching SIGSTOP");

Modified: head/sys/kern/kern_synch.c
==============================================================================
--- head/sys/kern/kern_synch.c  Tue Jul 14 22:51:31 2009        (r195701)
+++ head/sys/kern/kern_synch.c  Tue Jul 14 22:52:46 2009        (r195702)
@@ -188,6 +188,8 @@ _sleep(void *ident, struct lock_object *
                flags = SLEEPQ_SLEEP;
        if (catch)
                flags |= SLEEPQ_INTERRUPTIBLE;
+       if (priority & PBDRY)
+               flags |= SLEEPQ_STOP_ON_BDRY;
 
        sleepq_lock(ident);
        CTR5(KTR_PROC, "sleep: thread %ld (pid %ld, %s) on %s (%p)",

Modified: head/sys/kern/kern_thread.c
==============================================================================
--- head/sys/kern/kern_thread.c Tue Jul 14 22:51:31 2009        (r195701)
+++ head/sys/kern/kern_thread.c Tue Jul 14 22:52:46 2009        (r195702)
@@ -598,18 +598,17 @@ thread_single(int mode)
                                                wakeup_swapper |=
                                                    sleepq_abort(td2, ERESTART);
                                        break;
+                               case SINGLE_NO_EXIT:
+                                       if (TD_IS_SUSPENDED(td2) &&
+                                           !(td2->td_flags & TDF_BOUNDARY))
+                                               wakeup_swapper |=
+                                                   thread_unsuspend_one(td2);
+                                       if (TD_ON_SLEEPQ(td2) &&
+                                           (td2->td_flags & TDF_SINTR))
+                                               wakeup_swapper |=
+                                                   sleepq_abort(td2, ERESTART);
+                                       break;
                                default:
-                                       if (TD_IS_SUSPENDED(td2)) {
-                                               thread_unlock(td2);
-                                               continue;
-                                       }
-                                       /*
-                                        * maybe other inhibited states too?
-                                        */
-                                       if ((td2->td_flags & TDF_SINTR) &&
-                                           (td2->td_inhibitors &
-                                           (TDI_SLEEPING | TDI_SWAPPED)))
-                                               thread_suspend_one(td2);
                                        break;
                                }
                        }

Modified: head/sys/kern/subr_sleepqueue.c
==============================================================================
--- head/sys/kern/subr_sleepqueue.c     Tue Jul 14 22:51:31 2009        
(r195701)
+++ head/sys/kern/subr_sleepqueue.c     Tue Jul 14 22:52:46 2009        
(r195702)
@@ -341,6 +341,8 @@ sleepq_add(void *wchan, struct lock_obje
        if (flags & SLEEPQ_INTERRUPTIBLE) {
                td->td_flags |= TDF_SINTR;
                td->td_flags &= ~TDF_SLEEPABORT;
+               if (flags & SLEEPQ_STOP_ON_BDRY)
+                       td->td_flags |= TDF_SBDRY;
        }
        thread_unlock(td);
 }
@@ -378,7 +380,7 @@ sleepq_catch_signals(void *wchan, int pr
        struct thread *td;
        struct proc *p;
        struct sigacts *ps;
-       int sig, ret;
+       int sig, ret, stop_allowed;
 
        td = curthread;
        p = curproc;
@@ -395,6 +397,8 @@ sleepq_catch_signals(void *wchan, int pr
                sleepq_switch(wchan, pri);
                return (0);
        }
+       stop_allowed = (td->td_flags & TDF_SBDRY) ? SIG_STOP_NOT_ALLOWED :
+           SIG_STOP_ALLOWED;
        thread_unlock(td);
        mtx_unlock_spin(&sc->sc_lock);
        CTR3(KTR_PROC, "sleepq catching signals: thread %p (pid %ld, %s)",
@@ -402,7 +406,7 @@ sleepq_catch_signals(void *wchan, int pr
        PROC_LOCK(p);
        ps = p->p_sigacts;
        mtx_lock(&ps->ps_mtx);
-       sig = cursig(td);
+       sig = cursig(td, stop_allowed);
        if (sig == 0) {
                mtx_unlock(&ps->ps_mtx);
                ret = thread_suspend_check(1);
@@ -560,7 +564,7 @@ sleepq_check_signals(void)
 
        /* We are no longer in an interruptible sleep. */
        if (td->td_flags & TDF_SINTR)
-               td->td_flags &= ~TDF_SINTR;
+               td->td_flags &= ~(TDF_SINTR | TDF_SBDRY);
 
        if (td->td_flags & TDF_SLEEPABORT) {
                td->td_flags &= ~TDF_SLEEPABORT;
@@ -682,7 +686,7 @@ sleepq_resume_thread(struct sleepqueue *
 
        td->td_wmesg = NULL;
        td->td_wchan = NULL;
-       td->td_flags &= ~TDF_SINTR;
+       td->td_flags &= ~(TDF_SINTR | TDF_SBDRY);
 
        CTR3(KTR_PROC, "sleepq_wakeup: thread %p (pid %ld, %s)",
            (void *)td, (long)td->td_proc->p_pid, td->td_name);

Modified: head/sys/kern/subr_trap.c
==============================================================================
--- head/sys/kern/subr_trap.c   Tue Jul 14 22:51:31 2009        (r195701)
+++ head/sys/kern/subr_trap.c   Tue Jul 14 22:52:46 2009        (r195702)
@@ -221,7 +221,7 @@ ast(struct trapframe *framep)
        if (flags & TDF_NEEDSIGCHK) {
                PROC_LOCK(p);
                mtx_lock(&p->p_sigacts->ps_mtx);
-               while ((sig = cursig(td)) != 0)
+               while ((sig = cursig(td, SIG_STOP_ALLOWED)) != 0)
                        postsig(sig);
                mtx_unlock(&p->p_sigacts->ps_mtx);
                PROC_UNLOCK(p);

Modified: head/sys/sys/param.h
==============================================================================
--- head/sys/sys/param.h        Tue Jul 14 22:51:31 2009        (r195701)
+++ head/sys/sys/param.h        Tue Jul 14 22:52:46 2009        (r195702)
@@ -187,6 +187,7 @@
 #define        PRIMASK 0x0ff
 #define        PCATCH  0x100           /* OR'd with pri for tsleep to check 
signals */
 #define        PDROP   0x200   /* OR'd with pri to stop re-entry of interlock 
mutex */
+#define        PBDRY   0x400   /* for PCATCH stop is done on the user boundary 
*/
 
 #define        NZERO   0               /* default "nice" */
 

Modified: head/sys/sys/proc.h
==============================================================================
--- head/sys/sys/proc.h Tue Jul 14 22:51:31 2009        (r195701)
+++ head/sys/sys/proc.h Tue Jul 14 22:52:46 2009        (r195702)
@@ -320,7 +320,7 @@ do {                                                        
                \
 #define        TDF_BOUNDARY    0x00000400 /* Thread suspended at user boundary 
*/
 #define        TDF_ASTPENDING  0x00000800 /* Thread has some asynchronous 
events. */
 #define        TDF_TIMOFAIL    0x00001000 /* Timeout from sleep after we were 
awake. */
-#define        TDF_UNUSED2000  0x00002000 /* --available-- */
+#define        TDF_SBDRY       0x00002000 /* Stop only on usermode boundary. */
 #define        TDF_UPIBLOCKED  0x00004000 /* Thread blocked on user PI mutex. 
*/
 #define        TDF_NEEDSUSPCHK 0x00008000 /* Thread may need to suspend. */
 #define        TDF_NEEDRESCHED 0x00010000 /* Thread needs to yield. */

Modified: head/sys/sys/signalvar.h
==============================================================================
--- head/sys/sys/signalvar.h    Tue Jul 14 22:51:31 2009        (r195701)
+++ head/sys/sys/signalvar.h    Tue Jul 14 22:52:46 2009        (r195702)
@@ -311,10 +311,14 @@ extern int kern_logsigexit;       /* Sysctl va
 #define SIGIO_LOCKED() mtx_owned(&sigio_lock)
 #define SIGIO_ASSERT(type)     mtx_assert(&sigio_lock, type)
 
+/* stop_allowed parameter for cursig */
+#define        SIG_STOP_ALLOWED        100
+#define        SIG_STOP_NOT_ALLOWED    101
+
 /*
  * Machine-independent functions:
  */
-int    cursig(struct thread *td);
+int    cursig(struct thread *td, int stop_allowed);
 void   execsigs(struct proc *p);
 void   gsignal(int pgid, int sig);
 void   killproc(struct proc *p, char *why);

Modified: head/sys/sys/sleepqueue.h
==============================================================================
--- head/sys/sys/sleepqueue.h   Tue Jul 14 22:51:31 2009        (r195701)
+++ head/sys/sys/sleepqueue.h   Tue Jul 14 22:52:46 2009        (r195702)
@@ -93,6 +93,8 @@ struct thread;
 #define        SLEEPQ_SX               0x03            /* Used by an sx lock. 
*/
 #define        SLEEPQ_LK               0x04            /* Used by a lockmgr. */
 #define        SLEEPQ_INTERRUPTIBLE    0x100           /* Sleep is 
interruptible. */
+#define        SLEEPQ_STOP_ON_BDRY     0x200           /* Stop sleeping thread 
on
+                                                  user mode boundary */
 
 void   init_sleepqueues(void);
 int    sleepq_abort(struct thread *td, int intrval);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to