Itoyori  v0.0.1
physical_mem.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <sys/mman.h>
4 #include <sys/stat.h>
5 #include <fcntl.h>
6 #include <unistd.h>
7 #include <cstdio>
8 #include <cstdlib>
9 #include <cstdint>
10 #include <string>
11 #include <sstream>
12 
13 #include "ityr/common/util.hpp"
15 
16 namespace ityr::common {
17 
18 class physical_mem {
19 public:
21  physical_mem(const std::string& shm_name, std::size_t size, bool own)
22  : shm_name_(shm_name), size_(size), own_(own), fd_(init_shmem_fd()) {}
23 
24  ~physical_mem() { destroy(); }
25 
26  physical_mem(const physical_mem&) = delete;
27  physical_mem& operator=(const physical_mem&) = delete;
28 
30  : shm_name_(std::move(pm.shm_name_)), size_(pm.size_), own_(pm.own_), fd_(pm.fd_) { pm.fd_ = -1; }
32  destroy();
33  shm_name_ = std::move(pm.shm_name_);
34  size_ = pm.size_;
35  own_ = pm.own_;
36  fd_ = pm.fd_;
37  pm.fd_ = -1;
38  return *this;
39  }
40 
41  std::size_t size() const { return size_; }
42 
43  void map_to_vm(void* addr, std::size_t size, std::size_t offset) const {
44  ITYR_CHECK(addr != nullptr);
45  ITYR_CHECK(reinterpret_cast<uintptr_t>(addr) % get_page_size() == 0);
46  ITYR_CHECK(offset % get_page_size() == 0);
47  ITYR_CHECK(offset + size <= size_);
48  // MAP_FIXED_NOREPLACE is never set here, as this map method is used to
49  // map to physical memory a given virtual address, which is already reserved by mmap.
50  void* ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd_, offset);
51  if (ret == MAP_FAILED) {
52  perror("mmap");
53  die("[ityr::common::physical_mem] mmap(%p, %lu, ...) failed", addr, size);
54  }
55  }
56 
57 private:
58  void destroy() {
59  if (fd_ != -1) {
60  close(fd_);
61  if (own_ && shm_unlink(shm_name_.c_str()) == -1) {
62  perror("shm_unlink");
63  die("[ityr::common::physical_mem] shm_unlink() failed");
64  }
65  }
66  }
67 
68  int init_shmem_fd() const {
69  int oflag = O_RDWR;
70  if (own_) oflag |= O_CREAT | O_TRUNC;
71 
72  int fd = shm_open(shm_name_.c_str(), oflag, S_IRUSR | S_IWUSR);
73  if (fd == -1) {
74  perror("shm_open");
75  die("[ityr::common::physical_mem] shm_open() failed");
76  }
77 
78  if (own_ && ftruncate(fd, size_) == -1) {
79  perror("ftruncate");
80  die("[ityr::common::physical_mem] ftruncate(%d, %lu) failed", fd, size_);
81  }
82 
83  return fd;
84  }
85 
86  std::string shm_name_;
87  std::size_t size_;
88  bool own_;
89  int fd_ = -1;
90 };
91 
92 ITYR_TEST_CASE("[ityr::common::physical_mem] map physical memory to two different virtual addresses") {
93  runtime_options opts;
94  singleton_initializer<topology::instance> topo;
95 
96  std::size_t pagesize = get_page_size();
97 
98  std::stringstream ss;
99  ss << "/ityr_test_" << topology::my_rank();
100 
101  std::size_t alloc_size = 16 * pagesize;
102 
103  physical_mem pm(ss.str(), alloc_size, true);
104 
105  virtual_mem vm1(alloc_size);
106  virtual_mem vm2(alloc_size);
107  ITYR_CHECK(vm1.addr() != vm2.addr());
108 
109  int* b1;
110  int* b2;
111 
112  ITYR_SUBCASE("map whole memory") {
113  b1 = reinterpret_cast<int*>(vm1.addr());
114  b2 = reinterpret_cast<int*>(vm2.addr());
115  pm.map_to_vm(b1, alloc_size, 0);
116  pm.map_to_vm(b2, alloc_size, 0);
117  }
118 
119  ITYR_SUBCASE("map partial memory") {
120  std::size_t offset = 3 * pagesize;
121  b1 = reinterpret_cast<int*>(reinterpret_cast<std::byte*>(vm1.addr()) + offset);
122  b2 = reinterpret_cast<int*>(reinterpret_cast<std::byte*>(vm2.addr()) + offset);
123  pm.map_to_vm(b1, pagesize, offset);
124  pm.map_to_vm(b2, pagesize, offset);
125  }
126 
127  ITYR_CHECK(b1 != b2);
128  ITYR_CHECK(b1[0] == 0);
129  ITYR_CHECK(b2[0] == 0);
130  b1[0] = 417;
131  ITYR_CHECK(b1[0] == 417);
132  ITYR_CHECK(b2[0] == 417);
133 }
134 
135 }
Definition: physical_mem.hpp:18
physical_mem()
Definition: physical_mem.hpp:20
physical_mem & operator=(const physical_mem &)=delete
physical_mem(physical_mem &&pm)
Definition: physical_mem.hpp:29
physical_mem & operator=(physical_mem &&pm)
Definition: physical_mem.hpp:31
physical_mem(const physical_mem &)=delete
physical_mem(const std::string &shm_name, std::size_t size, bool own)
Definition: physical_mem.hpp:21
std::size_t size() const
Definition: physical_mem.hpp:41
~physical_mem()
Definition: physical_mem.hpp:24
void map_to_vm(void *addr, std::size_t size, std::size_t offset) const
Definition: physical_mem.hpp:43
#define ITYR_SUBCASE(name)
Definition: util.hpp:41
#define ITYR_CHECK(cond)
Definition: util.hpp:48
rank_t my_rank()
Definition: topology.hpp:207
Definition: allocator.hpp:16
std::size_t get_page_size()
Definition: util.hpp:170
ForwardIteratorD move(const ExecutionPolicy &policy, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIteratorD first_d)
Move a range to another.
Definition: parallel_loop.hpp:934