提交 6600eed0 创建 作者: Frans Kaashoek's avatar Frans Kaashoek

enumerate name space

compiling, but unused, primitive rcu
上级 50d66311
......@@ -28,7 +28,8 @@ OBJS = \
uart.o\
vectors.o\
vm.o\
ns.o
ns.o \
rcu.o
# Cross-compiling (e.g., on Mac OS X)
TOOLPREFIX = x86_64-jos-elf-
......
......@@ -102,6 +102,8 @@ int ns_allockey(struct ns*);
int ns_insert(struct ns*, int key, void*);
void* ns_lookup(struct ns*, int);
int ns_remove(struct ns *ns, int key);
void ns_enumerate(struct ns *ns, void (*f)(int, void *));
// picirq.c
void picenable(int);
......@@ -122,7 +124,6 @@ int fork(int);
int growproc(int);
int kill(int);
void pinit(void);
void procdump(int);
void procdumpall(void);
void scheduler(void) __attribute__((noreturn));
void sched(void);
......@@ -131,6 +132,9 @@ int wait(void);
void yield(void);
void migrate(void);
// rcu.c
void rcuinit(void);
// swtch.S
void swtch(struct context**, struct context*);
......
......@@ -51,6 +51,7 @@ mainc(void)
uartinit(); // serial port
kvmalloc(); // initialize the kernel page table
nsinit(); // initialize name space module
rcuinit(); // initialize rcu module
pinit(); // process table
tvinit(); // trap vectors
binit(); // buffer cache
......
......@@ -124,3 +124,16 @@ ns_remove(struct ns *ns, int key)
return r;
}
void
ns_enumerate(struct ns *ns, void (*f)(int, void *))
{
acquire(&ns->lock);
for (int i = 0; i < NHASH; i++) {
struct elem *e = TAILQ_FIRST(&(ns->table[i].chain));
while (e != NULL) {
(*f)(e->key, e->val);
e = TAILQ_NEXT(e, chain);
}
}
release(&ns->lock);
}
......@@ -12,3 +12,4 @@
#define MAXARG 32 // max exec arguments
#define MAXNAME 16 // max string names
#define MINCYCTHRESH 1000000 // min cycles a proc executes on a core before allowed to be stolen
#define INF 0xFFFFFFFF
......@@ -11,8 +11,8 @@
struct runq runqs[NCPU];
int idle[NCPU];
struct ns *nspid;
static struct proc *initproc;
static struct ns *nspid;
extern void forkret(void);
extern void trapret(void);
......@@ -55,9 +55,11 @@ allocproc(void)
p->state = EMBRYO;
p->pid = ns_allockey(nspid);
p->epoch = INF;
p->cpuid = cpu->id;
if (ns_insert(nspid, p->pid, (void *) p) < 0)
panic("allocproc: ns_insert");
p->cpuid = cpu->id;
// Allocate kernel stack if possible.
if((p->kstack = kalloc()) == 0){
......@@ -614,13 +616,10 @@ kill(int pid)
return 0;
}
//PAGEBREAK: 36
// Print a process listing to console. For debugging.
// Runs when user types ^P on console.
// No lock to avoid wedging a stuck machine further.
void
procdump(int c)
void procdump(int k, void *v)
{
struct proc *p = (struct proc *) v;
static char *states[] = {
[UNUSED] "unused",
[EMBRYO] "embryo",
......@@ -631,31 +630,27 @@ procdump(int c)
};
char *state;
#if 0
if(p->state >= 0 && p->state < NELEM(states) && states[p->state])
state = states[p->state];
else
state = "???";
cprintf("%d %s %s %d, ", p->pid, state, p->name, p->cpuid);
uint pc[10];
if(p->state == SLEEPING){
getcallerpcs((uint*)p->context->ebp+2, pc);
for(i=0; i<10 && pc[i] != 0; i++)
for(int i=0; i<10 && pc[i] != 0; i++)
cprintf(" %p", pc[i]);
}
#endif
struct proc *q;
cprintf("runq: ");
STAILQ_FOREACH(q, &runqs[c].runq, run_next) {
if(q->state >= 0 && q->state < NELEM(states) && states[q->state])
state = states[q->state];
else
state = "???";
cprintf("%d %s %s, ", q->pid, state, q->name);
}
cprintf("\n");
}
//PAGEBREAK: 36
// Print a process listing to console. For debugging.
// Runs when user types ^P on console.
// No lock to avoid wedging a stuck machine further.
void
procdumpall(void)
{
int c;
for (c = 0; c < NCPU; c++) {
procdump(c);
}
ns_enumerate(nspid, procdump);
}
......@@ -88,6 +88,7 @@ struct proc {
SLIST_HEAD(childlist, proc) childq;
SLIST_ENTRY(proc) child_next;
struct condvar cv;
uint epoch;
};
// Process memory is laid out contiguously, low addresses first:
......@@ -129,6 +130,7 @@ extern struct cpu cpus[NCPU];
extern struct runq runqs[NCPU];
extern struct condtab condtabs[NCPU];
extern int ncpu;
extern struct ns *nspid;
// Per-CPU variables, holding pointers to the
// current cpu and to the current process.
......
#include "types.h"
#include "defs.h"
#include "param.h"
#include "mmu.h"
#include "x86.h"
#include "spinlock.h"
#include "condvar.h"
#include "queue.h"
#include "proc.h"
#define NRCU 1000
#define NDELAY 500
struct rcu {
void *item;
unsigned long epoch;
struct rcu *rcu;
void (*dofree)(void *);
};
static struct rcu *rcu_delayed_head;
static struct rcu *rcu_delayed_tail;
static struct rcu *rcu_freelist;
static uint global_epoch;
static uint min_epoch;
static struct spinlock rcu_lock;
static int delayed_nfree;
static int ninuse;
void
rcuinit(void)
{
struct rcu *r;
int i;
initlock(&rcu_lock, "rcu");
for (i = 0; i < NRCU; i++) {
r = (struct rcu *) kmalloc(sizeof(struct rcu));
r->rcu = rcu_freelist;
rcu_freelist = r;
}
cprintf("rcu_init: allocated %ld bytes\n", sizeof(struct rcu) * NRCU);
}
struct rcu *
rcu_alloc()
{
struct rcu *r = rcu_freelist;
if (r == 0) {
panic("rcu_alloc");
}
rcu_freelist = r->rcu;
return r;
}
void
rcu_min(int key, void *v){
struct proc *p = (struct proc *) v;
if (min_epoch > p->epoch) {
min_epoch = p->epoch;
}
}
// XXX use atomic instruction to update list (instead of holding lock)
// lists of lists?
void
rcu_gc(void)
{
struct rcu *r, *nr;
int n = 0;
min_epoch = global_epoch;
ns_enumerate(nspid, rcu_min);
for (r = rcu_delayed_head; r != NULL; r = nr) {
if (r->epoch >= min_epoch)
break;
// printf("free: %ld\n", r->epoch);
if (r->dofree == 0)
panic("rcu_gc");
r->dofree(r->item);
delayed_nfree--;
n++;
rcu_delayed_head = r->rcu;
if (rcu_delayed_head == 0)
rcu_delayed_tail = 0;
nr = r->rcu;
r->rcu = rcu_freelist;
rcu_freelist = r;
}
// printf("rcu_gc: n=%d ndelayed_free=%d nfree=%d ninuse=%d\n", n, delayed_nfree,
// tree_nfree, tree_ninuse);
}
// XXX Use atomic instruction to update list (instead of holding lock)
void
rcu_delayed(void *e, void (*dofree)(void *))
{
struct rcu *r = rcu_alloc();
if (r == 0)
panic("rcu_delayed");
r->dofree = dofree;
r->item = e;
r->rcu = 0;
r->epoch = global_epoch;
// printf("rcu_delayed: %ld\n", global_epoch);
if (rcu_delayed_tail != 0)
rcu_delayed_tail->rcu = r;
rcu_delayed_tail = r;
if (rcu_delayed_head == 0) rcu_delayed_head = r;
delayed_nfree++;
ninuse--;
}
void
rcu_begin_read(int tid)
{
proc->epoch = global_epoch;
__sync_synchronize();
}
void
rcu_end_read(int tid)
{
proc->epoch = INF;
}
void
rcu_begin_write(int tid)
{
acquire(&rcu_lock);
}
void
rcu_end_write(int tid)
{
// for other data structures using rcu, use atomic add:
__sync_fetch_and_add(&global_epoch, 1);
rcu_gc();
release(&rcu_lock);
}
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论