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