chans and maps of interfaces

R=r
DELTA=746  (729 added, 1 deleted, 16 changed)
OCL=20858
CL=20858
diff --git a/src/runtime/chan.c b/src/runtime/chan.c
index 45b32d3..14b5ce3 100644
--- a/src/runtime/chan.c
+++ b/src/runtime/chan.c
@@ -17,10 +17,10 @@
 struct	SudoG
 {
 	G*	g;		// g and selgen constitute
-	byte	elem[8];	// synch data element
 	int16	offset;		// offset of case number
 	int32	selgen;		// a weak pointer to g
 	SudoG*	link;
+	byte	elem[8];	// synch data element (+ more)
 };
 
 struct	WaitQ
@@ -45,7 +45,7 @@
 struct	Link
 {
 	Link*	link;			// asynch queue circular linked list
-	byte	elem[8];		// asynch queue data element
+	byte	elem[8];		// asynch queue data element (+ more)
 };
 
 struct	Scase
@@ -65,7 +65,7 @@
 	uint16	tcase;			// total count of scase[]
 	uint16	ncase;			// currently filled scase[]
 	Select*	link;			// for freelist
-	Scase	scase[1];		// one per case
+	Scase*	scase[1];		// one per case
 };
 
 static	Select*	selfree[20];
@@ -108,7 +108,7 @@
 		b = nil;
 		e = nil;
 		for(i=0; i<hint; i++) {
-			d = mal(sizeof(*d));
+			d = mal(sizeof(*d) + c->elemsize - sizeof(d->elem));
 			if(e == nil)
 				e = d;
 			d->link = b;
@@ -430,7 +430,11 @@
 	if(i >= sel->tcase)
 		throw("selectsend: too many cases");
 	sel->ncase = i+1;
-	cas = &sel->scase[i];
+	cas = sel->scase[i];
+	if(cas == nil) {
+		cas = mal(sizeof *cas + c->elemsize - sizeof(cas->u.elem));
+		sel->scase[i] = cas;
+	}
 
 	cas->pc = sys·getcallerpc(&sel);
 	cas->chan = c;
@@ -473,8 +477,11 @@
 	if(i >= sel->tcase)
 		throw("selectrecv: too many cases");
 	sel->ncase = i+1;
-	cas = &sel->scase[i];
-
+	cas = sel->scase[i];
+	if(cas == nil) {
+		cas = mal(sizeof *cas);
+		sel->scase[i] = cas;
+	}
 	cas->pc = sys·getcallerpc(&sel);
 	cas->chan = c;
 
@@ -506,13 +513,16 @@
 {
 	int32 i;
 	Scase *cas;
-	
+
 	i = sel->ncase;
 	if(i >= sel->tcase)
 		throw("selectdefault: too many cases");
 	sel->ncase = i+1;
-	cas = &sel->scase[i];
-
+	cas = sel->scase[i];
+	if(cas == nil) {
+		cas = mal(sizeof *cas);
+		sel->scase[i] = cas;
+	}
 	cas->pc = sys·getcallerpc(&sel);
 	cas->chan = nil;
 
@@ -579,7 +589,7 @@
 	// pass 1 - look for something already waiting
 	dfl = nil;
 	for(i=0; i<sel->ncase; i++) {
-		cas = &sel->scase[o];
+		cas = sel->scase[o];
 
 		if(cas->send == 2) {	// default
 			dfl = cas;
@@ -613,16 +623,16 @@
 		if(o >= sel->ncase)
 			o -= sel->ncase;
 	}
-	
+
 	if(dfl != nil) {
 		cas = dfl;
 		goto retc;
 	}
-		
+
 
 	// pass 2 - enqueue on all chans
 	for(i=0; i<sel->ncase; i++) {
-		cas = &sel->scase[o];
+		cas = sel->scase[o];
 		c = cas->chan;
 
 		if(c->dataqsiz > 0) {
@@ -682,7 +692,7 @@
 	lock(&chanlock);
 	sg = g->param;
 	o = sg->offset;
-	cas = &sel->scase[o];
+	cas = sel->scase[o];
 	c = cas->chan;
 
 	if(xxx) {
@@ -832,7 +842,7 @@
 	if(sg != nil) {
 		c->free = sg->link;
 	} else
-		sg = mal(sizeof(*sg));
+		sg = mal(sizeof(*sg) + c->elemsize - sizeof(sg->elem));
 	sg->selgen = g->selgen;
 	sg->g = g;
 	sg->offset = 0;
diff --git a/src/runtime/hashmap.c b/src/runtime/hashmap.c
index 83fe06c..5b32fe5 100644
--- a/src/runtime/hashmap.c
+++ b/src/runtime/hashmap.c
@@ -8,6 +8,7 @@
 /* Return a pointer to the struct/union of type "type"
    whose "field" field is addressed by pointer "p". */
 
+
 struct hash {	   /* a hash table; initialize with hash_init() */
 	uint32 count;	  /* elements in table - must be first */
 
@@ -291,7 +292,7 @@
 		int32 shift = HASH_BITS - (st->power + used);
 		int32 index_mask = (1 << st->power) - 1;
 		int32 i = (hash >> shift) & index_mask;	   /* i is the natural position of hash */
-		
+
 		e = HASH_OFFSET (st->entry, i * elemsize); /* e points to element i */
 		e_hash = e->hash;
 		if ((e_hash & HASH_MASK) != HASH_SUBHASH) {      /* a subtable */
@@ -332,7 +333,7 @@
 		int32 shift = HASH_BITS - (st->power + used);
 		int32 index_mask = (1 << st->power) - 1;
 		int32 i = (hash >> shift) & index_mask;	   /* i is the natural position of hash */
-		
+
 		e = HASH_OFFSET (st->entry, i * elemsize); /* e points to element i */
 		e_hash = e->hash;
 		if ((e_hash & HASH_MASK) != HASH_SUBHASH) {      /* a subtable */
@@ -378,7 +379,7 @@
 		struct hash_entry *e = start_e;		   /* e is going to range over [start_e, end_e) */
 		struct hash_entry *end_e;
 		hash_hash_t e_hash = e->hash;
-		
+
 		if ((e_hash & HASH_MASK) == HASH_SUBHASH) {      /* a subtable */
 			pst = (struct hash_subtable **) e->data;
 			flags += HASH_MAKE_USED (st->power);
@@ -662,8 +663,8 @@
 {
 	Hmap *h;
 
-	if(keyalg >= 3 ||
-	   valalg >= 3) {
+	if(keyalg >= 4 ||
+	   valalg >= 4) {
 		prints("0<=");
 		sys·printint(keyalg);
 		prints("<");
diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c
index baf6eb6..3d0ee7f 100644
--- a/src/runtime/runtime.c
+++ b/src/runtime/runtime.c
@@ -644,11 +644,12 @@
 }
 
 Alg
-algarray[3] =
+algarray[4] =
 {
 	{	memhash,	memequal,	memprint,	memcopy	},  // 0
 	{	stringhash,	stringequal,	stringprint,	stringcopy	},  // 1
 //	{	pointerhash,	pointerequal,	pointerprint,	pointercopy	},  // 2
 	{	memhash,	memequal,	memprint,	memcopy	},  // 2 - treat pointers as ints
+	{	memhash,	memequal,	memprint,	memcopy	},  // 3 - treat interfaces as memory
 };
 
diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h
index dea47f7..b2395e2 100644
--- a/src/runtime/runtime.h
+++ b/src/runtime/runtime.h
@@ -220,7 +220,7 @@
 /*
  * external data
  */
-extern	Alg	algarray[3];
+extern	Alg	algarray[4];
 extern	string	emptystring;
 G*	allg;
 int32	goidgen;