Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

RCRegion.cc

Go to the documentation of this file.
00001 #ifndef PLATFORM_APERIOS
00002 #include "RCRegion.h"
00003 #include "Shared/MarkScope.h"
00004 #include "Shared/debuget.h"
00005 #include "Thread.h"
00006 #include <unistd.h>
00007 #include <sstream>
00008 #include <sys/stat.h>
00009 #include <errno.h>
00010 
00011 #if TEKKOTSU_SHM_STYLE!=SYSV_SHM && TEKKOTSU_SHM_STYLE!=POSIX_SHM
00012 #  error Unknown TEKKOTSU_SHM_STYLE setting
00013 #endif
00014 
00015 #if TEKKOTSU_SHM_STYLE==SYSV_SHM
00016 #  include <sys/ipc.h>
00017 #  include <sys/shm.h>
00018 #elif TEKKOTSU_SHM_STYLE==POSIX_SHM
00019 #  include <sys/mman.h>
00020 #  include <sys/fcntl.h>
00021 #  ifdef USE_UNBACKED_SHM
00022 plist::Primitive<bool> RCRegion::useUniqueMemoryRegions(false);
00023 #  else
00024 plist::Primitive<std::string> RCRegion::shmRoot("/tmp/tekkotsu_sim/");
00025 plist::Primitive<bool> RCRegion::useUniqueMemoryRegions(true);
00026 #  endif
00027 pid_t RCRegion::rootPID(::getpid());
00028 #endif
00029 
00030 using namespace std;
00031 
00032 typedef MarkScope AutoLock;
00033 
00034 #if TEKKOTSU_SHM_STYLE==SYSV_SHM
00035 key_t RCRegion::nextKey=1024;
00036 #elif TEKKOTSU_SHM_STYLE==POSIX_SHM
00037 key_t RCRegion::nextKey=0;
00038 #endif
00039 
00040 RCRegion::attachedRegions_t RCRegion::attachedRegions;
00041 bool RCRegion::isFaultShutdown=false;
00042 ThreadNS::Lock* RCRegion::staticLock=NULL;
00043 
00044 
00045 #if TEKKOTSU_SHM_STYLE==SYSV_SHM
00046 //under SYSV shared memory, the keys are just numbers, and it's just as likely that the conflicted
00047 //region belongs to an unrelated process as it is that the region is from a previous run -- so we
00048 //take the safe route and rename our own keys
00049 RCRegion::ConflictResolutionStrategy RCRegion::conflictStrategy=RCRegion::RENAME;
00050 
00051 #elif TEKKOTSU_SHM_STYLE==POSIX_SHM
00052 //under POSIX shared memory, the keys are names, so we can have some confidence that a region
00053 //with the same name is ours from a previous run, so we replace it to avoid leaking (although
00054 //it's still possible we're conflicting with another application, but good name choices should
00055 //mitigate this)
00056 RCRegion::ConflictResolutionStrategy RCRegion::conflictStrategy=RCRegion::REPLACE;
00057 
00058 #endif
00059 
00060 RCRegion * RCRegion::attach(const Identifier& rid) {
00061   MarkScope l(getStaticLock());
00062   attachedRegions_t::iterator it=attachedRegions.find(rid.key);
00063   if(it==attachedRegions.end())
00064     return new RCRegion(rid); // the constructor will add entry to attachedRegions
00065   else {
00066     ASSERTRETVAL((*it).second!=NULL,"ERROR: attached region is NULL!",NULL);
00067     (*it).second->AddReference();
00068     return (*it).second;
00069   }
00070 }
00071 
00072 void RCRegion::AddReference() {
00073   AutoLock autolock(*lock);
00074   //cout << "AddReference " << id.shmid << ' ' << ProcessID::getID();
00075   references[ProcessID::getID()]++;
00076   references[ProcessID::NumProcesses]++;
00077   //cout << " counts are now:";
00078   //for(unsigned int i=0; i<ProcessID::NumProcesses+1; i++)
00079   //  cout << ' ' << references[i];
00080   //cout << endl;
00081 }
00082 
00083 void RCRegion::RemoveReference() {
00084   //cout << "RemoveReference " << id.key << ' ' << ProcessID::getID();
00085   //if(MutexLockBase::getSemaphoreManager()!=NULL) //check in case this region contained the mutexman and SharedObject just destructed it
00086   lock->lock(ProcessID::getID());
00087   if(references[ProcessID::getID()] == 0) {
00088     cerr << "Warning: RCRegion reference count underflow on " << id.key << " by " << ProcessID::getID() << "!  ";
00089     for(unsigned int i=0; i<ProcessID::NumProcesses+1; i++)
00090       cerr << ' ' << references[i];
00091     cerr << endl;
00092     return;
00093   }
00094   bool wasLastProcRef=(--references[ProcessID::getID()] == 0);
00095   bool wasLastAnyRef=(--references[ProcessID::NumProcesses] == 0);
00096   ASSERT(wasLastProcRef || !wasLastAnyRef,"global reference decremented beyond process reference");
00097   //if(MutexLockBase::getSemaphoreManager()!=NULL)
00098   /*if(isFaultShutdown) {
00099     cerr << "Process " << ProcessID::getID() << " dereferenced " << id.key << ".  Counts are now:";
00100     for(unsigned int i=0; i<ProcessID::NumProcesses+1; i++)
00101       cerr << ' ' << references[i];
00102     cerr << endl;
00103   }*/
00104   ThreadNS::Lock * old=NULL;
00105   if(!wasLastProcRef) {
00106     lock->unlock();
00107   } else {
00108     MarkScope l(getStaticLock());
00109     //cout << " detach";
00110     if(wasLastAnyRef)
00111       lock->~MutexLock<ProcessID::NumProcesses>();
00112     else
00113       lock->unlock();
00114     lock=NULL;
00115 #if TEKKOTSU_SHM_STYLE==SYSV_SHM
00116     if(shmdt(base)<0)
00117       perror("Warning: Region detach");
00118     base=NULL;
00119     references=NULL;
00120     if(wasLastAnyRef) {
00121       //cout << " delete" << endl;
00122       if(shmctl(id.shmid,IPC_RMID,NULL)<0)
00123         perror("Warning: Region delete");
00124     }
00125 #elif TEKKOTSU_SHM_STYLE==POSIX_SHM
00126     if(munmap(base,calcRealSize(id.size))<0) {
00127       perror("Warning: Shared memory unmap (munmap)");
00128     }
00129     base=NULL;
00130     references=NULL;
00131     if(wasLastAnyRef) {
00132       //cout << " delete" << endl;
00133       if(!unlinkRegion()) {
00134         int err=errno;
00135         if(isFaultShutdown && (err==EINVAL || err==ENOENT))
00136           //On a fault shutdown, we initially try to unlink everything right away,
00137           // so an error now is just confirmation that it worked
00138           cerr << "Region " << id.key << " appears to have been successfully unlinked" << endl;
00139         else {
00140           cerr << "Warning: Shared memory unlink of region " << id.key << " returned " << strerror(err);
00141           if(err==EINVAL || err==ENOENT)
00142             cerr << "\n         May have already been unlinked by a dying process.";
00143           cerr << endl;
00144         }
00145       } else if(isFaultShutdown)
00146         //That shouldn't have succeeded on a faultShutdown...
00147         cerr << "Region " << id.key << " appears to have been successfully unlinked (nonstandard)" << endl;
00148     }
00149 #else
00150 #  error "Unknown TEKKOTSU_SHM_STYLE setting"
00151 #endif
00152     delete this;
00153     if(attachedRegions.size()==0 && !isFaultShutdown) {
00154       //was last attached region, clean up lock for good measure
00155       old=staticLock;
00156       staticLock=NULL;
00157     }
00158   }
00159   delete old;
00160   //cout << endl;
00161 }
00162 
00163 void RCRegion::AddSharedReference() {
00164   AutoLock autolock(*lock);
00165   //cout << "AddSharedReference " << id.shmid << ' ' << ProcessID::getID();
00166   references[ProcessID::NumProcesses]++;
00167   //cout << " counts are now:";
00168   //for(unsigned int i=0; i<ProcessID::NumProcesses+1; i++)
00169   //  cout << ' ' << references[i];
00170   //cout << endl;
00171 }
00172 
00173 void RCRegion::RemoveSharedReference() {
00174   AutoLock autolock(*lock);
00175   //cout << "RemoveSharedReference " << id.shmid << ' ' << ProcessID::getID();
00176   if(references[ProcessID::NumProcesses]==0) {
00177     cerr << "Warning: RCRegion shared reference count underflow on " << id.key << " by " << ProcessID::getID() << "!  ";
00178     for(unsigned int i=0; i<ProcessID::NumProcesses+1; i++)
00179       cerr << ' ' << references[i];
00180     cerr << endl;
00181     return;
00182   }
00183   references[ProcessID::NumProcesses]--;
00184   ASSERT(references[ProcessID::NumProcesses]>0,"removal of shared reference was last reference -- should have local reference as well");
00185   //cout << " counts are now:";
00186   //for(unsigned int i=0; i<ProcessID::NumProcesses+1; i++)
00187   //  cout << ' ' << references[i];
00188   //cout << endl;
00189 }
00190 
00191 
00192 void RCRegion::aboutToFork(ProcessID::ProcessID_t newID) {
00193   //cout << "RCRegion aboutToFork to " << newID << endl;
00194   ThreadNS::Lock* old;
00195   {
00196     MarkScope l(getStaticLock());
00197     attachedRegions_t::const_iterator it=attachedRegions.begin();
00198     for(; it!=attachedRegions.end(); ++it) {
00199       //cout << "Duplicating attachments for " << (*it).first;
00200       (*it).second->references[newID]=(*it).second->references[ProcessID::getID()];
00201       (*it).second->references[ProcessID::NumProcesses]+=(*it).second->references[newID];
00202       //cout << " counts are now:";
00203       //for(unsigned int i=0; i<ProcessID::NumProcesses+1; i++)
00204       //  cout << ' ' << (*it).second->references[i];
00205       //cout << endl;
00206     }
00207     old=staticLock;
00208     staticLock=NULL;
00209   }
00210   delete old;
00211 }
00212 
00213 void RCRegion::faultShutdown() {
00214   MarkScope l(getStaticLock());
00215   if(isFaultShutdown) {
00216     cerr << "WARNING: RCRegion::faultShutdown() called again... ignoring" << endl;
00217     return;
00218   }
00219   isFaultShutdown=true;
00220   if(attachedRegions.size()==0) {
00221     cerr << "WARNING: RCRegion::faultShutdown() called without any attached regions (may be a good thing?)" << endl;
00222     return;
00223   }
00224 #if TEKKOTSU_SHM_STYLE==POSIX_SHM
00225   //this may not really work, but it's worth a last-ditch attempt
00226   //in case the reference counts are screwed up.
00227   attachedRegions_t::const_iterator it=attachedRegions.begin();
00228   for(; it!=attachedRegions.end(); ++it) {
00229     cerr << "RCRegion::faultShutdown(): Process " << ProcessID::getID() << " unlinking " << (*it).second->id.key << endl;
00230 #ifdef USE_UNBACKED_SHM
00231     shm_unlink(getQualifiedName((*it).second->id.key).c_str());
00232 #else
00233     unlink(getQualifiedName((*it).second->id.key).c_str());
00234 #endif
00235   }
00236 #endif
00237   for(unsigned int i=0; i<100; i++) {
00238     unsigned int attempts=ProcessID::NumProcesses;
00239     unsigned int lastSize=attachedRegions.size();
00240     while(attachedRegions.size()==lastSize && attempts-->0)
00241       (*attachedRegions.begin()).second->RemoveReference();
00242     if(attempts==-1U) {
00243       cout << "Warning: could not dereference " << attachedRegions.begin()->second->id.key << endl;
00244       attachedRegions.erase(attachedRegions.begin());
00245     }
00246     if(attachedRegions.size()==0)
00247       break;
00248   }
00249 }
00250 
00251 RCRegion::attachedRegions_t::const_iterator RCRegion::attachedBegin(bool threadSafe) {
00252   if(threadSafe) {
00253     MarkScope l(getStaticLock());
00254     attachedRegions.begin()->second->AddReference();
00255     return attachedRegions.begin();
00256   } else
00257     return attachedRegions.begin();
00258 }
00259 RCRegion::attachedRegions_t::const_iterator RCRegion::attachedEnd() {
00260   return attachedRegions.end();
00261 }
00262 void RCRegion::attachedAdvance(RCRegion::attachedRegions_t::const_iterator& it, int x/*=1*/) {
00263   MarkScope l(getStaticLock());
00264   if(it!=attachedRegions.end())
00265     it->second->RemoveReference();
00266   std::advance(it,x);
00267   if(it!=attachedRegions.end())
00268     it->second->AddReference();
00269 }
00270 
00271 RCRegion::~RCRegion() {
00272   MarkScope l(getStaticLock());
00273   attachedRegions.erase(id.key);
00274   ASSERT(base==NULL,"destructed with attachment!");
00275   ASSERT(references==NULL,"destructed with local references!");
00276   //cout << "~RCRegion " << id.shmid << ' ' << ProcessID::getID() << endl;
00277 }
00278   
00279 unsigned int RCRegion::calcRealSize(unsigned int size) {
00280   size=((size+align-1)/align)*align; //round up for field alignment
00281   size+=extra; //add room for the reference count
00282   unsigned int pagesize=::getpagesize();
00283   unsigned int pages=(size+pagesize-1)/pagesize;
00284   return pages*pagesize; //round up to the nearest page
00285 }
00286 
00287 
00288 ThreadNS::Lock& RCRegion::getStaticLock() {
00289   if(staticLock==NULL)
00290     staticLock=new ThreadNS::Lock();
00291   return *staticLock;
00292 }
00293 
00294 #if TEKKOTSU_SHM_STYLE==SYSV_SHM
00295 
00296 void RCRegion::init(size_t sz, key_t sug_key, bool create) {
00297   ThreadNS::Lock l(getStaticLock());
00298   id.size=sz;
00299   sz=calcRealSize(sz);
00300   if(create) {
00301     int flags = 0666 | IPC_CREAT | IPC_EXCL;
00302     if(sug_key==IPC_PRIVATE) {
00303       if((id.shmid=shmget(sug_key, sz, flags)) < 0) {
00304         int err=errno;
00305         if(err != EEXIST) {
00306           cerr << "ERROR: Getting new private region " << key << " of size " << sz ": " << strerror(err) << " (shmget)" << endl;
00307           exit(EXIT_FAILURE);
00308         }
00309       }
00310       id.key=sug_key;
00311     } else {
00312       nextKey=sug_key;
00313       switch(conflictStrategy) {
00314         case RENAME:
00315           while((id.shmid=shmget(id.key=nextKey++, sz, flags)) < 0) {
00316             int err=errno;
00317             if(err != EEXIST) {
00318               cerr << "ERROR: Getting new region " << key << " of size " << sz ": " << strerror(err) << " (shmget)" << endl;
00319               exit(EXIT_FAILURE);
00320             }
00321           }
00322           break;
00323         case REPLACE:
00324           if((id.shmid=shmget(id.key=nextKey, sz, flags)) >= 0)
00325             break;
00326           int err=errno;
00327           if(err != EEXIST) {
00328             cerr << "ERROR: Getting new region " << key << " of size " << sz ": " << strerror(err) << " (shmget)" << endl;
00329             exit(EXIT_FAILURE);
00330           }
00331 #ifdef DEBUG
00332           cerr << "Warning: conflicted key " << key << ", attempting to replace\n"
00333              << "         (may have been leftover from a previous crash)" << endl;
00334 #endif
00335           if(shmctl(id.shmid,IPC_RMID,NULL)<0)
00336             perror("Warning: Region delete from conflict - is another simulator running?");
00337           //note fall-through from REPLACE into EXIT - only try delete once, and then recreate and exit if it fails again
00338         case EXIT: 
00339           if((id.shmid=shmget(id.key=nextKey, sz, flags)) < 0) {
00340             int err=errno;
00341             cerr << "ERROR: Getting new region " << key << " of size " << sz ": " << strerror(err) << " (shmget)" << endl;
00342             exit(EXIT_FAILURE);
00343           }
00344       }
00345     }
00346   } else {
00347     int flags = 0666;
00348     if((id.shmid=shmget(sug_key, sz, flags)) < 0) {
00349       int err=errno;
00350       cerr << "ERROR: Getting existing region " << key << " of size " << sz ": " << strerror(err) << " (shmget)" << endl;
00351       exit(EXIT_FAILURE);
00352     }
00353     id.key=sug_key;
00354   }
00355   //cout << "ATTACHING " << id.shmid << " NOW" << endl;
00356   base=static_cast<char*>(shmat(id.shmid, NULL, SHM_RND));
00357   int err=errno;
00358   //cout << "Base is " << (void*)base << endl;
00359   if (base == reinterpret_cast<char*>(-1)) {
00360     cerr << "ERROR: Attaching region " << key << " of size " << sz << ": " << strerror(err) << " (shmat)" << endl;
00361     if(shmctl(id.shmid,IPC_RMID,NULL)<0)
00362       perror("Region delete");
00363     exit(EXIT_FAILURE);
00364   }
00365   lock=reinterpret_cast<MutexLock<ProcessID::NumProcesses>*>(base+sz-sizeof(MutexLock<ProcessID::NumProcesses>));
00366   references=reinterpret_cast<unsigned int*>(base+sz-extra);
00367   if(create) {
00368     new (lock) MutexLock<ProcessID::NumProcesses>;
00369     AutoLock autolock(*lock,ProcessID::getID());
00370     for(unsigned int i=0; i<ProcessID::NumProcesses+1; i++)
00371       references[i]=0;
00372   }
00373   AddReference();
00374   attachedRegions[id.key]=this;
00375 }
00376 
00377 #elif TEKKOTSU_SHM_STYLE==POSIX_SHM
00378   
00379 std::string RCRegion::getQualifiedName(const std::string& key) {
00380 #ifdef USE_UNBACKED_SHM
00381   string idval="/";
00382 #else
00383   string idval=shmRoot;
00384 #endif
00385   if(useUniqueMemoryRegions) {
00386     char pidstr[10];
00387     snprintf(pidstr,10,"%d-",rootPID);
00388     idval+=pidstr;
00389   }
00390   idval+=key;
00391   return idval;
00392 }
00393 int RCRegion::openRegion(int mode) const {
00394 #ifdef USE_UNBACKED_SHM
00395   return shm_open(getQualifiedName().c_str(),mode,0666);
00396 #else
00397   return open(getQualifiedName().c_str(),mode,0666);
00398 #endif
00399 }
00400 bool RCRegion::unlinkRegion() const {
00401 #ifdef USE_UNBACKED_SHM
00402   return shm_unlink(getQualifiedName().c_str())==0;
00403 #else
00404   return unlink(getQualifiedName().c_str())==0;
00405 #endif
00406 }
00407 void RCRegion::init(size_t sz, const std::string& name, bool create) {
00408   MarkScope l(getStaticLock());
00409   id.size=sz; //size of requested region
00410   sz=calcRealSize(sz); //add some additional space for region lock and reference counts
00411 #ifndef USE_UNBACKED_SHM
00412   struct stat statbuf;
00413   //cout << "Checking " << shmRoot.substr(0,shmRoot.rfind('/')) << endl;
00414   if(stat(shmRoot.substr(0,shmRoot.rfind('/')).c_str(),&statbuf)) {
00415     for(string::size_type c=shmRoot.find('/',1); c!=string::npos; c=shmRoot.find('/',c+1)) {
00416       //cout << "Checking " << shmRoot.substr(0,c) << endl;
00417       if(stat(shmRoot.substr(0,c).c_str(),&statbuf)) {
00418         mkdir(shmRoot.substr(0,c).c_str(),0777);
00419       } else if(!(statbuf.st_mode&S_IFDIR)) {
00420         cerr << "*** ERROR " << shmRoot.substr(0,c) << " exists and is not a directory" << endl;
00421         cerr << "           Cannot create file-backed shared memory regions in " << shmRoot << endl;
00422         exit(EXIT_FAILURE);
00423       }
00424     }
00425     cout << "Created '" << shmRoot.substr(0,shmRoot.rfind('/')) << "' for file-backed shared memory storage" << endl;
00426   } else if(!(statbuf.st_mode&S_IFDIR)) {
00427     cerr << "*** ERROR " << shmRoot.substr(0,shmRoot.rfind('/')) << " exists and is not a directory" << endl;
00428     cerr << "           Cannot create file-backed shared memory regions with prefix " << shmRoot << endl;
00429     exit(EXIT_FAILURE);
00430   }
00431 #endif
00432   int fd;
00433   if(name.size()>=MAX_NAME_LEN)
00434     cerr << "*** WARNING RCRegion named " << name << " will be clipped to " << name.substr(0,MAX_NAME_LEN-1) << endl;
00435   strncpy(id.key,name.c_str(),MAX_NAME_LEN-1);
00436   id.key[MAX_NAME_LEN-1]='\0';
00437   if(create) {
00438     static unsigned int renameSN=0;
00439     switch(conflictStrategy) {
00440       case RENAME: {
00441         char origName[MAX_NAME_LEN];
00442         strncpy(origName,id.key,MAX_NAME_LEN);
00443         if((fd=openRegion(O_RDWR|O_CREAT|O_EXCL))>=0)
00444           break;
00445         do {
00446           int err=errno;
00447           if(err!=EEXIST) {
00448             cerr << "ERROR: Opening new region " << id.key << ": " << strerror(err) << " (shm_open)" << endl;
00449             exit(EXIT_FAILURE);
00450           }
00451           unsigned int p=snprintf(id.key,MAX_NAME_LEN,"%s-%d",origName,++renameSN);
00452           if(p>=MAX_NAME_LEN) {
00453             cerr << "ERROR: conflicted key " << origName << ", attempting to rename, but generated name is too long" << endl;
00454             exit(EXIT_FAILURE);
00455           }
00456           //id.key[MAX_NAME_LEN-1]='\0';
00457 #ifdef DEBUG
00458           cerr << "Warning: conflicted key " << origName << ", attempting to rename as " << id.key << "\n"
00459             << "         (may have been leftover from a previous crash)" << endl;
00460 #endif
00461         } while((fd=openRegion(O_RDWR|O_CREAT|O_EXCL))<0);
00462         break;
00463       }
00464       case REPLACE: {
00465         if((fd=openRegion(O_RDWR|O_CREAT|O_EXCL))>=0)
00466           break;
00467         int err=errno;
00468         if(err!=EEXIST) {
00469           cerr << "ERROR: Opening new region " << id.key << ": " << strerror(err) << " (shm_open)" << endl;
00470           exit(EXIT_FAILURE);
00471         }
00472 #ifdef DEBUG
00473         cerr << "Warning: conflicted key " << id.key << ", attempting to replace\n"
00474              << "         (may have been leftover from a previous crash)" << endl;
00475 #endif
00476         if(!unlinkRegion())
00477           perror("Warning: Shared memory unlink");
00478       }
00479       //note fall-through from REPLACE into EXIT - only try delete once, and then recreate and exit if it fails again
00480       case EXIT: {
00481         if((fd=openRegion(O_RDWR|O_CREAT|O_EXCL))<0) {
00482           int err=errno;
00483           cerr << "ERROR: Opening new region " << id.key << ": " << strerror(err) << " (shm_open)" << endl;
00484           if(err==EEXIST)
00485             cerr << "This error suggests a leaked memory region, perhaps from a bad crash on a previous run.\n"
00486 #ifdef USE_UNBACKED_SHM
00487               << "You may either be able to use shm_unlink to remove the region, or reboot.\n"
00488 #endif
00489               << "Also make sure that no other copies of the simulator are already running." << endl;
00490           exit(EXIT_FAILURE);
00491         }
00492       }
00493     }
00494     if (ftruncate(fd,sz)<0) {
00495       int err=errno;
00496       cerr << "ERROR: Sizing region " << id.key << " to " << sz << ": " << strerror(err) << " (ftruncate)" << endl;
00497       if(close(fd)<0)
00498         perror("Warning: Closing temporary file descriptor from shm_open");
00499       if(!unlinkRegion())
00500         perror("Warning: Shared memory unlink");
00501       exit(EXIT_FAILURE);
00502     }
00503   } else {
00504     if((fd=openRegion(O_RDWR))<0) {
00505       int err=errno;
00506       cerr << "ERROR: Opening existing region " << id.key << ": " << strerror(err) << " (shm_open)" << endl;
00507       exit(EXIT_FAILURE);
00508     }
00509   }
00510   base=static_cast<char*>(mmap(NULL,sz,PROT_READ|PROT_WRITE,MAP_SHARED,fd,(off_t)0)); 
00511   int err=errno;
00512   if (base == MAP_FAILED) { /* MAP_FAILED generally defined as ((void*)-1) */
00513     cerr << "ERROR: Attaching region " << id.key << " of size " << sz << ": " << strerror(err) << " (mmap)" << endl;
00514     if(close(fd)<0)
00515       perror("Warning: Closing temporary file descriptor from shm_open");
00516     if(!unlinkRegion())
00517       perror("Warning: Shared memory unlink");
00518     exit(EXIT_FAILURE);
00519   }
00520   if(close(fd)<0) {
00521     perror("Warning: Closing temporary file descriptor from shm_open");
00522   }
00523   lock=reinterpret_cast<MutexLock<ProcessID::NumProcesses>*>(base+sz-sizeof(MutexLock<ProcessID::NumProcesses>));
00524   references=reinterpret_cast<unsigned int*>(base+sz-extra);
00525   if(create) {
00526     new (lock) MutexLock<ProcessID::NumProcesses>;
00527     AutoLock autolock(*lock);
00528     for(unsigned int i=0; i<ProcessID::NumProcesses+1; i++)
00529       references[i]=0;
00530   }
00531   AddReference();
00532   attachedRegions[id.key]=this;
00533 }
00534 
00535 #else
00536 #  error "Unknown TEKKOTSU_SHM_STYLE setting"
00537 #endif
00538 
00539 /*
00540  class syserr : public std::exception {
00541 public:
00542 #if TEKKOTSU_SHM_STYLE==SYSV_SHM
00543    syserr(int errnum, const key_t& key, const std::string& msg) throw() : info()
00544 #elif TEKKOTSU_SHM_STYLE==POSIX_SHM
00545    syserr(int errnum, const std::string& key, const std::string& msg) throw() : info()
00546 #endif
00547  {
00548      stringstream tmp;
00549      tmp << "Exception regarding region " << key << ": " << msg << '(' << strerror(errnum) << ')';
00550      info=tmp.c_str();
00551  }
00552    virtual ~syserr() throw() {}
00553    virtual const char * what() const throw() { return info.c_str(); }
00554 protected:
00555       std::string info;
00556  };
00557  */
00558 
00559 /*! @file
00560 * @brief Implements RCRegion, which provides compatability with the OPEN-R type of the same name
00561 * @author ejt (Creator)
00562 *
00563 * $Author: ejt $
00564 * $Name: tekkotsu-3_0 $
00565 * $Revision: 1.10 $
00566 * $State: Exp $
00567 * $Date: 2006/08/15 21:45:36 $
00568 */
00569 
00570 #endif

Tekkotsu v3.0
Generated Wed Oct 4 00:03:45 2006 by Doxygen 1.4.7