Browse Source

Plan 9 from Bell Labs 2012-04-26

David du Colombier 12 years ago
parent
commit
228a44ca92
6 changed files with 121 additions and 57 deletions
  1. 4 2
      sys/man/8/prep
  2. 1 1
      sys/src/9/omap/kbd.c
  3. 4 50
      sys/src/9/pc/main.c
  4. 5 1
      sys/src/9/port/chan.c
  5. 15 1
      sys/src/cmd/ecp.c
  6. 92 2
      sys/src/cmd/ip/httpd/httpd.c

+ 4 - 2
sys/man/8/prep

@@ -652,7 +652,9 @@ partition and then executes the boot block for
 that partition.
 The partition boot block then loads a bootstrap
 program such as
-.IR 9load (8),
+.I 9load
+(see
+.IR 9boot (8)),
 which then loads the operating system.
 If MS-DOS or Windows is already installed
 on your disk, the master boot record
@@ -730,7 +732,7 @@ assembler source for
 .IR floppy (3),
 .IR sd (3),
 .IR usb (4),
-.IR 9load (8),
+.IR 9boot (8),
 .IR mkusbboot (8),
 .IR partfs (8)
 .SH BUGS

+ 1 - 1
sys/src/9/omap/kbd.c

@@ -1,5 +1,5 @@
 /*
- * simulated keyboard input for omap35 with no keyboard (except via uart or usb)
+ * simulated keyboard input for systems with none (except via uart or usb)
  *
  * gutted version of ps2 version from ../pc
  */

+ 4 - 50
sys/src/9/pc/main.c

@@ -10,10 +10,6 @@
 #include	"reboot.h"
 #include	"mp.h"
 
-enum {
-	Less_power_slower = 1,
-};
-
 Mach *m;
 
 /*
@@ -35,6 +31,7 @@ char *confval[MAXCONF];
 int nconf;
 uchar *sp;	/* user stack of init proc */
 int delaylink;
+int always_idle;
 
 static void
 options(void)
@@ -81,90 +78,52 @@ extern void (*i8237alloc)(void);
 void
 main(void)
 {
-cgapost(0);
 	mach0init();
-cgapost(1);
 	options();
-cgapost(2);
 	ioinit();
-cgapost(3);
 	i8250console();
-cgapost(4);
 	quotefmtinstall();
-cgapost(5);
 	screeninit();
 
 	print("\nPlan 9\n");
 
-cgapost(6);
 	trapinit0();
-cgapost(7);
 	mmuinit0();
 
-cgapost(0x10);
 	kbdinit();
-cgapost(0x11);
 	i8253init();
-cgapost(0x12);
 	cpuidentify();
-cgapost(0x13);
 	meminit();
-cgapost(0x14);
 	confinit();
-cgapost(0x15);
 	archinit();
-cgapost(0x16);
 	xinit();
-cgapost(0x17);
 	if(i8237alloc != nil)
 		i8237alloc();
-cgapost(0x18);
 	trapinit();
-cgapost(0x19);
 	printinit();
-cgapost(0x1a);
 	cpuidprint();
-cgapost(0x1b);
 	mmuinit();
-cgapost(0x1c);
 	if(arch->intrinit)	/* launches other processors on an mp */
 		arch->intrinit();
-cgapost(0x1d);
 	timersinit();
-cgapost(0x1e);
 	mathinit();
-cgapost(0x1f);
 	kbdenable();
-cgapost(0x20);
 	if(arch->clockenable)
 		arch->clockenable();
-cgapost(0x21);
 	procinit0();
-cgapost(0x22);
 	initseg();
 	if(delaylink){
-cgapost(0x23);
 		bootlinks();
-cgapost(0x24);
 		pcimatch(0, 0, 0);
 	}else
-{
-cgapost(0x25);
 		links();
-}
-cgapost(0x26);
 	conf.monitor = 1;
 	chandevreset();
-cgapost(0x60);
 	pageinit();
-cgapost(0x61);
 	i8253link();
-cgapost(0x62);
 	swapinit();
-cgapost(0x63);
 	userinit();
 	active.thunderbirdsarego = 1;
-cgapost(0x99);
 	schedinit();
 }
 
