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 
37 using namespace std;
38 using 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 
48 class QASharedMemoryHeader : public SharedMemoryHeader
49 {
50 private:
51  typedef struct
52  {
53  unsigned int type;
54  } qashmem_header_t;
55 
56 public:
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 
117 private:
118  qashmem_header_t header;
119 };
120 
121 bool quit;
122 
123 void
124 signal_handler(int signum)
125 {
126  quit = true;
127 }
128 
129 void
130 do_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 
182 int
183 main(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
fawkes::SharedMemory
Definition: shm.h:56
fawkes::SharedMemoryHeader
Definition: shm.h:37
fawkes::SharedMemory::unlock
void unlock()
Unlock memory.
Definition: shm.cpp:1029
fawkes::SharedMemory::memptr
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:738
fawkes::SharedMemory::lock_for_write
void lock_for_write()
Lock shared memory segment for writing.
Definition: shm.cpp:963
fawkes
fawkes::Exception::print_trace
void print_trace()
Prints trace to stderr.
Definition: exception.cpp:600
fawkes::ShmCouldNotAttachException
Definition: shm_exceptions.h:37
fawkes::SharedMemory::add_semaphore
void add_semaphore()
Add semaphore to shared memory segment.
Definition: shm.cpp:856
fawkes::SharedMemory::lock_for_read
void lock_for_read()
Lock shared memory segment for reading.
Definition: shm.cpp:913