提交 b9682048 创建 作者: Silas Boyd-Wickizer's avatar Silas Boyd-Wickizer

Merge branch 'filetable' into scale-amd64

......@@ -26,7 +26,8 @@ UPROGS= \
wqsh \
cp \
perf \
xls
xls \
xdu
# pdu
# pls
......
......@@ -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();
......
......@@ -4,13 +4,15 @@
#include "ns.hh"
#include "gc.hh"
#include "atomic.hh"
#include "ref.hh"
u64 namehash(const strbuf<DIRSIZ>&);
struct file {
struct file : public referenced {
file() : type(file::FD_NONE), readable(0), writable(0),
socket(0), pipe(nullptr), ip(nullptr), off(0),
ref_(1) {}
socket(0), pipe(nullptr), ip(nullptr), off(0) {
inc();
}
file *dup();
void close();
......@@ -25,8 +27,8 @@ struct file {
u32 off;
NEW_DELETE_OPS(file);
private:
std::atomic<int> ref_;
protected:
virtual void onzero() const;
};
// in-core file system types
......
......@@ -28,16 +28,20 @@ public:
destroylock(&lock_);
}
file *getfile(int fd) {
bool getfile(int fd, sref<file> *sf) {
file *f;
if (fd < 0 || fd >= NOFILE)
return nullptr;
return false;
acquire(&lock_);
f = ofile_[fd];
// XXX(sbw) f->inc();
if (!f) {
release(&lock_);
return false;
}
sf->init(f);
release(&lock_);
return f;
return true;
}
int allocfd(struct file *f) {
......
#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_;
};
......@@ -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,7 +72,7 @@ sys_async(int fd, size_t count, off_t off,
msg = &ipcctl->msg[msgid];
ubuf = (kshared+PGSIZE+(pageid*PGSIZE));
if ((f = myproc()->ftable->getfile(fd)) == nullptr)
if (!myproc()->ftable->getfile(fd, &f))
return -1;
if (f->type != file::FD_INODE)
return -1;
......
......@@ -10,11 +10,8 @@
struct devsw __mpalign__ devsw[NDEV];
void
file::close(void)
file::onzero() const
{
if (--ref_ > 0)
return;
if(type == file::FD_PIPE)
pipeclose(pipe, writable);
else if(type == file::FD_INODE)
......@@ -26,11 +23,16 @@ file::close(void)
delete this;
}
void
file::close(void)
{
dec();
}
file*
file::dup(void)
{
if (ref_++ < 1)
panic("file::dup");
inc();
return this;
}
......
......@@ -460,11 +460,16 @@ fork(int flags)
// Clear %eax so that fork returns 0 in the child.
np->tf->rax = 0;
np->ftable = new filetable(*myproc()->ftable);
if (np->ftable == nullptr) {
// XXX(sbw) leaking?
freeproc(np);
return -1;
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);
......
......@@ -12,24 +12,16 @@
#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((f = myproc()->ftable->getfile(fd)) == nullptr)
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)
{
return myproc()->ftable->allocfd(f);
}
......@@ -37,35 +29,37 @@ fdalloc(struct file *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;
f->dup();
}
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 fileread(f.ptr(), 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 ((f = myproc()->ftable->getfile(fd)) == nullptr)
if (!getfile(fd, &f))
return -1;
for(uptr va = PGROUNDDOWN(i); va < i+count; va = va + PGSIZE)
......@@ -86,19 +80,19 @@ sys_pread(int fd, void *ubuf, size_t count, off_t 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 filewrite(f.ptr(), 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()->ftable->close(fd);
return 0;
......@@ -107,11 +101,11 @@ sys_close(int fd)
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 filestat(f.ptr(), st);
}
// Create the path new as a link to the same inode as old.
......@@ -287,8 +281,8 @@ sys_openat(int dirfd, const char *path, int omode)
} else if (dirfd < 0 || dirfd >= NOFILE) {
return -1;
} else {
struct file *fdir = myproc()->ftable->getfile(dirfd);
if (fdir == nullptr || fdir->type != file::FD_INODE)
sref<file> fdir;
if (!getfile(dirfd, &fdir) || fdir->type != file::FD_INODE)
return -1;
cwd = fdir->ip;
}
......@@ -430,17 +424,16 @@ freesocket(int fd)
myproc()->ftable->close(fd);
}
static int
getsocket(int fd, struct file **ret)
static bool
getsocket(int fd, sref<file> *f)
{
struct file *f;
if ((f = myproc()->ftable->getfile(fd)) == nullptr)
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
......@@ -494,9 +487,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);
......@@ -506,9 +499,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);
......@@ -518,11 +511,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))
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论