예제 #1
0
파일: sched.c 프로젝트: wind15973/research
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);
    }
}
예제 #2
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);
}
예제 #3
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);
	}
}