]> git.ipfire.org Git - thirdparty/squid.git/blob - src/ipc/mem/Segment.cc
Added reserve() method to allow nested classes or similar related users of
[thirdparty/squid.git] / src / ipc / mem / Segment.cc
1 /*
2 * $Id$
3 *
4 * DEBUG: section 54 Interprocess Communication
5 *
6 */
7
8 #include "config.h"
9
10 #include "ipc/mem/Segment.h"
11 #include "protos.h"
12
13 #include <fcntl.h>
14 #include <sys/mman.h>
15 #include <sys/stat.h>
16 #include <sys/types.h>
17 #include <unistd.h>
18
19 Ipc::Mem::Segment::Segment(const char *const id):
20 theName(GenerateName(id)), theFD(-1), theMem(NULL),
21 theSize(0), theReserved(0)
22 {
23 }
24
25 Ipc::Mem::Segment::~Segment() {
26 if (theFD >= 0) {
27 detach();
28 if (close(theFD) != 0)
29 debugs(54, 5, HERE << "close: " << xstrerror());
30 }
31 }
32
33 void
34 Ipc::Mem::Segment::create(const int aSize)
35 {
36 assert(aSize > 0);
37 assert(theFD < 0);
38
39 theFD = shm_open(theName.termedBuf(), O_CREAT | O_RDWR | O_TRUNC,
40 S_IRUSR | S_IWUSR);
41 if (theFD < 0) {
42 debugs(54, 5, HERE << "shm_open: " << xstrerror());
43 fatal("Ipc::Mem::Segment::create failed to shm_open");
44 }
45
46 if (ftruncate(theFD, aSize)) {
47 debugs(54, 5, HERE << "ftruncate: " << xstrerror());
48 fatal("Ipc::Mem::Segment::create failed to ftruncate");
49 }
50
51 theSize = aSize;
52 theReserved = 0;
53
54 attach();
55 }
56
57 void
58 Ipc::Mem::Segment::open()
59 {
60 assert(theFD < 0);
61
62 theFD = shm_open(theName.termedBuf(), O_RDWR, 0);
63 if (theFD < 0) {
64 debugs(54, 5, HERE << "shm_open: " << xstrerror());
65 String s = "Ipc::Mem::Segment::open failed to shm_open";
66 s.append(theName);
67 fatal(s.termedBuf());
68 }
69
70 {
71 struct stat s;
72 memset(&s, 0, sizeof(s));
73 if (fstat(theFD, &s)) {
74 debugs(54, 5, HERE << "fstat: " << xstrerror());
75 String s = "Ipc::Mem::Segment::open failed to fstat";
76 s.append(theName);
77 fatal(s.termedBuf());
78 }
79
80 theSize = s.st_size;
81 }
82
83 attach();
84 }
85
86 /// Map the shared memory segment to the process memory space.
87 void
88 Ipc::Mem::Segment::attach()
89 {
90 assert(theFD >= 0);
91 assert(!theMem);
92
93 void *const p =
94 mmap(NULL, theSize, PROT_READ | PROT_WRITE, MAP_SHARED, theFD, 0);
95 if (p == MAP_FAILED) {
96 debugs(54, 5, HERE << "mmap: " << xstrerror());
97 fatal("Ipc::Mem::Segment::attach failed to mmap");
98 }
99 theMem = p;
100 }
101
102 /// Unmap the shared memory segment from the process memory space.
103 void
104 Ipc::Mem::Segment::detach()
105 {
106 if (!theMem)
107 return;
108
109 if (munmap(theMem, theSize)) {
110 debugs(54, 5, HERE << "munmap: " << xstrerror());
111 fatal("Ipc::Mem::Segment::detach failed to munmap");
112 }
113 theMem = 0;
114 }
115
116 void *
117 Ipc::Mem::Segment::reserve(size_t chunkSize)
118 {
119 assert(chunkSize <= theSize);
120 assert(theReserved <= theSize - chunkSize);
121 theReserved += chunkSize;
122 return reinterpret_cast<char*>(mem()) + theReserved;
123 }
124
125 /// Generate name for shared memory segment. Replaces all slashes with dots.
126 String
127 Ipc::Mem::Segment::GenerateName(const char *id)
128 {
129 String name("/squid-");
130 for (const char *slash = strchr(id, '/'); slash; slash = strchr(id, '/')) {
131 if (id != slash) {
132 name.append(id, slash - id);
133 name.append('.');
134 }
135 id = slash + 1;
136 }
137 name.append(id);
138 return name;
139 }