@@ -215,14 +174,12 @@ init0(void)
 
 	up->nerrlab = 0;
 
-cgapost(0x70);
 	spllo();
 
 	/*
 	 * These are o.k. because rootinit is null.
 	 * Then early kproc's will have a root and dot.
 	 */
-cgapost(0x71);
 	up->slash = namec("#/", Atodir, 0, 0);
 	pathclose(up->slash->path);
 	up->slash->path = newpath("/");
@@ -231,7 +188,6 @@ cgapost(0x71);
 	chandevinit();
 
 	if(!waserror()){
-cgapost(0x72);
 		snprint(buf, sizeof(buf), "%s %s", arch->id, conffile);
 		ksetenv("terminal", buf, 0);
 		ksetenv("cputype", "386", 0);
@@ -246,9 +202,7 @@ cgapost(0x72);
 		}
 		poperror();
 	}
-cgapost(0x73);
 	kproc("alarm", alarmkproc, 0);
-cgapost(0x9);
 	touser(sp);
 }
 
@@ -966,13 +920,13 @@ idlehands(void)
 	/*
 	 * we used to halt only on single-core setups. halting in an smp system 
 	 * can result in a startup latency for processes that become ready.
-	 * if less_power_slower is true, we care more about saving energy
+	 * if always_idle is zero, we care more about saving energy
 	 * than reducing this latency.
 	 *
-	 * the performance loss of less_power_slower seems to be minute
+	 * the performance loss with always_idle == 0 seems to be slight
 	 * and it reduces lock contention (thus system time and real time)
 	 * on many-core systems with large values of NPROC.
 	 */
-	if(conf.nmach == 1 || Less_power_slower)
+	if(conf.nmach == 1 || always_idle == 0)
 		halt();
 }

+ 5 - 1
sys/src/9/port/chan.c

@@ -185,7 +185,7 @@ kstrdup(char **p, char *s)
 	free(prev);
 }
 
-static int debugstart;
+static int debugstart = 1;
 
 void
 chandevreset(void)
@@ -1378,7 +1378,11 @@ namec(char *aname, int amode, int omode, ulong perm)
 		t = devno(r, 1);
 		if(t == -1)
 			error(Ebadsharp);
+		if(debugstart && !devtab[t]->attached)
+			print("attach #%C...", devtab[t]->dc);
 		c = devtab[t]->attach(up->genbuf+n);
+		if(debugstart && c != nil)
+			devtab[t]->attached = 1;
 		break;
 
 	default:

+ 15 - 1
sys/src/cmd/ecp.c

@@ -176,8 +176,10 @@ static int
 bio(File *fp, Rdwrfn *rdwr, char *buff, Daddr stsect, int sects, int mustseek)
 {
 	int xfered;
+	char *tail;
 	ulong toread, bytes = sects * sectsz;
 	static int reblocked = 0;
+	static char magic[] = "\235any old ☺ rubbish\173";
 
 	if (mustseek) {
 		if (!fp->seekable)
@@ -188,10 +190,22 @@ bio(File *fp, Rdwrfn *rdwr, char *buff, Daddr stsect, int sects, int mustseek)
 	if ((long)blocksize != blocksize || (long)bytes != bytes)
 		sysfatal("i/o count too big: %lud", bytes);
 
+	SET(tail);
+	if (rdwr == read) {
+		strcpy(buff, magic);
+		tail = buff + bytes - sizeof magic;
+		strcpy(tail, magic);
+	}
 	werrstr("");
 	xfered = (*rdwr)(fp->fd, buff, bytes);
-	if (xfered == bytes)
+	if (xfered == bytes) {
+		/* don't trust the hardware; it may lie */
+		if (rdwr == read &&
+		    (strcmp(buff, magic) == 0 || strcmp(tail, magic) == 0))
+			fprint(2, "%s: `good' read didn't change buffer\n",
+				argv0);
 		return Enone;			/* did as we asked */
+	}
 	if (xfered < 0)
 		return Eio;			/* out-and-out i/o error */
 	/*

+ 92 - 2
sys/src/cmd/ip/httpd/httpd.c

@@ -6,19 +6,32 @@
 #include "httpd.h"
 #include "httpsrv.h"
 
+enum {
+	Nbuckets	= 256,
+};
+
 typedef struct Strings		Strings;
+typedef struct System		System;
 
 struct Strings
 {
 	char	*s1;
 	char	*s2;
 };
+struct System {
+	char	*rsys;
+	ulong	reqs;
+	ulong	first;
+	ulong	last;
+	System	*next;			/* next in chain */
+};
 
 char	*netdir;
 char	*HTTPLOG = "httpd/log";
 
 static	char		netdirb[256];
 static	char		*namespace;
+static	System		syss[Nbuckets];
 
 static	void		becomenone(char*);
 static	char		*csquery(char*, char*, char*);
@@ -164,6 +177,77 @@ mkhspriv(void)
 	return p;
 }
 
