diff --git a/util/pcie-defs.h b/util/pcie-defs.h index 04c9ebd..ce114ba 100644 --- a/util/pcie-defs.h +++ b/util/pcie-defs.h @@ -31,6 +31,9 @@ struct pcie_bars { pthread_mutex_t locks[NUM_LOCKS]; FILE *fserport; + + /* fd holding OFD-owned lock for BAR resource files */ + int fd_lock; }; #endif diff --git a/util/pcie-open.cc b/util/pcie-open.cc index 744db2a..e56813e 100644 --- a/util/pcie-open.cc +++ b/util/pcie-open.cc @@ -28,6 +28,27 @@ void configure_mutexes(struct pcie_bars &bars) throw std::runtime_error("couldn't initialize mutex"); } +void lock_file(int fd) +{ + struct flock arg = { + /* exclusive lock */ + .l_type = F_WRLCK, + /* lock the whole file */ + .l_whence = SEEK_SET, + .l_start = 0, + .l_len = 0, + /* application is resposible for setting to 0 */ + .l_pid = 0, + }; + if (fcntl(fd, F_OFD_SETLK, &arg) < 0) { + /* allow program to work when F_OFD_SETLK isn't implemented */ + if (errno == EINVAL) + fputs("WARNING: F_OFD_SETLK not supported!\n", stderr); + else + throw std::runtime_error(std::string("couldn't lock file")); + } +} + } void dev_open_slot(struct pcie_bars &bars, int slot) @@ -69,6 +90,12 @@ void dev_open(struct pcie_bars &bars, const char *pci_address) if (fd < 0) throw std::runtime_error(std::string("couldn't open resource file: ") + pci_address); } + + if (bar == 0) { + lock_file(fd); + bars.fd_lock = fd; + } + struct stat st; fstat(fd, &st); bars.sizes[i] = st.st_size; @@ -130,6 +157,8 @@ void dev_close(struct pcie_bars &bars) return; } + close(bars.fd_lock); + auto unmap = [&bars](auto &p, unsigned i) { munmap(const_cast(p), bars.sizes[i]); p = 0;