]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/ipc/mem/Segment.cc
4 * DEBUG: section 54 Interprocess Communication
9 #include "base/TextException.h"
10 #include "compat/shm.h"
11 #include "ipc/mem/Segment.h"
20 Ipc::Mem::Segment::reserve(size_t chunkSize
)
23 // check for overflows
24 // chunkSize >= 0 may result in warnings on systems where off_t is unsigned
25 assert(!chunkSize
|| static_cast<off_t
>(chunkSize
) > 0);
26 assert(static_cast<off_t
>(chunkSize
) <= theSize
);
27 assert(theReserved
<= theSize
- static_cast<off_t
>(chunkSize
));
28 void *result
= reinterpret_cast<char*>(theMem
) + theReserved
;
29 theReserved
+= chunkSize
;
35 Ipc::Mem::Segment::Segment(const char *const id
):
36 theFD(-1), theName(GenerateName(id
)), theMem(NULL
),
37 theSize(0), theReserved(0), doUnlink(false)
41 Ipc::Mem::Segment::~Segment()
45 if (close(theFD
) != 0)
46 debugs(54, 5, HERE
<< "close " << theName
<< ": " << xstrerror());
52 // fake Ipc::Mem::Segment::Enabled (!HAVE_SHM) is more selective
54 Ipc::Mem::Segment::Enabled()
60 Ipc::Mem::Segment::create(const off_t aSize
)
65 theFD
= shm_open(theName
.termedBuf(), O_CREAT
| O_RDWR
| O_TRUNC
,
68 debugs(54, 5, HERE
<< "shm_open " << theName
<< ": " << xstrerror());
69 fatal("Ipc::Mem::Segment::create failed to shm_open");
72 if (ftruncate(theFD
, aSize
)) {
73 debugs(54, 5, HERE
<< "ftruncate " << theName
<< ": " << xstrerror());
74 fatal("Ipc::Mem::Segment::create failed to ftruncate");
77 assert(statSize("Ipc::Mem::Segment::create") == aSize
); // paranoid
83 debugs(54, 3, HERE
<< "created " << theName
<< " segment: " << theSize
);
89 Ipc::Mem::Segment::open()
93 theFD
= shm_open(theName
.termedBuf(), O_RDWR
, 0);
95 debugs(54, 5, HERE
<< "shm_open " << theName
<< ": " << xstrerror());
96 String s
= "Ipc::Mem::Segment::open failed to shm_open ";
101 theSize
= statSize("Ipc::Mem::Segment::open");
103 debugs(54, 3, HERE
<< "opened " << theName
<< " segment: " << theSize
);
108 /// Map the shared memory segment to the process memory space.
110 Ipc::Mem::Segment::attach()
115 // mmap() accepts size_t for the size; we give it off_t which might
116 // be bigger; assert overflows until we support multiple mmap()s?
117 assert(theSize
== static_cast<off_t
>(static_cast<size_t>(theSize
)));
120 mmap(NULL
, theSize
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, theFD
, 0);
121 if (p
== MAP_FAILED
) {
122 debugs(54, 5, HERE
<< "mmap " << theName
<< ": " << xstrerror());
123 fatal("Ipc::Mem::Segment::attach failed to mmap");
128 /// Unmap the shared memory segment from the process memory space.
130 Ipc::Mem::Segment::detach()
135 if (munmap(theMem
, theSize
)) {
136 debugs(54, 5, HERE
<< "munmap " << theName
<< ": " << xstrerror());
137 fatal("Ipc::Mem::Segment::detach failed to munmap");
143 Ipc::Mem::Segment::unlink()
145 if (shm_unlink(theName
.termedBuf()) != 0)
146 debugs(54, 5, HERE
<< "shm_unlink(" << theName
<< "): " << xstrerror());
148 debugs(54, 3, HERE
<< "unlinked " << theName
<< " segment");
151 /// determines the size of the underlying "file"
153 Ipc::Mem::Segment::statSize(const char *context
) const
158 memset(&s
, 0, sizeof(s
));
160 if (fstat(theFD
, &s
) != 0) {
161 debugs(54, 5, HERE
<< "fstat " << theName
<< ": " << xstrerror());
163 s
.append("failed to fstat(2) ");
165 fatal(s
.termedBuf());
171 /// Generate name for shared memory segment. Replaces all slashes with dots.
173 Ipc::Mem::Segment::GenerateName(const char *id
)
175 String
name("/squid-");
176 for (const char *slash
= strchr(id
, '/'); slash
; slash
= strchr(id
, '/')) {
178 name
.append(id
, slash
- id
);
191 typedef std::map
<String
, Ipc::Mem::Segment
*> SegmentMap
;
192 static SegmentMap Segments
;
194 Ipc::Mem::Segment::Segment(const char *const id
):
195 theName(id
), theMem(NULL
), theSize(0), theReserved(0), doUnlink(false)
199 Ipc::Mem::Segment::~Segment()
202 delete [] static_cast<char *>(theMem
);
203 debugs(54, 3, HERE
<< "deleted " << theName
<< " segment");
208 Ipc::Mem::Segment::Enabled()
210 return !InDaemonMode() || (!UsingSmp() && IamWorkerProcess());
214 Ipc::Mem::Segment::create(const off_t aSize
)
218 checkSupport("Fake segment creation");
220 const bool inserted
= Segments
.insert(std::make_pair(theName
, this)).second
;
222 fatalf("Duplicate fake segment creation: %s", theName
.termedBuf());
224 theMem
= new char[aSize
];
228 debugs(54, 3, HERE
<< "created " << theName
<< " fake segment: " << theSize
);
232 Ipc::Mem::Segment::open()
235 checkSupport("Fake segment open");
237 const SegmentMap::const_iterator i
= Segments
.find(theName
);
238 if (i
== Segments
.end())
239 fatalf("Fake segment not found: %s", theName
.termedBuf());
241 const Segment
&segment
= *i
->second
;
242 theMem
= segment
.theMem
;
243 theSize
= segment
.theSize
;
245 debugs(54, 3, HERE
<< "opened " << theName
<< " fake segment: " << theSize
);
249 Ipc::Mem::Segment::checkSupport(const char *const context
)
252 debugs(54, 5, HERE
<< "True shared memory segments are not supported. "
253 "Cannot fake shared segments in SMP config.");
254 fatalf("%s failed", context
);
261 Ipc::Mem::RegisteredRunner::run(const RunnerRegistry
&r
)
263 // If Squid is built with real segments, we create() real segments
264 // in the master process only. Otherwise, we create() fake
265 // segments in each worker process. We assume that only workers
266 // need and can work with fake segments.
268 if (IamMasterProcess())
270 if (IamWorkerProcess())
274 // we assume that master process does not need shared segments
275 // unless it is also a worker
276 if (!InDaemonMode() || !IamMasterProcess())