Optional<Reflector> Reflector::create(size_t size) { static const char *path = "reflector.shm"; FileDescriptor fd; void *lower = nullptr; void *upper = nullptr; void *both = nullptr; int sts = -1; if ((size == 0) || (size % 4096)) { return Optional<Reflector>(); } fd.reset(shm_open(path, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR)); if (fd.empty()) { return Optional<Reflector>(); } sts = shm_unlink(path); if (sts < 0) { return Optional<Reflector>(); } sts = ftruncate(fd.get(), size); if (sts < 0) { return Optional<Reflector>(); } both = mmap(nullptr, size * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd.get(), 0); if (both == MAP_FAILED) { return Optional<Reflector>(); } lower = mremap(both, size * 2, size, 0); if (lower == MAP_FAILED) { sts = munmap(both, size * 2); assert(sts >= 0); return Optional<Reflector>(); } else if (lower != both) { sts = munmap(lower, size); assert(sts); return Optional<Reflector>(); } upper = static_cast<uint8_t*>(lower) + size; upper = mmap(upper, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd.get(), 0); if (upper == MAP_FAILED) { sts = munmap(lower, size); assert(sts >= 0); return Optional<Reflector>(); } return Optional<Reflector>(Reflector(std::move(fd), lower, size)); }
MMap::MMap (const FileDescriptor& fd, bool const sequential) : size (fd.size()), ptr (mmap (NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_NORESERVE, fd.get(), 0)), mapped (ptr != GU_MAP_FAILED) { if (!mapped) { gu_throw_error(errno) << "mmap() on '" << fd.name() << "' failed"; } #if !defined(__sun__) && !defined(__APPLE__) && !defined(__FreeBSD__) /* Solaris, Darwin, and FreeBSD do not have MADV_DONTFORK */ if (posix_madvise (ptr, size, MADV_DONTFORK)) { int const err(errno); log_warn << "Failed to set MADV_DONTFORK on " << fd.name() << ": " << err << " (" << strerror(err) << ")"; } #endif /* benefits are questionable */ if (sequential && posix_madvise (ptr, size, MADV_SEQUENTIAL)) { int const err(errno); log_warn << "Failed to set MADV_SEQUENTIAL on " << fd.name() << ": " << err << " (" << strerror(err) << ")"; } log_debug << "Memory mapped: " << ptr << " (" << size << " bytes)"; }