shared_mem.cc 4.42 KB
Newer Older
1
2
3
4
5
6
7
/*!
 *  Copyright (c) 2019 by Contributors
 * \file shared_mem.cc
 * \brief Shared memory management.
 */
#ifndef _WIN32
#include <fcntl.h>
8
#include <sys/mman.h>
9
10
#include <unistd.h>
#endif
11
12
#include <dgl/runtime/shared_mem.h>
#include <dmlc/logging.h>
13
14
15
#include <stdio.h>
#include <string.h>

16
17
#include "resource_manager.h"

18
19
20
namespace dgl {
namespace runtime {

21
22
23
24
/*
 * Shared memory is a resource that cannot be cleaned up if the process doesn't
 * exit normally. We'll manage the resource with ResourceManager.
 */
25
class SharedMemoryResource : public Resource {
26
27
28
  std::string name;

 public:
29
  explicit SharedMemoryResource(const std::string &name) { this->name = name; }
30
31

  void Destroy() {
32
    // LOG(INFO) << "remove " << name << " for shared memory";
33
#ifndef _WIN32
34
    shm_unlink(name.c_str());
35
36
37
#else  // _WIN32
    // NOTHING; Windows automatically removes the shared memory object once all
    // handles are unmapped.
38
#endif
39
40
41
  }
};

42
43
SharedMemory::SharedMemory(const std::string &name) {
  this->name = name;
44
  this->own_ = false;
45
#ifndef _WIN32
46
  this->fd_ = -1;
47
48
49
#else
  this->handle_ = nullptr;
#endif
50
51
  this->ptr_ = nullptr;
  this->size_ = 0;
52
53
54
}

SharedMemory::~SharedMemory() {
55
#ifndef _WIN32
56
57
  if (ptr_ && size_ != 0) CHECK(munmap(ptr_, size_) != -1) << strerror(errno);
  if (fd_ != -1) close(fd_);
58
  if (own_) {
59
    // LOG(INFO) << "remove " << name << " for shared memory";
60
61
    if (name != "") {
      shm_unlink(name.c_str());
62
63
      // The resource has been deleted. We don't need to keep track of it any
      // more.
64
65
      DeleteResource(name);
    }
66
  }
67
#else
68
69
70
  if (ptr_) CHECK(UnmapViewOfFile(ptr_)) << "Win32 Error: " << GetLastError();
  if (handle_) CloseHandle(handle_);
    // Windows do not need a separate shm_unlink step.
71
#endif  // _WIN32
72
73
}

74
void *SharedMemory::CreateNew(size_t sz) {
75
#ifndef _WIN32
76
  this->own_ = true;
77

78
79
  // We need to create a shared-memory file.
  // TODO(zhengda) we need to report error if the shared-memory file exists.
80
  int flag = O_RDWR | O_CREAT;
81
82
  fd_ = shm_open(name.c_str(), flag, S_IRUSR | S_IWUSR);
  CHECK_NE(fd_, -1) << "fail to open " << name << ": " << strerror(errno);
83
  // Shared memory cannot be deleted if the process exits abnormally in Linux.
84
  AddResource(name, std::shared_ptr<Resource>(new SharedMemoryResource(name)));
85
  auto res = ftruncate(fd_, sz);
86
87
  CHECK_NE(res, -1) << "Failed to truncate the file. " << strerror(errno);
  ptr_ = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd_, 0);
88
  CHECK_NE(ptr_, MAP_FAILED)
89
90
      << "Failed to map shared memory. mmap failed with error "
      << strerror(errno);
91
92
  this->size_ = sz;
  return ptr_;
93
#else
94
  handle_ = CreateFileMapping(
95
96
      INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE,
      static_cast<DWORD>(sz >> 32), static_cast<DWORD>(sz & 0xFFFFFFFF),
97
      name.c_str());
98
99
  CHECK(handle_ != nullptr)
      << "fail to open " << name << ", Win32 error: " << GetLastError();
100
101
102
103
104
105
106
107
  ptr_ = MapViewOfFile(handle_, FILE_MAP_ALL_ACCESS, 0, 0, sz);
  if (ptr_ == nullptr) {
    LOG(FATAL) << "Memory mapping failed, Win32 error: " << GetLastError();
    CloseHandle(handle_);
    return nullptr;
  }
  this->size_ = sz;
  return ptr_;
108
#endif  // _WIN32
109
110
}

111
void *SharedMemory::Open(size_t sz) {
112
#ifndef _WIN32
113
  int flag = O_RDWR;
114
115
  fd_ = shm_open(name.c_str(), flag, S_IRUSR | S_IWUSR);
  CHECK_NE(fd_, -1) << "fail to open " << name << ": " << strerror(errno);
116
  ptr_ = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd_, 0);
117
  CHECK_NE(ptr_, MAP_FAILED)
118
119
      << "Failed to map shared memory. mmap failed with error "
      << strerror(errno);
120
121
  this->size_ = sz;
  return ptr_;
122
#else
123
  handle_ = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, name.c_str());
124
125
  CHECK(handle_ != nullptr)
      << "fail to open " << name << ", Win32 Error: " << GetLastError();
126
127
128
129
130
131
132
133
  ptr_ = MapViewOfFile(handle_, FILE_MAP_ALL_ACCESS, 0, 0, sz);
  if (ptr_ == nullptr) {
    LOG(FATAL) << "Memory mapping failed, Win32 error: " << GetLastError();
    CloseHandle(handle_);
    return nullptr;
  }
  this->size_ = sz;
  return ptr_;
134
#endif  // _WIN32
135
}
136
137

bool SharedMemory::Exist(const std::string &name) {
138
#ifndef _WIN32
139
140
141
  int fd = shm_open(name.c_str(), O_RDONLY, S_IRUSR | S_IWUSR);
  if (fd >= 0) {
    close(fd);
142
143
144
145
    return true;
  } else {
    return false;
  }
146
#else
147
148
149
150
151
152
153
  HANDLE handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, name.c_str());
  if (handle != nullptr) {
    CloseHandle(handle);
    return true;
  } else {
    return false;
  }
154
#endif  // _WIN32
155
}
156
157
158

}  // namespace runtime
}  // namespace dgl