+static uint 
+hashstr(char* key)
+{
+	/* asu works better than pjw for urls */
+	uchar *k = (unsigned char*)key;
+	uint h = 0;
+
+	while(*k!=0)
+		h = 65599*h + *k++;
+        return h;
+}
+
+static System *
+hashsys(char *rsys)
+{
+	int notme;
+	System *sys;
+
+	sys = syss + hashstr(rsys) % nelem(syss);
+	/* if the bucket is empty, just use it, else find or allocate ours */
+	if(sys->rsys != nil) {
+		/* find match or chain end */
+		for(; notme = (strcmp(sys->rsys, rsys) != 0) &&
+		    sys->next != nil; sys = sys->next)
+			;
+		if(notme) {
+			sys->next = malloc(sizeof *sys);  /* extend chain */
+			sys = sys->next;
+		} else
+			return sys;
+	}
+	if(sys != nil) {
+		memset(sys, 0, sizeof *sys);
+		sys->rsys = strdup(rsys);
+	}
+	return sys;
+}
+
+/*
+ * be sure to call this at least once per listen in the parent,
+ * to update the hash chains.
+ * it's okay to call it in the child too, but then sys->reqs only gets
+ * updated in the child.
+ */
+static int
+isswamped(char *rsys)
+{
+	ulong period;
+	System *sys = hashsys(rsys);
+
+	if(sys == nil)
+		return 0;
+	sys->last = time(nil);
+	if(sys->first == 0)
+		sys->first = sys->last;
+	period = sys->first - sys->last;
+	return ++sys->reqs > 30 && period > 30 && sys->reqs / period >= 2;
+}
+
+/* must only be called in child */
+static void
+throttle(int nctl, NetConnInfo *nci, int swamped)
+{
+	if(swamped || isswamped(nci->rsys)) {		/* shed load */
+		syslog(0, HTTPLOG, "overloaded by %s", nci->rsys);
+		sleep(30);
+		close(nctl);
+		exits(nil);
+	}
+}
+
 static void
 dolisten(char *address)
 {
@@ -171,7 +255,7 @@ dolisten(char *address)
 	HConnect *c;
 	NetConnInfo *nci;
 	char ndir[NETPATHLEN], dir[NETPATHLEN], *p, *scheme;
-	int ctl, nctl, data, t, ok, spotchk;
+	int ctl, nctl, data, t, ok, spotchk, swamped;
 	TLSconn conn;
 
 	spotchk = 0;
@@ -203,6 +287,10 @@ dolisten(char *address)
 			syslog(0, HTTPLOG, "ctls = %d", ctl);
 			return;
 		}
+		swamped = 0;
+		nci = getnetconninfo(ndir, -1);
+		if (nci)
+			swamped = isswamped(nci->rsys);
 
 		/*
 		 *  start a process for the service
@@ -237,7 +325,8 @@ dolisten(char *address)
 			close(ctl);
 			close(nctl);
 
-			nci = getnetconninfo(ndir, -1);
+			if (nci == nil)
+				nci = getnetconninfo(ndir, -1);
 			c = mkconnect(scheme, nci->lserv);
 			hp = mkhspriv();
 			hp->remotesys = nci->rsys;
@@ -253,6 +342,7 @@ dolisten(char *address)
 			 * only works for http/1.1 or later.
 			 */
 			for(t = 15*60*1000; ; t = 15*1000){
+				throttle(nctl, nci, swamped);
 				if(hparsereq(c, t) <= 0)
 					exits(nil);
 				ok = doreq(c);