提交 b635db5d 创建 作者: Nickolai Zeldovich's avatar Nickolai Zeldovich

different ns key types (int, str)

上级 8e18824b
......@@ -44,13 +44,13 @@ binit(void)
b->flags = 0;
initlock(&b->lock, "bcache-lock");
initcondvar(&b->cv, "bcache-cv");
if (ns_insert(bufns, b->sector, b) < 0)
if (ns_insert(bufns, KI(b->sector), b) < 0)
panic("binit ns_insert");
}
}
static void *
evict(uint key, void *bp)
evict(void *vkey, void *bp)
{
struct buf *b = bp;
acquire(&b->lock);
......@@ -61,7 +61,7 @@ evict(uint key, void *bp)
}
static void *
evict_valid(uint key, void *bp)
evict_valid(void *vkey, void *bp)
{
struct buf *b = bp;
acquire(&b->lock);
......@@ -83,7 +83,7 @@ bget(uint dev, uint sector, int *writer)
// Try for cached block.
// XXX ignore dev
rcu_begin_read();
b = ns_lookup(bufns, sector);
b = ns_lookup(bufns, KI(sector));
if (b) {
if (b->dev != dev)
panic("dev mismatch");
......@@ -113,7 +113,7 @@ bget(uint dev, uint sector, int *writer)
if (victim == 0)
panic("bget all busy");
victim->flags |= B_BUSY;
ns_remove(bufns, victim->sector, victim);
ns_remove(bufns, KI(victim->sector), victim);
release(&victim->lock);
rcu_delayed(victim, kmfree);
......@@ -126,7 +126,7 @@ bget(uint dev, uint sector, int *writer)
initlock(&b->lock, b->lockname+3);
initcondvar(&b->cv, b->lockname);
rcu_begin_read();
if (ns_insert(bufns, b->sector, b) < 0) {
if (ns_insert(bufns, KI(b->sector), b) < 0) {
rcu_delayed(b, kmfree);
goto loop;
}
......
......@@ -99,15 +99,30 @@ void mpinit(void);
void mpstartthem(void);
// ns.c
enum {
nskey_int = 1,
nskey_str,
};
struct nskey {
int type;
union {
uint i;
char *s;
} u;
};
#define KI(v) (struct nskey){.type=nskey_int,.u.i=v}
#define KS(v) (struct nskey){.type=nskey_str,.u.s=v}
void nsinit(void);
struct ns* nsalloc(int allowdup);
int ns_allockey(struct ns*);
int ns_insert(struct ns*, uint key, void*);
void* ns_lookup(struct ns*, uint);
int ns_remove(struct ns *ns, uint key, void *val);
void* ns_enumerate(struct ns *ns, void *(*f)(uint, void *));
void* ns_enumerate_key(struct ns *ns, uint key, void *(*f)(void *));
int ns_insert(struct ns*, struct nskey key, void*);
void* ns_lookup(struct ns*, struct nskey key);
int ns_remove(struct ns *ns, struct nskey key, void *val);
void* ns_enumerate(struct ns *ns, void *(*f)(void *, void *));
void* ns_enumerate_key(struct ns *ns, struct nskey key, void *(*f)(void *));
// picirq.c
void picenable(int);
......@@ -166,6 +181,7 @@ char* safestrcpy(char*, const char*, int);
int strlen(const char*);
int strncmp(const char*, const char*, uint);
char* strncpy(char*, const char*, int);
int strcmp(const char *p, const char *q);
// syscall.c
int argint(int, int*);
......
......@@ -143,7 +143,7 @@ iinit(void)
ip->inum = -i-1;
initlock(&ip->lock, "icache-lock");
initcondvar(&ip->cv, "icache-cv");
ns_insert(ins, ip->inum, ip);
ns_insert(ins, KI(ip->inum), ip);
}
}
......@@ -205,7 +205,7 @@ iupdate(struct inode *ip)
}
static void *
evict(uint key, void *p)
evict(void *vkey, void *p)
{
struct inode *ip = p;
acquire(&ip->lock);
......@@ -230,7 +230,7 @@ iget(uint dev, uint inum)
retry:
// Try for cached inode.
rcu_begin_read();
ip = ns_lookup(ins, inum); // XXX ignore dev
ip = ns_lookup(ins, KI(inum)); // XXX ignore dev
if (ip) {
if (ip->dev != dev) panic("iget dev mismatch");
// tricky: first bump ref, then check free flag
......@@ -265,7 +265,7 @@ iget(uint dev, uint inum)
goto retry_evict;
}
release(&victim->lock);
ns_remove(ins, victim->inum, victim);
ns_remove(ins, KI(victim->inum), victim);
rcu_delayed(victim, kmfree);
ip = kmalloc(sizeof(*ip));
......@@ -277,7 +277,7 @@ iget(uint dev, uint inum)
snprintf(ip->lockname, sizeof(ip->lockname), "cv:ino:%d", ip->inum);
initlock(&ip->lock, ip->lockname+3);
initcondvar(&ip->cv, ip->lockname);
if (ns_insert(ins, ip->inum, ip) < 0) {
if (ns_insert(ins, KI(ip->inum), ip) < 0) {
rcu_delayed(ip, kmfree);
goto retry;
}
......
......@@ -2,6 +2,7 @@
#include "defs.h"
#include "spinlock.h"
#include "param.h"
#include <stddef.h>
// name spaces
// XXX maybe use open hash table, no chain, better cache locality
......@@ -13,10 +14,13 @@
#endif
struct elem {
uint key;
void *val;
int next_lock;
struct elem * volatile next;
union {
uint ikey;
char skey[0];
};
};
struct bucket {
......@@ -50,16 +54,71 @@ nsalloc(int allowdup)
}
static struct elem *
elemalloc(void)
elemalloc(struct nskey *k)
{
struct elem *e = 0;
e = kmalloc(sizeof(struct elem));
int sz;
switch (k->type) {
case nskey_int:
sz = sizeof(*e);
break;
case nskey_str:
sz = offsetof(struct elem, skey) + strlen(k->u.s) + 1;
break;
default:
panic("key type");
}
e = kmalloc(sz);
if (e == 0)
return 0;
memset(e, 0, sizeof(struct elem));
memset(e, 0, sz);
return e;
}
static int
h(struct nskey *k)
{
switch (k->type) {
case nskey_int:
return k->u.i % NHASH;
case nskey_str:
return k->u.s[0] % NHASH; // XXX
default:
panic("key type");
}
}
static void
setkey(struct elem *e, struct nskey *k)
{
switch (k->type) {
case nskey_int:
e->ikey = k->u.i;
break;
case nskey_str:
strncpy(e->skey, k->u.s, __INT_MAX__);
break;
default:
panic("key type");
}
}
static int
cmpkey(struct elem *e, struct nskey *k)
{
switch (k->type) {
case nskey_int:
return e->ikey == k->u.i;
break;
case nskey_str:
return !strcmp(e->skey, k->u.s);
break;
default:
panic("key type");
}
}
// XXX need something more scalable; partition the name space?
int
ns_allockey(struct ns *ns)
......@@ -69,13 +128,13 @@ ns_allockey(struct ns *ns)
}
int
ns_insert(struct ns *ns, uint key, void *val)
ns_insert(struct ns *ns, struct nskey key, void *val)
{
struct elem *e = elemalloc();
struct elem *e = elemalloc(&key);
if (e) {
e->key = key;
setkey(e, &key);
e->val = val;
uint i = key % NHASH;
uint i = h(&key);
rcu_begin_write(0);
retry:
......@@ -83,7 +142,7 @@ ns_insert(struct ns *ns, uint key, void *val)
struct elem *root = ns->table[i].chain;
if (!ns->allowdup) {
for (struct elem *x = root; x; x = x->next) {
if (x->key == key) {
if (cmpkey(x, &key)) {
rcu_end_write(0);
rcu_delayed(e, kmfree);
return -1;
......@@ -102,15 +161,15 @@ ns_insert(struct ns *ns, uint key, void *val)
}
void*
ns_lookup(struct ns *ns, uint key)
ns_lookup(struct ns *ns, struct nskey key)
{
uint i = key % NHASH;
uint i = h(&key);
rcu_begin_read();
struct elem *e = ns->table[i].chain;
while (e != NULL) {
if (e->key == key) {
if (cmpkey(e, &key)) {
rcu_end_read();
return e->val;
}
......@@ -122,9 +181,9 @@ ns_lookup(struct ns *ns, uint key)
}
int
ns_remove(struct ns *ns, uint key, void *v)
ns_remove(struct ns *ns, struct nskey key, void *v)
{
uint i = key % NHASH;
uint i = h(&key);
rcu_begin_write(0);
retry:
......@@ -138,7 +197,7 @@ ns_remove(struct ns *ns, uint key, void *v)
if (!e)
break;
if (e->key == key && (e->val == v || v == 0)) {
if (cmpkey(e, &key) && (e->val == v || v == 0)) {
// XXX annotate as locks for mtrace
if (!__sync_bool_compare_and_swap(&e->next_lock, 0, 1))
goto retry;
......@@ -166,13 +225,13 @@ ns_remove(struct ns *ns, uint key, void *v)
}
void *
ns_enumerate(struct ns *ns, void *(*f)(uint, void *))
ns_enumerate(struct ns *ns, void *(*f)(void *, void *))
{
rcu_begin_read();
for (int i = 0; i < NHASH; i++) {
struct elem *e = ns->table[i].chain;
while (e != NULL) {
void *r = (*f)(e->key, e->val);
void *r = (*f)(&e->ikey, e->val);
if (r) {
rcu_end_read();
return r;
......@@ -185,13 +244,13 @@ ns_enumerate(struct ns *ns, void *(*f)(uint, void *))
}
void *
ns_enumerate_key(struct ns *ns, uint key, void *(*f)(void *))
ns_enumerate_key(struct ns *ns, struct nskey key, void *(*f)(void *))
{
uint i = key % NHASH;
uint i = h(&key);
rcu_begin_read();
struct elem *e = ns->table[i].chain;
while (e) {
if (e->key == key) {
if (cmpkey(e, &key)) {
void *r = (*f)(e->val);
if (r) {
rcu_end_read();
......
......@@ -63,12 +63,12 @@ allocproc(void)
initlock(&p->lock, p->lockname+3);
initcondvar(&p->cv, p->lockname);
if (ns_insert(nspid, p->pid, (void *) p) < 0)
if (ns_insert(nspid, KI(p->pid), (void *) p) < 0)
panic("allocproc: ns_insert");
// Allocate kernel stack if possible.
if((p->kstack = kalloc()) == 0){
if (ns_remove(nspid, p->pid, p) < 0)
if (ns_remove(nspid, KI(p->pid), p) < 0)
panic("allocproc: ns_remove");
rcu_delayed(p, kmfree);
return 0;
......@@ -109,7 +109,7 @@ addrun(struct proc *p)
if (p->on_runq >= 0)
panic("addrun on runq already");
ns_insert(nsrunq, p->cpuid, p);
ns_insert(nsrunq, KI(p->cpuid), p);
p->on_runq = p->cpuid;
}
......@@ -123,7 +123,7 @@ delrun(struct proc *p)
if (p->on_runq < 0)
panic("delrun not on runq");
if (ns_remove(nsrunq, p->on_runq, p) < 0)
if (ns_remove(nsrunq, KI(p->on_runq), p) < 0)
panic("delrun: ns_remove");
p->on_runq = -1;
}
......@@ -269,7 +269,7 @@ fork(int flags)
kfree(np->kstack);
np->kstack = 0;
np->state = UNUSED;
if (ns_remove(nspid, np->pid, np) < 0)
if (ns_remove(nspid, KI(np->pid), np) < 0)
panic("fork: ns_remove");
rcu_delayed(np, kmfree);
return -1;
......@@ -384,7 +384,7 @@ wait(void)
p->kstack = 0;
vmap_decref(p->vmap);
p->state = UNUSED;
if (ns_remove(nspid, p->pid, p) < 0)
if (ns_remove(nspid, KI(p->pid), p) < 0)
panic("wait: ns_remove");
p->pid = 0;
p->parent = 0;
......@@ -445,7 +445,7 @@ migrate(struct proc *p)
}
static void *
steal_cb(uint k, void *v)
steal_cb(void *vk, void *v)
{
struct proc *p = v;
......@@ -514,7 +514,7 @@ scheduler(void)
// Enable interrupts on this processor.
sti();
struct proc *p = ns_enumerate_key(nsrunq, cpu->id, choose_runnable);
struct proc *p = ns_enumerate_key(nsrunq, KI(cpu->id), choose_runnable);
if (p) {
acquire(&p->lock);
if (p->state != RUNNABLE) {
......@@ -630,7 +630,7 @@ kill(int pid)
{
struct proc *p;
p = (struct proc *) ns_lookup(nspid, pid);
p = (struct proc *) ns_lookup(nspid, KI(pid));
if (p == 0) {
panic("kill");
return -1;
......@@ -653,7 +653,7 @@ kill(int pid)
return 0;
}
void *procdump(uint k, void *v)
void *procdump(void *vk, void *v)
{
struct proc *p = (struct proc *) v;
......
......@@ -48,7 +48,7 @@ rcu_alloc()
}
void *
rcu_min(uint key, void *v){
rcu_min(void *vkey, void *v){
struct proc *p = (struct proc *) v;
if (min_epoch[cpu->id].x > p->epoch) {
min_epoch[cpu->id].x = p->epoch;
......@@ -93,8 +93,9 @@ rcu_gc(void)
kmfree(r);
}
release(&rcu_lock[cpu->id].l);
// cprintf("rcu_gc: cpu %d n %d delayed_nfree=%d min_epoch=%d\n",
// cpu->id, n, delayed_nfree[cpu->id], min_epoch[cpu->id]);
if (rcu_debug)
cprintf("rcu_gc: cpu %d n %d delayed_nfree=%d min_epoch=%d\n",
cpu->id, n, delayed_nfree[cpu->id], min_epoch[cpu->id]);
popcli();
// global_epoch can be bumped anywhere; this seems as good a place as any
......
......@@ -99,3 +99,11 @@ strlen(const char *s)
return n;
}
int
strcmp(const char *p, const char *q)
{
while(*p && *p == *q)
p++, q++;
return (uchar)*p - (uchar)*q;
}
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论