提交 fb099945 创建 作者: Robert Morris's avatar Robert Morris

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

#pragma once
#include "cpputil.hh" #include "cpputil.hh"
#include "ns.hh" #include "ns.hh"
#include "gc.hh" #include "gc.hh"
...@@ -6,8 +8,14 @@ ...@@ -6,8 +8,14 @@
u64 namehash(const strbuf<DIRSIZ>&); u64 namehash(const strbuf<DIRSIZ>&);
struct file { struct file {
enum { FD_NONE, FD_PIPE, FD_INODE, FD_SOCKET } type; file() : type(file::FD_NONE), readable(0), writable(0),
std::atomic<int> ref; // reference count socket(0), pipe(nullptr), ip(nullptr), off(0),
ref_(1) {}
file *dup();
void close();
enum { FD_NONE, FD_PIPE, FD_INODE, FD_SOCKET } type;
char readable; char readable;
char writable; char writable;
...@@ -15,8 +23,11 @@ struct file { ...@@ -15,8 +23,11 @@ struct file {
struct pipe *pipe; struct pipe *pipe;
struct inode *ip; struct inode *ip;
u32 off; u32 off;
}; NEW_DELETE_OPS(file);
private:
std::atomic<int> ref_;
};
// in-core file system types // 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]->close();
ofile_[fd] = 0;
}
}
destroylock(&lock_);
}
file *getfile(int fd) {
file *f;
if (fd < 0 || fd >= NOFILE)
return nullptr;
acquire(&lock_);
f = ofile_[fd];
// XXX(sbw) f->inc();
release(&lock_);
return f;
}
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) {
struct file *f = ofile_[fd];
acquire(&lock_);
ofile_[fd] = nullptr;
release(&lock_);
f->close();
}
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. // On-disk file system format.
// Both the kernel and user programs use this header file. // Both the kernel and user programs use this header file.
......
...@@ -3,6 +3,9 @@ ...@@ -3,6 +3,9 @@
#include "spinlock.h" #include "spinlock.h"
#include "atomic.hh" #include "atomic.hh"
#include "cpputil.hh" #include "cpputil.hh"
#include "fs.h"
#include "file.hh"
#include "filetable.hh"
// Saved registers for kernel context switches. // Saved registers for kernel context switches.
// (also implicitly defined in swtch.S) // (also implicitly defined in swtch.S)
...@@ -47,7 +50,7 @@ struct proc : public rcu_freed { ...@@ -47,7 +50,7 @@ struct proc : public rcu_freed {
struct trapframe *tf; // Trap frame for current syscall struct trapframe *tf; // Trap frame for current syscall
struct context *context; // swtch() here to run process struct context *context; // swtch() here to run process
int killed; // If non-zero, have been killed int killed; // If non-zero, have been killed
struct file *ofile[NOFILE]; // Open files filetable *ftable;
struct inode *cwd; // Current directory struct inode *cwd; // Current directory
char name[16]; // Process name (debugging) char name[16]; // Process name (debugging)
u64 tsc; u64 tsc;
......
...@@ -72,9 +72,9 @@ sys_async(int fd, size_t count, off_t off, ...@@ -72,9 +72,9 @@ sys_async(int fd, size_t count, off_t off,
msg = &ipcctl->msg[msgid]; msg = &ipcctl->msg[msgid];
ubuf = (kshared+PGSIZE+(pageid*PGSIZE)); ubuf = (kshared+PGSIZE+(pageid*PGSIZE));
if(fd < 0 || fd >= NOFILE || (f=myproc()->ofile[fd]) == 0) if ((f = myproc()->ftable->getfile(fd)) == nullptr)
return -1; return -1;
if(f->type != file::FD_INODE) if (f->type != file::FD_INODE)
return -1; return -1;
f->ip->ref++; f->ip->ref++;
......
...@@ -9,41 +9,29 @@ ...@@ -9,41 +9,29 @@
struct devsw __mpalign__ devsw[NDEV]; struct devsw __mpalign__ devsw[NDEV];
// Allocate a file structure. void
struct file* file::close(void)
filealloc(void)
{ {
struct file *f = (file*) kmalloc(sizeof(struct file)); if (--ref_ > 0)
f->ref = 1; return;
f->type = file::FD_NONE;
return f;
}
// Increment ref count for file f. if(type == file::FD_PIPE)
struct file* pipeclose(pipe, writable);
filedup(struct file *f) else if(type == file::FD_INODE)
{ iput(ip);
if (f->ref++ < 1) else if(type == file::FD_SOCKET)
panic("filedup"); netclose(socket);
return f; else if(type != file::FD_NONE)
panic("file::close bad type");
delete this;
} }
// Close file f. (Decrement ref count, close when reaches 0.) file*
void file::dup(void)
fileclose(struct file *f)
{ {
if (--f->ref > 0) if (ref_++ < 1)
return; panic("file::dup");
return 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));
} }
// Get metadata about file f. // Get metadata about file f.
......
...@@ -28,7 +28,7 @@ pipealloc(struct file **f0, struct file **f1) ...@@ -28,7 +28,7 @@ pipealloc(struct file **f0, struct file **f1)
p = 0; p = 0;
*f0 = *f1 = 0; *f0 = *f1 = 0;
if((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0) if((*f0 = new file()) == 0 || (*f1 = new file()) == 0)
goto bad; goto bad;
if((p = (pipe*)kmalloc(sizeof(*p))) == 0) if((p = (pipe*)kmalloc(sizeof(*p))) == 0)
goto bad; goto bad;
...@@ -55,9 +55,9 @@ pipealloc(struct file **f0, struct file **f1) ...@@ -55,9 +55,9 @@ pipealloc(struct file **f0, struct file **f1)
kmfree((char*)p, sizeof(*p)); kmfree((char*)p, sizeof(*p));
} }
if(*f0) if(*f0)
fileclose(*f0); (*f0)->close();
if(*f1) if(*f1)
fileclose(*f1); (*f1)->close();
return -1; return -1;
} }
......
...@@ -38,7 +38,7 @@ enum { sched_debug = 0 }; ...@@ -38,7 +38,7 @@ enum { sched_debug = 0 };
proc::proc(int npid) : proc::proc(int npid) :
rcu_freed("proc"), vmap(0), brk(0), kstack(0), rcu_freed("proc"), vmap(0), brk(0), kstack(0),
pid(npid), parent(0), tf(0), context(0), killed(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), on_runq(-1), cpu_pin(0), runq(0), oncv(0), cv_wakeup(0),
user_fs_(0), state_(EMBRYO) user_fs_(0), state_(EMBRYO)
{ {
...@@ -48,7 +48,6 @@ proc::proc(int npid) : ...@@ -48,7 +48,6 @@ proc::proc(int npid) :
memset(&childq, 0, sizeof(childq)); memset(&childq, 0, sizeof(childq));
memset(&child_next, 0, sizeof(child_next)); memset(&child_next, 0, sizeof(child_next));
memset(ofile, 0, sizeof(ofile));
memset(&runqlink, 0, sizeof(runqlink)); memset(&runqlink, 0, sizeof(runqlink));
memset(&cv_waiters, 0, sizeof(cv_waiters)); memset(&cv_waiters, 0, sizeof(cv_waiters));
memset(&cv_sleep, 0, sizeof(cv_sleep)); memset(&cv_sleep, 0, sizeof(cv_sleep));
...@@ -122,19 +121,13 @@ void ...@@ -122,19 +121,13 @@ void
exit(void) exit(void)
{ {
struct proc *p, *np; struct proc *p, *np;
int fd;
int wakeupinit; int wakeupinit;
if(myproc() == bootproc) if(myproc() == bootproc)
panic("init exiting"); panic("init exiting");
// Close all open files. if (myproc()->ftable)
for(fd = 0; fd < NOFILE; fd++){ myproc()->ftable->decref();
if(myproc()->ofile[fd]){
fileclose(myproc()->ofile[fd]);
myproc()->ofile[fd] = 0;
}
}
// Kernel threads might not have a cwd // Kernel threads might not have a cwd
if (myproc()->cwd != nullptr) { if (myproc()->cwd != nullptr) {
...@@ -246,6 +239,9 @@ inituser(void) ...@@ -246,6 +239,9 @@ inituser(void)
extern u64 _initcode_size; extern u64 _initcode_size;
p = allocproc(); p = allocproc();
p->ftable = new filetable();
if (p->ftable == nullptr)
panic("userinit: new filetable");
bootproc = p; bootproc = p;
if((p->vmap = new vmap()) == 0) if((p->vmap = new vmap()) == 0)
panic("userinit: out of vmaps?"); panic("userinit: out of vmaps?");
...@@ -432,7 +428,7 @@ procdumpall(void) ...@@ -432,7 +428,7 @@ procdumpall(void)
int int
fork(int flags) fork(int flags)
{ {
int i, pid; int pid;
struct proc *np; struct proc *np;
int cow = 1; int cow = 1;
...@@ -464,9 +460,13 @@ fork(int flags) ...@@ -464,9 +460,13 @@ fork(int flags)
// Clear %eax so that fork returns 0 in the child. // Clear %eax so that fork returns 0 in the child.
np->tf->rax = 0; np->tf->rax = 0;
for(i = 0; i < NOFILE; i++) np->ftable = new filetable(*myproc()->ftable);
if(myproc()->ofile[i]) if (np->ftable == nullptr) {
np->ofile[i] = filedup(myproc()->ofile[i]); // XXX(sbw) leaking?
freeproc(np);
return -1;
}
np->cwd = idup(myproc()->cwd); np->cwd = idup(myproc()->cwd);
pid = np->pid; pid = np->pid;
safestrcpy(np->name, myproc()->name, sizeof(myproc()->name)); safestrcpy(np->name, myproc()->name, sizeof(myproc()->name));
......
...@@ -19,7 +19,7 @@ argfd(int fd, struct file **pf) ...@@ -19,7 +19,7 @@ argfd(int fd, struct file **pf)
{ {
struct file *f; struct file *f;
if(fd < 0 || fd >= NOFILE || (f=myproc()->ofile[fd]) == 0) if((f = myproc()->ftable->getfile(fd)) == nullptr)
return -1; return -1;
if(pf) if(pf)
*pf = f; *pf = f;
...@@ -31,15 +31,7 @@ argfd(int fd, struct file **pf) ...@@ -31,15 +31,7 @@ argfd(int fd, struct file **pf)
static int static int
fdalloc(struct file *f) fdalloc(struct file *f)
{ {
int fd; return myproc()->ftable->allocfd(f);
for(fd = 0; fd < NOFILE; fd++){
if(myproc()->ofile[fd] == 0){
myproc()->ofile[fd] = f;
return fd;
}
}
return -1;
} }
long long
...@@ -52,7 +44,7 @@ sys_dup(int ofd) ...@@ -52,7 +44,7 @@ sys_dup(int ofd)
return -1; return -1;
if((fd=fdalloc(f)) < 0) if((fd=fdalloc(f)) < 0)
return -1; return -1;
filedup(f); f->dup();
return fd; return fd;
} }
...@@ -73,7 +65,7 @@ sys_pread(int fd, void *ubuf, size_t count, off_t offset) ...@@ -73,7 +65,7 @@ sys_pread(int fd, void *ubuf, size_t count, off_t offset)
uptr i = (uptr)ubuf; uptr i = (uptr)ubuf;
int r; int r;
if(fd < 0 || fd >= NOFILE || (f=myproc()->ofile[fd]) == 0) if ((f = myproc()->ftable->getfile(fd)) == nullptr)
return -1; return -1;
for(uptr va = PGROUNDDOWN(i); va < i+count; va = va + PGSIZE) for(uptr va = PGROUNDDOWN(i); va < i+count; va = va + PGSIZE)
...@@ -108,8 +100,7 @@ sys_close(int fd) ...@@ -108,8 +100,7 @@ sys_close(int fd)
if(argfd(fd, &f) < 0) if(argfd(fd, &f) < 0)
return -1; return -1;
myproc()->ofile[fd] = 0; myproc()->ftable->close(fd);
fileclose(f);
return 0; return 0;
} }
...@@ -296,8 +287,8 @@ sys_openat(int dirfd, const char *path, int omode) ...@@ -296,8 +287,8 @@ sys_openat(int dirfd, const char *path, int omode)
} else if (dirfd < 0 || dirfd >= NOFILE) { } else if (dirfd < 0 || dirfd >= NOFILE) {
return -1; return -1;
} else { } else {
struct file *fdir = myproc()->ofile[dirfd]; struct file *fdir = myproc()->ftable->getfile(dirfd);
if (fdir->type != file::FD_INODE) if (fdir == nullptr || fdir->type != file::FD_INODE)
return -1; return -1;
cwd = fdir->ip; cwd = fdir->ip;
} }
...@@ -326,9 +317,9 @@ sys_openat(int dirfd, const char *path, int omode) ...@@ -326,9 +317,9 @@ sys_openat(int dirfd, const char *path, int omode)
} }
} }
if((f = filealloc()) == 0 || (fd = fdalloc(f)) < 0){ if((f = new file()) == 0 || (fd = fdalloc(f)) < 0){
if(f) if(f)
fileclose(f); f->close();
iunlockput(ip); iunlockput(ip);
return -1; return -1;
} }
...@@ -424,9 +415,8 @@ sys_pipe(int *fd) ...@@ -424,9 +415,8 @@ sys_pipe(int *fd)
fd0 = -1; fd0 = -1;
if((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0){ if((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0){
if(fd0 >= 0) if(fd0 >= 0)
myproc()->ofile[fd0] = 0; myproc()->ftable->close(fd0);
fileclose(rf); wf->close();
fileclose(wf);
return -1; return -1;
} }
fd[0] = fd0; fd[0] = fd0;
...@@ -437,15 +427,14 @@ sys_pipe(int *fd) ...@@ -437,15 +427,14 @@ sys_pipe(int *fd)
static void static void
freesocket(int fd) freesocket(int fd)
{ {
fileclose(myproc()->ofile[fd]); myproc()->ftable->close(fd);
myproc()->ofile[fd] = 0;
} }
static int static int
getsocket(int fd, struct file **ret) getsocket(int fd, struct file **ret)
{ {
struct file *f; struct file *f;
if (fd < 0 || fd >= NOFILE || (f=myproc()->ofile[fd]) == 0) if ((f = myproc()->ftable->getfile(fd)) == nullptr)
return -1; return -1;
if (f->type != file::FD_SOCKET) if (f->type != file::FD_SOCKET)
return -1; return -1;
...@@ -460,13 +449,13 @@ allocsocket(struct file **rf, int *rfd) ...@@ -460,13 +449,13 @@ allocsocket(struct file **rf, int *rfd)
struct file *f; struct file *f;
int fd; int fd;
f = filealloc(); f = new file();
if (f == nullptr) if (f == nullptr)
return -1; return -1;
fd = fdalloc(f); fd = fdalloc(f);
if (fd < 0) { if (fd < 0) {
fileclose(f); f->close();
return fd; return fd;
} }
...@@ -493,8 +482,7 @@ sys_socket(int domain, int type, int protocol) ...@@ -493,8 +482,7 @@ sys_socket(int domain, int type, int protocol)
s = netsocket(domain, type, protocol); s = netsocket(domain, type, protocol);
if (s < 0) { if (s < 0) {
myproc()->ofile[fd] = 0; myproc()->ftable->close(fd);
fileclose(f);
return s; return s;
} }
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论