qa_ipc_shmem_lock.cpp

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

Generated on Tue Feb 22 13:32:28 2011 for Fawkes API by  doxygen 1.4.7