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 <utils/ipc/shm.h>
28 #include <utils/ipc/shm_exceptions.h>
29 
30 #include <cstring>
31 #include <cstdlib>
32 #include <signal.h>
33 #include <iostream>
34 #include <sys/types.h>
35 #include <sys/wait.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 
49 class QASharedMemoryHeader : public SharedMemoryHeader
50 {
51  private:
52  typedef struct {
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 operator==(const SharedMemoryHeader &s) const
70  {
71  const QASharedMemoryHeader *qs = dynamic_cast<const QASharedMemoryHeader *>(&s);
72  return (qs && (header.type == qs->header.type));
73  }
74 
75  virtual bool matches(void *memptr)
76  {
77  return (memcmp(memptr, &header, sizeof(qashmem_header_t)) == 0);
78  }
79 
80  virtual size_t size()
81  {
82  return sizeof(qashmem_header_t);
83  }
84 
85  virtual bool create()
86  {
87  return true;
88  }
89 
90  virtual void initialize(void *memptr)
91  {
92  memcpy(memptr, (char *)&header, sizeof(qashmem_header_t));
93  }
94 
95  virtual void set(void *memptr)
96  {
97  memcpy((char *)&header, memptr, sizeof(qashmem_header_t));
98  }
99 
100  virtual void reset()
101  {
102  }
103 
104  virtual size_t data_size()
105  {
106  return 1024;
107  }
108 
109  private:
110  qashmem_header_t header;
111 };
112 
113 
114 bool quit;
115 
116 void
117 signal_handler(int signum)
118 {
119  quit = true;
120 }
121 
122 
123 void
124 do_child(unsigned int child_id, QASharedMemoryHeader *header)
125 {
126  cout << "Child " << child_id << " is alive" << endl;
127 
128  // This will attach to the existing shmem segment,
129  // use ipcs to check
130  SharedMemory *sr = new SharedMemory(MAGIC_TOKEN, header,
131  /* read only */ false,
132  /* create */ false,
133  /* destroy */ false);
134 
135 
136  int *mc = (int *)sr->memptr();
137 
138  cout << "Child " << child_id << " entering loop" << endl;
139  while ( ! quit ) {
140  int m;
141  m = mc[1]; m++;
142  //cout << "Child: sleeping" << endl;
143  usleep(12932);
144  //cout << "Child: wasting time" << endl;
145  WASTETIME;
146  //cout << "Child: done wasting time, setting to " << m << endl;
147  // mc[1] = m;
148  cout << "Child " << child_id << ": locking (read)" << endl;
149  sr->lock_for_read();
150  cout << "Child " << child_id << ": locked (read)" << endl;
151  m = mc[0]; m++;
152  usleep(23419);
153  WASTETIME;
154  cout << "Child " << child_id << ": unlocking (read)" << endl;
155  sr->unlock();
156 
157  cout << "Child " << child_id << ": locking (write)" << endl;
158  sr->lock_for_write();
159  cout << "Child " << child_id << ": locked (write)" << endl;
160  mc[0] = m;
161  cout << "Child " << child_id << ": unlocking (write)" << endl;
162  sr->unlock();
163 
164  //cout << "Child: unlocked" << endl;
165  // std::cout << "Child " << child_id << ": unprotected: " << mc[1] << " protected: " << mc[0] << endl;
166  usleep(1231);
167  }
168 
169  cout << "Child " << child_id << " exiting" << endl;
170 
171  delete sr;
172 }
173 
174 
175 int
176 main(int argc, char **argv)
177 {
178  quit = false;
179  signal(SIGINT, signal_handler);
180 
181  QASharedMemoryHeader *h1 = new QASharedMemoryHeader(1);
182 
183  SharedMemory *sw;
184 
185  cout << "Use the locking/locked comments to verify!" << endl;
186 
187  try {
188  cout << "Creating shared memory segment" << endl;
189  // This will create the shared memory segment
190  sw = new SharedMemory(MAGIC_TOKEN, h1,
191  /* read only */ false,
192  /* create */ true,
193  /* destroy */ true);
194 
195  // Add protection via semaphore
196  cout << "Adding semaphore set for protection" << endl;
197  sw->add_semaphore();
198 
199  } catch ( ShmCouldNotAttachException &e ) {
200  e.print_trace();
201  exit(1);
202  }
203 
204  pid_t child_pid;
205 
206 
207  if ((child_pid = fork()) == 0) {
208  // child == reader
209  do_child(1, h1);
210  } else {
211  if ((child_pid = fork()) == 0) {
212  // child == reader
213  do_child(2, h1);
214  } else {
215  // father
216  cout << "Father (Writer) is alive" << endl;
217  int *mf = (int *)sw->memptr();
218 
219  while ( ! quit ) {
220  int m;
221  m = mf[1]; m++;
222  usleep(34572);
223  WASTETIME;
224  mf[1] = m;
225  cout << "Father: locking" << endl;
226  sw->lock_for_write();
227  cout << "Father: locked" << endl;
228  m = mf[0]; m++;
229  usleep(12953);
230  WASTETIME;
231  mf[0] = m;
232  sw->unlock();
233  std::cout << "Father: unprotected: " << mf[1] << " protected: " << mf[0] << endl;
234  usleep(3453);
235  }
236 
237  cout << "Father: Waiting for child to exit" << endl;
238  int status;
239  waitpid(child_pid, &status, 0);
240 
241  delete sw;
242  delete h1;
243  }
244  }
245 }
246 
247 /// @endcond
void lock_for_write()
Lock shared memory segment for writing.
Definition: shm.cpp:918
Fawkes library namespace.
STL namespace.
void lock_for_read()
Lock shared memory segment for reading.
Definition: shm.cpp:867
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:682
Could not attach to shared memory segment.
void add_semaphore()
Add semaphore to shared memory segment.
Definition: shm.cpp:810
Shared memory segment.
Definition: shm.h:49
void print_trace()
Prints trace to stderr.
Definition: exception.cpp:619
Interface for shared memory header.
Definition: shm.h:33
void unlock()
Unlock memory.
Definition: shm.cpp:985