gem5 v24.0.0.0
Loading...
Searching...
No Matches
shared_memory_server.cc
Go to the documentation of this file.
1/*
2 * Copyright 2022 Google, Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met: redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer;
8 * redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution;
11 * neither the name of the copyright holders nor the names of its
12 * contributors may be used to endorse or promote products derived from
13 * this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
29
30#include <arpa/inet.h>
31#include <fcntl.h>
32#include <poll.h>
33#include <sys/mman.h>
34#include <sys/socket.h>
35#include <sys/stat.h>
36#include <sys/types.h>
37#include <unistd.h>
38
39#include <algorithm>
40#include <cerrno>
41#include <cstring>
42
43// check if filesystem library is available
44#if defined(__cpp_lib_filesystem) || __has_include(<filesystem>)
45 #include <filesystem>
46#else
47 // This is only reachable if we're using GCC 7 or clang versions 6
48 // through 10 (note: gem5 does not support GCC versions older than
49 // GCC 7 or clang versions older than clang 6.0 as they do not
50 // support the C++17 standard).
51 // If we're using GCC 7 or clang versions 6 through 10, we need to use
52 // <experimental/filesystem>.
53 #include <experimental/filesystem>
54 namespace std {
55 namespace filesystem = experimental::filesystem;
56 }
57#endif
58
59#include "base/logging.hh"
60#include "base/output.hh"
62
63namespace gem5
64{
65namespace memory
66{
67
68namespace
69{
70
72buildListenSocket(const std::string &path, const std::string &name)
73{
74 fatal_if(path.empty(), "%s: Empty socket path", name);
75 if (path[0] == '@')
76 return listenSocketUnixAbstractConfig(path.substr(1)).build(name);
77
78 std::filesystem::path p(path);
80 p.parent_path(), p.filename()).build(name);
81}
82
83} // anonymous namespace
84
85SharedMemoryServer::SharedMemoryServer(const SharedMemoryServerParams& params)
86 : SimObject(params),
87 system(params.system),
88 listener(buildListenSocket(params.server_path, name()))
89{
90 fatal_if(system == nullptr, "Requires a system to share memory from!");
91 listener->listen();
92
93 listenSocketEvent.reset(new ListenSocketEvent(listener->getfd(), this));
95 inform("%s: listening at %s", name(), *listener);
96}
97
99
101 int fd, SharedMemoryServer* shm_server)
102 : PollEvent(fd, POLLIN), shmServer(shm_server),
103 eventName(shmServer->name() + ".fd" + std::to_string(fd))
104{
105}
106
107const std::string&
109{
110 return eventName;
111}
112
113bool
115{
116 char* char_buffer = reinterpret_cast<char*>(buffer);
117 for (size_t offset = 0; offset < size;) {
118 ssize_t retv = recv(pfd.fd, char_buffer + offset, size - offset, 0);
119 if (retv >= 0) {
120 offset += retv;
121 } else if (errno != EINTR) {
122 warn("%s: recv failed: %s", name(), strerror(errno));
123 return false;
124 }
125 }
126 return true;
127}
128
129void
131{
132 int cli_fd = shmServer->listener->accept();
133 inform("%s: accept new connection %d", name(), cli_fd);
134 shmServer->clientSocketEvents[cli_fd].reset(
135 new ClientSocketEvent(cli_fd, shmServer));
136 pollQueue.schedule(shmServer->clientSocketEvents[cli_fd].get());
137}
138
139void
141{
142 do {
143 // Ensure the connection is not closed nor broken.
144 if (revents & (POLLHUP | POLLERR | POLLNVAL)) {
145 break;
146 }
147
148 // Receive a request packet. We ignore the endianness as unix socket
149 // only allows communication on the same system anyway.
150 RequestType req_type;
151 struct
152 {
153 uint64_t start;
154 uint64_t end;
155 } request;
156 if (!tryReadAll(&req_type, sizeof(req_type))) {
157 break;
158 }
159 if (req_type != RequestType::kGetPhysRange) {
160 warn("%s: receive unknown request: %d", name(),
161 static_cast<int>(req_type));
162 break;
163 }
164 if (!tryReadAll(&request, sizeof(request))) {
165 break;
166 }
167 AddrRange range(request.start, request.end);
168 inform("%s: receive request: %s", name(), range.to_string());
169
170 // Identify the backing store.
171 const auto& stores = shmServer->system->getPhysMem().getBackingStore();
172 auto it = std::find_if(
173 stores.begin(), stores.end(), [&](const BackingStoreEntry& entry) {
174 return entry.shmFd >= 0 && range.isSubset(entry.range);
175 });
176 if (it == stores.end()) {
177 warn("%s: cannot find backing store for %s", name(),
178 range.to_string());
179 break;
180 }
181 inform("%s: find shared backing store for %s at %s, shm=%d:%lld",
182 name(), range.to_string(), it->range.to_string(), it->shmFd,
183 (unsigned long long)it->shmOffset);
184
185 // Populate response message.
186 // mmap fd @ offset <===> [start, end] in simulated phys mem.
187 msghdr msg = {};
188 // Setup iovec for fields other than fd. We ignore the endianness as
189 // unix socket only allows communication on the same system anyway.
190 struct
191 {
192 off_t offset;
193 } response;
194 // (offset of the request range in shared memory) =
195 // (offset of the full range in shared memory) +
196 // (offset of the request range in the full range)
197 response.offset = it->shmOffset + (range.start() - it->range.start());
198 iovec ios = {.iov_base = &response, .iov_len = sizeof(response)};
199 msg.msg_iov = &ios;
200 msg.msg_iovlen = 1;
201 // Setup fd as an ancillary data.
202 union
203 {
204 char buf[CMSG_SPACE(sizeof(it->shmFd))];
205 struct cmsghdr align;
206 } cmsgs;
207 msg.msg_control = cmsgs.buf;
208 msg.msg_controllen = sizeof(cmsgs.buf);
209 cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
210 cmsg->cmsg_level = SOL_SOCKET;
211 cmsg->cmsg_type = SCM_RIGHTS;
212 cmsg->cmsg_len = CMSG_LEN(sizeof(it->shmFd));
213 memcpy(CMSG_DATA(cmsg), &it->shmFd, sizeof(it->shmFd));
214 // Send the response.
215 int retv = sendmsg(pfd.fd, &msg, 0);
216 if (retv < 0) {
217 warn("%s: sendmsg failed: %s", name(), strerror(errno));
218 break;
219 }
220 if (retv != sizeof(response)) {
221 warn("%s: failed to send all response at once", name());
222 break;
223 }
224
225 // Request done.
226 inform("%s: request done", name());
227 return;
228 } while (false);
229
230 // If we ever reach here, our client either close the connection or is
231 // somehow broken. We'll just close the connection and move on.
232 inform("%s: closing connection", name());
233 close(pfd.fd);
234 shmServer->clientSocketEvents.erase(pfd.fd);
235}
236
237} // namespace memory
238} // namespace gem5
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
Definition addr_range.hh:82
ListenSocketPtr build(const std::string &name) const
Definition socket.hh:123
virtual std::string name() const
Definition named.hh:47
Abstract superclass for simulation objects.
A single entry for the backing store.
Definition physical.hh:65
BaseShmPollEvent(int fd, SharedMemoryServer *shm_server)
SharedMemoryServer(const SharedMemoryServerParams &params)
std::unique_ptr< ListenSocketEvent > listenSocketEvent
Addr start() const
Get the start address of the range.
std::string to_string() const
Get a string representation of the range.
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition logging.hh:236
PollQueue pollQueue
Definition pollevent.cc:55
void schedule(PollEvent *event)
Definition pollevent.cc:159
#define warn(...)
Definition logging.hh:256
#define inform(...)
Definition logging.hh:257
Bitfield< 14, 12 > fd
Definition types.hh:150
Bitfield< 23, 0 > offset
Definition types.hh:144
Bitfield< 0 > p
Bitfield< 15 > system
Definition misc.hh:1032
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
ListenSocketConfig listenSocketUnixAbstractConfig(std::string path)
Definition socket.cc:400
ListenSocketConfig listenSocketUnixFileConfig(std::string dir, std::string fname)
Definition socket.cc:370
std::unique_ptr< ListenSocket > ListenSocketPtr
Definition socket.hh:112
Overload hash function for BasicBlockRange type.
Definition binary32.hh:81
Definition mem.h:38
const std::string & name()
Definition trace.cc:48

Generated on Tue Jun 18 2024 16:24:05 for gem5 by doxygen 1.11.0