Plan 9 from Bell Labs’s /usr/web/sources/contrib/quanstro/root/sys/src/fs/port/main.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#include	"all.h"
#include	"mem.h"
#include	"io.h"
#include	"ureg.h"

Rendez dawnrend;
Queue	*raheadseqq;

void
machinit(void)
{
	int n;

	n = m->machno;
	memset(m, 0, sizeof(Mach));
	m->machno = n;
	m->mmask = 1<<m->machno;
	m->lights = 0;
	dofilter(&m->idle);

	active.exiting = 0;
	active.machs = 1;
}

static
void
confinit(void)
{
	conf.nmach = 1;
	conf.nproc = 80;

	conf.mem = meminit();
	conf.sparemem = conf.mem/12;		/* 8% spare for chk etc */
	if(conf.sparemem > 100*MiB)
		conf.sparemem = 100*MiB;

	conf.nuid = 1000;
	conf.nserve = 15;
	conf.nrahead = 20;
	conf.nfile = 30000;
	conf.nlgmsg = 100;
	conf.nsmmsg = 500;
	/*
	 * if you have trouble with IDE DMA or RWM (multi-sector transfers),
	 * perhaps due to old hardware, set idedma to zero in localconfinit().
	 */
	conf.idedma = 1;

	localconfinit();

	conf.nwpath = conf.nfile*8;
	conf.nauth = conf.nfile/10;
	conf.gidspace = conf.nuid*3;

	cons.flags = 0;
}

void
main(void)
{
	int i;

	echo = 1;
	predawn = 1;
		formatinit();
		machinit();
		cpuidentify();
		vecinit();
		confinit();
		if(conf.uartonly)
			uartspecial(0, kbdchar, conschar, conf.uartonly);
		lockinit();
		printinit();
		procinit();
		clockinit();

		print("Plan 9 fileserver\n");
		print("\t%d-bit, %d-byte blocks\n", sizeof(Off)*8-1, RBUFSIZE);

		profinit();

		mainlock.wr.name = "mainw";
		mainlock.rd.name = "mainr";
		reflock.name = "ref";

		qlock(&reflock);
		qunlock(&reflock);
		serveq = newqueue(1000);
		raheadq = newqueue(1000);
		raheadseqq = newqueue(1000);

		mbinit();
		sntpinit();
		otherinit();

		files = ialloc(conf.nfile * sizeof(*files), 0);
		for(i=0; i<conf.nfile; i++) {
			qlock(&files[i]);
			files[i].name = "file";
			qunlock(&files[i]);
		}

		wpaths = ialloc(conf.nwpath * sizeof(*wpaths), 0);
		uid = ialloc(conf.nuid * sizeof(*uid), 0);
		gidspace = ialloc(conf.gidspace * sizeof(*gidspace), 0);
		authinit();

		iobufinit();
		arginit();
		userinit(touser, 0, "ini");

	predawn = 0;
		wakeup(&dawnrend);
		launchinit();
		schedinit();
}

/*
 * read ahead processes.
 * read message from q and then
 * read the device.
 */
//#ifdef notdef
static int
rbcmp(void *va, void *vb)
{
	Rabuf *ra, *rb;

	ra = *(Rabuf**)va;
	rb = *(Rabuf**)vb;
	if(rb == 0)
		return 1;
	if(ra == 0)
		return -1;
	if(ra->dev > rb->dev)
		return 1;
	if(ra->dev < rb->dev)
		return -1;
	if(ra->addr > rb->addr)
		return 1;
	if(ra->addr < rb->addr)
		return -1;
	return 0;
}

static void
raheadq0(void)
{
	Rabuf *rb;
	Iobuf *p;

loop:
	rb = recv(raheadseqq, 1);
	p = getbuf(rb->dev, rb->addr, Bread);
	if(p)
		putbuf(p);

	lock(&rabuflock);
	rb->link = rabuffree;
	rabuffree = rb;
	unlock(&rabuflock);
	goto loop;
}

void
raheadsort(void)
{
	Rabuf *rb[50];
	int i, n;

	for(i = 0; i < conf.nrahead; i++)
		userinit(raheadq0, 0, "rah");
	for(;;){
		rb[0] = recv(raheadq, 1);
		for(n = 1; n < nelem(rb); n++) {
			/* roll the dice; hope waiting helps */
			while(raheadq->count == 0 && raheadseqq->count > 0)
				waitmsec(1);
			if(raheadq->count == 0)
				break;
			rb[n] = recv(raheadq, 1);
		}
//print("n=%d %lld\n", n, rb[0]->addr);
		qsort(rb, n, sizeof *rb, rbcmp);
		for(i = 0; i < n; i++)
			send(raheadseqq, rb[i]);
	}
}
//#endif

