a3b98398cb
- The MD functions critical_enter/exit are renamed to start with a cpu_ prefix. - MI wrapper functions critical_enter/exit maintain a per-thread nesting count and a per-thread critical section saved state set when entering a critical section while at nesting level 0 and restored when exiting to nesting level 0. This moves the saved state out of spin mutexes so that interlocking spin mutexes works properly. - Most low-level MD code that used critical_enter/exit now use cpu_critical_enter/exit. MI code such as device drivers and spin mutexes use the MI wrappers. Note that since the MI wrappers store the state in the current thread, they do not have any return values or arguments. - mtx_intr_enable() is replaced with a constant CRITICAL_FORK which is assigned to curthread->td_savecrit during fork_exit(). Tested on: i386, alpha
111 lines
2.1 KiB
C
111 lines
2.1 KiB
C
/*-
|
|
* Copyright (c) 2000, All rights reserved. See /usr/src/COPYRIGHT
|
|
*
|
|
* $FreeBSD$
|
|
*/
|
|
|
|
#include "opt_ktrace.h"
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/kernel.h>
|
|
#include <sys/ktr.h>
|
|
#include <sys/kthread.h>
|
|
#include <sys/lock.h>
|
|
#include <sys/mutex.h>
|
|
#include <sys/pcpu.h>
|
|
#include <sys/proc.h>
|
|
#include <sys/resourcevar.h>
|
|
#include <sys/smp.h>
|
|
#include <sys/unistd.h>
|
|
#ifdef KTRACE
|
|
#include <sys/uio.h>
|
|
#include <sys/ktrace.h>
|
|
#endif
|
|
|
|
static void idle_setup(void *dummy);
|
|
SYSINIT(idle_setup, SI_SUB_SCHED_IDLE, SI_ORDER_FIRST, idle_setup, NULL)
|
|
|
|
static void idle_proc(void *dummy);
|
|
|
|
/*
|
|
* Setup per-cpu idle process contexts. The AP's shouldn't be running or
|
|
* accessing their idle processes at this point, so don't bother with
|
|
* locking.
|
|
*/
|
|
static void
|
|
idle_setup(void *dummy)
|
|
{
|
|
#ifdef SMP
|
|
struct pcpu *pc;
|
|
#endif
|
|
struct proc *p;
|
|
int error;
|
|
|
|
#ifdef SMP
|
|
SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
|
|
error = kthread_create(idle_proc, NULL, &p,
|
|
RFSTOPPED | RFHIGHPID, "idle: cpu%d", pc->pc_cpuid);
|
|
pc->pc_idlethread = &p->p_thread;
|
|
if (pc->pc_curthread == NULL) {
|
|
pc->pc_curthread = pc->pc_idlethread;
|
|
pc->pc_idlethread->td_critnest = 0;
|
|
}
|
|
#else
|
|
error = kthread_create(idle_proc, NULL, &p,
|
|
RFSTOPPED | RFHIGHPID, "idle");
|
|
PCPU_SET(idlethread, &p->p_thread);
|
|
#endif
|
|
if (error)
|
|
panic("idle_setup: kthread_create error %d\n", error);
|
|
|
|
p->p_flag |= P_NOLOAD;
|
|
p->p_stat = SRUN;
|
|
#ifdef SMP
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* idle process context
|
|
*/
|
|
static void
|
|
idle_proc(void *dummy)
|
|
{
|
|
#ifdef DIAGNOSTIC
|
|
int count;
|
|
#endif
|
|
|
|
for (;;) {
|
|
mtx_assert(&Giant, MA_NOTOWNED);
|
|
|
|
#ifdef DIAGNOSTIC
|
|
count = 0;
|
|
|
|
while (count >= 0 && procrunnable() == 0) {
|
|
#else
|
|
while (procrunnable() == 0) {
|
|
#endif
|
|
/*
|
|
* This is a good place to put things to be done in
|
|
* the background, including sanity checks.
|
|
*/
|
|
|
|
#ifdef DIAGNOSTIC
|
|
if (count++ < 0)
|
|
CTR0(KTR_PROC, "idle_proc: timed out waiting"
|
|
" for a process");
|
|
#endif
|
|
|
|
#ifdef __i386__
|
|
cpu_idle();
|
|
#endif
|
|
}
|
|
|
|
mtx_lock_spin(&sched_lock);
|
|
curproc->p_stats->p_ru.ru_nvcsw++;
|
|
mi_switch();
|
|
mtx_unlock_spin(&sched_lock);
|
|
}
|
|
}
|