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: ...@@ -5,27 +5,24 @@ public:
filetable() : ref_(1) { filetable() : ref_(1) {
for(int fd = 0; fd < NOFILE; fd++) for(int fd = 0; fd < NOFILE; fd++)
ofile_[fd] = nullptr; ofile_[fd] = nullptr;
initlock(&lock_, "filetable", 0);
} }
filetable(const filetable &f) : ref_(1) { filetable(const filetable &f) : ref_(1) {
for(int fd = 0; fd < NOFILE; fd++) { for(int fd = 0; fd < NOFILE; fd++) {
if (f.ofile_[fd]) if (f.ofile_[fd])
ofile_[fd] = f.ofile_[fd]->dup(); ofile_[fd].store(f.ofile_[fd].load()->dup());
else else
ofile_[fd] = nullptr; ofile_[fd] = nullptr;
} }
initlock(&lock_, "filetable", 0);
} }
~filetable() { ~filetable() {
for(int fd = 0; fd < NOFILE; fd++){ for(int fd = 0; fd < NOFILE; fd++){
if (ofile_[fd]){ if (ofile_[fd]){
ofile_[fd]->dec(); ofile_[fd].load()->dec();
ofile_[fd] = 0; ofile_[fd] = nullptr;
} }
} }
destroylock(&lock_);
} }
bool getfile(int fd, sref<file> *sf) { bool getfile(int fd, sref<file> *sf) {
...@@ -40,15 +37,9 @@ public: ...@@ -40,15 +37,9 @@ public:
} }
int allocfd(struct file *f) { int allocfd(struct file *f) {
acquire(&lock_); for (int fd = 0; fd < NOFILE; fd++)
for (int fd = 0; fd < NOFILE; fd++) { if (ofile_[fd] == nullptr && cmpxch(&ofile_[fd], (file*)nullptr, f))
if (ofile_[fd] == nullptr){
ofile_[fd] = f;
release(&lock_);
return fd; return fd;
}
}
release(&lock_);
cprintf("filetable::allocfd: failed\n"); cprintf("filetable::allocfd: failed\n");
return -1; return -1;
} }
...@@ -56,15 +47,13 @@ public: ...@@ -56,15 +47,13 @@ public:
void close(int fd) { void close(int fd) {
// XXX(sbw) if f->ref_ > 1 the kernel will not actually close // XXX(sbw) if f->ref_ > 1 the kernel will not actually close
// the file when this function returns (i.e. sys_close can return // the file when this function returns (i.e. sys_close can return
// while the file/pipe/socket is still open). Maybe we should clear // while the file/pipe/socket is still open).
// ofile_[fd], wait until f.ref_ == 1, f->dec(), and then return.
acquire(&lock_); file* f = ofile_[fd].exchange(nullptr);
struct file *f = ofile_[fd]; if (f != nullptr)
ofile_[fd] = nullptr;
release(&lock_);
if (f)
f->dec(); f->dec();
else
cprintf("filetable::close: bad fd %u\n", fd);
} }
void decref() { void decref() {
...@@ -79,7 +68,6 @@ public: ...@@ -79,7 +68,6 @@ public:
NEW_DELETE_OPS(filetable) NEW_DELETE_OPS(filetable)
private: private:
struct file *ofile_[NOFILE]; std::atomic<file*> ofile_[NOFILE];
std::atomic<u64> ref_; std::atomic<u64> ref_;
struct spinlock lock_;
}; };
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论