104 lines · 2.3 KB · C++
RawDownload
//// Dis VM// File: fd_manager.cpp// Author: arr// #include <array>#include <mutex>#include <vector>#include <queue>#include <exceptions.h>#include <vm_memory.h>#include "sys_utils.h" using disvm::runtime::vm_alloc_t;using disvm::runtime::word_t; using disvm::runtime::sys::vm_fd_t; namespace{    std::mutex fd_map_lock;    auto fd_map = std::vector<vm_fd_t *>{};    auto fd_available = std::priority_queue<word_t, std::vector<word_t>, std::greater<word_t>>{};} word_t disvm::runtime::sys::create_fd_record(vm_fd_t * vm_fd){    assert(vm_fd != nullptr);     std::lock_guard<std::mutex> lock{ fd_map_lock };     word_t new_fd;    if (fd_available.empty())    {        new_fd = fd_map.size();        fd_map.push_back(vm_fd);    }    else    {        new_fd = fd_available.top();        fd_available.pop();         assert(fd_map[new_fd] == nullptr && "Reused FD should be null");        fd_map[new_fd] = vm_fd;    }     return new_fd;} bool disvm::runtime::sys::try_update_fd_record(word_t fd, vm_fd_t *vm_fd){    assert(fd != sys::vm_invalid_fd);    assert(vm_fd != nullptr);     std::lock_guard<std::mutex> lock{ fd_map_lock };    if (fd < 0 || static_cast<word_t>(fd_map.size()) <= fd)        return false;     auto vm_fd_curr = fd_map[fd];    auto current_ref = vm_fd_curr->release();    if (current_ref == 0)        delete vm_fd_curr;     fd_map[fd] = vm_fd;    return true;} vm_fd_t * disvm::runtime::sys::fetch_fd_record(word_t fd){    assert(fd != sys::vm_invalid_fd);     std::lock_guard<std::mutex> lock{ fd_map_lock };    if (fd < 0 || static_cast<word_t>(fd_map.size()) <= fd)        return nullptr;     auto vm_fd = fd_map[fd];    if (vm_fd != nullptr)        vm_fd->add_ref();     return vm_fd;} void disvm::runtime::sys::drop_fd_record(word_t fd){    assert(fd != sys::vm_invalid_fd);     std::lock_guard<std::mutex> lock{ fd_map_lock };    if (fd < 0 || static_cast<word_t>(fd_map.size()) <= fd)        return;     assert(fd_map[fd] != nullptr);     // Manual management of file descriptors, since there is an inherent life time    // race amoung the enclosing ADT instances that can have a reference.    auto vm_fd = fd_map[fd];    auto current_ref = vm_fd->release();    if (current_ref == 0)    {        delete vm_fd;        fd_map[fd] = nullptr;        fd_available.push(fd);    }}