17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <auth.h>
47dd7cddfSDavid du Colombier #include <fcall.h>
57dd7cddfSDavid du Colombier #include <thread.h>
6*9a747e4fSDavid du Colombier #include <9p.h>
77dd7cddfSDavid du Colombier
87dd7cddfSDavid du Colombier enum {
97dd7cddfSDavid du Colombier NHASH = 128
107dd7cddfSDavid du Colombier };
117dd7cddfSDavid du Colombier
127dd7cddfSDavid du Colombier typedef struct Intlist Intlist;
137dd7cddfSDavid du Colombier struct Intlist
147dd7cddfSDavid du Colombier {
157dd7cddfSDavid du Colombier ulong id;
167dd7cddfSDavid du Colombier void* aux;
177dd7cddfSDavid du Colombier Intlist* link;
187dd7cddfSDavid du Colombier };
197dd7cddfSDavid du Colombier
207dd7cddfSDavid du Colombier struct Intmap
217dd7cddfSDavid du Colombier {
227dd7cddfSDavid du Colombier RWLock;
237dd7cddfSDavid du Colombier Intlist* hash[NHASH];
247dd7cddfSDavid du Colombier void (*inc)(void*);
257dd7cddfSDavid du Colombier };
267dd7cddfSDavid du Colombier
277dd7cddfSDavid du Colombier static ulong
hashid(ulong id)287dd7cddfSDavid du Colombier hashid(ulong id)
297dd7cddfSDavid du Colombier {
307dd7cddfSDavid du Colombier return id%NHASH;
317dd7cddfSDavid du Colombier }
327dd7cddfSDavid du Colombier
337dd7cddfSDavid du Colombier static void
nop(void *)347dd7cddfSDavid du Colombier nop(void*)
357dd7cddfSDavid du Colombier {
367dd7cddfSDavid du Colombier }
377dd7cddfSDavid du Colombier
387dd7cddfSDavid du Colombier Intmap*
allocmap(void (* inc)(void *))397dd7cddfSDavid du Colombier allocmap(void (*inc)(void*))
407dd7cddfSDavid du Colombier {
417dd7cddfSDavid du Colombier Intmap *m;
427dd7cddfSDavid du Colombier
43*9a747e4fSDavid du Colombier m = emalloc9p(sizeof(*m));
447dd7cddfSDavid du Colombier if(inc == nil)
457dd7cddfSDavid du Colombier inc = nop;
467dd7cddfSDavid du Colombier m->inc = inc;
477dd7cddfSDavid du Colombier return m;
487dd7cddfSDavid du Colombier }
497dd7cddfSDavid du Colombier
507dd7cddfSDavid du Colombier void
freemap(Intmap * map,void (* destroy)(void *))51*9a747e4fSDavid du Colombier freemap(Intmap *map, void (*destroy)(void*))
527dd7cddfSDavid du Colombier {
53*9a747e4fSDavid du Colombier int i;
54*9a747e4fSDavid du Colombier Intlist *p, *nlink;
55*9a747e4fSDavid du Colombier
56*9a747e4fSDavid du Colombier if(destroy == nil)
57*9a747e4fSDavid du Colombier destroy = nop;
58*9a747e4fSDavid du Colombier for(i=0; i<NHASH; i++){
59*9a747e4fSDavid du Colombier for(p=map->hash[i]; p; p=nlink){
60*9a747e4fSDavid du Colombier nlink = p->link;
61*9a747e4fSDavid du Colombier destroy(p->aux);
62*9a747e4fSDavid du Colombier free(p);
63*9a747e4fSDavid du Colombier }
64*9a747e4fSDavid du Colombier }
65*9a747e4fSDavid du Colombier
667dd7cddfSDavid du Colombier free(map);
677dd7cddfSDavid du Colombier }
687dd7cddfSDavid du Colombier
697dd7cddfSDavid du Colombier static Intlist**
llookup(Intmap * map,ulong id)707dd7cddfSDavid du Colombier llookup(Intmap *map, ulong id)
717dd7cddfSDavid du Colombier {
727dd7cddfSDavid du Colombier Intlist **lf;
737dd7cddfSDavid du Colombier
747dd7cddfSDavid du Colombier for(lf=&map->hash[hashid(id)]; *lf; lf=&(*lf)->link)
757dd7cddfSDavid du Colombier if((*lf)->id == id)
767dd7cddfSDavid du Colombier break;
777dd7cddfSDavid du Colombier return lf;
787dd7cddfSDavid du Colombier }
797dd7cddfSDavid du Colombier
807dd7cddfSDavid du Colombier /*
817dd7cddfSDavid du Colombier * The RWlock is used as expected except that we allow
827dd7cddfSDavid du Colombier * inc() to be called while holding it. This is because we're
837dd7cddfSDavid du Colombier * locking changes to the tree structure, not to the references.
847dd7cddfSDavid du Colombier * Inc() is expected to have its own locking.
857dd7cddfSDavid du Colombier */
867dd7cddfSDavid du Colombier void*
lookupkey(Intmap * map,ulong id)877dd7cddfSDavid du Colombier lookupkey(Intmap *map, ulong id)
887dd7cddfSDavid du Colombier {
897dd7cddfSDavid du Colombier Intlist *f;
907dd7cddfSDavid du Colombier void *v;
917dd7cddfSDavid du Colombier
927dd7cddfSDavid du Colombier rlock(map);
937dd7cddfSDavid du Colombier if(f = *llookup(map, id)){
947dd7cddfSDavid du Colombier v = f->aux;
957dd7cddfSDavid du Colombier map->inc(v);
967dd7cddfSDavid du Colombier }else
977dd7cddfSDavid du Colombier v = nil;
987dd7cddfSDavid du Colombier runlock(map);
997dd7cddfSDavid du Colombier return v;
1007dd7cddfSDavid du Colombier }
1017dd7cddfSDavid du Colombier
1027dd7cddfSDavid du Colombier void*
insertkey(Intmap * map,ulong id,void * v)1037dd7cddfSDavid du Colombier insertkey(Intmap *map, ulong id, void *v)
1047dd7cddfSDavid du Colombier {
1057dd7cddfSDavid du Colombier Intlist *f;
1067dd7cddfSDavid du Colombier void *ov;
1077dd7cddfSDavid du Colombier ulong h;
1087dd7cddfSDavid du Colombier
1097dd7cddfSDavid du Colombier wlock(map);
1107dd7cddfSDavid du Colombier if(f = *llookup(map, id)){
1117dd7cddfSDavid du Colombier /* no decrement for ov because we're returning it */
1127dd7cddfSDavid du Colombier ov = f->aux;
1137dd7cddfSDavid du Colombier f->aux = v;
114*9a747e4fSDavid du Colombier }else{
115*9a747e4fSDavid du Colombier f = emalloc9p(sizeof(*f));
1167dd7cddfSDavid du Colombier f->id = id;
1177dd7cddfSDavid du Colombier f->aux = v;
1187dd7cddfSDavid du Colombier h = hashid(id);
1197dd7cddfSDavid du Colombier f->link = map->hash[h];
1207dd7cddfSDavid du Colombier map->hash[h] = f;
1217dd7cddfSDavid du Colombier ov = nil;
1227dd7cddfSDavid du Colombier }
1237dd7cddfSDavid du Colombier wunlock(map);
1247dd7cddfSDavid du Colombier return ov;
1257dd7cddfSDavid du Colombier }
1267dd7cddfSDavid du Colombier
1277dd7cddfSDavid du Colombier int
caninsertkey(Intmap * map,ulong id,void * v)1287dd7cddfSDavid du Colombier caninsertkey(Intmap *map, ulong id, void *v)
1297dd7cddfSDavid du Colombier {
1307dd7cddfSDavid du Colombier Intlist *f;
1317dd7cddfSDavid du Colombier int rv;
1327dd7cddfSDavid du Colombier ulong h;
1337dd7cddfSDavid du Colombier
1347dd7cddfSDavid du Colombier wlock(map);
1357dd7cddfSDavid du Colombier if(*llookup(map, id))
1367dd7cddfSDavid du Colombier rv = 0;
1377dd7cddfSDavid du Colombier else{
138*9a747e4fSDavid du Colombier f = emalloc9p(sizeof *f);
1397dd7cddfSDavid du Colombier f->id = id;
1407dd7cddfSDavid du Colombier f->aux = v;
1417dd7cddfSDavid du Colombier h = hashid(id);
1427dd7cddfSDavid du Colombier f->link = map->hash[h];
1437dd7cddfSDavid du Colombier map->hash[h] = f;
1447dd7cddfSDavid du Colombier rv = 1;
1457dd7cddfSDavid du Colombier }
1467dd7cddfSDavid du Colombier wunlock(map);
1477dd7cddfSDavid du Colombier return rv;
1487dd7cddfSDavid du Colombier }
1497dd7cddfSDavid du Colombier
1507dd7cddfSDavid du Colombier void*
deletekey(Intmap * map,ulong id)1517dd7cddfSDavid du Colombier deletekey(Intmap *map, ulong id)
1527dd7cddfSDavid du Colombier {
1537dd7cddfSDavid du Colombier Intlist **lf, *f;
1547dd7cddfSDavid du Colombier void *ov;
1557dd7cddfSDavid du Colombier
1567dd7cddfSDavid du Colombier wlock(map);
1577dd7cddfSDavid du Colombier if(f = *(lf = llookup(map, id))){
1587dd7cddfSDavid du Colombier ov = f->aux;
1597dd7cddfSDavid du Colombier *lf = f->link;
1607dd7cddfSDavid du Colombier free(f);
161*9a747e4fSDavid du Colombier }else
1627dd7cddfSDavid du Colombier ov = nil;
1637dd7cddfSDavid du Colombier wunlock(map);
1647dd7cddfSDavid du Colombier return ov;
1657dd7cddfSDavid du Colombier }
166