qa_ipc_shmem_lock.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <utils/ipc/shm.h>
00028 #include <utils/ipc/shm_exceptions.h>
00029
00030 #include <cstring>
00031 #include <cstdlib>
00032 #include <signal.h>
00033 #include <iostream>
00034 #include <sys/types.h>
00035 #include <sys/wait.h>
00036
00037 using namespace std;
00038 using namespace fawkes;
00039
00040 #define MAGIC_TOKEN "FawkesShmemQAApp"
00041
00042 #define WASTETIME \
00043 for ( unsigned int i = 0; i < 50000000; i++) { \
00044 unsigned int j; \
00045 j = i + i; \
00046 }
00047
00048
00049 class QASharedMemoryHeader : public SharedMemoryHeader
00050 {
00051 private:
00052 typedef struct {
00053 unsigned int type;
00054 } qashmem_header_t;
00055
00056 public:
00057 QASharedMemoryHeader(unsigned int type)
00058 {
00059 header.type = type;
00060 }
00061
00062 virtual SharedMemoryHeader *
00063 clone() const
00064 {
00065 QASharedMemoryHeader *qs = new QASharedMemoryHeader(header.type);
00066 return qs;
00067 }
00068
00069 virtual bool operator==(const SharedMemoryHeader &s) const
00070 {
00071 const QASharedMemoryHeader *qs = dynamic_cast<const QASharedMemoryHeader *>(&s);
00072 return (qs && (header.type == qs->header.type));
00073 }
00074
00075 virtual bool matches(void *memptr)
00076 {
00077 return (memcmp(memptr, &header, sizeof(qashmem_header_t)) == 0);
00078 }
00079
00080 virtual size_t size()
00081 {
00082 return sizeof(qashmem_header_t);
00083 }
00084
00085 virtual bool create()
00086 {
00087 return true;
00088 }
00089
00090 virtual void initialize(void *memptr)
00091 {
00092 memcpy(memptr, (char *)&header, sizeof(qashmem_header_t));
00093 }
00094
00095 virtual void set(void *memptr)
00096 {
00097 memcpy((char *)&header, memptr, sizeof(qashmem_header_t));
00098 }
00099
00100 virtual void reset()
00101 {
00102 }
00103
00104 virtual size_t data_size()
00105 {
00106 return 1024;
00107 }
00108
00109 private:
00110 qashmem_header_t header;
00111 };
00112
00113
00114 bool quit;
00115
00116 void
00117 signal_handler(int signum)
00118 {
00119 quit = true;
00120 }
00121
00122
00123 void
00124 do_child(unsigned int child_id, QASharedMemoryHeader *header)
00125 {
00126 cout << "Child " << child_id << " is alive" << endl;
00127
00128
00129
00130 SharedMemory *sr = new SharedMemory(MAGIC_TOKEN, header,
00131 false,
00132 false,
00133 false);
00134
00135
00136 int *mc = (int *)sr->memptr();
00137
00138 cout << "Child " << child_id << " entering loop" << endl;
00139 while ( ! quit ) {
00140 int m;
00141 m = mc[1]; m++;
00142
00143 usleep(12932);
00144
00145 WASTETIME;
00146
00147
00148 cout << "Child " << child_id << ": locking (read)" << endl;
00149 sr->lock_for_read();
00150 cout << "Child " << child_id << ": locked (read)" << endl;
00151 m = mc[0]; m++;
00152 usleep(23419);
00153 WASTETIME;
00154 cout << "Child " << child_id << ": unlocking (read)" << endl;
00155 sr->unlock();
00156
00157 cout << "Child " << child_id << ": locking (write)" << endl;
00158 sr->lock_for_write();
00159 cout << "Child " << child_id << ": locked (write)" << endl;
00160 mc[0] = m;
00161 cout << "Child " << child_id << ": unlocking (write)" << endl;
00162 sr->unlock();
00163
00164
00165
00166 usleep(1231);
00167 }
00168
00169 cout << "Child " << child_id << " exiting" << endl;
00170
00171 delete sr;
00172 }
00173
00174
00175 int
00176 main(int argc, char **argv)
00177 {
00178 quit = false;
00179 signal(SIGINT, signal_handler);
00180
00181 QASharedMemoryHeader *h1 = new QASharedMemoryHeader(1);
00182
00183 SharedMemory *sw;
00184
00185 cout << "Use the locking/locked comments to verify!" << endl;
00186
00187 try {
00188 cout << "Creating shared memory segment" << endl;
00189
00190 sw = new SharedMemory(MAGIC_TOKEN, h1,
00191 false,
00192 true,
00193 true);
00194
00195
00196 cout << "Adding semaphore set for protection" << endl;
00197 sw->add_semaphore();
00198
00199 } catch ( ShmCouldNotAttachException &e ) {
00200 e.print_trace();
00201 exit(1);
00202 }
00203
00204 pid_t child_pid;
00205
00206
00207 if ((child_pid = fork()) == 0) {
00208
00209 do_child(1, h1);
00210 } else {
00211 if ((child_pid = fork()) == 0) {
00212
00213 do_child(2, h1);
00214 } else {
00215
00216 cout << "Father (Writer) is alive" << endl;
00217 int *mf = (int *)sw->memptr();
00218
00219 while ( ! quit ) {
00220 int m;
00221 m = mf[1]; m++;
00222 usleep(34572);
00223 WASTETIME;
00224 mf[1] = m;
00225 cout << "Father: locking" << endl;
00226 sw->lock_for_write();
00227 cout << "Father: locked" << endl;
00228 m = mf[0]; m++;
00229 usleep(12953);
00230 WASTETIME;
00231 mf[0] = m;
00232 sw->unlock();
00233 std::cout << "Father: unprotected: " << mf[1] << " protected: " << mf[0] << endl;
00234 usleep(3453);
00235 }
00236
00237 cout << "Father: Waiting for child to exit" << endl;
00238 int status;
00239 waitpid(child_pid, &status, 0);
00240
00241 delete sw;
00242 delete h1;
00243 }
00244 }
00245 }
00246
00247