main.c

来自「著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是」· C语言 代码 · 共 761 行

C
761
字号
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"io.h"#include	"ureg.h"#include	"init.h"#include	"pool.h"Mach *m;static  uchar *sp;	/* stack pointer for /boot *//* * Where configuration info is left for the loaded programme. * This will turn into a structure as more is done by the boot loader * (e.g. why parse the .ini file twice?). * There are 1024 bytes available at CONFADDR. */#define BOOTLINE	((char*)CONFADDR)#define BOOTLINELEN	64#define BOOTARGS	((char*)(CONFADDR+BOOTLINELEN))#define	BOOTARGSLEN	(1024-BOOTLINELEN)#define	MAXCONF		32char bootdisk[NAMELEN];char *confname[MAXCONF];char *confval[MAXCONF];int nconf;extern void ns16552install(void);	/* botch: config */static int isoldbcom;static intgetcfields(char* lp, char** fields, int n, char* sep){	int i;	for(i = 0; lp && *lp && i < n; i++){		while(*lp && strchr(sep, *lp) != 0)			*lp++ = 0;		if(*lp == 0)			break;		fields[i] = lp;		while(*lp && strchr(sep, *lp) == 0){			if(*lp == '\\' && *(lp+1) == '\n')				*lp++ = ' ';			lp++;		}	}	return i;}static voidoptions(void){	uchar *bda;	long i, n;	char *cp, *line[MAXCONF], *p, *q;	if(strncmp(BOOTARGS, "ZORT 0\r\n", 8)){		isoldbcom = 1;		memmove(BOOTARGS, KADDR(1024), BOOTARGSLEN);		memmove(BOOTLINE, KADDR(0x100), BOOTLINELEN);		bda = KADDR(0x400);		bda[0x13] = 639;		bda[0x14] = 639>>8;	}	/*	 *  parse configuration args from dos file plan9.ini	 */	cp = BOOTARGS;	/* where b.com leaves its config */	cp[BOOTARGSLEN-1] = 0;	/*	 * Strip out '\r', change '\t' -> ' '.	 */	p = cp;	for(q = cp; *q; q++){		if(*q == '\r')			continue;		if(*q == '\t')			*q = ' ';		*p++ = *q;	}	*p = 0;	n = getcfields(cp, line, MAXCONF, "\n");	for(i = 0; i < n; i++){		if(*line[i] == '#')			continue;		cp = strchr(line[i], '=');		if(cp == 0)			continue;		*cp++ = 0;		if(cp - line[i] >= NAMELEN+1)			*(line[i]+NAMELEN-1) = 0;		confname[nconf] = line[i];		confval[nconf] = cp;		nconf++;	}}voidmain(void){	outb(0x3F2, 0x00);			/* botch: turn off the floppy motor */	/*	 * There is a little leeway here in the ordering but care must be	 * taken with dependencies:	 *	function		dependencies	 *	========		============	 *	machinit		depends on: m->machno, m->pdb	 *	cpuidentify		depends on: m	 *	confinit		calls: meminit	 *	meminit			depends on: cpuidentify (needs to know processor	 *				  type for caching, etc.)	 *	archinit		depends on: meminit (MP config table may be at the	 *				  top of system physical memory);	 *				conf.nmach (not critical, mpinit will check);	 *	arch->intrinit		depends on: trapinit	 */	conf.nmach = 1;	MACHP(0) = (Mach*)CPU0MACH;	m->pdb = (ulong*)CPU0PDB;	machinit();	ioinit();	active.machs = 1;	active.exiting = 0;	options();	screeninit();	cpuidentify();	confinit();	archinit();	xinit();	trapinit();	printinit();	cpuidprint();	if(isoldbcom)		print("    ****OLD B.COM - UPGRADE****\n");	mmuinit();	if(arch->intrinit)		arch->intrinit();	ns16552install();			/* botch: config */	mathinit();	kbdinit();	if(arch->clockenable)		arch->clockenable();	procinit0();	initseg();	links();conf.monitor = 1;	chandevreset();	pageinit();	swapinit();	userinit();	schedinit();}voidmachinit(void){	int machno;	ulong *pdb;	machno = m->machno;	pdb = m->pdb;	memset(m, 0, sizeof(Mach));	m->machno = machno;	m->pdb = pdb;}voidksetterm(char *f){	char buf[2*NAMELEN];	sprint(buf, f, conffile);	ksetenv("terminal", buf);}voidinit0(void){	int i;	char tstr[32];	up->nerrlab = 0;	spllo();	/*	 * These are o.k. because rootinit is null.	 * Then early kproc's will have a root and dot.	 */	up->slash = namec("#/", Atodir, 0, 0);	cnameclose(up->slash->name);	up->slash->name = newcname("/");	up->dot = cclone(up->slash, 0);	chandevinit();	if(!waserror()){		strcpy(tstr, arch->id);		strcat(tstr, " %s");		ksetterm(tstr);		ksetenv("cputype", "386");		if(cpuserver)			ksetenv("service", "cpu");		else			ksetenv("service", "terminal");		for(i = 0; i < nconf; i++)			if(confname[i] && confname[i][0] != '*')				ksetenv(confname[i], confval[i]);		poperror();	}	kproc("alarm", alarmkproc, 0);	touser(sp);}voiduserinit(void){	Proc *p;	Segment *s;	KMap *k;	Page *pg;	p = newproc();	p->pgrp = newpgrp();	p->egrp = smalloc(sizeof(Egrp));	p->egrp->ref = 1;	p->fgrp = dupfgrp(nil);	p->rgrp = newrgrp();	p->procmode = 0640;	strcpy(p->text, "*init*");	strcpy(p->user, eve);	p->fpstate = FPinit;	fpoff();	/*	 * Kernel Stack	 *	 * N.B. The -12 for the stack pointer is important.	 *	4 bytes for gotolabel's return PC	 */	p->sched.pc = (ulong)init0;	p->sched.sp = (ulong)p->kstack+KSTACK-(1+MAXSYSARG)*BY2WD;	/*	 * User Stack	 */	s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);	p->seg[SSEG] = s;	pg = newpage(1, 0, USTKTOP-BY2PG);	segpage(s, pg);	k = kmap(pg);	bootargs(VA(k));	kunmap(k);	/*	 * Text	 */	s = newseg(SG_TEXT, UTZERO, 1);	s->flushme++;	p->seg[TSEG] = s;	pg = newpage(1, 0, UTZERO);	memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));	segpage(s, pg);	k = kmap(s->map[0]->pages[0]);	memmove((ulong*)VA(k), initcode, sizeof initcode);	kunmap(k);	ready(p);}uchar *pusharg(char *p){	int n;	n = strlen(p)+1;	sp -= n;	memmove(sp, p, n);	return sp;}voidbootargs(ulong base){ 	int i, ac;	uchar *av[32];	uchar **lsp;	char *cp = BOOTLINE;	char buf[64];	sp = (uchar*)base + BY2PG - MAXSYSARG*BY2WD;	ac = 0;	av[ac++] = pusharg("/386/9dos");	cp[BOOTLINELEN-1] = 0;	buf[0] = 0;	if(strncmp(cp, "fd", 2) == 0){		sprint(buf, "local!#f/fd%lddisk", strtol(cp+2, 0, 0));		av[ac++] = pusharg(buf);	} else if(strncmp(cp, "sd", 2) == 0){		sprint(buf, "local!#S/sd%c%c/fs", *(cp+2), *(cp+3));		av[ac++] = pusharg(buf);	} else if(strncmp(cp, "ether", 5) == 0)		av[ac++] = pusharg("-n");	if(buf[0]){		cp = strchr(buf, '!');		if(cp){			strcpy(bootdisk, cp+1);			addconf("bootdisk", bootdisk);		}	}	/* 4 byte word align stack */	sp = (uchar*)((ulong)sp & ~3);	/* build argc, argv on stack */	sp -= (ac+1)*sizeof(sp);	lsp = (uchar**)sp;	for(i = 0; i < ac; i++)		*lsp++ = av[i] + ((USTKTOP - BY2PG) - base);	*lsp = 0;	sp += (USTKTOP - BY2PG) - base - sizeof(ulong);}Conf	conf;voidaddconf(char *name, char *val){	if(nconf >= MAXCONF)		return;	confname[nconf] = name;	confval[nconf] = val;	nconf++;}char*getconf(char *name){	int i;	for(i = 0; i < nconf; i++)		if(cistrcmp(confname[i], name) == 0)			return confval[i];	return 0;}voidconfinit(void){	char *p;	int userpcnt;	ulong kpages, maxmem;	if(p = getconf("*maxmem"))		maxmem = strtoul(p, 0, 0);	else		maxmem = 0;	if(p = getconf("*kernelpercent"))		userpcnt = 100 - strtol(p, 0, 0);	else		userpcnt = 0;	meminit(maxmem);	conf.npage = conf.npage0 + conf.npage1;	conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;	if(cpuserver)		conf.nproc *= 3;	if(conf.nproc > 2000)		conf.nproc = 2000;	conf.nimage = 200;	conf.nswap = conf.nproc*80;	conf.nswppo = 4096;	if(cpuserver) {		if(userpcnt < 10)			userpcnt = 70;		kpages = conf.npage - (conf.npage*userpcnt)/100;		/*		 * Hack for the big boys. Only good while physmem < 4GB.		 * Give the kernel a max. of 16MB + enough to allocate the		 * page pool.		 * This is an overestimate as conf.upages < conf.npages.		 * The patch of nimage is a band-aid, scanning the whole		 * page list in imagereclaim just takes too long.		 */		if(kpages > (16*MB + conf.npage*sizeof(Page))/BY2PG){			kpages = (16*MB + conf.npage*sizeof(Page))/BY2PG;			conf.nimage = 2000;			kpages += (conf.nproc*KSTACK)/BY2PG;		}	} else {		if(userpcnt < 10) {			if(conf.npage*BY2PG < 16*MB)				userpcnt = 40;			else				userpcnt = 60;		}		kpages = conf.npage - (conf.npage*userpcnt)/100;		/*		 * Make sure terminals with low memory get at least		 * 4MB on the first Image chunk allocation.		 */		if(conf.npage*BY2PG < 16*MB)			imagmem->minarena = 4*1024*1024;	}	conf.upages = conf.npage - kpages;	conf.ialloc = (kpages/2)*BY2PG;	/*	 * Guess how much is taken by the large permanent	 * datastructures. Mntcache and Mntrpc are not accounted for	 * (probably ~300KB).	 */	kpages *= BY2PG;	kpages -= conf.upages*sizeof(Page)		+ conf.nproc*sizeof(Proc)		+ conf.nimage*sizeof(Image)		+ conf.nswap		+ conf.nswppo*sizeof(Page);	mainmem->maxsize = kpages;	if(!cpuserver){		/*		 * give terminals lots of image memory, too; the dynamic		 * allocation will balance the load properly, hopefully.		 * be careful with 32-bit overflow.		 */		imagmem->maxsize = kpages;	}}static char* mathmsg[] ={	"invalid",	"denormalized",	"div-by-zero",	"overflow",	"underflow",	"precision",	"stack",	"error",};static voidmathnote(void){	int i;	ulong status;	char *msg, note[ERRLEN];	status = up->fpsave.status;	/*	 * Some attention should probably be paid here to the	 * exception masks and error summary.	 */	msg = "unknown";	for(i = 0; i < 8; i++){		if(!((1<<i) & status))			continue;		msg = mathmsg[i];		break;	}	sprint(note, "sys: fp: %s fppc=0x%lux", msg, up->fpsave.pc);	postnote(up, 1, note, NDebug);}/* *  math coprocessor error */static voidmatherror(Ureg *ur, void*){	/*	 *  a write cycle to port 0xF0 clears the interrupt latch attached	 *  to the error# line from the 387	 */	if(!(m->cpuiddx & 0x01))		outb(0xF0, 0xFF);	/*	 *  save floating point state to check out error	 */	fpenv(&up->fpsave);	mathnote();	if(ur->pc & KZERO)		panic("fp: status %lux fppc=0x%lux pc=0x%lux",			up->fpsave.status, up->fpsave.pc, ur->pc);}/* *  math coprocessor emulation fault */static voidmathemu(Ureg*, void*){	switch(up->fpstate){	case FPinit:		fpinit();		up->fpstate = FPactive;		break;	case FPinactive:		/*		 * Before restoring the state, check for any pending		 * exceptions, there's no way to restore the state without		 * generating an unmasked exception.		 * More attention should probably be paid here to the		 * exception masks and error summary.		 */		if((up->fpsave.status & ~up->fpsave.control) & 0x07F){			mathnote();			break;		}		fprestore(&up->fpsave);		up->fpstate = FPactive;		break;	case FPactive:		panic("math emu", 0);		break;	}}/* *  math coprocessor segment overrun */static voidmathover(Ureg*, void*){	pexit("math overrun", 0);}voidmathinit(void){	trapenable(VectorCERR, matherror, 0, "matherror");	if(X86FAMILY(m->cpuidax) == 3)		intrenable(IrqIRQ13, matherror, 0, BUSUNKNOWN, "matherror");	trapenable(VectorCNA, mathemu, 0, "mathemu");	trapenable(VectorCSO, mathover, 0, "mathover");}/* *  set up floating point for a new process */voidprocsetup(Proc *p){	p->fpstate = FPinit;	fpoff();}/* *  Save the mach dependent part of the process state. */voidprocsave(Proc *p){	if(p->fpstate == FPactive){		if(p->state == Moribund)			fpoff();		else{			/*			 * Fpsave() stores without handling pending			 * unmasked exeptions. Postnote() can't be called			 * here as sleep() already has up->rlock, so			 * the handling of pending exceptions is delayed			 * until the process runs again and generates an			 * emulation fault to activate the FPU.			 */			fpsave(&up->fpsave);		}		p->fpstate = FPinactive;	}	/*	 * Switch to the prototype page tables for this processor.	 * While this processor is in the scheduler, the process could run	 * on another processor and exit, returning the page tables to	 * the free list where they could be reallocated and overwritten.	 * When this processor eventually has to get an entry from the	 * trashed page tables it will crash.	 */	mmuflushtlb(PADDR(m->pdb));}voidexit(int ispanic){	int ms, once;	lock(&active);	if(ispanic)		active.ispanic = ispanic;	else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)		active.ispanic = 0;	once = active.machs & (1<<m->machno);	active.machs &= ~(1<<m->machno);	active.exiting = 1;	unlock(&active);	if(once)		print("cpu%d: exiting\n", m->machno);	spllo();	for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){		delay(TK2MS(2));		if(active.machs == 0 && consactive() == 0)			break;	}	if(active.ispanic && m->machno == 0){		if(cpuserver)			delay(10000);		else			for(;;);	}	else		delay(1000);	arch->reset();}intisaconfig(char *class, int ctlrno, ISAConf *isa){	char cc[NAMELEN], *p, *q, *r;	int n;	sprint(cc, "%s%d", class, ctlrno);	for(n = 0; n < nconf; n++){		if(cistrncmp(confname[n], cc, NAMELEN))			continue;		isa->nopt = 0;		p = confval[n];		while(*p){			while(*p == ' ' || *p == '\t')				p++;			if(*p == '\0')				break;			if(cistrncmp(p, "type=", 5) == 0){				p += 5;				for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){					if(*p == '\0' || *p == ' ' || *p == '\t')						break;					*q = *p++;				}				*q = '\0';			}			else if(cistrncmp(p, "port=", 5) == 0)				isa->port = strtoul(p+5, &p, 0);			else if(cistrncmp(p, "irq=", 4) == 0)				isa->irq = strtoul(p+4, &p, 0);			else if(cistrncmp(p, "dma=", 4) == 0)				isa->dma = strtoul(p+4, &p, 0);			else if(cistrncmp(p, "mem=", 4) == 0)				isa->mem = strtoul(p+4, &p, 0);			else if(cistrncmp(p, "size=", 5) == 0)				isa->size = strtoul(p+5, &p, 0);			else if(cistrncmp(p, "freq=", 5) == 0)				isa->freq = strtoul(p+5, &p, 0);			else if(isa->nopt < NISAOPT){				r = isa->opt[isa->nopt];				while(*p && *p != ' ' && *p != '\t'){					*r++ = *p++;					if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)						break;				}				*r = '\0';				isa->nopt++;			}			while(*p && *p != ' ' && *p != '\t')				p++;		}		return 1;	}	return 0;}/*intiprint(char *fmt, ...){	char buf[PRINTSIZE];	int n;	va_list arg;	va_start(arg, fmt);	n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf;	va_end(arg);	screenputs(buf, n);	return n;}*/intcistrcmp(char *a, char *b){	int ac, bc;	for(;;){		ac = *a++;		bc = *b++;			if(ac >= 'A' && ac <= 'Z')			ac = 'a' + (ac - 'A');		if(bc >= 'A' && bc <= 'Z')			bc = 'a' + (bc - 'A');		ac -= bc;		if(ac)			return ac;		if(bc == 0)			break;	}	return 0;}intcistrncmp(char *a, char *b, int n){	unsigned ac, bc;	while(n > 0){		ac = *a++;		bc = *b++;		n--;		if(ac >= 'A' && ac <= 'Z')			ac = 'a' + (ac - 'A');		if(bc >= 'A' && bc <= 'Z')			bc = 'a' + (bc - 'A');		ac -= bc;		if(ac)			return ac;		if(bc == 0)			break;	}	return 0;}

⌨️ 快捷键说明

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