/* [<][>][^][v][top][bottom][index][help] */
1 /****************************************************************************
2 * Copyright (C) 2006-2008 by Jason Ansel, Kapil Arya, and Gene Cooperman *
3 * jansel@csail.mit.edu, kapil@ccs.neu.edu, gene@ccs.neu.edu *
4 * *
5 * This file is part of the dmtcp/src module of DMTCP (DMTCP:dmtcp/src). *
6 * *
7 * DMTCP:dmtcp/src is free software: you can redistribute it and/or *
8 * modify it under the terms of the GNU Lesser General Public License as *
9 * published by the Free Software Foundation, either version 3 of the *
10 * License, or (at your option) any later version. *
11 * *
12 * DMTCP:dmtcp/src is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU Lesser General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU Lesser General Public *
18 * License along with DMTCP:dmtcp/src. If not, see *
19 * <http://www.gnu.org/licenses/>. *
20 ****************************************************************************/
21
22 #ifndef SYSVIPC_H
23 #define SYSVIPC_H
24
25 #include <vector>
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <map>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <unistd.h>
32 #include <sys/ipc.h>
33 #include <sys/shm.h>
34 #include <sys/sem.h>
35 #include <sys/msg.h>
36
37 #include "dmtcpalloc.h"
38 #include "jbuffer.h"
39 #include "jserialize.h"
40 #include "jassert.h"
41 #include "jconvert.h"
42 #include "jalloc.h"
43 #include "virtualidtable.h"
44 #include "shareddata.h"
45
46 #include "sysvipcwrappers.h"
47
48 #define REAL_TO_VIRTUAL_SHM_ID(id) SysVShm::instance().realToVirtualId(id)
49 #define VIRTUAL_TO_REAL_SHM_ID(id) SysVShm::instance().virtualToRealId(id)
50
51 #define REAL_TO_VIRTUAL_SEM_ID(id) SysVSem::instance().realToVirtualId(id)
52 #define VIRTUAL_TO_REAL_SEM_ID(id) SysVSem::instance().virtualToRealId(id)
53
54 #define REAL_TO_VIRTUAL_MSQ_ID(id) SysVMsq::instance().realToVirtualId(id)
55 #define VIRTUAL_TO_REAL_MSQ_ID(id) SysVMsq::instance().virtualToRealId(id)
56
57 union semun {
58 int val; /* Value for SETVAL */
59 struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
60 unsigned short *array; /* Array for GETALL, SETALL */
61 struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */
62 };
63
64 namespace dmtcp
65 {
66 class SysVObj;
67 class ShmSegment;
68 class Semaphore;
69 class MsgQueue;
70
71 class SysVIPC
72 {
73 public:
74 #ifdef JALIB_ALLOCATOR
75 static void* operator new(size_t nbytes, void* p) { return p; }
76 static void* operator new(size_t nbytes) { JALLOC_HELPER_NEW(nbytes); }
77 static void operator delete(void* p) { JALLOC_HELPER_DELETE(p); }
78 #endif
79
80 SysVIPC(const char *str, int32_t id, int type);
81 void removeStaleObjects();
82 void resetOnFork();
83 void leaderElection();
84 void preCkptDrain();
85 void preCheckpoint();
86 void preResume();
87 void refill(bool isRestart);
88 void postRestart();
89 int virtualToRealId(int virtId);
90 int realToVirtualId(int realId);
91 void updateMapping(int virtId, int realId);
92 int getNewVirtualId();
93 void serialize(jalib::JBinarySerializer& o);
94
95 virtual void on_shmget(int shmid, key_t key, size_t size, int shmflg) {}
96 virtual void on_shmat(int shmid, const void *shmaddr, int shmflg,
97 void* newaddr) {}
98 virtual void on_shmdt(const void *shmaddr) {}
99
100 virtual void on_semget(int semid, key_t key, int nsems, int semflg) {}
101 virtual void on_semctl(int semid, int semnum, int cmd, union semun arg) {}
102 virtual void on_semop(int semid, struct sembuf *sops, unsigned nsops) {}
103
104 virtual void on_msgget(int msqid, key_t key, int msgflg) {}
105 virtual void on_msgctl(int msqid, int cmd, struct msqid_ds *buf) {}
106 virtual void on_msgsnd(int msqid, const void *msgp, size_t msgsz,
107 int msgflg) {}
108 virtual void on_msgrcv(int msqid, const void *msgp, size_t msgsz,
109 int msgtyp, int msgflg) {}
110
111 protected:
112 map<int, SysVObj*> _map;
113 typedef map<int, SysVObj*>::iterator Iterator;
114 VirtualIdTable<int32_t> _virtIdTable;
115 int _type;
116 };
117
118 class SysVShm : public SysVIPC
119 {
120 public:
121 SysVShm()
122 : SysVIPC("SysVShm", getpid(), SYSV_SHM_ID) {}
123
124 static SysVShm& instance();
125
126 int shmaddrToShmid(const void* shmaddr);
127 virtual void on_shmget(int shmid, key_t key, size_t size, int shmflg);
128 virtual void on_shmat(int shmid, const void *shmaddr, int shmflg,
129 void* newaddr);
130 virtual void on_shmdt(const void *shmaddr);
131 };
132
133 class SysVSem : public SysVIPC
134 {
135 public:
136 SysVSem()
137 : SysVIPC("SysVSem", getpid(), SYSV_SEM_ID) {}
138
139 static SysVSem& instance();
140 virtual void on_semget(int semid, key_t key, int nsems, int semflg);
141 virtual void on_semctl(int semid, int semnum, int cmd, union semun arg);
142 virtual void on_semop(int semid, struct sembuf *sops, unsigned nsops);
143 };
144
145 class SysVMsq : public SysVIPC
146 {
147 public:
148 SysVMsq()
149 : SysVIPC("SysVMsq", getpid(), SYSV_MSQ_ID) {}
150
151 static SysVMsq& instance();
152 virtual void on_msgget(int msqid, key_t key, int msgflg);
153 virtual void on_msgctl(int msqid, int cmd, struct msqid_ds *buf);
154 virtual void on_msgsnd(int msqid, const void *msgp, size_t msgsz,
155 int msgflg);
156 virtual void on_msgrcv(int msqid, const void *msgp, size_t msgsz,
157 int msgtyp, int msgflg);
158 };
159
160 class SysVObj
161 {
162 public:
163 #ifdef JALIB_ALLOCATOR
164 static void* operator new(size_t nbytes, void* p) { return p; }
165 static void* operator new(size_t nbytes) { JALLOC_HELPER_NEW(nbytes); }
166 static void operator delete(void* p) { JALLOC_HELPER_DELETE(p); }
167 #endif
168
169 SysVObj(int id, int realId, int key, int flags) {
170 _key = key;
171 _flags = flags;
172 _id = id;
173 _realId = realId;
174 _isCkptLeader = false;
175 }
176 virtual ~SysVObj() {}
177
178 int virtualId() { return _id; }
179
180 bool isCkptLeader() { return _isCkptLeader; }
181
182 virtual bool isStale() = 0;
183 virtual void resetOnFork() = 0;
184 virtual void leaderElection() = 0;
185 virtual void preCkptDrain() = 0;
186 virtual void preCheckpoint() = 0;
187 virtual void postRestart() = 0;
188 virtual void refill(bool isRestart) = 0;
189 virtual void preResume() = 0;
190
191 protected:
192 int _id;
193 int _realId;
194 key_t _key;
195 int _flags;
196 bool _isCkptLeader;
197 };
198
199 class ShmSegment : public SysVObj
200 {
201 public:
202 #ifdef JALIB_ALLOCATOR
203 static void* operator new(size_t nbytes, void* p) { return p; }
204 static void* operator new(size_t nbytes) { JALLOC_HELPER_NEW(nbytes); }
205 static void operator delete(void* p) { JALLOC_HELPER_DELETE(p); }
206 #endif
207
208 ShmSegment(int shmid, int realShmid, key_t key, size_t size, int shmflg);
209
210 virtual bool isStale();
211 virtual void resetOnFork() {}
212 virtual void leaderElection();
213 virtual void preCkptDrain();
214 virtual void preCheckpoint();
215 virtual void postRestart();
216 virtual void refill(bool isRestart);
217 virtual void preResume();
218
219 bool isValidShmaddr(const void* shmaddr);
220 void remapAll();
221 void remapFirstAddrForOwnerOnRestart();
222
223 void on_shmat(const void *shmaddr, int shmflg);
224 void on_shmdt(const void *shmaddr);
225
226 private:
227 size_t _size;
228 int _dmtcpMappedAddr;
229 shmatt_t _nattch;
230 unsigned short _mode;
231 struct shmid_ds _shminfo;
232 typedef map<const void*, int> ShmaddrToFlag;
233 typedef map<const void*, int>::iterator ShmaddrToFlagIter;
234 ShmaddrToFlag _shmaddrToFlag;
235 };
236
237 class Semaphore : public SysVObj
238 {
239 public:
240 #ifdef JALIB_ALLOCATOR
241 static void* operator new(size_t nbytes, void* p) { return p; }
242 static void* operator new(size_t nbytes) { JALLOC_HELPER_NEW(nbytes); }
243 static void operator delete(void* p) { JALLOC_HELPER_DELETE(p); }
244 #endif
245 Semaphore(int semid, int realSemid, key_t key, int nsems, int semflg);
246 ~Semaphore() { delete _semval; delete _semadj; }
247 void on_semop(struct sembuf *sops, unsigned nsops);
248
249 virtual bool isStale();
250 virtual void resetOnFork();
251 virtual void leaderElection();
252 virtual void preCkptDrain();
253 virtual void preCheckpoint();
254 virtual void postRestart();
255 virtual void refill(bool isRestart);
256 virtual void preResume() {}
257
258 private:
259 int _nsems;
260 unsigned short *_semval;
261 int *_semadj;
262 };
263
264 class MsgQueue : public SysVObj
265 {
266 public:
267 #ifdef JALIB_ALLOCATOR
268 static void* operator new(size_t nbytes, void* p) { return p; }
269 static void* operator new(size_t nbytes) { JALLOC_HELPER_NEW(nbytes); }
270 static void operator delete(void* p) { JALLOC_HELPER_DELETE(p); }
271 #endif
272 MsgQueue(int msqid, int realMsqid, key_t key, int msgflg);
273
274 virtual bool isStale();
275 virtual void resetOnFork() {}
276 virtual void leaderElection();
277 virtual void preCkptDrain();
278 virtual void preCheckpoint();
279 virtual void postRestart();
280 virtual void refill(bool isRestart);
281 virtual void preResume() {}
282
283 private:
284 vector<jalib::JBuffer> _msgInQueue;
285 msgqnum_t _qnum;
286 };
287 }
288 #endif