Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Implement wakeup_one(), which wakes up the highest prior...



details:   https://anonhg.NetBSD.org/src/rev/b6e266cb24be
branches:  trunk
changeset: 474937:b6e266cb24be
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Mon Jul 26 23:00:58 1999 +0000

description:
Implement wakeup_one(), which wakes up the highest priority process
first in line for the specified identifier.  For use in places where
you don't want a Thundering Herd.

While here, add an optimization to wakeup() suggested by Ross Harvey.

diffstat:

 sys/kern/kern_synch.c |  146 +++++++++++++++++++++++++++++++++++++++++++------
 sys/sys/proc.h        |    3 +-
 2 files changed, 130 insertions(+), 19 deletions(-)

diffs (198 lines):

diff -r c18b627807f2 -r b6e266cb24be sys/kern/kern_synch.c
--- a/sys/kern/kern_synch.c     Mon Jul 26 22:43:13 1999 +0000
+++ b/sys/kern/kern_synch.c     Mon Jul 26 23:00:58 1999 +0000
@@ -1,4 +1,41 @@
-/*     $NetBSD: kern_synch.c,v 1.62 1999/07/25 06:30:35 thorpej Exp $  */
+/*     $NetBSD: kern_synch.c,v 1.63 1999/07/26 23:00:59 thorpej Exp $  */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
 
 /*-
  * Copyright (c) 1982, 1986, 1990, 1991, 1993
@@ -74,6 +111,8 @@
 void updatepri __P((struct proc *));
 void endtsleep __P((void *));
 
+__inline void awaken __P((struct proc *));
+
 /*
  * Force switch among equal priority processes every 100ms.
  */
@@ -520,6 +559,29 @@
 }
 
 /*
+ * Optimized-for-wakeup() version of setrunnable().
+ */
+__inline void
+awaken(p)
+       struct proc *p;
+{
+
+       if (p->p_slptime > 1)
+               updatepri(p);
+       p->p_slptime = 0;
+       p->p_stat = SRUN;
+       /*
+        * Since curpriority is a user priority, p->p_priority
+        * is always better than curpriority.
+        */
+       if (p->p_flag & P_INMEM) {
+               setrunqueue(p);
+               need_resched();
+       } else
+               wakeup((caddr_t)&proc0);
+}
+
+/*
  * Make all processes sleeping on the specified identifier runnable.
  */
 void
@@ -544,23 +606,7 @@
                        if (qp->sq_tailp == &p->p_forw)
                                qp->sq_tailp = q;
                        if (p->p_stat == SSLEEP) {
-                               /* OPTIMIZED EXPANSION OF setrunnable(p); */
-                               if (p->p_slptime > 1)
-                                       updatepri(p);
-                               p->p_slptime = 0;
-                               p->p_stat = SRUN;
-                               if (p->p_flag & P_INMEM)
-                                       setrunqueue(p);
-                               /*
-                                * Since curpriority is a user priority,
-                                * p->p_priority is always better than
-                                * curpriority.
-                                */
-                               if ((p->p_flag & P_INMEM) == 0)
-                                       wakeup((caddr_t)&proc0);
-                               else
-                                       need_resched();
-                               /* END INLINE EXPANSION */
+                               awaken(p);
                                goto restart;
                        }
                } else
@@ -570,6 +616,70 @@
 }
 
 /*
+ * Make the highest priority process first in line on the specified
+ * identifier runnable.
+ */
+void
+wakeup_one(ident)
+       void *ident;
+{
+       struct slpque *qp;
+       struct proc *p, **q;
+       struct proc *best_sleepp, **best_sleepq;
+       struct proc *best_stopp, **best_stopq;
+       int s;
+
+       best_sleepp = best_stopp = NULL;
+       best_sleepq = best_stopq = NULL;
+
+       s = splhigh();
+       qp = &slpque[LOOKUP(ident)];
+       for (q = &qp->sq_head; (p = *q) != NULL; q = &p->p_forw) {
+#ifdef DIAGNOSTIC
+               if (p->p_back || (p->p_stat != SSLEEP && p->p_stat != SSTOP))
+                       panic("wakeup_one");
+#endif
+               if (p->p_wchan == ident) {
+                       if (p->p_stat == SSLEEP) {
+                               if (best_sleepp == NULL ||
+                                   p->p_priority < best_sleepp->p_priority) {
+                                       best_sleepp = p;
+                                       best_sleepq = q;
+                               }
+                       } else {
+                               if (best_stopp == NULL ||
+                                   p->p_priority < best_stopp->p_priority) {
+                                       best_stopp = p;
+                                       best_stopq = q;
+                               }
+                       }
+               }
+       }
+
+       /*
+        * Consider any SSLEEP process higher than the highest priority SSTOP
+        * process.
+        */
+       if (best_sleepp != NULL) {
+               p = best_sleepp;
+               q = best_sleepq;
+       } else {
+               p = best_stopp;
+               q = best_stopq;
+       }
+
+       if (p != NULL) {
+               p->p_wchan = 0;
+               *q = p->p_forw;
+               if (qp->sq_tailp == &p->p_forw)
+                       qp->sq_tailp = q;
+               if (p->p_stat == SSLEEP)
+                       awaken(p);
+       }
+       splx(s);
+}
+
+/*
  * The machine independent parts of mi_switch().
  * Must be called at splstatclock() or higher.
  */
diff -r c18b627807f2 -r b6e266cb24be sys/sys/proc.h
--- a/sys/sys/proc.h    Mon Jul 26 22:43:13 1999 +0000
+++ b/sys/sys/proc.h    Mon Jul 26 23:00:58 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: proc.h,v 1.81 1999/07/25 06:30:33 thorpej Exp $        */
+/*     $NetBSD: proc.h,v 1.82 1999/07/26 23:00:58 thorpej Exp $        */
 
 /*-
  * Copyright (c) 1986, 1989, 1991, 1993
@@ -362,6 +362,7 @@
 int    tsleep __P((void *chan, int pri, const char *wmesg, int timo));
 void   unsleep __P((struct proc *));
 void   wakeup __P((void *chan));
+void   wakeup_one __P((void *chan));
 void   reaper __P((void));
 void   exit1 __P((struct proc *, int));
 void   exit2 __P((struct proc *));



Home | Main Index | Thread Index | Old Index