Fawkes API Fawkes Development Version
qa_ipc_shmem_lock.cpp
1
2/***************************************************************************
3 * qa_shmem_lock.h - QA for protected IPC shared memory
4 *
5 * Generated: Fri Oct 06 13:32:03 2006
6 * Copyright 2005-2006 Tim Niemueller [www.niemueller.de]
7 *
8 ****************************************************************************/
9
10/* This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version. A runtime exception applies to
14 * this software (see LICENSE.GPL_WRE file mentioned below for details).
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Library General Public License for more details.
20 *
21 * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22 */
23
24// Do not include in api reference
25///@cond QA
26
27#include <sys/types.h>
28#include <sys/wait.h>
29#include <utils/ipc/shm.h>
30#include <utils/ipc/shm_exceptions.h>
31
32#include <cstdlib>
33#include <cstring>
34#include <iostream>
35#include <signal.h>
36
37using namespace std;
38using namespace fawkes;
39
40#define MAGIC_TOKEN "FawkesShmemQAApp"
41
42#define WASTETIME \
43 for (unsigned int i = 0; i < 50000000; i++) { \
44 unsigned int j; \
45 j = i + i; \
46 }
47
48class QASharedMemoryHeader : public SharedMemoryHeader
49{
50private:
51 typedef struct
52 {
53 unsigned int type;
54 } qashmem_header_t;
55
56public:
57 QASharedMemoryHeader(unsigned int type)
58 {
59 header.type = type;
60 }
61
62 virtual SharedMemoryHeader *
63 clone() const
64 {
65 QASharedMemoryHeader *qs = new QASharedMemoryHeader(header.type);
66 return qs;
67 }
68
69 virtual bool
70 operator==(const SharedMemoryHeader &s) const
71 {
72 const QASharedMemoryHeader *qs = dynamic_cast<const QASharedMemoryHeader *>(&s);
73 return (qs && (header.type == qs->header.type));
74 }
75
76 virtual bool
77 matches(void *memptr)
78 {
79 return (memcmp(memptr, &header, sizeof(qashmem_header_t)) == 0);
80 }
81
82 virtual size_t
83 size()
84 {
85 return sizeof(qashmem_header_t);
86 }
87
88 virtual bool
89 create()
90 {
91 return true;
92 }
93
94 virtual void
95 initialize(void *memptr)
96 {
97 memcpy(memptr, (char *)&header, sizeof(qashmem_header_t));
98 }
99
100 virtual void
101 set(void *memptr)
102 {
103 memcpy((char *)&header, memptr, sizeof(qashmem_header_t));
104 }
105
106 virtual void
107 reset()
108 {
109 }
110
111 virtual size_t
112 data_size()
113 {
114 return 1024;
115 }
116
117private:
118 qashmem_header_t header;
119};
120
121bool quit;
122
123void
124signal_handler(int signum)
125{
126 quit = true;
127}
128
129void
130do_child(unsigned int child_id, QASharedMemoryHeader *header)
131{
132 cout << "Child " << child_id << " is alive" << endl;
133
134 // This will attach to the existing shmem segment,
135 // use ipcs to check
136 SharedMemory *sr = new SharedMemory(MAGIC_TOKEN,
137 header,
138 /* read only */ false,
139 /* create */ false,
140 /* destroy */ false);
141
142 int *mc = (int *)sr->memptr();
143
144 cout << "Child " << child_id << " entering loop" << endl;
145 while (!quit) {
146 int m;
147 m = mc[1];
148 m++;
149 //cout << "Child: sleeping" << endl;
150 usleep(12932);
151 //cout << "Child: wasting time" << endl;
152 WASTETIME;
153 //cout << "Child: done wasting time, setting to " << m << endl;
154 // mc[1] = m;
155 cout << "Child " << child_id << ": locking (read)" << endl;
156 sr->lock_for_read();
157 cout << "Child " << child_id << ": locked (read)" << endl;
158 m = mc[0];
159 m++;
160 usleep(23419);
161 WASTETIME;
162 cout << "Child " << child_id << ": unlocking (read)" << endl;
163 sr->unlock();
164
165 cout << "Child " << child_id << ": locking (write)" << endl;
166 sr->lock_for_write();
167 cout << "Child " << child_id << ": locked (write)" << endl;
168 mc[0] = m;
169 cout << "Child " << child_id << ": unlocking (write)" << endl;
170 sr->unlock();
171
172 //cout << "Child: unlocked" << endl;
173 // std::cout << "Child " << child_id << ": unprotected: " << mc[1] << " protected: " << mc[0] << endl;
174 usleep(1231);
175 }
176
177 cout << "Child " << child_id << " exiting" << endl;
178
179 delete sr;
180}
181
182int
183main(int argc, char **argv)
184{
185 quit = false;
186 signal(SIGINT, signal_handler);
187
188 QASharedMemoryHeader *h1 = new QASharedMemoryHeader(1);
189
190 SharedMemory *sw;
191
192 cout << "Use the locking/locked comments to verify!" << endl;
193
194 try {
195 cout << "Creating shared memory segment" << endl;
196 // This will create the shared memory segment
197 sw = new SharedMemory(MAGIC_TOKEN,
198 h1,
199 /* read only */ false,
200 /* create */ true,
201 /* destroy */ true);
202
203 // Add protection via semaphore
204 cout << "Adding semaphore set for protection" << endl;
205 sw->add_semaphore();
206
207 } catch (ShmCouldNotAttachException &e) {
208 e.print_trace();
209 exit(1);
210 }
211
212 pid_t child_pid;
213
214 if ((child_pid = fork()) == 0) {
215 // child == reader
216 do_child(1, h1);
217 } else {
218 if ((child_pid = fork()) == 0) {
219 // child == reader
220 do_child(2, h1);
221 } else {
222 // father
223 cout << "Father (Writer) is alive" << endl;
224 int *mf = (int *)sw->memptr();
225
226 while (!quit) {
227 int m;
228 m = mf[1];
229 m++;
230 usleep(34572);
231 WASTETIME;
232 mf[1] = m;
233 cout << "Father: locking" << endl;
234 sw->lock_for_write();
235 cout << "Father: locked" << endl;
236 m = mf[0];
237 m++;
238 usleep(12953);
239 WASTETIME;
240 mf[0] = m;
241 sw->unlock();
242 std::cout << "Father: unprotected: " << mf[1] << " protected: " << mf[0] << endl;
243 usleep(3453);
244 }
245
246 cout << "Father: Waiting for child to exit" << endl;
247 int status;
248 waitpid(child_pid, &status, 0);
249
250 delete sw;
251 delete h1;
252 }
253 }
254}
255
256/// @endcond
void print_trace() noexcept
Prints trace to stderr.
Definition: exception.cpp:601
Interface for shared memory header.
Definition: shm.h:34
Shared memory segment.
Definition: shm.h:53
void add_semaphore()
Add semaphore to shared memory segment.
Definition: shm.cpp:852
void lock_for_write()
Lock shared memory segment for writing.
Definition: shm.cpp:959
void * memptr() const
Get a pointer to the shared memory This method returns a pointer to the data-segment of the shared me...
Definition: shm.cpp:734
void unlock()
Unlock memory.
Definition: shm.cpp:1025
void lock_for_read()
Lock shared memory segment for reading.
Definition: shm.cpp:909
Could not attach to shared memory segment.
Fawkes library namespace.