summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/runtime/chan.c42
-rw-r--r--src/runtime/hashmap.c11
-rw-r--r--src/runtime/runtime.c3
-rw-r--r--src/runtime/runtime.h2
4 files changed, 35 insertions, 23 deletions
diff --git a/src/runtime/chan.c b/src/runtime/chan.c
index 45b32d3e9..14b5ce3a6 100644
--- a/src/runtime/chan.c
+++ b/src/runtime/chan.c
@@ -17,10 +17,10 @@ typedef struct Scase Scase;
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 Hchan
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 @@ struct Select
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 @@ sys·newchan(uint32 elemsize, uint32 elemalg, uint32 hint,
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 @@ sys·selectsend(Select *sel, Hchan *c, ...)
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 @@ sys·selectrecv(Select *sel, Hchan *c, ...)
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 @@ sys·selectdefault(Select *sel, ...)
{
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 @@ sys·selectgo(Select *sel)
// 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 @@ sys·selectgo(Select *sel)
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 @@ sys·selectgo(Select *sel)
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 @@ allocsg(Hchan *c)
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 83fe06c66..5b32fe588 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 @@ hash_lookup (struct hash *h, void *data, void **pres)
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 @@ hash_remove (struct hash *h, void *data, void *arg)
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 @@ hash_insert_internal (struct hash_subtable **pst, int32 flags, hash_hash_t hash,
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 @@ sys·newmap(uint32 keysize, uint32 valsize,
{
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 baf6eb68b..3d0ee7f1e 100644
--- a/src/runtime/runtime.c
+++ b/src/runtime/runtime.c
@@ -644,11 +644,12 @@ pointercopy(uint32 s, void **a, void **b)
}
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 dea47f72e..b2395e236 100644
--- a/src/runtime/runtime.h
+++ b/src/runtime/runtime.h
@@ -220,7 +220,7 @@ struct Func
/*
* external data
*/
-extern Alg algarray[3];
+extern Alg algarray[4];
extern string emptystring;
G* allg;
int32 goidgen;