Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * qa_shmem_lock.h - QA for protected IPC shared memory 00004 * 00005 * Generated: Fri Oct 06 13:32:03 2006 00006 * Copyright 2005-2006 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. A runtime exception applies to 00014 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 00022 */ 00023 00024 // Do not include in api reference 00025 ///@cond QA 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 // This will attach to the existing shmem segment, 00129 // use ipcs to check 00130 SharedMemory *sr = new SharedMemory(MAGIC_TOKEN, header, 00131 /* read only */ false, 00132 /* create */ false, 00133 /* destroy */ 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 //cout << "Child: sleeping" << endl; 00143 usleep(12932); 00144 //cout << "Child: wasting time" << endl; 00145 WASTETIME; 00146 //cout << "Child: done wasting time, setting to " << m << endl; 00147 // mc[1] = m; 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 //cout << "Child: unlocked" << endl; 00165 // std::cout << "Child " << child_id << ": unprotected: " << mc[1] << " protected: " << mc[0] << endl; 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 // This will create the shared memory segment 00190 sw = new SharedMemory(MAGIC_TOKEN, h1, 00191 /* read only */ false, 00192 /* create */ true, 00193 /* destroy */ true); 00194 00195 // Add protection via semaphore 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 // child == reader 00209 do_child(1, h1); 00210 } else { 00211 if ((child_pid = fork()) == 0) { 00212 // child == reader 00213 do_child(2, h1); 00214 } else { 00215 // father 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 /// @endcond