提交 80920c8a 创建 作者: 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

......@@ -8,9 +8,9 @@
u64 namehash(const strbuf<DIRSIZ>&);
struct file : public referenced {
static file *alloc();
file *dup();
struct file : public referenced, public rcu_freed {
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);
......@@ -25,10 +25,14 @@ struct file : public referenced {
struct pipe *pipe;
struct inode *ip;
u32 off;
NEW_DELETE_OPS(file);
virtual void do_gc(void);
private:
file();
file& operator=(const file&);
file(const file& x);
NEW_DELETE_OPS(file);
protected:
virtual void onzero() const;
......
......@@ -2,58 +2,40 @@
class filetable {
public:
filetable() : ref_(1) {
for(int fd = 0; fd < NOFILE; fd++)
ofile_[fd] = nullptr;
initlock(&lock_, "filetable", 0);
static filetable* alloc() {
return new filetable();
}
filetable(const filetable &f) : ref_(1) {
filetable* copy() {
filetable* t = alloc();
if (t == nullptr)
return nullptr;
for(int fd = 0; fd < NOFILE; fd++) {
if (f.ofile_[fd])
ofile_[fd] = f.ofile_[fd]->dup();
sref<file> f;
if (getfile(fd, &f))
t->ofile_[fd].store(f->dup());
else
ofile_[fd] = nullptr;
t->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_);
return t;
}
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_);
scoped_gc_epoch gc;
file* f = ofile_[fd];
if (!f || !sf->init(f))
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_);
for (int fd = 0; fd < NOFILE; fd++)
if (ofile_[fd] == nullptr && cmpxch(&ofile_[fd], (file*)nullptr, f))
return fd;
}
}
release(&lock_);
cprintf("filetable::allocfd: failed\n");
return -1;
}
......@@ -61,15 +43,13 @@ public:
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.
// while the file/pipe/socket is still open).
acquire(&lock_);
struct file *f = ofile_[fd];
ofile_[fd] = nullptr;
release(&lock_);
if (f)
file* f = ofile_[fd].exchange(nullptr);
if (f != nullptr)
f->dec();
else
cprintf("filetable::close: bad fd %u\n", fd);
}
void decref() {
......@@ -81,10 +61,25 @@ public:
ref_++;
}
NEW_DELETE_OPS(filetable)
private:
struct file *ofile_[NOFILE];
filetable() : ref_(1) {
for(int fd = 0; fd < NOFILE; fd++)
ofile_[fd] = nullptr;
}
~filetable() {
for(int fd = 0; fd < NOFILE; fd++){
if (ofile_[fd]){
ofile_[fd].load()->dec();
ofile_[fd] = nullptr;
}
}
}
filetable& operator=(const filetable&);
filetable(const filetable& x);
NEW_DELETE_OPS(filetable);
std::atomic<file*> ofile_[NOFILE];
std::atomic<u64> ref_;
struct spinlock lock_;
};
#include "atomic.hh"
template <class T>
class sref {
public:
......@@ -13,13 +11,11 @@ public:
ptr_->dec();
}
void init(T* p) {
const T* save = ptr_;
bool init(T* p) {
if (ptr_ || !p->tryinc())
return false;
ptr_ = p;
if (ptr_)
ptr_->inc();
if (save)
save->dec();
return true;
}
bool operator==(const sref<T>& pr) const { return ptr_ == pr.ptr_; }
......@@ -40,65 +36,36 @@ private:
T *ptr_;
};
template <class T>
class lref {
class referenced {
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();
}
// Start with 1 reference
referenced() { ref_.v = 0; }
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_; }
// The number of valid references is:
// ref_.invalid ? 0 : ref_.count+1;
lref<T>& operator=(const lref<T>& pr) {
const T* save = ptr_;
ptr_ = pr.ptr_;
if (ptr_)
ptr_->inc();
if (save)
save->dec();
return *this;
inline bool valid() const {
return ref_.invalid == 0;
}
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 void inc() const {
// If references is 0 (i.e. ref_.count is 0xffffffff) a 32-bit
// increment will increases ref_.count to 0, but ref_.invalid
// will remain unchanged.
asm volatile("lock; incl %0" : "+m" (ref_.count));
}
inline const referenced* inc() const {
++ref_;
return this;
inline bool tryinc() const {
inc();
return valid();
}
inline void dec() const {
if (--ref_ == 0)
unsigned char c;
// If references is 1 (i.e. ref_.v is 0), a 64-bit decrement will
// underflow ref_.invalid to 0xffffffff (and ref_.count to 0xffffffff).
asm volatile("lock; decq %0; sets %1" : "+m" (ref_.v), "=qm" (c));
if (c)
onzero();
}
......@@ -109,5 +76,11 @@ protected:
virtual void onzero() const { delete this; }
private:
mutable std::atomic<u64> ref_;
mutable union {
volatile u64 v;
struct {
volatile u32 count;
volatile u32 invalid;
};
} ref_;
};
......@@ -16,10 +16,10 @@ file::alloc(void)
}
file::file(void)
: type(file::FD_NONE), readable(0), writable(0),
: rcu_freed("file"),
type(file::FD_NONE), readable(0), writable(0),
socket(0), pipe(nullptr), ip(nullptr), off(0)
{
inc();
}
void
......@@ -33,6 +33,12 @@ file::onzero(void) const
netclose(socket);
else if(type != file::FD_NONE)
panic("file::close bad type");
gc_delayed((file*)this);
}
void
file::do_gc(void)
{
delete this;
}
......
......@@ -377,7 +377,7 @@ fork(int flags)
myproc()->ftable->incref();
np->ftable = myproc()->ftable;
} else {
np->ftable = new filetable(*myproc()->ftable);
np->ftable = myproc()->ftable->copy();
if (np->ftable == nullptr) {
// XXX(sbw) leaking?
freeproc(np);
......
......@@ -21,7 +21,7 @@ inituser(void)
extern u64 _initcode_size;
p = proc::alloc();
p->ftable = new filetable();
p->ftable = filetable::alloc();
if (p->ftable == nullptr)
panic("userinit: new filetable");
bootproc = p;
......
......@@ -84,13 +84,13 @@ long
uwq_worker::wait(void)
{
acquire(&lock_);
if (uwq_->ref() == 0)
if (!uwq_->valid())
this->exit();
running_ = false;
cv_sleep(&cv_, &lock_);
if (uwq_->ref() == 0)
if (!uwq_->valid())
this->exit();
release(&lock_);
return 0;
......@@ -119,7 +119,6 @@ uwq::alloc(vmap* vmap, filetable *ftable)
ksfree(slab_userwq, len);
return nullptr;
}
u->inc();
if (mapkva(vmap->pml4, (char*)len, USERWQ, USERWQSIZE)) {
ftable->decref();
......@@ -172,7 +171,7 @@ uwq::tryworker(void)
// Try to start a worker thread
scoped_acquire lock0(&lock_);
if (ref() == 0)
if (!valid())
return false;
int slot = -1;
......
......@@ -33,7 +33,7 @@
#define PERFSIZE (1<<20ull)
#elif defined(HW_qemu)
#define NCPU 8 // maximum number of CPUs
#define MTRACE 1
#define MTRACE 0
#define PERFSIZE (16<<20ull)
#elif defined(HW_ud0)
#define NCPU 4 // maximum number of CPUs
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论