Make all the filetable member functions lock free.

..allocfd might still cause bottlenecks as threads race to allocate FD slots..
上级 85235464
......@@ -5,27 +5,24 @@ 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();
ofile_[fd].store(f.ofile_[fd].load()->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;
ofile_[fd].load()->dec();
ofile_[fd] = nullptr;
}
}
destroylock(&lock_);
}
bool getfile(int fd, sref<file> *sf) {
......@@ -40,15 +37,9 @@ public:
}
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;
}
......@@ -56,15 +47,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.
acquire(&lock_);
struct file *f = ofile_[fd];
ofile_[fd] = nullptr;
release(&lock_);
if (f)
// while the file/pipe/socket is still open).
file* f = ofile_[fd].exchange(nullptr);
if (f != nullptr)
f->dec();
else
cprintf("filetable::close: bad fd %u\n", fd);
}
void decref() {
......@@ -79,7 +68,6 @@ public:
NEW_DELETE_OPS(filetable)
private:
struct file *ofile_[NOFILE];
std::atomic<file*> ofile_[NOFILE];
std::atomic<u64> ref_;
struct spinlock lock_;
};
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论