提交 0a9b36be 创建 作者: 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

......@@ -23,7 +23,11 @@ UPROGS= \
preadtest \
scripttest \
ftest \
perf
wqsh \
cp \
perf \
xls \
xdu
# pdu
# pls
......
#include "types.h"
#include "user.h"
#include "fcntl.h"
int
main(int argc, char *argv[])
{
if(argc != 3){
printf("Usage: cp fromfile tofile\n");
exit();
}
int fd1 = open(argv[1], 0);
if(fd1 < 0){
printf("cp: cannot open %s\n", argv[1]);
exit();
}
int fd2 = open(argv[2], O_CREATE|O_WRONLY);
if(fd2 < 0){
printf("cp: cannot create %s\n", argv[2]);
exit();
}
int n;
char buf[512];
while((n = read(fd1, buf, sizeof(buf))) > 0){
if(write(fd2, buf, n) != n){
printf("cp: write failed\n");
exit();
}
}
exit();
}
......@@ -1628,6 +1628,41 @@ tls_test(void)
fprintf(1, "tls_test ok\n");
}
static pthread_barrier_t ftable_bar;
static volatile int ftable_fd;
static void*
ftablethr(void *arg)
{
char buf[32];
int r;
pthread_barrier_wait(&ftable_bar);
r = read(ftable_fd, buf, sizeof(buf));
if (r < 0)
fprintf(2, "ftablethr: FAILED bad fd\n");
return 0;
}
static void
ftabletest(void)
{
printf("ftabletest...\n");
pthread_barrier_init(&ftable_bar, 0, 2);
pthread_t th;
pthread_create(&th, 0, &ftablethr, 0);
ftable_fd = open("README", 0);
if (ftable_fd < 0)
die("open");
pthread_barrier_wait(&ftable_bar);
wait();
printf("ftabletest ok\n");
}
static pthread_key_t tkey;
static pthread_barrier_t bar0, bar1;
enum { nthread = 8 };
......@@ -1718,6 +1753,7 @@ main(int argc, char *argv[])
bigdir(); // slow
tls_test();
thrtest();
ftabletest();
exectest();
......
#include "types.h"
#include "user.h"
#include "fcntl.h"
#include "wq.hh"
class thing {
protected:
int done;
public:
static void * operator new(unsigned long n){
return malloc(n);
}
static void operator delete(void *p){
free(p);
}
thing() { done = 0; }
virtual ~thing();
virtual void print() = 0;
virtual void run() = 0;
int checkdone() { return done; }
};
class cmd : public thing {
private:
int argc;
char *argv[20];
public:
cmd() { argc = 0; }
void print();
void run();
static cmd *parse();
};
class sequence : public thing {
private:
int n;
class cmd *a[20];
public:
sequence() { n = 0; }
void print();
void run();
static sequence *parse();
};
thing::~thing()
{
}
int
isspace(char c)
{
return c == ' ' || c == '\t' || c == '\n' || c == '\r';
}
cmd *
cmd::parse()
{
char buf[512];
gets(buf, sizeof(buf));
if(buf[0] == 0)
return 0;
cmd *c = new cmd();
for(int i = 0; buf[i]; ){
int j;
for(j = i; buf[j] && !isspace(buf[j]); j++)
;
char *p = (char *) malloc(j - i + 1);
assert(p);
memmove(p, buf + i, j - i);
p[j - i] = '\0';
assert(c->argc < 20);
c->argv[c->argc++] = p;
while(isspace(buf[j]))
j++;
i = j;
}
return c;
}
void
cmd::run()
{
int pid = fork(0);
if(pid < 0){
printf("fork failed\n");
exit();
}
if(pid == 0){
argv[argc] = 0;
exec(argv[0], (const char **) argv);
printf("exec failed\n");
exit();
} else {
wait();
done = 1;
}
}
void
cmd::print()
{
for(int i = 0; i < argc; i++)
printf("%s ", argv[i]);
printf("\n");
}
sequence *
sequence::parse()
{
sequence *s = new sequence();
while(cmd *c = cmd::parse()){
assert(s->n < 20);
s->a[s->n++] = c;
}
return s;
}
void
blah(void *x)
{
thing *t = (thing *) x;
t->run();
}
void
sequence::run()
{
for(int i = 0; i < n; i++){
cwork *w = new cwork();
w->rip = (void*) blah;
w->arg0 = a[i];
wq_push(w);
}
while(1){
int do_more = 0;
for(int i = 0; i < n; i++){
if(a[i]->checkdone() == 0){
do_more += 1;
}
}
if(do_more == 0)
break;
wq_trywork();
}
done = 1;
}
void
sequence::print()
{
for(int i = 0; i < n; i++)
a[i]->print();
}
int
main(void)
{
initwq();
sequence *s = sequence::parse();
if(s){
s->run();
}
}
......@@ -73,5 +73,6 @@ main(int ac, char **av)
{
initwq();
printf("%ld\n", du(open(".", 0)));
wq_dump();
return 0;
}
......@@ -6,12 +6,14 @@
#include <fcntl.h>
#include <unistd.h>
#include "user/dirit.hh"
#include "wq.hh"
#define ST_SIZE(st) (st).st_size
#define ST_TYPE(st) (ST_ISDIR(st) ? 1 : ST_ISREG(st) ? 2 : 3)
#define ST_INO(st) (st).st_ino
#define ST_ISDIR(st) S_ISDIR((st).st_mode)
#define ST_ISREG(st) S_ISREG((st).st_mode)
#define BSIZ 256
#define xfstatat(fd, n, st) fstatat(fd, n, st, 0)
#else // assume xv6
#include "types.h"
#include "stat.h"
......@@ -19,6 +21,7 @@
#include "fs.h"
#include "lib.h"
#include "dirit.hh"
#include "wq.hh"
#define ST_SIZE(st) (st).size
#define ST_TYPE(st) (st).type
#define ST_INO(st) (st).ino
......@@ -26,12 +29,12 @@
#define ST_ISREG(st) ((st).type == T_FILE)
#define BSIZ (DIRSIZ + 1)
#define stderr 2
#define xfstatat fstatat
#endif
void
ls(const char *path)
{
char buf[512], *p;
int fd;
struct stat st;
......@@ -48,30 +51,26 @@ ls(const char *path)
if (ST_ISREG(st)) {
printf("%u %10lu %10lu %s\n", ST_TYPE(st), ST_INO(st), ST_SIZE(st), path);
close(fd);
} else if (ST_ISDIR(st)) {
if(strlen(path) + 1 + BSIZ > sizeof buf) {
printf("ls: path too long\n");
}
strcpy(buf, path);
p = buf+strlen(buf);
*p++ = '/';
dirit di(fd);
for (; !di.end(); ++di) {
const char *name = *di;
size_t len = strlen(name);
memmove(p, name, len);
p[len] = 0;
if (stat(buf, &st) < 0){
wq_for<dirit>(di,
[](dirit &i)->bool { return !i.end(); },
[&fd](const char *name)->void
{
struct stat st;
if (xfstatat(fd, name, &st) < 0){
printf("ls: cannot stat %s\n", name);
free((void*)name);
printf("ls: cannot stat %s\n", buf);
continue;
return;
}
printf("%u %10lu %10lu %s\n", ST_TYPE(st), ST_INO(st), ST_SIZE(st), name);
free((void*)name);
}
}
});
} else {
close(fd);
}
}
int
......@@ -79,11 +78,16 @@ main(int argc, char *argv[])
{
int i;
if(argc < 2){
initwq();
if(argc < 2) {
ls(".");
return 0;
}
for(i=1; i<argc; i++)
} else {
// XXX(sbw) wq_for
for (i=1; i<argc; i++)
ls(argv[i]);
}
wq_dump();
return 0;
}
......@@ -13,7 +13,7 @@ public:
return *this;
}
const char * operator*() {
const char * copy_value() {
char *buf = (char*)malloc(256);
return name(buf, 256);
}
......
#pragma once
#include "cpputil.hh"
#include "ns.hh"
#include "gc.hh"
#include "atomic.hh"
#include "ref.hh"
u64 namehash(const strbuf<DIRSIZ>&);
struct file {
struct file : public referenced {
static file *alloc();
file *dup();
int stat(struct stat*);
int read(char *addr, int n);
ssize_t pread(char *addr, size_t n, off_t offset);
int write(char *addr, int n);
enum { FD_NONE, FD_PIPE, FD_INODE, FD_SOCKET } type;
std::atomic<int> ref; // reference count
char readable;
char writable;
......@@ -15,8 +25,14 @@ struct file {
struct pipe *pipe;
struct inode *ip;
u32 off;
};
NEW_DELETE_OPS(file);
private:
file();
protected:
virtual void onzero() const;
};
// in-core file system types
......
#include "atomic.hh"
class filetable {
public:
filetable() : ref_(1) {
for(int fd = 0; fd < NOFILE; fd++)
ofile_[fd] = nullptr;
initlock(&lock_, "filetable", 0);
}
filetable(const filetable &f) : ref_(1) {
for(int fd = 0; fd < NOFILE; fd++) {
if (f.ofile_[fd])
ofile_[fd] = f.ofile_[fd]->dup();
else
ofile_[fd] = nullptr;
}
initlock(&lock_, "filetable", 0);
}
~filetable() {
for(int fd = 0; fd < NOFILE; fd++){
if (ofile_[fd]){
ofile_[fd]->dec();
ofile_[fd] = 0;
}
}
destroylock(&lock_);
}
bool getfile(int fd, sref<file> *sf) {
file *f;
if (fd < 0 || fd >= NOFILE)
return false;
acquire(&lock_);
f = ofile_[fd];
if (!f) {
release(&lock_);
return false;
}
sf->init(f);
release(&lock_);
return true;
}
int allocfd(struct file *f) {
acquire(&lock_);
for (int fd = 0; fd < NOFILE; fd++) {
if (ofile_[fd] == nullptr){
ofile_[fd] = f;
release(&lock_);
return fd;
}
}
release(&lock_);
return -1;
}
void close(int fd) {
// XXX(sbw) if f->ref_ > 1 the kernel will not actually close
// the file when this function returns (i.e. sys_close can return
// while the file/pipe/socket is still open). Maybe we should clear
// ofile_[fd], wait until f.ref_ == 1, f->dec(), and then return.
acquire(&lock_);
struct file *f = ofile_[fd];
ofile_[fd] = nullptr;
release(&lock_);
if (f)
f->dec();
}
void decref() {
if (--ref_ == 0)
delete this;
}
void incref() {
ref_++;
}
NEW_DELETE_OPS(filetable)
private:
struct file *ofile_[NOFILE];
std::atomic<u64> ref_;
struct spinlock lock_;
};
#pragma once
// On-disk file system format.
// Both the kernel and user programs use this header file.
......
......@@ -86,15 +86,6 @@ void e1000hwaddr(u8 *hwaddr);
// exec.c
int exec(const char*, char**);
// file.c
struct file* filealloc(void);
void fileclose(struct file*);
struct file* filedup(struct file*);
void fileinit(void);
int fileread(struct file*, char*, int n);
int filestat(struct file*, struct stat*);
int filewrite(struct file*, char*, int n);
// fs.c
int namecmp(const char*, const char*);
struct inode* dirlookup(struct inode*, char*);
......
......@@ -3,6 +3,9 @@
#include "spinlock.h"
#include "atomic.hh"
#include "cpputil.hh"
#include "fs.h"
#include "file.hh"
#include "filetable.hh"
// Saved registers for kernel context switches.
// (also implicitly defined in swtch.S)
......@@ -47,7 +50,7 @@ struct proc : public rcu_freed {
struct trapframe *tf; // Trap frame for current syscall
struct context *context; // swtch() here to run process
int killed; // If non-zero, have been killed
struct file *ofile[NOFILE]; // Open files
filetable *ftable;
struct inode *cwd; // Current directory
char name[16]; // Process name (debugging)
u64 tsc;
......
#include "atomic.hh"
template <class T>
class sref {
public:
sref(T* p = nullptr) : ptr_(p) {
if (ptr_)
ptr_->inc();
}
~sref() {
if (ptr_)
ptr_->dec();
}
void init(T* p) {
const T* save = ptr_;
ptr_ = p;
if (ptr_)
ptr_->inc();
if (save)
save->dec();
}
bool operator==(const sref<T>& pr) const { return ptr_ == pr.ptr_; }
bool operator!=(const sref<T>& pr) const { return ptr_ != pr.ptr_; }
bool operator==(T* p) const { return ptr_ == p; }
bool operator!=(T* p) const { return ptr_ != p; }
const T * operator->() const { return ptr_; }
T * operator->() { return ptr_; }
T * ptr() const { return ptr_; }
private:
sref<T>& operator=(sref<T>& mp);
sref<T>& operator=(T* p);
sref<T>& operator=(const sref<T>& pr);
sref(const sref<T>& pr);
T *ptr_;
};
template <class T>
class lref {
public:
lref(T* p = nullptr) : ptr_(p) {
if (ptr_)
ptr_->inc();
}
lref(const lref<T>& pr) : ptr_(pr.ptr_) {
if (ptr_)
ptr_->inc();
}
~lref() {
if (ptr_)
ptr_->dec();
}
bool operator==(const lref<T>& pr) const { return ptr_ == pr.ptr_; }
bool operator!=(const lref<T>& pr) const { return ptr_ != pr.ptr_; }
bool operator==(T* p) const { return ptr_ == p; }
bool operator!=(T* p) const { return ptr_ != p; }
const T * operator->() const { return ptr_; }
T * operator->() { return ptr_; }
T * ptr() const { return ptr_; }
lref<T>& operator=(const lref<T>& pr) {
const T* save = ptr_;
ptr_ = pr.ptr_;
if (ptr_)
ptr_->inc();
if (save)
save->dec();
return *this;
}
private:
lref<T>& operator=( lref<T>& mp );
lref<T>& operator=( T* p );
T *ptr_;
};
class referenced {
public:
referenced() : ref_(0) {}
u64 ref() const {
return ref_;
}
inline const referenced* inc() const {
++ref_;
return this;
}
inline void dec() const {
if (--ref_ == 0)
onzero();
}
NEW_DELETE_OPS(referenced);
protected:
virtual ~referenced() { }
virtual void onzero() const { delete this; }
private:
mutable std::atomic<u64> ref_;
};
......@@ -34,6 +34,7 @@ int setfs(u64 base);
// ulib.c
int stat(char*, struct stat*);
int fstatat(int dirfd, const char*, struct stat*);
char* strcpy(char*, const char*);
void *memmove(void*, const void*, int);
char* strchr(const char*, char c);
......
......@@ -17,3 +17,9 @@ release(struct uspinlock *lk)
{
xchg32(&lk->locked, 0);
}
static int inline
tryacquire(struct uspinlock *lk)
{
return xchg32(&lk->locked, 1) == 0;
}
......@@ -7,6 +7,7 @@ class work;
int wq_trywork(void);
int wq_push(work *w);
void initwq(void);
void wq_dump(void);
struct work {
virtual void run() = 0;
......@@ -37,7 +38,8 @@ struct cwork : public work {
#define xmalloc(n) kmalloc(n)
#define xfree(p, sz) kmfree(p, sz)
#else
#warning "Unknown wq implementation"
#define xmalloc(n) malloc(n)
#define xfree(p, sz) free(p)
#endif
#include "wqfor.hh"
struct forframe
{
forframe(int v) : v_(v) {}
int inc() { return __sync_add_and_fetch(&v_, 1); }
int dec() { return __sync_sub_and_fetch(&v_, 1); }
bool zero() volatile { return v_ == 0; };
volatile int v_;
};
template <typename IT, typename BODY>
struct forwork : public work {
typedef std::atomic<int> forframe;
forwork(IT &it, bool (*cond)(IT &it), BODY &body, forframe &frame)
: it_(it), cond_(cond), body_(body), frame_(frame) {}
virtual void run() {
decltype(*it_) v = *it_;
decltype(it_.copy_value()) v = it_.copy_value();
++it_;
if (cond_(it_)) {
forwork<IT, BODY> *w = new forwork<IT, BODY>(it_, cond_, body_, frame_);
++frame_;
frame_.inc();
wq_push(w);
}
body_(v);
--frame_;
frame_.dec();
delete this;
}
......@@ -37,19 +44,19 @@ template <typename IT, typename BODY>
static inline void
wq_for(IT &init, bool (*cond)(IT &it), BODY body)
{
typename forwork<IT, BODY>::forframe frame(0);
forframe frame(0);
// XXX(sbw) should be able to coarsen loop
decltype(*init) v = *init;
decltype(init.copy_value()) v = init.copy_value();
++init;
if (cond(init)) {
forwork<IT, BODY> *w = new forwork<IT, BODY>(init, cond, body, frame);
++frame;
frame.inc();
wq_push(w);
}
body(v);
while (frame != 0)
while (!frame.zero())
wq_trywork();
}
// XXX(sbw)
#include "types.h"
#include "uspinlock.h"
#include "amd64.h"
#include "user.h"
#include "wq.hh"
#include "pthread.h"
typedef struct uspinlock wqlock_t;
static pthread_key_t idkey;
int
mycpuid(void)
{
return (int)(u64)pthread_getspecific(idkey);
}
static inline void*
allocwq(void)
{
return malloc(WQSIZE);
}
static inline void
wqlock_acquire(wqlock_t *lock)
{
acquire(lock);
}
static inline int
wqlock_tryacquire(wqlock_t *lock)
{
return tryacquire(lock);
}
static inline void
wqlock_release(wqlock_t *lock)
{
release(lock);
}
static inline void
wqlock_init(wqlock_t *lock)
{
lock->locked = 0;
}
static void
setaffinity(int c)
{
// XXX(sbw)
}
static void*
workerth(void *x)
{
u64 c = (u64)x;
setaffinity(c);
pthread_setspecific(idkey, (void*)c);
while (1)
wq_trywork();
return 0;
}
static inline void
wqarch_init(void)
{
pthread_t th;
int r;
if (pthread_key_create(&idkey, 0))
die("wqarch_init: pthread_key_create");
pthread_setspecific(idkey, 0);
setaffinity(0);
for (int i = 1; i < NCPU; i++) {
r = pthread_create(&th, 0, workerth, (void*)(u64)i);
if (r < 0)
die("wqarch_init: pthread_create");
}
}
#define xprintf printf
#define pushcli()
#define popcli()
......@@ -56,7 +56,7 @@ long
sys_async(int fd, size_t count, off_t off,
msgid_t msgid, pageid_t pageid)
{
struct file *f;
sref<file> f;;
cwork *w;
char *kshared = myproc()->vmap->kshared;
......@@ -72,9 +72,9 @@ sys_async(int fd, size_t count, off_t off,
msg = &ipcctl->msg[msgid];
ubuf = (kshared+PGSIZE+(pageid*PGSIZE));
if(fd < 0 || fd >= NOFILE || (f=myproc()->ofile[fd]) == 0)
if (!myproc()->ftable->getfile(fd, &f))
return -1;
if(f->type != file::FD_INODE)
if (f->type != file::FD_INODE)
return -1;
f->ip->ref++;
......
......@@ -9,102 +9,111 @@
struct devsw __mpalign__ devsw[NDEV];
// Allocate a file structure.
struct file*
filealloc(void)
file*
file::alloc(void)
{
struct file *f = (file*) kmalloc(sizeof(struct file));
f->ref = 1;
f->type = file::FD_NONE;
return f;
return new file();
}
// Increment ref count for file f.
struct file*
filedup(struct file *f)
file::file(void)
: type(file::FD_NONE), readable(0), writable(0),
socket(0), pipe(nullptr), ip(nullptr), off(0)
{
if (f->ref++ < 1)
panic("filedup");
return f;
inc();
}
// Close file f. (Decrement ref count, close when reaches 0.)
void
fileclose(struct file *f)
file::onzero(void) const
{
if (--f->ref > 0)
return;
if(type == file::FD_PIPE)
pipeclose(pipe, writable);
else if(type == file::FD_INODE)
iput(ip);
else if(type == file::FD_SOCKET)
netclose(socket);
else if(type != file::FD_NONE)
panic("file::close bad type");
delete this;
}
if(f->type == file::FD_PIPE)
pipeclose(f->pipe, f->writable);
else if(f->type == file::FD_INODE)
iput(f->ip);
else if(f->type == file::FD_SOCKET)
netclose(f->socket);
else if(f->type != file::FD_NONE)
panic("fileclose bad type");
kmfree(f, sizeof(struct file));
file*
file::dup(void)
{
inc();
return this;
}
// Get metadata about file f.
int
filestat(struct file *f, struct stat *st)
file::stat(struct stat *st)
{
if(f->type == file::FD_INODE){
ilock(f->ip, 0);
if(f->ip->type == 0)
if(type == file::FD_INODE){
ilock(ip, 0);
if(ip->type == 0)
panic("filestat");
stati(f->ip, st);
iunlock(f->ip);
stati(ip, st);
iunlock(ip);
return 0;
}
return -1;
}
// Read from file f. Addr is kernel address.
int
fileread(struct file *f, char *addr, int n)
file::read(char *addr, int n)
{
int r;
if(f->readable == 0)
if(readable == 0)
return -1;
if(f->type == file::FD_PIPE)
return piperead(f->pipe, addr, n);
if(f->type == file::FD_INODE){
ilock(f->ip, 0);
if(f->ip->type == 0)
if(type == file::FD_PIPE)
return piperead(pipe, addr, n);
if(type == file::FD_INODE){
ilock(ip, 0);
if(ip->type == 0)
panic("fileread");
if((r = readi(f->ip, addr, f->off, n)) > 0)
f->off += r;
iunlock(f->ip);
if((r = readi(ip, addr, off, n)) > 0)
off += r;
iunlock(ip);
return r;
}
if(f->type == file::FD_SOCKET)
return netread(f->socket, addr, n);
if(type == file::FD_SOCKET)
return netread(socket, addr, n);
panic("fileread");
}
// Write to file f. Addr is kernel address.
ssize_t
file::pread(char *addr, size_t n, off_t off)
{
if(type == file::FD_INODE){
int r;
ilock(ip, 0);
if(ip->type == 0)
panic("file::pread");
r = readi(ip, addr, off, n);
iunlock(ip);
return r;
}
return -1;
}
int
filewrite(struct file *f, char *addr, int n)
file::write(char *addr, int n)
{
int r;
if(f->writable == 0)
if(writable == 0)
return -1;
if(f->type == file::FD_PIPE)
return pipewrite(f->pipe, addr, n);
if(f->type == file::FD_INODE){
ilock(f->ip, 1);
if(f->ip->type == 0 || f->ip->type == T_DIR)
if(type == file::FD_PIPE)
return pipewrite(pipe, addr, n);
if(type == file::FD_INODE){
ilock(ip, 1);
if(ip->type == 0 || ip->type == T_DIR)
panic("filewrite but 0 or T_DIR");
if((r = writei(f->ip, addr, f->off, n)) > 0)
f->off += r;
iunlock(f->ip);
if((r = writei(ip, addr, off, n)) > 0)
off += r;
iunlock(ip);
return r;
}
if(f->type == file::FD_SOCKET)
return netwrite(f->socket, addr, n);
if(type == file::FD_SOCKET)
return netwrite(socket, addr, n);
panic("filewrite");
}
......@@ -28,7 +28,7 @@ pipealloc(struct file **f0, struct file **f1)
p = 0;
*f0 = *f1 = 0;
if((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0)
if((*f0 = file::alloc()) == 0 || (*f1 = file::alloc()) == 0)
goto bad;
if((p = (pipe*)kmalloc(sizeof(*p))) == 0)
goto bad;
......@@ -55,9 +55,9 @@ pipealloc(struct file **f0, struct file **f1)
kmfree((char*)p, sizeof(*p));
}
if(*f0)
fileclose(*f0);
(*f0)->dec();
if(*f1)
fileclose(*f1);
(*f1)->dec();
return -1;
}
......
......@@ -38,7 +38,7 @@ enum { sched_debug = 0 };
proc::proc(int npid) :
rcu_freed("proc"), vmap(0), brk(0), kstack(0),
pid(npid), parent(0), tf(0), context(0), killed(0),
cwd(0), tsc(0), curcycles(0), cpuid(0), epoch(0),
ftable(0), cwd(0), tsc(0), curcycles(0), cpuid(0), epoch(0),
on_runq(-1), cpu_pin(0), runq(0), oncv(0), cv_wakeup(0),
user_fs_(0), state_(EMBRYO)
{
......@@ -48,7 +48,6 @@ proc::proc(int npid) :
memset(&childq, 0, sizeof(childq));
memset(&child_next, 0, sizeof(child_next));
memset(ofile, 0, sizeof(ofile));
memset(&runqlink, 0, sizeof(runqlink));
memset(&cv_waiters, 0, sizeof(cv_waiters));
memset(&cv_sleep, 0, sizeof(cv_sleep));
......@@ -122,19 +121,13 @@ void
exit(void)
{
struct proc *p, *np;
int fd;
int wakeupinit;
if(myproc() == bootproc)
panic("init exiting");
// Close all open files.
for(fd = 0; fd < NOFILE; fd++){
if(myproc()->ofile[fd]){
fileclose(myproc()->ofile[fd]);
myproc()->ofile[fd] = 0;
}
}
if (myproc()->ftable)
myproc()->ftable->decref();
// Kernel threads might not have a cwd
if (myproc()->cwd != nullptr) {
......@@ -246,6 +239,9 @@ inituser(void)
extern u64 _initcode_size;
p = allocproc();
p->ftable = new filetable();
if (p->ftable == nullptr)
panic("userinit: new filetable");
bootproc = p;
if((p->vmap = new vmap()) == 0)
panic("userinit: out of vmaps?");
......@@ -432,7 +428,7 @@ procdumpall(void)
int
fork(int flags)
{
int i, pid;
int pid;
struct proc *np;
int cow = 1;
......@@ -464,9 +460,18 @@ fork(int flags)
// Clear %eax so that fork returns 0 in the child.
np->tf->rax = 0;
for(i = 0; i < NOFILE; i++)
if(myproc()->ofile[i])
np->ofile[i] = filedup(myproc()->ofile[i]);
if (flags == 0) {
np->ftable = new filetable(*myproc()->ftable);
if (np->ftable == nullptr) {
// XXX(sbw) leaking?
freeproc(np);
return -1;
}
} else {
myproc()->ftable->incref();
np->ftable = myproc()->ftable;
}
np->cwd = idup(myproc()->cwd);
pid = np->pid;
safestrcpy(np->name, myproc()->name, sizeof(myproc()->name));
......
......@@ -12,115 +12,91 @@
#include "cpu.hh"
#include "net.hh"
// Fetch the nth word-sized system call argument as a file descriptor
// and return both the descriptor and the corresponding struct file.
static int
argfd(int fd, struct file **pf)
static bool
getfile(int fd, sref<file> *f)
{
struct file *f;
if(fd < 0 || fd >= NOFILE || (f=myproc()->ofile[fd]) == 0)
return -1;
if(pf)
*pf = f;
return 0;
return myproc()->ftable->getfile(fd, f);
}
// Allocate a file descriptor for the given file.
// Takes over file reference from caller on success.
static int
fdalloc(struct file *f)
fdalloc(file *f)
{
int fd;
for(fd = 0; fd < NOFILE; fd++){
if(myproc()->ofile[fd] == 0){
myproc()->ofile[fd] = f;
return fd;
}
}
return -1;
return myproc()->ftable->allocfd(f);
}
long
sys_dup(int ofd)
{
struct file *f;
sref<file> f;
int fd;
if(argfd(ofd, &f) < 0)
if (!getfile(ofd, &f))
return -1;
if((fd=fdalloc(f)) < 0)
f->inc();
if ((fd = fdalloc(f.ptr())) < 0) {
f->dec();
return -1;
filedup(f);
}
return fd;
}
s64
sys_read(int fd, char *p, int n)
{
struct file *f;
sref<file> f;
if(argfd(fd, &f) < 0 || argcheckptr(p, n) < 0)
if(!getfile(fd, &f) || argcheckptr(p, n) < 0)
return -1;
return fileread(f, p, n);
return f->read(p, n);
}
ssize_t
sys_pread(int fd, void *ubuf, size_t count, off_t offset)
{
struct file *f;
sref<file> f;
uptr i = (uptr)ubuf;
int r;
if(fd < 0 || fd >= NOFILE || (f=myproc()->ofile[fd]) == 0)
if (!getfile(fd, &f))
return -1;
for(uptr va = PGROUNDDOWN(i); va < i+count; va = va + PGSIZE)
if(pagefault(myproc()->vmap, va, 0) < 0)
return -1;
if(f->type == file::FD_INODE){
ilock(f->ip, 0);
if(f->ip->type == 0)
panic("fileread");
r = readi(f->ip, (char*)ubuf, offset, count);
iunlock(f->ip);
return r;
}
return -1;
return f->pread((char*)ubuf, count, offset);
}
long
sys_write(int fd, char *p, int n)
{
struct file *f;
sref<file> f;
if(argfd(fd, &f) < 0 || argcheckptr(p, n) < 0)
if (!getfile(fd, &f) || argcheckptr(p, n) < 0)
return -1;
return filewrite(f, p, n);
return f->write(p, n);
}
long
sys_close(int fd)
{
struct file *f;
sref<file> f;
if(argfd(fd, &f) < 0)
if (!getfile(fd, &f))
return -1;
myproc()->ofile[fd] = 0;
fileclose(f);
myproc()->ftable->close(fd);
return 0;
}
long
sys_fstat(int fd, struct stat *st)
{
struct file *f;
sref<file> f;
if(argfd(fd, &f) < 0 || argcheckptr(st, sizeof(*st)) < 0)
if (!getfile(fd, &f) || argcheckptr(st, sizeof(*st)) < 0)
return -1;
return filestat(f, st);
return f->stat(st);
}
// Create the path new as a link to the same inode as old.
......@@ -296,8 +272,8 @@ sys_openat(int dirfd, const char *path, int omode)
} else if (dirfd < 0 || dirfd >= NOFILE) {
return -1;
} else {
struct file *fdir = myproc()->ofile[dirfd];
if (fdir->type != file::FD_INODE)
sref<file> fdir;
if (!getfile(dirfd, &fdir) || fdir->type != file::FD_INODE)
return -1;
cwd = fdir->ip;
}
......@@ -326,9 +302,9 @@ sys_openat(int dirfd, const char *path, int omode)
}
}
if((f = filealloc()) == 0 || (fd = fdalloc(f)) < 0){
if((f = file::alloc()) == 0 || (fd = fdalloc(f)) < 0){
if(f)
fileclose(f);
f->dec();
iunlockput(ip);
return -1;
}
......@@ -424,9 +400,8 @@ sys_pipe(int *fd)
fd0 = -1;
if((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0){
if(fd0 >= 0)
myproc()->ofile[fd0] = 0;
fileclose(rf);
fileclose(wf);
myproc()->ftable->close(fd0);
wf->dec();
return -1;
}
fd[0] = fd0;
......@@ -437,21 +412,19 @@ sys_pipe(int *fd)
static void
freesocket(int fd)
{
fileclose(myproc()->ofile[fd]);
myproc()->ofile[fd] = 0;
myproc()->ftable->close(fd);
}
static int
getsocket(int fd, struct file **ret)
static bool
getsocket(int fd, sref<file> *f)
{
struct file *f;
if (fd < 0 || fd >= NOFILE || (f=myproc()->ofile[fd]) == 0)
return -1;
if (f->type != file::FD_SOCKET)
return -1;
*ret = f;
return 0;
if (!getfile(fd, f))
return false;
if ((*f)->type != file::FD_SOCKET) {
f->init(nullptr);
return false;
}
return true;
}
static int
......@@ -460,13 +433,13 @@ allocsocket(struct file **rf, int *rfd)
struct file *f;
int fd;
f = filealloc();
f = file::alloc();
if (f == nullptr)
return -1;
fd = fdalloc(f);
if (fd < 0) {
fileclose(f);
f->dec();
return fd;
}
......@@ -493,8 +466,7 @@ sys_socket(int domain, int type, int protocol)
s = netsocket(domain, type, protocol);
if (s < 0) {
myproc()->ofile[fd] = 0;
fileclose(f);
myproc()->ftable->close(fd);
return s;
}
......@@ -506,9 +478,9 @@ long
sys_bind(int xsock, void *xaddr, int xaddrlen)
{
extern long netbind(int, void*, int);
struct file *f;
sref<file> f;
if (getsocket(xsock, &f))
if (!getsocket(xsock, &f))
return -1;
return netbind(f->socket, xaddr, xaddrlen);
......@@ -518,9 +490,9 @@ long
sys_listen(int xsock, int backlog)
{
extern long netlisten(int, int);
struct file *f;
sref<file> f;
if (getsocket(xsock, &f))
if (!getsocket(xsock, &f))
return -1;
return netlisten(f->socket, backlog);
......@@ -530,11 +502,12 @@ long
sys_accept(int xsock, void *xaddr, void *xaddrlen)
{
extern long netaccept(int, void*, void*);
struct file *f, *cf;
file *cf;
sref<file> f;
int cfd;
int ss;
if (getsocket(xsock, &f))
if (!getsocket(xsock, &f))
return -1;
if (allocsocket(&cf, &cfd))
......
......@@ -2,7 +2,7 @@ $(O)/lib/%.o: CFLAGS:=$(CFLAGS)
$(O)/lib/%.o: CXXFLAGS:=$(CXXFLAGS)
ULIB = ulib.o usys.o printf.o umalloc.o uthread.o fmt.o stream.o ipc.o \
threads.o crt.o
threads.o crt.o wq.o
ULIB := $(addprefix $(O)/lib/, $(ULIB))
.PRECIOUS: $(O)/lib/%.o
......
......@@ -2,6 +2,7 @@
.align 8
.globl _start
_start:
call usetup
pop %rdi
mov %rsp, %rsi
call main
......
......@@ -102,6 +102,20 @@ stat(char *n, struct stat *st)
}
int
fstatat(int dirfd, const char *n, struct stat *st)
{
int fd;
int r;
fd = openat(dirfd, n, O_RDONLY);
if(fd < 0)
return -1;
r = fstat(fd, st);
close(fd);
return r;
}
int
atoi(const char *s)
{
int n;
......@@ -136,3 +150,15 @@ open(const char *path, int omode)
{
return openat(AT_FDCWD, path, omode);
}
extern void __cxa_pure_virtual(void);
void __cxa_pure_virtual(void)
{
die("__cxa_pure_virtual");
}
void
usetup(void)
{
forkt_setup(getpid());
}
#if defined(LINUX)
#include "user/wqlinux.hh"
#include "percpu.hh"
#elif defined(XV6_KERNEL)
#include "wqkernel.hh"
#include "percpu.hh"
#else
#warning "Unknown wq implementation"
#include "wquser.hh"
#endif
#include "percpu.hh"
#define NSLOTS (1 << WQSHIFT)
......
......@@ -19,7 +19,7 @@ public:
return *this;
}
const char * operator*() {
const char * copy_value() {
char *buf = (char*)malloc(256);
return name(buf, 256);
}
......
......@@ -84,7 +84,5 @@ wqarch_init(void)
}
#define xprintf printf
#define xmalloc(n) malloc(n)
#define xfree(p, sz) free(p)
#define pushcli()
#define popcli()
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论