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

📄 slp.c

📁 UNIX v6源代码 这几乎是最经典的unix版本 unix操作系统设计和莱昂氏unix源代码分析都是用的该版
💻 C
字号:
#/* */#include "../param.h"#include "../user.h"#include "../proc.h"#include "../text.h"#include "../systm.h"#include "../file.h"#include "../inode.h"#include "../buf.h"/* * Give up the processor till a wakeup occurs * on chan, at which time the process * enters the scheduling queue at priority pri. * The most important effect of pri is that when * pri<0 a signal cannot disturb the sleep; * if pri>=0 signals will be processed. * Callers of this routine must be prepared for * premature return, and check that the reason for * sleeping has gone away. */sleep(chan, pri){	register *rp, s;	s = PS->integ;	rp = u.u_procp;	if(pri >= 0) {		if(issig())			goto psig;		spl6();		rp->p_wchan = chan;		rp->p_stat = SWAIT;		rp->p_pri = pri;		spl0();		if(runin != 0) {			runin = 0;			wakeup(&runin);		}		swtch();		if(issig())			goto psig;	} else {		spl6();		rp->p_wchan = chan;		rp->p_stat = SSLEEP;		rp->p_pri = pri;		spl0();		swtch();	}	PS->integ = s;	return;	/*	 * If priority was low (>=0) and	 * there has been a signal,	 * execute non-local goto to	 * the qsav location.	 * (see trap1/trap.c)	 */psig:	aretu(u.u_qsav);}/* * Wake up all processes sleeping on chan. */wakeup(chan){	register struct proc *p;	register c, i;	c = chan;	p = &proc[0];	i = NPROC;	do {		if(p->p_wchan == c) {			setrun(p);		}		p++;	} while(--i);}/* * Set the process running; * arrange for it to be swapped in if necessary. */setrun(p){	register struct proc *rp;	rp = p;	rp->p_wchan = 0;	rp->p_stat = SRUN;	if(rp->p_pri < curpri)		runrun++;	if(runout != 0 && (rp->p_flag&SLOAD) == 0) {		runout = 0;		wakeup(&runout);	}}/* * Set user priority. * The rescheduling flag (runrun) * is set if the priority is higher * than the currently running process. */setpri(up){	register *pp, p;	pp = up;	p = (pp->p_cpu & 0377)/16;	p =+ PUSER + pp->p_nice;	if(p > 127)		p = 127;	if(p > curpri)		runrun++;	pp->p_pri = p;}/* * The main loop of the scheduling (swapping) * process. * The basic idea is: *  see if anyone wants to be swapped in; *  swap out processes until there is room; *  swap him in; *  repeat. * Although it is not remarkably evident, the basic * synchronization here is on the runin flag, which is * slept on and is set once per second by the clock routine. * Core shuffling therefore takes place once per second. * * panic: swap error -- IO error while swapping. *	this is the one panic that should be *	handled in a less drastic way. Its *	very hard. */sched(){	struct proc *p1;	register struct proc *rp;	register a, n;	/*	 * find user to swap in	 * of users ready, select one out longest	 */	goto loop;sloop:	runin++;	sleep(&runin, PSWP);loop:	spl6();	n = -1;	for(rp = &proc[0]; rp < &proc[NPROC]; rp++)	if(rp->p_stat==SRUN && (rp->p_flag&SLOAD)==0 &&	    rp->p_time > n) {		p1 = rp;		n = rp->p_time;	}	if(n == -1) {		runout++;		sleep(&runout, PSWP);		goto loop;	}	/*	 * see if there is core for that process	 */	spl0();	rp = p1;	a = rp->p_size;	if((rp=rp->p_textp) != NULL)		if(rp->x_ccount == 0)			a =+ rp->x_size;	if((a=malloc(coremap, a)) != NULL)		goto found2;	/*	 * none found,	 * look around for easy core	 */	spl6();	for(rp = &proc[0]; rp < &proc[NPROC]; rp++)	if((rp->p_flag&(SSYS|SLOCK|SLOAD))==SLOAD &&	    (rp->p_stat == SWAIT || rp->p_stat==SSTOP))		goto found1;	/*	 * no easy core,	 * if this process is deserving,	 * look around for	 * oldest process in core	 */	if(n < 3)		goto sloop;	n = -1;	for(rp = &proc[0]; rp < &proc[NPROC]; rp++)	if((rp->p_flag&(SSYS|SLOCK|SLOAD))==SLOAD &&	   (rp->p_stat==SRUN || rp->p_stat==SSLEEP) &&	    rp->p_time > n) {		p1 = rp;		n = rp->p_time;	}	if(n < 2)		goto sloop;	rp = p1;	/*	 * swap user out	 */found1:	spl0();	rp->p_flag =& ~SLOAD;	xswap(rp, 1, 0);	goto loop;	/*	 * swap user in	 */found2:	if((rp=p1->p_textp) != NULL) {		if(rp->x_ccount == 0) {			if(swap(rp->x_daddr, a, rp->x_size, B_READ))				goto swaper;			rp->x_caddr = a;			a =+ rp->x_size;		}		rp->x_ccount++;	}	rp = p1;	if(swap(rp->p_addr, a, rp->p_size, B_READ))		goto swaper;	mfree(swapmap, (rp->p_size+7)/8, rp->p_addr);	rp->p_addr = a;	rp->p_flag =| SLOAD;	rp->p_time = 0;	goto loop;swaper:	panic("swap error");}/* * This routine is called to reschedule the CPU. * if the calling process is not in RUN state, * arrangements for it to restart must have * been made elsewhere, usually by calling via sleep. */swtch(){	static struct proc *p;	register i, n;	register struct proc *rp;	if(p == NULL)		p = &proc[0];	/*	 * Remember stack of caller	 */	savu(u.u_rsav);	/*	 * Switch to scheduler's stack	 */	retu(proc[0].p_addr);loop:	runrun = 0;	rp = p;	p = NULL;	n = 128;	/*	 * Search for highest-priority runnable process	 */	i = NPROC;	do {		rp++;		if(rp >= &proc[NPROC])			rp = &proc[0];		if(rp->p_stat==SRUN && (rp->p_flag&SLOAD)!=0) {			if(rp->p_pri < n) {				p = rp;				n = rp->p_pri;			}		}	} while(--i);	/*	 * If no process is runnable, idle.	 */	if(p == NULL) {		p = rp;		idle();		goto loop;	}	rp = p;	curpri = n;	/*	 * Switch to stack of the new process and set up	 * his segmentation registers.	 */	retu(rp->p_addr);	sureg();	/*	 * If the new process paused because it was	 * swapped out, set the stack level to the last call	 * to savu(u_ssav).  This means that the return	 * which is executed immediately after the call to aretu	 * actually returns from the last routine which did	 * the savu.	 *	 * You are not expected to understand this.	 */	if(rp->p_flag&SSWAP) {		rp->p_flag =& ~SSWAP;		aretu(u.u_ssav);	}	/*	 * The value returned here has many subtle implications.	 * See the newproc comments.	 */	return(1);}/* * Create a new process-- the internal version of * sys fork. * It returns 1 in the new process. * How this happens is rather hard to understand. * The essential fact is that the new process is created * in such a way that appears to have started executing * in the same call to newproc as the parent; * but in fact the code that runs is that of swtch. * The subtle implication of the returned value of swtch * (see above) is that this is the value that newproc's * caller in the new process sees. */newproc(){	int a1, a2;	struct proc *p, *up;	register struct proc *rpp;	register *rip, n;	p = NULL;	/*	 * First, just locate a slot for a process	 * and copy the useful info from this process into it.	 * The panic "cannot happen" because fork has already	 * checked for the existence of a slot.	 */retry:	mpid++;	if(mpid < 0) {		mpid = 0;		goto retry;	}	for(rpp = &proc[0]; rpp < &proc[NPROC]; rpp++) {		if(rpp->p_stat == NULL && p==NULL)			p = rpp;		if (rpp->p_pid==mpid)			goto retry;	}	if ((rpp = p)==NULL)		panic("no procs");	/*	 * make proc entry for new proc	 */	rip = u.u_procp;	up = rip;	rpp->p_stat = SRUN;	rpp->p_flag = SLOAD;	rpp->p_uid = rip->p_uid;	rpp->p_ttyp = rip->p_ttyp;	rpp->p_nice = rip->p_nice;	rpp->p_textp = rip->p_textp;	rpp->p_pid = mpid;	rpp->p_ppid = rip->p_pid;	rpp->p_time = 0;	/*	 * make duplicate entries	 * where needed	 */	for(rip = &u.u_ofile[0]; rip < &u.u_ofile[NOFILE];)		if((rpp = *rip++) != NULL)			rpp->f_count++;	if((rpp=up->p_textp) != NULL) {		rpp->x_count++;		rpp->x_ccount++;	}	u.u_cdir->i_count++;	/*	 * Partially simulate the environment	 * of the new process so that when it is actually	 * created (by copying) it will look right.	 */	savu(u.u_rsav);	rpp = p;	u.u_procp = rpp;	rip = up;	n = rip->p_size;	a1 = rip->p_addr;	rpp->p_size = n;	a2 = malloc(coremap, n);	/*	 * If there is not enough core for the	 * new process, swap out the current process to generate the	 * copy.	 */	if(a2 == NULL) {		rip->p_stat = SIDL;		rpp->p_addr = a1;		savu(u.u_ssav);		xswap(rpp, 0, 0);		rpp->p_flag =| SSWAP;		rip->p_stat = SRUN;	} else {	/*	 * There is core, so just copy.	 */		rpp->p_addr = a2;		while(n--)			copyseg(a1++, a2++);	}	u.u_procp = rip;	return(0);}/* * Change the size of the data+stack regions of the process. * If the size is shrinking, it's easy-- just release the extra core. * If it's growing, and there is core, just allocate it * and copy the image, taking care to reset registers to account * for the fact that the system's stack has moved. * If there is no core, arrange for the process to be swapped * out after adjusting the size requirement-- when it comes * in, enough core will be allocated. * Because of the ssave and SSWAP flags, control will * resume after the swap in swtch, which executes the return * from this stack level. * * After the expansion, the caller will take care of copying * the user's stack towards or away from the data area. */expand(newsize){	int i, n;	register *p, a1, a2;	p = u.u_procp;	n = p->p_size;	p->p_size = newsize;	a1 = p->p_addr;	if(n >= newsize) {		mfree(coremap, n-newsize, a1+newsize);		return;	}	savu(u.u_rsav);	a2 = malloc(coremap, newsize);	if(a2 == NULL) {		savu(u.u_ssav);		xswap(p, 1, n);		p->p_flag =| SSWAP;		swtch();		/* no return */	}	p->p_addr = a2;	for(i=0; i<n; i++)		copyseg(a1+i, a2++);	mfree(coremap, n, a1);	retu(p->p_addr);	sureg();}

⌨️ 快捷键说明

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