diff options
author | jhb <jhb@FreeBSD.org> | 2004-01-28 20:44:41 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2004-01-28 20:44:41 +0000 |
commit | 114683f922e2de33cfbe10397f96debe7878b8c8 (patch) | |
tree | 504f68e91f1f4fbd4d1299d5acfe7a0172ce4f9f /sys/kern | |
parent | 657a196e7a050d9d36fa60573c770822bdffdd5a (diff) | |
download | FreeBSD-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.c | 43 |
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"); } /* |