void coremu_cpu_sched(CMSchedEvent e) { switch (e) { case CM_EVENT_HALTED: sched_halted(); break; case CM_EVENT_PAUSE: sched_pause(); break; default: assert(0); } }
void taskq_thread(void *xtq) { sleepfn tqsleep = msleep; struct taskq *tq = xtq; struct task work; int last; if (ISSET(tq->tq_flags, TASKQ_MPSAFE)) KERNEL_UNLOCK(); if (ISSET(tq->tq_flags, TASKQ_CANTSLEEP)) { tqsleep = taskq_sleep; atomic_setbits_int(&curproc->p_flag, P_CANTSLEEP); } while (taskq_next_work(tq, &work, tqsleep)) { (*work.t_func)(work.t_arg); sched_pause(); } mtx_enter(&tq->tq_mtx); last = (--tq->tq_running == 0); mtx_leave(&tq->tq_mtx); if (ISSET(tq->tq_flags, TASKQ_MPSAFE)) KERNEL_LOCK(); if (ISSET(tq->tq_flags, TASKQ_CANTSLEEP)) atomic_clearbits_int(&curproc->p_flag, P_CANTSLEEP); if (last) wakeup_one(&tq->tq_running); kthread_exit(0); }
/* * System filesystem synchronizer daemon. */ void sched_sync(struct proc *p) { struct synclist *slp; struct vnode *vp; time_t starttime; int s; syncerproc = curproc; for (;;) { starttime = time_second; /* * Push files whose dirty time has expired. */ s = splbio(); slp = &syncer_workitem_pending[syncer_delayno]; syncer_delayno += 1; if (syncer_delayno == syncer_maxdelay) syncer_delayno = 0; while ((vp = LIST_FIRST(slp)) != NULL) { if (vget(vp, LK_EXCLUSIVE | LK_NOWAIT, p)) { /* * If we fail to get the lock, we move this * vnode one second ahead in time. * XXX - no good, but the best we can do. */ vn_syncer_add_to_worklist(vp, 1); continue; } splx(s); (void) VOP_FSYNC(vp, p->p_ucred, MNT_LAZY); vput(vp); s = splbio(); if (LIST_FIRST(slp) == vp) { /* * Note: disk vps can remain on the * worklist too with no dirty blocks, but * since sync_fsync() moves it to a different * slot we are safe. */ #ifdef DIAGNOSTIC if (LIST_FIRST(&vp->v_dirtyblkhd) == NULL && vp->v_type != VBLK) { vprint("fsync failed", vp); if (vp->v_mount != NULL) printf("mounted on: %s\n", vp->v_mount->mnt_stat.f_mntonname); panic("sched_sync: fsync failed"); } #endif /* DIAGNOSTIC */ /* * Put us back on the worklist. The worklist * routine will remove us from our current * position and then add us back in at a later * position. */ vn_syncer_add_to_worklist(vp, syncdelay); } sched_pause(); } splx(s); #ifdef FFS_SOFTUPDATES /* * Do soft update processing. */ softdep_process_worklist(NULL); #endif /* * The variable rushjob allows the kernel to speed up the * processing of the filesystem syncer process. A rushjob * value of N tells the filesystem syncer to process the next * N seconds worth of work on its queue ASAP. Currently rushjob * is used by the soft update code to speed up the filesystem * syncer process when the incore state is getting so far * ahead of the disk that the kernel memory pool is being * threatened with exhaustion. */ if (rushjob > 0) { rushjob -= 1; continue; } /* * If it has taken us less than a second to process the * current work, then wait. Otherwise start right over * again. We can still lose time if any single round * takes more than two seconds, but it does not really * matter as we are just trying to generally pace the * filesystem activity. */ if (time_second == starttime) tsleep(&lbolt, PPAUSE, "syncer", 0); } }