c++ify kernel/wq.cc

上级 afb40915
......@@ -252,10 +252,8 @@ int pagefault(struct vmap *, uptr, u32);
// wq.c
int wq_trywork(void);
int wq_push(struct work *w);
int wq_push(work *w);
void wq_dump(void);
struct work * allocwork(void);
void freework(struct work *w);
// cilk.c
void initcilkframe(struct cilkframe*);
......
struct work {
virtual void run() = 0;
};
struct cwork : public work{
virtual void run();
static void* operator new(unsigned long);
static void* operator new(unsigned long, cwork*);
static void operator delete(void*p);
void *rip;
void *arg0;
void *arg1;
void *arg2;
void *arg3;
void *arg4;
char data[];
};
struct run_work {
......@@ -15,7 +24,7 @@ struct run_work {
void initwq(void);
struct work * allocwork(void);
void freework(struct work *w);
int wq_push(struct work *w);
int wq_push(work *w);
template<typename IT, typename BODY>
struct for_work : public run_work {
......
......@@ -13,7 +13,7 @@
static_assert(sizeof(struct ipcctl) < PGSIZE, "struct ipcctl too large");
static void
pread_work(struct work *w, void *a0, void *a1, void *a2,
pread_work(void *a0, void *a1, void *a2,
void *a3, void *a4)
{
struct inode *ip = (inode*) a0;
......@@ -34,11 +34,11 @@ pread_work(struct work *w, void *a0, void *a1, void *a2,
iput(ip);
}
static struct work *
static cwork *
pread_allocwork(struct inode *ip, size_t count, off_t off,
struct ipcmsg *msg, void *ubuf)
{
struct work *w = allocwork();
cwork *w = new cwork();
if (w == nullptr)
return 0;
......@@ -57,7 +57,7 @@ sys_async(int fd, size_t count, off_t off,
msgid_t msgid, pageid_t pageid)
{
struct file *f;
struct work *w;
cwork *w;
char *kshared = myproc()->vmap->kshared;
struct ipcctl *ipcctl = (struct ipcctl*)kshared;
......@@ -85,7 +85,7 @@ sys_async(int fd, size_t count, off_t off,
}
if (wq_push(w) < 0) {
iput(f->ip);
freework(w);
delete w;
return -1;
}
msg->off = off;
......
......@@ -11,7 +11,7 @@
#include "file.hh"
void
script_mmap_work(struct work *w, void *a0, void *a1, void *a2, void *a3)
script_mmap_work(void *a0, void *a1, void *a2, void *a3)
{
void *addr = (void *) a0;
u64 len = (u64) a1;
......@@ -40,7 +40,7 @@ sys_script(void *addr, u64 len, u64 chunk)
if(x > chunk)
x = chunk;
struct work *w = allocwork();
cwork *w = new cwork();
if(w == 0)
panic("sys_script allocwork");
w->rip = (void*) script_mmap_work;
......
......@@ -8,7 +8,7 @@
#define NSLOTS (1 << WQSHIFT)
struct wqueue {
struct work *w[NSLOTS];
work *w[NSLOTS];
volatile int head __mpalign__;
volatile int tail;
......@@ -46,20 +46,8 @@ wq_stat(void)
return &stat[mycpu()->id];
}
struct work *
allocwork(void)
{
return (struct work *)kalloc();
}
void
freework(struct work *w)
{
kfree(w);
}
int
wq_push(struct work *w)
wq_push(work *w)
{
int i;
......@@ -78,51 +66,11 @@ wq_push(struct work *w)
return 0;
}
int
wq_push1(void (*fn)(struct work *w, void *a0), void *a0)
{
struct work *w = allocwork();
if (w == nullptr)
return -1;
w->rip = (void*) fn;
w->arg0 = a0;
if (wq_push(w) < 0) {
freework(w);
return -1;
}
return 0;
}
int
wq_push2(void (*fn)(struct work*, void*, void*), void *a0, void *a1)
{
struct work *w = allocwork();
if (w == nullptr)
return -1;
w->rip = (void*) fn;
w->arg0 = a0;
w->arg1 = a1;
if (wq_push(w) < 0) {
freework(w);
return -1;
}
return 0;
}
static void
__wq_run(struct work *w)
{
void (*fn)(struct work*, void*, void*, void*, void*, void*) =
(void(*)(work*,void*,void*,void*,void*,void*))w->rip;
fn(w, w->arg0, w->arg1, w->arg2, w->arg3, w->arg4);
freework(w);
}
static inline struct work *
static inline work*
__wq_pop(int c)
{
struct wqueue *wq = &queue[c];
struct work *w;
work *w;
int i;
i = wq->head;
......@@ -144,11 +92,11 @@ __wq_pop(int c)
return w;
}
static inline struct work *
static inline work*
__wq_steal(int c)
{
struct wqueue *wq = &queue[c];
struct work *w;
work *w;
int i;
if (tryacquire(&wq->lock) == 0)
......@@ -170,7 +118,7 @@ __wq_steal(int c)
int
wq_trywork(void)
{
struct work *w;
work *w;
u64 i, k;
// A "random" victim CPU
......@@ -178,7 +126,7 @@ wq_trywork(void)
w = __wq_pop(mycpu()->id);
if (w != nullptr) {
__wq_run(w);
w->run();
return 1;
}
......@@ -190,7 +138,7 @@ wq_trywork(void)
w = __wq_steal(j);
if (w != nullptr) {
__wq_run(w);
w->run();
return 1;
}
}
......@@ -207,137 +155,41 @@ wq_dump(void)
stat[i].push, stat[i].full, stat[i].pop, stat[i].steal);
}
static void
__test_stub(struct work *w, void *a0, void *a1)
{
//long i = (long)a0;
//cprintf("%u: %lu\n", cpunum(), i);
volatile atomic<int> *running = (volatile atomic<int>*) a1;
(*running)--;
}
void
testwq(void)
initwq(void)
{
enum { iters = 10 };
static volatile atomic<int> running(iters);
u64 e, s;
long i;
int i;
pushcli();
if (mycpu()->id == 0) {
microdelay(1);
s = rdtsc();
for (i = 0; i < iters; i++) {
if (wq_push2(__test_stub, (void*)i, (void*)&running) < 0)
panic("testwq: oops");
}
while (running)
nop_pause();
e = rdtsc();
cprintf("testwq: %lu\n", (e-s)/iters);
wq_dump();
} else {
while (running)
wq_trywork();
}
popcli();
for (i = 0; i < NCPU; i++)
initlock(&queue[i].lock, "wq lock", LOCKSTAT_WQ);
}
static struct work **
do_allocwork(struct work **w, int iters)
void
cwork::run(void)
{
int i;
for (i = 0; i < iters; i++)
w[i] = allocwork();
return w;
void (*fn)(void*, void*, void*, void*, void*) =
(void(*)(void*,void*,void*,void*,void*))rip;
fn(arg0, arg1, arg2, arg3, arg4);
delete this;
}
static struct work **
do_freework(struct work **w, int iters)
void*
cwork::operator new(unsigned long nbytes)
{
int i;
for (i = 0; i < iters; i++)
freework(w[i]);
return w;
assert(nbytes == sizeof(cwork));
return kmalloc(sizeof(cwork));
}
void
benchwq(void)
void*
cwork::operator new(unsigned long nbytes, cwork* buf)
{
enum { alloc_iters = 100 };
static volatile atomic<int> running(alloc_iters);
static struct work *w[alloc_iters];
u64 e2, e, s;
long i;
pushcli();
if (mycpu()->id == 0) {
microdelay(1);
// Warm up
do_allocwork(w, alloc_iters);
do_freework(w, alloc_iters);
s = rdtsc();
do_allocwork(w, alloc_iters);
e = rdtsc();
cprintf("allocwork: %lu\n", (e-s)/alloc_iters);
s = rdtsc();
do_freework(w, alloc_iters);
e = rdtsc();
cprintf("freework: %lu\n", (e-s)/alloc_iters);
do_allocwork(w, alloc_iters);
for (i = 0;i < alloc_iters; i++) {
w[i]->rip = (void*)__test_stub;
w[i]->arg1 = (void*)&running;
}
s = rdtsc();
for (i = 0; i < alloc_iters; i++) {
if (wq_push(w[i]) < 0)
panic("testwq: oops");
}
e = rdtsc();
while (running)
nop_pause();
e2 = rdtsc();
cprintf("wq_push: %lu\n", (e-s)/alloc_iters);
cprintf("wq finished: %lu\n", (e2-s)/alloc_iters);
do_allocwork(w, alloc_iters);
for (i = 0;i < alloc_iters; i++) {
w[i]->rip = (void*)__test_stub;
w[i]->arg1 = (void*)&running;
}
s = rdtsc();
for (i = 0; i < alloc_iters; i++) {
running = 1;
if (wq_push(w[i]) < 0)
panic("testwq: oops");
while (running)
nop_pause();
}
e = rdtsc();
cprintf("wq_push one: %lu\n", (e-s)/alloc_iters);
wq_dump();
}
popcli();
assert(nbytes == sizeof(cwork));
return buf;
}
void
initwq(void)
cwork::operator delete(void *p)
{
int i;
for (i = 0; i < NCPU; i++)
initlock(&queue[i].lock, "wq lock", LOCKSTAT_WQ);
kmfree(p, sizeof(cwork));
}
......@@ -97,7 +97,7 @@ wq_push(struct work *w)
}
static void
__wq_run(struct work *w)
__wq_run(work *w)
{
void (*fn)(struct work*, void*, void*, void*, void*, void*) =
(void(*)(work*,void*,void*,void*,void*,void*))w->rip;
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论