27 #include <sys/types.h>
48 *
this = std::move(other);
52 meta_path_ = other.meta_path_;
54 numa_node_ = other.numa_node_;
55 shmid_ = other.shmid_;
56 shmkey_ = other.shmkey_;
57 owner_pid_ = other.owner_pid_;
58 block_ = other.block_;
59 other.block_ =
nullptr;
64 return owner_pid_ != 0 && owner_pid_ == ::getpid();
68 const std::string& meta_path,
74 if (size % (1ULL << 21) != 0) {
75 size = ((size >> 21) + 1ULL) << 21;
81 std::string msg = std::string(
"Shared memory meta file already exists:") + meta_path;
84 std::ofstream file(meta_path, std::ofstream::binary);
85 if (!file.is_open()) {
86 std::string msg = std::string(
"Failed to create shared memory meta file:") + meta_path;
93 pid_t the_pid = ::getpid();
95 key_t the_key = (key64 >> 32) ^ key64;
99 std::string msg = std::string(
"Dubious shmkey");
104 file.write(reinterpret_cast<char*>(&size),
sizeof(size));
105 file.write(reinterpret_cast<char*>(&numa_node),
sizeof(numa_node));
106 file.write(reinterpret_cast<char*>(&the_key),
sizeof(key_t));
111 numa_node_ = numa_node;
112 owner_pid_ = the_pid;
113 meta_path_ = meta_path;
118 if (RUNNING_ON_VALGRIND) {
119 use_hugepages =
false;
131 IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | (use_hugepages ? SHM_HUGETLB : 0));
133 std::string msg = std::string(
"shmget() failed! size=") + std::to_string(size_)
134 + std::string(
", os_error=") +
assorted::os_error() + std::string(
", meta_path=") + meta_path;
138 block_ =
reinterpret_cast<char*
>(::shmat(shmid_,
nullptr, 0));
140 if (block_ == reinterpret_cast<void*>(-1)) {
141 ::shmctl(shmid_, IPC_RMID,
nullptr);
143 std::stringstream msg;
146 std::string str = msg.str();
150 std::memset(block_, 0, size_);
160 std::cerr <<
"Shared memory meta file does not exist:" << meta_path << std::endl;
164 std::ifstream file(meta_path, std::ifstream::binary);
165 if (!file.is_open()) {
166 std::cerr <<
"Failed to open shared memory meta file:" << meta_path << std::endl;
169 uint64_t shared_size = 0;
172 file.read(reinterpret_cast<char*>(&shared_size),
sizeof(shared_size));
173 file.read(reinterpret_cast<char*>(&numa_node),
sizeof(numa_node));
174 file.read(reinterpret_cast<char*>(&the_key),
sizeof(key_t));
178 if (shared_size < (1ULL << 21)) {
179 std::cerr <<
"Failed to read size of shared memory from meta file:" << meta_path
180 <<
". It looks like:" << shared_size << std::endl;
184 std::cerr <<
"Failed to read shmkey from meta file:" << meta_path << std::endl;
189 numa_node_ = numa_node;
190 meta_path_ = meta_path;
194 if (RUNNING_ON_VALGRIND) {
195 use_hugepages =
false;
197 shmid_ = ::shmget(shmkey_, size_, use_hugepages ? SHM_HUGETLB : 0);
199 std::cerr <<
"shmget() attach failed! size=" << size_ <<
", error=" <<
assorted::os_error()
204 block_ =
reinterpret_cast<char*
>(::shmat(shmid_,
nullptr, 0));
205 if (block_ == reinterpret_cast<void*>(-1)) {
207 std::cerr <<
"shmat attach failed!" << *
this <<
", error=" <<
assorted::os_error() << std::endl;
214 if (block_ !=
nullptr && shmid_ != 0) {
218 ::shmctl(shmid_, IPC_RMID,
nullptr);
223 if (block_ !=
nullptr) {
231 int dt_ret = ::shmdt(block_);
233 std::cerr <<
"shmdt() failed." << *
this <<
", error=" <<
assorted::os_error() << std::endl;
246 o <<
"<SharedMemory>";
248 o <<
"<size>" << v.
get_size() <<
"</size>";
249 o <<
"<owned>" << v.
is_owned() <<
"</owned>";
252 o <<
"<shmid>" << v.
get_shmid() <<
"</shmid>";
253 o <<
"<shmkey>" << v.
get_shmkey() <<
"</shmkey>";
254 o <<
"<address>" <<
reinterpret_cast<uintptr_t
>(v.
get_block()) <<
"</address>";
255 o <<
"</SharedMemory>";
bool remove(const Path &p)
Deletes a regular file or an empty directory.
bool is_owned() const
Returns if this process owns this memory and is responsible to delete it.
Automatically sets and resets numa_set_preferred().
key_t get_shmkey() const
Returns the key of this shared memory.
Root package of FOEDUS (Fast Optimistic Engine for Data Unification Services).
char * get_block() const
Returns the memory block.
Brings error stacktrace information as return value of functions.
Definitions of IDs in this package and a few related constant values.
Represents memory shared between processes.
int get_numa_node() const
Where the physical memory is allocated.
Analogue of boost::filesystem::path.
SharedMemory() noexcept
Empty constructor which allocates nothing.
uint64_t get_rdtsc()
Returns the current CPU cycle via x86 RDTSC.
bool exists(const Path &p)
Returns if the file exists.
std::ostream & operator<<(std::ostream &o, const AlignedMemory &v)
void attach(const std::string &meta_path, bool use_hugepages)
Attach an already-allocated shared memory so that this object points to the memory.
std::string os_error()
Thread-safe strerror(errno).
const ErrorStack kRetOk
Normal return value for no-error case.
const std::string & get_meta_path() const
Returns the path of the meta file.
Implements an RDTSC (Real-time time stamp counter) wait to emulate latency on slower devices...
int get_shmid() const
Returns the ID of this shared memory.
#define ERROR_STACK_MSG(e, m)
Overload of ERROR_STACK(e) to receive a custom error message.
0x0C01 : "SOC : Failed to allocate a shared memory. This is usually caused by a misconfigured envi...
void mark_for_release()
Marks the shared memory as being removed so that it will be reclaimed when all processes detach it...
SharedMemory & operator=(const SharedMemory &other)=delete
ErrorStack alloc(const std::string &meta_path, uint64_t size, int numa_node, bool use_hugepages)
Newly allocate a shared memory of given size on given NUMA node.
pid_t get_owner_pid() const
If non-zero, it means the ID of the process that allocated the shared memory.
uint64_t get_size() const
Returns the byte size of the memory block.
void release_block()
Releases the memory block IF this process has an ownership.