c++ify kernel/wq.cc

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