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