void
rahead(void)
{
	Rabuf *rb;
	Iobuf *p;

loop:
	rb = recv(raheadq, 1);
	p = getbuf(rb->dev, rb->addr, Bread);
	if(p)
		putbuf(p);

	lock(&rabuflock);
	rb->link = rabuffree;
	rabuffree = rb;
	unlock(&rabuflock);
	goto loop;
}

/*
 * main filesystem server loop.
 * entered by many processes.
 * they wait for message buffers and
 * then process them.
 */
void
serve(void)
{
	int i;
	Chan *cp;
	Msgbuf *mb;

	for (;;) {
		qlock(&reflock);
		mb = recv(serveq, 1);
		cp = mb->chan;
		rlock(&cp->reflock);
		qunlock(&reflock);

		rlock(&mainlock);

		if(serve9p(mb) != 1){
			print("bad message\n");
			for(i = 0; i < 12; i++)
				print(" %2.2ux", mb->data[i]);
			print("\n");
		}

		mbfree(mb);
		runlock(&mainlock);
		runlock(&cp->reflock);
	}
}

void
init0(void)
{
	m->proc = u;
	u->state = Running;
	u->mach = m;
	spllo();

	u->start();
}

/*
 * allow stuff like the floppy controller to be decoupled.
 */
static struct{
	void	(*f)(void*);
	void	*v;
}aetab[5];

void
atexit(void (*f)(void*), void *v)
{
	int i;
	
	for(i = 0; i < nelem(aetab); i++)
		if(aetab[i].f == 0){
			aetab[i].f = f;
			aetab[i].v = v;
			return;
		}
	panic("too many atexits");
}

static void
doexits(void){
	int i;

	for(i = 0; i < nelem(aetab); i++)
		if(aetab[i].f)
			aetab[i].f(aetab[i].v);
}

enum {
	Keydelay = 5*60,	/* seconds to wait for key press */
};

void
exit(void)
{
	if(m->machno == 0)
		doexits();
	u = 0;
	lock(&active);
	active.machs &= ~(1<<m->machno);
	active.exiting = 1;
	unlock(&active);
	if(!predawn)
		spllo();
	print("cpu %d exiting\n", m->machno);
	while(active.machs)
		delay(1);

	print("halted at %T.\npress a key to reboot sooner than %d mins.\n",
		time(), Keydelay/60);
	delay(500);		/* time to drain print q */

	splhi();
	/* reboot after delay (for debugging) or at key press */
	rawchar(Keydelay);

	spllo();
	delay(500);		/* time to drain echo q */
	print("rebooting...\n");
	delay(500);		/* time to drain print q */

	splhi();
	consreset();
	firmware();
}

#define	DUMPTIME	5	/* 5 am */
#define	WEEKMASK	0	/* every day (1=sun, 2=mon, 4=tue, etc.) */

/*
 * calculate the next dump time.
 * minimum delay is 100 minutes.
 */
Timet nextdump(Timet t)
{
	Timet n;

	n = nextime(t+MINUTE(100), DUMPTIME, WEEKMASK);
	if(!conf.nodump)
		print("next dump at %T\n", n);
	return n;
}

/*
 * process to copy dump blocks from
 * cache to worm. it runs flat out when
 * it gets work, but only looks for
 * work every 10 seconds.
 */
void
wormcopy(void)
{
	int f;
	Filsys *fs;
	Timet dt, t, nddate, ntoytime;

recalc:
	nddate = nextdump(t = time());
	ntoytime = t;
loop:
	dt = time() - t;
	if(dt < 0){
		print("time when back\n");
		goto recalc;
	}
	if(dt > MINUTE(100)){
		print("time jumped ahead\n");
		goto recalc;
	}
	t += dt;
	if(t > ntoytime) {
		dt = time() - rtctime();
		if(dt < 0)
			dt = -dt;
		if(dt > 10)
			print("rtc time more than 10 seconds out\n");
		else if(dt > 1)
			settime(rtctime());
		ntoytime = time() + HOUR(1);
		goto loop;
	}
	if(!conf.nodump)
	if(t > nddate){
		print("automatic dump %T\n", t);
		for(fs=filsys; fs->name; fs++)
			if(fs->dev->type == Devcw)
				cfsdump(fs);
		goto recalc;
	}

	f = 0;
	rlock(&mainlock);
	for(fs=filsys; fs->name; fs++)
		if(fs->dev->type == Devcw)
			f |= dumpblock(fs->dev);
	runlock(&mainlock);

	if(!f)
		waitmsec(10000);
	wormprobe();
	goto loop;
}

/*
 * process to synch blocks
 * it puts out a block/cache-line every second
 * it waits 10 seconds if caught up.
 * in both cases, it takes about 10 seconds
 * to get up-to-date.
 */
void
synccopy(void)
{
	int f;

	for (;;) {
		rlock(&mainlock);
		f = syncblock();
		runlock(&mainlock);
		if(!f)
			waitmsec(10000);
	//	else
	//		waitmsec(1000);
		/* pokewcp();	*/
	}
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.