提交 71d0a8c6 创建 作者: Nickolai Zeldovich's avatar Nickolai Zeldovich

Merge branch 'scale-amd64' of git+ssh://pdos.csail.mit.edu/home/am0/6.828/xv6 into scale-amd64

$(O)/bin/%.o: CFLAGS:=$(CFLAGS)
$(O)/bin/%.o: CXXFLAGS:=$(CXXFLAGS)
$(O)/bin/%.o: CFLAGS:=$(CFLAGS) -DXV6_USER
$(O)/bin/%.o: CXXFLAGS:=$(CXXFLAGS) -DXV6_USER
UPROGS= \
bench \
......
......@@ -12,6 +12,7 @@ typedef uint64_t u64;
#include "wq.hh"
#include "reducer.hh"
#include "user/dirit.hh"
#include "user/util.h"
#define ST_SIZE(st) (st).st_size
#define ST_ISDIR(st) S_ISDIR((st).st_mode)
#define BSIZ 256
......
......@@ -5,7 +5,9 @@
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include "types.h"
#include "user/dirit.hh"
#include "user/util.h"
#include "wq.hh"
#define ST_SIZE(st) (st).st_size
#define ST_TYPE(st) (ST_ISDIR(st) ? 1 : ST_ISREG(st) ? 2 : 3)
......
#pragma once
#include "wqtypes.hh"
#include "percpu.hh"
struct uwq_ipcbuf;
class work;
int wq_trywork(void);
......@@ -38,20 +42,56 @@ struct wframe {
volatile int v_;
};
#define NSLOTS (1 << WQSHIFT)
class wq {
public:
wq();
int push(work *w, int tcpuid);
int trywork();
void dump();
static void* operator new(unsigned long);
private:
work *steal(int c);
work *pop(int c);
void inclen(int c);
void declen(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_;
#if defined(XV6_USER)
uwq_ipcbuf* ipc_;
#endif
};
void* xallocwork(unsigned long nbytes);
void xfreework(void* ptr, unsigned long nbytes);
#if defined(XV6_USER)
void* wqalloc(unsigned long nbytes);
void wqfree(void *ptr);
extern u64 wq_maxworkers;
#endif
#if defined(LINUX)
#include <stdlib.h>
#include <assert.h>
#include <atomic>
#define xallocwork(n) malloc(n)
#define xfreework(p, sz) free(p)
#elif defined(XV6_KERNEL)
#define xallocwork(n) kmalloc(n, "xallocwork")
#define xfreework(p, sz) kmfree(p, sz)
#else // xv6 user
extern void* wqalloc(unsigned long nbytes);
extern void wqfree(void *ptr);
#define xallocwork(n) wqalloc(n)
#define xfreework(n, sz) wqfree(n)
extern u64 wq_maxworkers;
#endif
......
#include "types.h"
#include "wqtypes.hh"
#include "kernel.hh"
#include "spinlock.h"
#include "amd64.h"
#include "cpu.hh"
#include "kalloc.hh"
#include "wq.hh"
typedef struct spinlock wqlock_t;
static inline void*
allocwq(unsigned long nbytes)
......@@ -38,9 +35,4 @@ wqlock_init(wqlock_t *lock)
initlock(lock, "wq lock", LOCKSTAT_WQ);
}
static inline void
wqarch_init(void)
{
}
#define xprintf cprintf
#pragma once
#if defined (LINUX)
typedef pthread_spinlock_t wqlock_t;
#elif defined(XV6_KERNEL)
#include "types.h"
#include "spinlock.h"
typedef struct spinlock wqlock_t;
#else
#include "uspinlock.h"
typedef struct uspinlock wqlock_t;
#endif
......@@ -2,25 +2,11 @@
#include "uspinlock.h"
#include "amd64.h"
#include "user.h"
#include "wq.hh"
#include "pthread.h"
#include "memlayout.h"
#include "uwq.hh"
#include "atomic.hh"
#include "lib.h"
#include "elf.hh"
#include "wqtypes.hh"
typedef struct uspinlock wqlock_t;
static pthread_key_t idkey;
static std::atomic<int> nextid;
static volatile int exiting;
int
mycpuid(void)
{
return (int)(u64)pthread_getspecific(idkey);
}
int mycpuid(void);
static inline void*
allocwq(unsigned long nbytes)
......@@ -64,36 +50,4 @@ wqlock_init(wqlock_t *lock)
initlock(lock);
}
extern "C" long wqwait(void);
static void __attribute__((used))
initworker(void)
{
int id;
forkt_setup(0);
id = nextid++;
if (id >= NCPU)
die("initworker: to man IDs");
pthread_setspecific(idkey, (void*)(u64)id);
while (1) {
if (!wq_trywork())
assert(wqwait() == 0);
}
}
DEFINE_XV6_ADDRNOTE(xnote, XV6_ADDR_ID_WQ, &initworker);
static inline void
wqarch_init(void)
{
if (pthread_key_create(&idkey, 0))
die("wqarch_init: pthread_key_create");
int id = nextid++;
pthread_setspecific(idkey, (void*)(u64)id);
}
#define xprintf printf
#define pushcli()
#define popcli()
u64 wq_maxworkers = NWORKERS;
......@@ -47,7 +47,8 @@ OBJS = \
trap.o \
uaccess.o \
trapasm.o \
wq.o \
wqkern.o \
wqlib.o \
script.o \
zalloc.o \
incbin.o
......
#include "types.h"
#include "kernel.hh"
#include "spinlock.h"
#include "amd64.h"
#include "cpu.hh"
#include "kalloc.hh"
#include "wq.hh"
static wq *wq_;
void*
xallocwork(unsigned long nbytes)
{
return kmalloc(nbytes, "xallocwork");
}
void
xfreework(void* ptr, unsigned long nbytes)
{
kmfree(ptr, nbytes);
}
size_t
wq_size(void)
{
return sizeof(wq);
}
int
wq_push(work *w)
{
return wq_->push(w, mycpuid());
}
int
wq_pushto(work *w, int tcpuid)
{
return wq_->push(w, tcpuid);
}
int
wq_trywork(void)
{
return wq_->trywork();
}
void
wq_dump(void)
{
return wq_->dump();
}
void
initwq(void)
{
wq_ = new wq();
}
......@@ -2,7 +2,7 @@ $(O)/lib/%.o: CFLAGS:=$(CFLAGS) -DXV6_USER
$(O)/lib/%.o: CXXFLAGS:=$(CXXFLAGS) -DXV6_USER
ULIB = ulib.o usys.o printf.o umalloc.o uthread.o fmt.o stream.o ipc.o \
threads.o crt.o wq.o perf.o wqalloc.o
threads.o crt.o wqlib.o wquser.o perf.o wqalloc.o
ULIB := $(addprefix $(O)/lib/, $(ULIB))
.PRECIOUS: $(O)/lib/%.o
......
......@@ -5,88 +5,10 @@
#else
#include "wquser.hh"
#endif
#include "percpu.hh"
#define NSLOTS (1 << WQSHIFT)
#include "wq.hh"
enum { wq_steal_others = 1 };
class wq {
public:
wq();
int push(work *w, int tcpuid);
int trywork();
void dump();
static void* operator new(unsigned long);
private:
work *steal(int c);
work *pop(int c);
void inclen(int c);
void declen(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_;
#if defined(XV6_USER)
uwq_ipcbuf* ipc_;
#endif
};
static wq *wq_;
size_t
wq_size(void)
{
return sizeof(wq);
}
int
wq_push(work *w)
{
return wq_->push(w, mycpuid());
}
int
wq_pushto(work *w, int tcpuid)
{
return wq_->push(w, tcpuid);
}
int
wq_trywork(void)
{
return wq_->trywork();
}
void
wq_dump(void)
{
return wq_->dump();
}
void
initwq(void)
{
wq_ = new wq();
wqarch_init();
}
//
// wq
//
......@@ -138,24 +60,25 @@ wq::declen(int c)
}
int
wq::push(work *w, int tcpuid)
wq::push(work *w, int c)
{
struct wqueue* q = &q_[c];
int i;
acquire(&q_[tcpuid].lock);
i = q_[tcpuid].head;
if ((i - q_[tcpuid].tail) == NSLOTS) {
stat_[tcpuid].full++;
release(&q_[tcpuid].lock);
wqlock_acquire(&q->lock);
i = q->head;
if ((i - q->tail) == NSLOTS) {
stat_[c].full++;
wqlock_release(&q->lock);
return -1;
}
i = i & (NSLOTS-1);
q_[tcpuid].w[i] = w;
q->w[i] = w;
barrier();
q_[tcpuid].head++;
inclen(tcpuid);
stat_[tcpuid].push++;
release(&q_[tcpuid].lock);
q->head++;
inclen(c);
stat_[c].push++;
wqlock_release(&q->lock);
return 0;
}
......
#include "types.h"
#include "user.h"
#include "uwq.hh"
#include "wqtypes.hh"
#include "wq.hh"
#include "atomic.hh"
#include "pthread.h"
#include "elf.hh"
u64 wq_maxworkers = NWORKERS;
static pthread_key_t idkey;
static std::atomic<int> nextid;
static wq *wq_;
extern "C" long wqwait(void);
static void __attribute__((used))
initworker(void)
{
int id;
forkt_setup(0);
id = nextid++;
if (id >= NCPU)
die("initworker: to man IDs");
pthread_setspecific(idkey, (void*)(u64)id);
while (1) {
if (!wq_trywork())
assert(wqwait() == 0);
}
}
DEFINE_XV6_ADDRNOTE(xnote, XV6_ADDR_ID_WQ, &initworker);
int
mycpuid(void)
{
return (int)(u64)pthread_getspecific(idkey);
}
size_t
wq_size(void)
{
return sizeof(wq);
}
int
wq_push(work *w)
{
return wq_->push(w, mycpuid());
}
int
wq_pushto(work *w, int tcpuid)
{
return wq_->push(w, tcpuid);
}
int
wq_trywork(void)
{
return wq_->trywork();
}
void
wq_dump(void)
{
return wq_->dump();
}
void*
xallocwork(unsigned long nbytes)
{
return wqalloc(nbytes);
}
void
xfreework(void* ptr, unsigned long nbytes)
{
wqfree(ptr);
}
void
initwq(void)
{
if (pthread_key_create(&idkey, 0))
die("wqarch_init: pthread_key_create");
int id = nextid++;
pthread_setspecific(idkey, (void*)(u64)id);
wq_ = new wq();
if (wq_ == nullptr)
die("initwq");
}
#pragma once
#define DEBUG 1
#define DEBUG 0
#define NPROC 64 // maximum number of processes
#define KSTACKSIZE 8192 // size of per-process kernel stack
#define NOFILE 64 // open files per process
......
......@@ -5,6 +5,11 @@ NCXXFLAGS = -static -g -MD -m64 -O3 -Wall -Werror -DHW_$(HW) \
-iquote . -iquote include \
-include param.h -include include/compiler.h
$(O)/user/%.o: user/%.cc
@echo " CXX $@"
$(Q)mkdir -p $(@D)
$(Q)$(CXX) -DLINUX $(NCXXFLAGS) -c -o $@ $<
$(O)/user/%.o: lib/%.cc
@echo " CXX $@"
$(Q)mkdir -p $(@D)
......@@ -15,7 +20,7 @@ $(O)/user/%.o: bin/%.cc
$(Q)mkdir -p $(@D)
$(Q)$(CXX) -DLINUX $(NCXXFLAGS) -c -o $@ $<
$(O)/%: $(O)/user/%.o $(O)/user/wq.o
$(O)/%: $(O)/user/%.o $(O)/user/wqlib.o $(O)/user/wqlinux.o
@echo " LD $@"
$(Q)mkdir -p $(@D)
$(Q)$(CXX) -o $@ $^ -lpthread
......
......@@ -19,20 +19,15 @@ public:
return *this;
}
const char * copy_value() {
char *buf = (char*)malloc(256);
return name(buf, 256);
}
bool end() const { return end_; }
private:
char *name(char *buf, size_t n) const {
strncpy(buf, ent_->d_name, n-1);
buf[n-1] = 0;
return buf;
}
bool end() const { return end_; }
private:
void refill(void) {
struct dirent *result;
int r = readdir_r(d_, ent_, &result);
......@@ -46,3 +41,16 @@ private:
struct dirent *ent_;
DIR *d_;
};
static inline const char*
copy_value(dirit &it)
{
char *buf = (char*)malloc(256);
return it.name(buf, 256);
}
static inline void
free_value(dirit &it, const char *name)
{
free((void*)name);
}
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include "types.h"
#include "wq.hh"
#include "user/util.h"
static __thread int myid_;
static wq *wq_;
u64 wq_maxworkers = NCPU-1;
int
mycpuid(void)
{
return myid_;
}
size_t
wq_size(void)
{
return sizeof(wq);
}
int
wq_push(work *w)
{
return wq_->push(w, mycpuid());
}
int
wq_pushto(work *w, int tcpuid)
{
return wq_->push(w, tcpuid);
}
int
wq_trywork(void)
{
return wq_->trywork();
}
void
wq_dump(void)
{
return wq_->dump();
}
static void*
workerth(void *x)
{
u64 c = (u64)x;
myid_ = c;
setaffinity(c);
while (1)
wq_trywork();
return NULL;
}
void*
xallocwork(unsigned long nbytes)
{
return malloc(nbytes);
}
void
xfreework(void* ptr, unsigned long nbytes)
{
free(ptr);
}
void
initwq(void)
{
wq_ = new wq();
if (wq_ == nullptr)
die("initwq");
pthread_t th;
int r;
myid_ = 0;
setaffinity(0);
for (int i = 1; i < wq_maxworkers+1; i++) {
r = pthread_create(&th, NULL, workerth, (void*)(u64)i);
if (r < 0)
edie("pthread_create");
}
}
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <pthread.h>
#include "user/util.h"
#include "include/types.h"
#include "include/wq.hh"
static __thread int myid_;
typedef pthread_spinlock_t wqlock_t;
#include "types.h"
#include "wqtypes.hh"
int
mycpuid(void)
{
return myid_;
}
int mycpuid(void);
static inline void*
allocwq(unsigned long nbytes)
......@@ -55,34 +45,4 @@ rdtsc(void)
return ((u64)lo)|(((u64)hi)<<32);
}
static void*
workerth(void *x)
{
u64 c = (u64)x;
myid_ = c;
setaffinity(c);
while (1)
wq_trywork();
return NULL;
}
static inline void
wqarch_init(void)
{
pthread_t th;
int r;
myid_ = 0;
setaffinity(0);
for (int i = 1; i < NCPU; i++) {
r = pthread_create(&th, NULL, workerth, (void*)(u64)i);
if (r < 0)
edie("pthread_create");
}
}
#define xprintf printf
#define pushcli()
#define popcli()
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论