More c++ifying wq

上级 e1748848
...@@ -62,9 +62,9 @@ enum { ...@@ -62,9 +62,9 @@ enum {
slab_stack, slab_stack,
slab_perf, slab_perf,
slab_kshared, slab_kshared,
slab_wq,
slab_type_max slab_type_max
}; };
extern struct kmem kmems[NCPU]; extern struct kmem kmems[NCPU];
extern struct kmem slabmem[slab_type_max][NCPU]; extern struct kmem slabmem[slab_type_max][NCPU];
#pragma once
extern int mycpuid(void);
template <typename T> template <typename T>
struct percpu { struct percpu {
int myid() {
return mycpu()->id;
}
const T* operator->() const { const T* operator->() const {
return cpu(myid()); return cpu(mycpuid());
} }
T* operator->() { T* operator->() {
return cpu(myid()); return cpu(mycpuid());
} }
T& operator*() { T& operator*() {
return *cpu(myid()); return *cpu(mycpuid());
} }
T& operator[](int id) { T& operator[](int id) {
......
...@@ -57,4 +57,5 @@ void printf(const char*, ...); ...@@ -57,4 +57,5 @@ void printf(const char*, ...);
void fprintf(int, const char*, ...); void fprintf(int, const char*, ...);
void snprintf(char *buf, unsigned int n, const char *fmt, ...); void snprintf(char *buf, unsigned int n, const char *fmt, ...);
void die(const char* errstr, ...) __attribute__((noreturn)); void die(const char* errstr, ...) __attribute__((noreturn));
#define assert(c) if (!(c)) { fprintf(2, "%s:%d: ", __FILE__, __LINE__); die("assertion failure"); }
END_DECLS END_DECLS
#ifdef XV6_KERNEL
typedef struct spinlock wqlock_t;
#else
typedef int wqlock_t;
#endif
#include "percpu.hh"
#define NSLOTS (1 << WQSHIFT)
struct work { struct work {
virtual void run() = 0; virtual void run() = 0;
}; };
class wq {
public:
wq();
int push(work *w);
int trywork();
void dump();
static void* operator new(unsigned long);
private:
work *steal(int c);
work *pop(int c);
struct wqueue {
work *w[NSLOTS];
volatile int head __mpalign__;
volatile int tail;
wqlock_t lock;
};
struct stat {
u64 push;
u64 full;
u64 pop;
u64 steal;
};
percpu<wqueue> q_;
percpu<stat> stat_;
};
struct cwork : public work{ struct cwork : public work{
virtual void run(); virtual void run();
...@@ -17,17 +58,13 @@ struct cwork : public work{ ...@@ -17,17 +58,13 @@ struct cwork : public work{
void *arg4; void *arg4;
}; };
struct run_work {
virtual void run() = 0;
};
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(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 work {
for_work(IT &it, BODY body) : it_(it), body_(body) {} for_work(IT &it, BODY body) : it_(it), body_(body) {}
virtual void run() { printf("hi %s\n", *it_); } virtual void run() { printf("hi %s\n", *it_); }
...@@ -38,7 +75,7 @@ struct for_work : public run_work { ...@@ -38,7 +75,7 @@ struct for_work : public run_work {
}; };
static inline void static inline void
wq_push_cpp(struct run_work *w) wq_push_cpp(work *w)
{ {
w->run(); w->run();
} }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "mtrace.h" #include "mtrace.h"
#include "cpu.hh" #include "cpu.hh"
#include "multiboot.hh" #include "multiboot.hh"
#include "wq.hh"
static struct Mbmem mem[128]; static struct Mbmem mem[128];
static u64 nmem; static u64 nmem;
...@@ -273,6 +274,10 @@ initkalloc(u64 mbaddr) ...@@ -273,6 +274,10 @@ initkalloc(u64 mbaddr)
slabmem[slab_kshared][c].size = KSHAREDSIZE; slabmem[slab_kshared][c].size = KSHAREDSIZE;
slabmem[slab_kshared][c].ninit = CPUKSTACKS; slabmem[slab_kshared][c].ninit = CPUKSTACKS;
strncpy(slabmem[slab_wq][c].name, " wq", MAXNAME);
slabmem[slab_wq][c].size = PGROUNDUP(sizeof(wq));
slabmem[slab_wq][c].ninit = NCPU;
for (int i = 0; i < slab_type_max; i++) { for (int i = 0; i < slab_type_max; i++) {
slabmem[i][c].name[0] = (char) c + '0'; slabmem[i][c].name[0] = (char) c + '0';
slabinit(&slabmem[i][c], &p, &k); slabinit(&slabmem[i][c], &p, &k);
......
...@@ -20,6 +20,12 @@ proc_hash(const u32 &p) ...@@ -20,6 +20,12 @@ proc_hash(const u32 &p)
return p; return p;
} }
int
mycpuid(void)
{
return mycpu()->id;
}
xns<u32, proc*, proc_hash> *xnspid __mpalign__; xns<u32, proc*, proc_hash> *xnspid __mpalign__;
static struct proc *bootproc __mpalign__; static struct proc *bootproc __mpalign__;
......
...@@ -4,119 +4,134 @@ ...@@ -4,119 +4,134 @@
#include "amd64.h" #include "amd64.h"
#include "cpu.hh" #include "cpu.hh"
#include "wq.hh" #include "wq.hh"
#include "kalloc.hh"
#define NSLOTS (1 << WQSHIFT) static wq *wq_;
struct wqueue { int
work *w[NSLOTS]; wq_push(work *w)
volatile int head __mpalign__;
volatile int tail;
struct spinlock lock;
__padout__;
} __mpalign__;;
struct wqstat {
u64 push;
u64 full;
u64 pop;
u64 steal;
__padout__;
} __mpalign__;
struct wqueue queue[NCPU] __mpalign__;
struct wqstat stat[NCPU] __mpalign__;
static inline struct wqueue *
getwq(void)
{ {
pushcli(); return wq_->push(w);
return &queue[mycpu()->id];
} }
static inline void int
putwq(struct wqueue *wq) wq_trywork(void)
{ {
popcli(); return wq_->trywork();
}
void
wq_dump(void)
{
return wq_->dump();
}
void
initwq(void)
{
wq_ = new wq();
}
//
// wq
//
void*
wq::operator new(unsigned long nbytes)
{
assert(nbytes == sizeof(wq));
return ksalloc(slab_wq);
}
wq::wq(void)
{
int i;
for (i = 0; i < NCPU; i++)
initlock(&q_[i].lock, "wq lock", LOCKSTAT_WQ);
} }
static inline struct wqstat * void
wq_stat(void) wq::dump(void)
{ {
return &stat[mycpu()->id]; int i;
for (i = 0; i < NCPU; i++)
cprintf("push %lu full %lu pop %lu steal %lu\n",
stat_[i].push, stat_[i].full,
stat_[i].pop, stat_[i].steal);
} }
int int
wq_push(work *w) wq::push(work *w)
{ {
int i; int i;
struct wqueue *wq = getwq(); pushcli();
i = wq->head; i = q_->head;
if ((i - wq->tail) == NSLOTS) { if ((i - q_->tail) == NSLOTS) {
wq_stat()->full++; stat_->full++;
popcli();
return -1; return -1;
} }
i = i & (NSLOTS-1); i = i & (NSLOTS-1);
wq->w[i] = w; q_->w[i] = w;
barrier(); barrier();
wq->head++; q_->head++;
wq_stat()->push++; stat_->push++;
putwq(wq); popcli();
return 0; return 0;
} }
static inline work* inline work*
__wq_pop(int c) wq::pop(int c)
{ {
struct wqueue *wq = &queue[c]; struct wqueue *q = &q_[c];
work *w; work *w;
int i; int i;
i = wq->head; i = q->head;
if ((i - wq->tail) == 0) if ((i - q->tail) == 0)
return 0; return 0;
acquire(&wq->lock); acquire(&q->lock);
i = wq->head; i = q->head;
if ((i - wq->tail) == 0) { if ((i - q->tail) == 0) {
release(&wq->lock); release(&q->lock);
return 0; return 0;
} }
i = (i-1) & (NSLOTS-1); i = (i-1) & (NSLOTS-1);
w = wq->w[i]; w = q->w[i];
wq->head--; q->head--;
release(&wq->lock); release(&q->lock);
wq_stat()->pop++; stat_->pop++;
return w; return w;
} }
static inline work* inline work*
__wq_steal(int c) wq::steal(int c)
{ {
struct wqueue *wq = &queue[c]; struct wqueue *q = &q_[c];
work *w; work *w;
int i; int i;
if (tryacquire(&wq->lock) == 0) if (tryacquire(&q->lock) == 0)
return 0; return 0;
i = wq->tail; i = q->tail;
if ((i - wq->head) == 0) { if ((i - q->head) == 0) {
release(&wq->lock); release(&q->lock);
return 0; return 0;
} }
i = i & (NSLOTS-1); i = i & (NSLOTS-1);
w = wq->w[i]; w = q->w[i];
wq->tail++; q->tail++;
release(&wq->lock); release(&q->lock);
wq_stat()->steal++; stat_->steal++;
return w; return w;
} }
int int
wq_trywork(void) wq::trywork(void)
{ {
work *w; work *w;
u64 i, k; u64 i, k;
...@@ -124,7 +139,7 @@ wq_trywork(void) ...@@ -124,7 +139,7 @@ wq_trywork(void)
// A "random" victim CPU // A "random" victim CPU
k = rdtsc(); k = rdtsc();
w = __wq_pop(mycpu()->id); w = pop(mycpuid());
if (w != nullptr) { if (w != nullptr) {
w->run(); w->run();
return 1; return 1;
...@@ -133,10 +148,10 @@ wq_trywork(void) ...@@ -133,10 +148,10 @@ wq_trywork(void)
for (i = 0; i < NCPU; i++) { for (i = 0; i < NCPU; i++) {
u64 j = (i+k) % NCPU; u64 j = (i+k) % NCPU;
if (j == mycpu()->id) if (j == mycpuid())
continue; continue;
w = __wq_steal(j); w = steal(j);
if (w != nullptr) { if (w != nullptr) {
w->run(); w->run();
return 1; return 1;
...@@ -146,24 +161,9 @@ wq_trywork(void) ...@@ -146,24 +161,9 @@ wq_trywork(void)
return 0; return 0;
} }
void //
wq_dump(void) // cwork
{ //
int i;
for (i = 0; i < NCPU; i++)
cprintf("push %lu full %lu pop %lu steal %lu\n",
stat[i].push, stat[i].full, stat[i].pop, stat[i].steal);
}
void
initwq(void)
{
int i;
for (i = 0; i < NCPU; i++)
initlock(&queue[i].lock, "wq lock", LOCKSTAT_WQ);
}
void void
cwork::run(void) cwork::run(void)
{ {
...@@ -192,4 +192,3 @@ cwork::operator delete(void *p) ...@@ -192,4 +192,3 @@ cwork::operator delete(void *p)
{ {
kmfree(p, sizeof(cwork)); kmfree(p, sizeof(cwork));
} }
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论