summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2004-01-28 20:44:41 +0000
committerjhb <jhb@FreeBSD.org>2004-01-28 20:44:41 +0000
commit114683f922e2de33cfbe10397f96debe7878b8c8 (patch)
tree504f68e91f1f4fbd4d1299d5acfe7a0172ce4f9f /sys/kern
parent657a196e7a050d9d36fa60573c770822bdffdd5a (diff)
downloadFreeBSD-src-114683f922e2de33cfbe10397f96debe7878b8c8.zip
FreeBSD-src-114683f922e2de33cfbe10397f96debe7878b8c8.tar.gz
Move the loadav() callout into its own kthread since it uses allproc_lock
which is a sleepable lock and thus is not safe to acquire from a callout routine.
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_synch.c43
1 files changed, 31 insertions, 12 deletions
diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c
index a7c8f86..7ddd49b 100644
--- a/sys/kern/kern_synch.c
+++ b/sys/kern/kern_synch.c
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
#include <sys/condvar.h>
#include <sys/kernel.h>
#include <sys/ktr.h>
+#include <sys/kthread.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/proc.h>
@@ -76,7 +77,6 @@ SYSINIT(synch_setup, SI_SUB_KICK_SCHEDULER, SI_ORDER_FIRST, synch_setup, NULL)
int hogticks;
int lbolt;
-static struct callout loadav_callout;
static struct callout lbolt_callout;
struct loadavg averunnable =
@@ -96,7 +96,8 @@ static int fscale __unused = FSCALE;
SYSCTL_INT(_kern, OID_AUTO, fscale, CTLFLAG_RD, 0, FSCALE, "");
static void endtsleep(void *);
-static void loadav(void *arg);
+static void loadav(void);
+static void loadav_thread(void *dummy);
static void lboltcb(void *arg);
/*
@@ -581,7 +582,7 @@ setrunnable(struct thread *td)
* Completely Bogus.. only works with 1:1 (but compiles ok now :-)
*/
static void
-loadav(void *arg)
+loadav(void)
{
int i, nrun;
struct loadavg *avg;
@@ -610,14 +611,31 @@ nextproc:
for (i = 0; i < 3; i++)
avg->ldavg[i] = (cexp[i] * avg->ldavg[i] +
nrun * FSCALE * (FSCALE - cexp[i])) >> FSHIFT;
+}
- /*
- * Schedule the next update to occur after 5 seconds, but add a
- * random variation to avoid synchronisation with processes that
- * run at regular intervals.
- */
- callout_reset(&loadav_callout, hz * 4 + (int)(random() % (hz * 2 + 1)),
- loadav, NULL);
+/*
+ * Main loop for a kthread that executes loadav() periodically.
+ */
+static void
+loadav_thread(void *dummy)
+{
+ struct proc *p;
+ int nowake;
+
+ p = curthread->td_proc;
+ PROC_LOCK(p);
+ p->p_flag |= P_NOLOAD;
+ PROC_UNLOCK(p);
+ for (;;) {
+ loadav();
+ /*
+ * Schedule the next update to occur after 5 seconds, but
+ * add a random variation to avoid synchronisation with
+ * processes that run at regular intervals.
+ */
+ tsleep(&nowake, curthread->td_priority, "-", hz * 4 +
+ (int)(random() % (hz * 2 + 1)));
+ }
}
static void
@@ -632,12 +650,13 @@ static void
synch_setup(dummy)
void *dummy;
{
- callout_init(&loadav_callout, 0);
callout_init(&lbolt_callout, CALLOUT_MPSAFE);
/* Kick off timeout driven events by calling first time. */
- loadav(NULL);
lboltcb(NULL);
+
+ /* Kick off loadav kernel process. */
+ kthread_create(loadav_thread, NULL, NULL, 0, 0, "loadav");
}
/*
OpenPOWER on IntegriCloud