More c++ifying wq

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