⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kern_synch.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
		p->p_flag |= P_SINTR;		if (sig = CURSIG(p)) {			if (p->p_wchan)				unsleep(p);			p->p_stat = SRUN;			goto resume;		}		if (p->p_wchan == 0) {			catch = 0;			goto resume;		}	} else		sig = 0;	p->p_stat = SSLEEP;	p->p_stats->p_ru.ru_nvcsw++;	mi_switch();resume:	curpriority = p->p_usrpri;	splx(s);	p->p_flag &= ~P_SINTR;	if (p->p_flag & P_TIMEOUT) {		p->p_flag &= ~P_TIMEOUT;		if (sig == 0) {#ifdef KTRACE			if (KTRPOINT(p, KTR_CSW))				ktrcsw(p->p_tracep, 0, 0);#endif			return (EWOULDBLOCK);		}	} else if (timo)		untimeout(endtsleep, (void *)p);	if (catch && (sig != 0 || (sig = CURSIG(p)))) {#ifdef KTRACE		if (KTRPOINT(p, KTR_CSW))			ktrcsw(p->p_tracep, 0, 0);#endif		if (p->p_sigacts->ps_sigintr & sigmask(sig))			return (EINTR);		return (ERESTART);	}#ifdef KTRACE	if (KTRPOINT(p, KTR_CSW))		ktrcsw(p->p_tracep, 0, 0);#endif	return (0);}/* * Implement timeout for tsleep. * If process hasn't been awakened (wchan non-zero), * set timeout flag and undo the sleep.  If proc * is stopped, just unsleep so it will remain stopped. */voidendtsleep(arg)	void *arg;{	register struct proc *p;	int s;	p = (struct proc *)arg;	s = splhigh();	if (p->p_wchan) {		if (p->p_stat == SSLEEP)			setrunnable(p);		else			unsleep(p);		p->p_flag |= P_TIMEOUT;	}	splx(s);}/* * Short-term, non-interruptable sleep. */voidsleep(ident, priority)	void *ident;	int priority;{	register struct proc *p = curproc;	register struct slpque *qp;	register s;	extern int cold;#ifdef DIAGNOSTIC	if (priority > PZERO) {		printf("sleep called with priority %d > PZERO, wchan: %x\n",		    priority, ident);		panic("old sleep");	}#endif	s = splhigh();	if (cold || panicstr) {		/*		 * After a panic, or during autoconfiguration,		 * just give interrupts a chance, then just return;		 * don't run any other procs or panic below,		 * in case this is the idle process and already asleep.		 */		splx(safepri);		splx(s);		return;	}#ifdef DIAGNOSTIC	if (ident == NULL || p->p_stat != SRUN || p->p_back)		panic("sleep");#endif	p->p_wchan = ident;	p->p_wmesg = NULL;	p->p_slptime = 0;	p->p_priority = priority;	qp = &slpque[LOOKUP(ident)];	if (qp->sq_head == 0)		qp->sq_head = p;	else		*qp->sq_tailp = p;	*(qp->sq_tailp = &p->p_forw) = 0;	p->p_stat = SSLEEP;	p->p_stats->p_ru.ru_nvcsw++;#ifdef KTRACE	if (KTRPOINT(p, KTR_CSW))		ktrcsw(p->p_tracep, 1, 0);#endif	mi_switch();#ifdef KTRACE	if (KTRPOINT(p, KTR_CSW))		ktrcsw(p->p_tracep, 0, 0);#endif	curpriority = p->p_usrpri;	splx(s);}/* * Remove a process from its wait queue */voidunsleep(p)	register struct proc *p;{	register struct slpque *qp;	register struct proc **hp;	int s;	s = splhigh();	if (p->p_wchan) {		hp = &(qp = &slpque[LOOKUP(p->p_wchan)])->sq_head;		while (*hp != p)			hp = &(*hp)->p_forw;		*hp = p->p_forw;		if (qp->sq_tailp == &p->p_forw)			qp->sq_tailp = hp;		p->p_wchan = 0;	}	splx(s);}/* * Make all processes sleeping on the specified identifier runnable. */voidwakeup(ident)	register void *ident;{	register struct slpque *qp;	register struct proc *p, **q;	int s;	s = splhigh();	qp = &slpque[LOOKUP(ident)];restart:	for (q = &qp->sq_head; p = *q; ) {#ifdef DIAGNOSTIC		if (p->p_back || p->p_stat != SSLEEP && p->p_stat != SSTOP)			panic("wakeup");#endif		if (p->p_wchan == ident) {			p->p_wchan = 0;			*q = p->p_forw;			if (qp->sq_tailp == &p->p_forw)				qp->sq_tailp = q;			if (p->p_stat == SSLEEP) {				/* OPTIMIZED EXPANSION OF setrunnable(p); */				if (p->p_slptime > 1)					updatepri(p);				p->p_slptime = 0;				p->p_stat = SRUN;				if (p->p_flag & P_INMEM)					setrunqueue(p);				/*				 * Since curpriority is a user priority,				 * p->p_priority is always better than				 * curpriority.				 */				if ((p->p_flag & P_INMEM) == 0)					wakeup((caddr_t)&proc0);				else					need_resched();				/* END INLINE EXPANSION */				goto restart;			}		} else			q = &p->p_forw;	}	splx(s);}/* * The machine independent parts of mi_switch(). * Must be called at splstatclock() or higher. */voidmi_switch(){	register struct proc *p = curproc;	/* XXX */	register struct rlimit *rlim;	register long s, u;	struct timeval tv;	/*	 * Compute the amount of time during which the current	 * process was running, and add that to its total so far.	 */	microtime(&tv);	u = p->p_rtime.tv_usec + (tv.tv_usec - runtime.tv_usec);	s = p->p_rtime.tv_sec + (tv.tv_sec - runtime.tv_sec);	if (u < 0) {		u += 1000000;		s--;	} else if (u >= 1000000) {		u -= 1000000;		s++;	}	p->p_rtime.tv_usec = u;	p->p_rtime.tv_sec = s;	/*	 * Check if the process exceeds its cpu resource allocation.	 * If over max, kill it.  In any case, if it has run for more	 * than 10 minutes, reduce priority to give others a chance.	 */	rlim = &p->p_rlimit[RLIMIT_CPU];	if (s >= rlim->rlim_cur) {		if (s >= rlim->rlim_max)			psignal(p, SIGKILL);		else {			psignal(p, SIGXCPU);			if (rlim->rlim_cur < rlim->rlim_max)				rlim->rlim_cur += 5;		}	}	if (s > 10 * 60 && p->p_ucred->cr_uid && p->p_nice == NZERO) {		p->p_nice = NZERO + 4;		resetpriority(p);	}	/*	 * Pick a new current process and record its start time.	 */	cnt.v_swtch++;	cpu_switch(p);	microtime(&runtime);}/* * Initialize the (doubly-linked) run queues * to be empty. */rqinit(){	register int i;	for (i = 0; i < NQS; i++)		qs[i].ph_link = qs[i].ph_rlink = (struct proc *)&qs[i];}/* * Change process state to be runnable, * placing it on the run queue if it is in memory, * and awakening the swapper if it isn't in memory. */voidsetrunnable(p)	register struct proc *p;{	register int s;	s = splhigh();	switch (p->p_stat) {	case 0:	case SRUN:	case SZOMB:	default:		panic("setrunnable");	case SSTOP:	case SSLEEP:		unsleep(p);		/* e.g. when sending signals */		break;	case SIDL:		break;	}	p->p_stat = SRUN;	if (p->p_flag & P_INMEM)		setrunqueue(p);	splx(s);	if (p->p_slptime > 1)		updatepri(p);	p->p_slptime = 0;	if ((p->p_flag & P_INMEM) == 0)		wakeup((caddr_t)&proc0);	else if (p->p_priority < curpriority)		need_resched();}/* * Compute the priority of a process when running in user mode. * Arrange to reschedule if the resulting priority is better * than that of the current process. */voidresetpriority(p)	register struct proc *p;{	register unsigned int newpriority;	newpriority = PUSER + p->p_estcpu / 4 + 2 * p->p_nice;	newpriority = min(newpriority, MAXPRI);	p->p_usrpri = newpriority;	if (newpriority < curpriority)		need_resched();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -