// $Id$ // Memory_Pool.cpp #define ACE_BUILD_DLL #include "ace/Memory_Pool.h" #if !defined (__ACE_INLINE__) #include "ace/Memory_Pool.i" #endif /* __ACE_INLINE__ */ #include "ace/Auto_Ptr.h" #if defined (ACE_HAS_POSITION_INDEPENDENT_MALLOC) #include "ace/Based_Pointer_T.h" #endif /* ACE_HAS_POSITION_INDEPENDENT_MALLOC */ ACE_RCSID(ace, Memory_Pool, "$Id$") ACE_ALLOC_HOOK_DEFINE(ACE_Local_Memory_Pool) void ACE_Local_Memory_Pool::dump (void) const { ACE_TRACE ("ACE_Local_Memory_Pool::dump"); } ACE_Local_Memory_Pool::ACE_Local_Memory_Pool (LPCTSTR , const OPTIONS *) { ACE_TRACE ("ACE_Local_Memory_Pool::ACE_Local_Memory_Pool"); } void * ACE_Local_Memory_Pool::acquire (size_t nbytes, size_t &rounded_bytes) { ACE_TRACE ("ACE_Local_Memory_Pool::acquire"); rounded_bytes = this->round_up (nbytes); char *temp = 0; ACE_NEW_RETURN (temp, char[rounded_bytes], 0); ACE_Auto_Basic_Array_Ptr cp (temp); if (this->allocated_chunks_.insert (cp.get ()) != 0) ACE_ERROR_RETURN ((LM_ERROR, ASYS_TEXT ("(%P|%t) insertion into set failed\n")), 0); return cp.release (); } int ACE_Local_Memory_Pool::release (void) { ACE_TRACE ("ACE_Local_Memory_Pool::release"); // Zap the memory we allocated. for (ACE_Unbounded_Set::iterator i = this->allocated_chunks_.begin (); i != this->allocated_chunks_.end (); ++i) delete [] *i; return 0; } ACE_ALLOC_HOOK_DEFINE(ACE_MMAP_Memory_Pool) void ACE_MMAP_Memory_Pool::dump (void) const { ACE_TRACE ("ACE_MMAP_Memory_Pool::dump"); } int ACE_MMAP_Memory_Pool::release (void) { ACE_TRACE ("ACE_MMAP_Memory_Pool::release"); #if defined (ACE_HAS_POSITION_INDEPENDENT_MALLOC) ACE_POSITION_INDEPENDENT_REPOSITORY::instance ()->unbind (this->mmap_.addr (), this->mmap_.size ()); #endif /* ACE_HAS_POSITION_INDEPENDENT_MALLOC */ this->mmap_.remove (); return 0; } int ACE_MMAP_Memory_Pool::sync (ssize_t len, int flags) { ACE_TRACE ("ACE_MMAP_Memory_Pool::sync"); if (len < 0) len = ACE_OS::lseek (this->mmap_.handle (), 0, SEEK_END); return this->mmap_.sync (len, flags); } // Sync bytes of the memory region to the backing store starting // at . int ACE_MMAP_Memory_Pool::sync (void *addr, size_t len, int flags) { ACE_TRACE ("ACE_MMAP_Memory_Pool::sync"); return ACE_OS::msync (addr, len, flags); } // Change the protection of the pages of the mapped region to // starting at base_addr_> up to bytes. If == -1 // then change protection of all pages in the mapped region. int ACE_MMAP_Memory_Pool::protect (ssize_t len, int prot) { ACE_TRACE ("ACE_MMAP_Memory_Pool::protect"); if (len < 0) len = ACE_OS::lseek (this->mmap_.handle (), 0, SEEK_END); return this->mmap_.protect (len, prot); } // Change the protection of the pages of the mapped region to // starting at up to bytes. int ACE_MMAP_Memory_Pool::protect (void *addr, size_t len, int prot) { ACE_TRACE ("ACE_MMAP_Memory_Pool::protect"); return ACE_OS::mprotect (addr, len, prot); } ACE_MMAP_Memory_Pool::ACE_MMAP_Memory_Pool (LPCTSTR backing_store_name, const OPTIONS *options) : base_addr_ (0), flags_ (MAP_SHARED), write_each_page_ (0), minimum_bytes_ (0), sa_ (0) { ACE_TRACE ("ACE_MMAP_Memory_Pool::ACE_MMAP_Memory_Pool"); #if (defined (ACE_HAS_SIGINFO_T) && !defined (ACE_LACKS_SI_ADDR)) || defined (ACE_WIN32) // For plaforms that give the faulting address. guess_on_fault_ = 0; #else // For plaforms that do NOT give the faulting address, let the // options decide whether to guess or not. if (options) guess_on_fault_ = options->guess_on_fault_; else // If no options are specified, default to true. guess_on_fault_ = 1; #endif // Only change the defaults if != 0. if (options) { if (options->use_fixed_addr_) { this->base_addr_ = options->base_addr_; ACE_SET_BITS (flags_, MAP_FIXED); } this->write_each_page_ = options->write_each_page_; this->minimum_bytes_ = options->minimum_bytes_; if (options->flags_ != 0) this->flags_ = options->flags_; if (options->sa_ != 0) this->sa_ = options->sa_; } if (backing_store_name == 0) // Only create a new unique filename for the backing store file // if the user didn't supply one... backing_store_name = ACE_DEFAULT_BACKING_STORE; // from "ace/OS.h" ACE_OS::strncpy (this->backing_store_name_, backing_store_name, (sizeof this->backing_store_name_ / sizeof (TCHAR))); #if !defined (ACE_WIN32) && !defined (CHORUS) if (this->signal_handler_.register_handler (SIGSEGV, this) == -1) ACE_ERROR ((LM_ERROR, "%p\n", this->backing_store_name_)); #endif /* ACE_WIN32 */ } // Compute the new map_size of the backing store and commit the // memory. int ACE_MMAP_Memory_Pool::commit_backing_store_name (size_t rounded_bytes, off_t &map_size) { ACE_TRACE ("ACE_MMAP_Memory_Pool::commit_backing_store_name"); #if defined (CHORUS) map_size = rounded_bytes; #else size_t seek_len; if (this->write_each_page_) // Write to the end of every block to ensure that we have enough // space in the backing store. seek_len = this->round_up (1); // round_up(1) is one page. else // We're willing to risk it all in the name of efficiency... seek_len = rounded_bytes; // The following loop will execute multiple times (if // this->write_each_page == 1) or just once (if // this->write_each_page == 0). for (size_t cur_block = 0; cur_block < rounded_bytes; cur_block += seek_len) { map_size = ACE_OS::lseek (this->mmap_.handle () , seek_len - 1, SEEK_END); if (map_size == -1 || ACE_OS::write (this->mmap_.handle (), "", 1) == -1) ACE_ERROR_RETURN ((LM_ERROR, ASYS_TEXT ("(%P|%t) %p\n"), this->backing_store_name_), -1); } // Increment by one to put us at the beginning of the next chunk... map_size++; #endif /* CHORUS */ return 0; } // Memory map the file up to bytes. int ACE_MMAP_Memory_Pool::map_file (off_t map_size) { ACE_TRACE ("ACE_MMAP_Memory_Pool::map_file"); // Unmap the existing mapping. this->mmap_.unmap (); // Remap the file. if (this->mmap_.map (map_size, PROT_RDWR, this->flags_, this->base_addr_, 0, this->sa_) == -1 || this->base_addr_ != 0 && this->mmap_.addr () != this->base_addr_) { #if 0 ACE_ERROR ((LM_ERROR, ASYS_TEXT ("(%P|%t) addr = %u, base_addr = %u, map_size = %u, %p\n"), this->mmap_.addr (), this->base_addr_, map_size, this->backing_store_name_)); #endif /* 0 */ return -1; } else { #if defined (ACE_HAS_POSITION_INDEPENDENT_MALLOC) ACE_POSITION_INDEPENDENT_REPOSITORY::instance ()->bind (this->base_addr_, map_size); #endif /* ACE_HAS_POSITION_INDEPENDENT_MALLOC */ return 0; } } // Ask operating system for more shared memory, increasing the mapping // accordingly. Note that this routine assumes that the appropriate // locks are held when it is called. void * ACE_MMAP_Memory_Pool::acquire (size_t nbytes, size_t &rounded_bytes) { ACE_TRACE ("ACE_MMAP_Memory_Pool::acquire"); rounded_bytes = this->round_up (nbytes); // ACE_DEBUG ((LM_DEBUG, "(%P|%t) acquiring more chunks, nbytes = // %d, rounded_bytes = %d\n", nbytes, rounded_bytes)); off_t map_size; if (this->commit_backing_store_name (rounded_bytes, map_size) == -1) return 0; else if (this->map_file (map_size) == -1) return 0; // ACE_DEBUG ((LM_DEBUG, "(%P|%t) acquired more chunks, nbytes = %d, // rounded_bytes = %d, map_size = %d\n", nbytes, rounded_bytes, // map_size)); return (void *) ((char *) this->mmap_.addr () + (this->mmap_.size () - rounded_bytes)); } // Ask system for initial chunk of shared memory. void * ACE_MMAP_Memory_Pool::init_acquire (size_t nbytes, size_t &rounded_bytes, int &first_time) { ACE_TRACE ("ACE_MMAP_Memory_Pool::init_acquire"); first_time = 0; if (nbytes < (size_t) this->minimum_bytes_) nbytes = this->minimum_bytes_; if (this->mmap_.open (this->backing_store_name_, O_RDWR | O_CREAT | O_TRUNC | O_EXCL, ACE_DEFAULT_FILE_PERMS, this->sa_) != -1) { // First time in, so need to acquire memory. first_time = 1; return this->acquire (nbytes, rounded_bytes); } else if (errno == EEXIST) { errno = 0; // Reopen file *without* using O_EXCL... if (this->mmap_.map (this->backing_store_name_, #if defined (CHORUS) nbytes, #else -1, #endif /* CHORUS */ O_RDWR, ACE_DEFAULT_FILE_PERMS, PROT_RDWR, this->flags_, this->base_addr_, 0, this->sa_) == -1) ACE_ERROR_RETURN ((LM_ERROR, ASYS_TEXT ("%p\n"), ASYS_TEXT ("open")), 0); return this->mmap_.addr (); } else ACE_ERROR_RETURN ((LM_ERROR, ASYS_TEXT ("%p\n"), ASYS_TEXT ("open")), 0); } int ACE_MMAP_Memory_Pool::remap (void *addr) { ACE_TRACE ("ACE_MMAP_Memory_Pool::remap"); ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("Remapping with fault address at: %X\n"), addr)); off_t current_map_size = ACE_OS::filesize (this->mmap_.handle ()); // ACE_OS::lseek (this->mmap_.handle (), 0, SEEK_END); if (!(addr < (void *) ((char *) this->mmap_.addr () + current_map_size) && addr >= this->mmap_.addr ())) return -1; // Extend the mapping to cover the size of the backing store. return this->map_file (current_map_size); } ACE_MMAP_Memory_Pool_Options::ACE_MMAP_Memory_Pool_Options (void *base_addr, int use_fixed_addr, int write_each_page, off_t minimum_bytes, u_int flags, int guess_on_fault, LPSECURITY_ATTRIBUTES sa) : base_addr_ (base_addr), use_fixed_addr_ (use_fixed_addr), write_each_page_ (write_each_page), minimum_bytes_ (minimum_bytes), flags_ (flags), guess_on_fault_ (guess_on_fault), sa_ (sa) { ACE_TRACE ("ACE_MMAP_Memory_Pool_Options::ACE_MMAP_Memory_Pool_Options"); // HP-UX 11, 64-bit bug workaround. #if defined (__hpux) && defined (__LP64__) long temp = ACE_DEFAULT_BASE_ADDRL; base_addr_ = (void *) temp; #endif /* defined (__hpux) && defined (__LP64__) */ } // Handle SIGSEGV and SIGBUS signals to remap memory properly. When a // process reads or writes to non-mapped memory a signal (SIGBUS or // SIGSEGV) will be triggered. At that point, the ACE_Sig_Handler // (which is part of the ACE_Reactor) will catch the signal and // dispatch the handle_signal() method defined here. If the SIGSEGV // signal occurred due to the fact that the mapping wasn't uptodate // with respect to the backing store, the handler method below will // update the mapping accordingly. When the signal handler returns, // the instruction should be restarted and the operation should work. int ACE_MMAP_Memory_Pool::handle_signal (int signum, siginfo_t *siginfo, ucontext_t *) { if (signum != SIGSEGV) return -1; else ; // ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("(%P|%t) received %S\n"), signum)); // ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("(%P|%t) new mapping address = %u\n"), (char *) this->base_addr_ + current_map_size)); #if defined (ACE_HAS_SIGINFO_T) && !defined (ACE_LACKS_SI_ADDR) // Make sure that the pointer causing the problem is within the // range of the backing store. if (siginfo != 0) { // ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("(%P|%t) si_signo = %d, si_code = %d, addr = %u\n"), siginfo->si_signo, siginfo->si_code, siginfo->si_addr)); if (this->remap ((void *) siginfo->si_addr) == -1) return -1; // ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) address %u out of range\n", // siginfo->si_addr), -1); return 0; } #else ACE_UNUSED_ARG(siginfo); #endif /* ACE_HAS_SIGINFO_T && !defined ACE_LACKS_SI_ADDR */ // If guess_on_fault_ is true, then we want to try to remap without // knowing the faulting address. guess_on_fault_ can only be true // on platforms that do not provide the faulting address through // signals or exceptions. // We check to see if the mapping is up to date. If it is, then this // fault isn't due to this mapping and we pass it on. if (guess_on_fault_) { // check if the current mapping is up to date. off_t current_map_size = ACE_OS::filesize (this->mmap_.handle ()); if (ACE_static_cast(size_t, current_map_size) == this->mmap_.size()) { // It is up to date so this is a bad address. return -1; } // Extend the mapping to cover the size of the backing store. return this->map_file (current_map_size); } else return -1; } ACE_ALLOC_HOOK_DEFINE(ACE_Lite_MMAP_Memory_Pool) ACE_Lite_MMAP_Memory_Pool::ACE_Lite_MMAP_Memory_Pool (LPCTSTR backing_store_name, const OPTIONS *options) : ACE_MMAP_Memory_Pool (backing_store_name, options) { ACE_TRACE ("ACE_Lite_MMAP_Memory_Pool::ACE_Lite_MMAP_Memory_Pool"); } int ACE_Lite_MMAP_Memory_Pool::sync (ssize_t, int) { ACE_TRACE ("ACE_Lite_MMAP_Memory_Pool::sync"); return 0; } int ACE_Lite_MMAP_Memory_Pool::sync (void *, size_t, int) { ACE_TRACE ("ACE_Lite_MMAP_Memory_Pool::sync"); return 0; } #if !defined (ACE_LACKS_SBRK) ACE_ALLOC_HOOK_DEFINE(ACE_Sbrk_Memory_Pool) // Ask system for more local memory via sbrk(2). void * ACE_Sbrk_Memory_Pool::acquire (size_t nbytes, size_t &rounded_bytes) { ACE_TRACE ("ACE_Sbrk_Memory_Pool::acquire"); rounded_bytes = this->round_up (nbytes); // ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("(%P|%t) acquiring more chunks, nbytes = %d, rounded_bytes = %d\n"), nbytes, rounded_bytes)); void *cp = ACE_OS::sbrk (rounded_bytes); if (cp == MAP_FAILED) ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) cp = %u\n", cp), 0); else // ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("(%P|%t) acquired more chunks, nbytes = %d, rounded_bytes = %d, new break = %u\n"), nbytes, rounded_bytes, cp)); return cp; } void ACE_Sbrk_Memory_Pool::dump (void) const { ACE_TRACE ("ACE_Sbrk_Memory_Pool::dump"); } ACE_Sbrk_Memory_Pool::ACE_Sbrk_Memory_Pool (LPCTSTR , const OPTIONS *) { ACE_TRACE ("ACE_Sbrk_Memory_Pool::ACE_Sbrk_Memory_Pool"); } #endif /* !ACE_LACKS_SBRK */ #if !defined (ACE_LACKS_SYSV_SHMEM) ACE_ALLOC_HOOK_DEFINE(ACE_Shared_Memory_Pool) ACE_Shared_Memory_Pool_Options::ACE_Shared_Memory_Pool_Options (char *base_addr, size_t max_segments, size_t file_perms, off_t minimum_bytes, size_t segment_size) : base_addr_ (base_addr), max_segments_ (max_segments), minimum_bytes_ (minimum_bytes), file_perms_ (file_perms), segment_size_ (segment_size) { ACE_TRACE ("ACE_Shared_Memory_Pool_Options::ACE_Shared_Memory_Pool_Options"); // HP-UX 11, 64-bit bug workaround #if defined (__hpux) && defined (__LP64__) long temp = ACE_DEFAULT_BASE_ADDRL; base_addr_ = (char *) temp; #endif /* defined (__hpux) && defined (__LP64__) */ } void ACE_Shared_Memory_Pool::dump (void) const { ACE_TRACE ("ACE_Shared_Memory_Pool::dump"); } int ACE_Shared_Memory_Pool::in_use (off_t &offset, size_t &counter) { offset = 0; SHM_TABLE *st = ACE_reinterpret_cast (SHM_TABLE *, this->base_addr_); shmid_ds buf; for (counter = 0; counter < this->max_segments_ && st[counter].used_ == 1; counter++) { if (ACE_OS::shmctl (st[counter].shmid_, IPC_STAT, &buf) == -1) ACE_ERROR_RETURN ((LM_ERROR, ASYS_TEXT ("(%P|%t) %p\n"), ASYS_TEXT ("shmctl")), -1); offset += buf.shm_segsz; // ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("(%P|%t) segment size = %d, offset = %d\n"), buf.shm_segsz, offset)); } return 0; } int ACE_Shared_Memory_Pool::find_seg (const void* const searchPtr, off_t &offset, size_t &counter) { offset = 0; SHM_TABLE *st = ACE_reinterpret_cast (SHM_TABLE *, this->base_addr_); shmid_ds buf; for (counter = 0; counter < this->max_segments_ && st[counter].used_ == 1; counter++) { if (ACE_OS::shmctl (st[counter].shmid_, IPC_STAT, &buf) == -1) ACE_ERROR_RETURN ((LM_ERROR, ASYS_TEXT ("(%P|%t) %p\n"), ASYS_TEXT ("shmctl")), -1); offset += buf.shm_segsz; // If segment 'counter' starts at a location greater than the // place we are searching for. We then decrement the offset to // the start of counter-1. (flabar@vais.net) if ((offset + (off_t)(this->base_addr_) ) > (off_t)searchPtr) { --counter; offset -= buf.shm_segsz; return 0; } // ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("(%P|%t) segment size = %d, offset = %d\n"), buf.shm_segsz, offset)); } return 0; } int ACE_Shared_Memory_Pool::commit_backing_store_name (size_t rounded_bytes, off_t &offset) { ACE_TRACE ("ACE_Shared_Memory_Pool::update"); size_t counter; SHM_TABLE *st = ACE_reinterpret_cast (SHM_TABLE *, this->base_addr_); if (this->in_use (offset, counter) == -1) return -1; if (counter == this->max_segments_) ACE_ERROR_RETURN ((LM_ERROR, "exceeded max number of segments = %d, base = %u, offset = %u\n", counter, this->base_addr_, offset), -1); else { int shmid = ACE_OS::shmget (st[counter].key_, rounded_bytes, this->file_perms_ | IPC_CREAT | IPC_EXCL); if (shmid == -1) ACE_ERROR_RETURN ((LM_ERROR, ASYS_TEXT ("(%P|%t) %p\n"), ASYS_TEXT ("shmget")), 0); st[counter].shmid_ = shmid; st[counter].used_ = 1; void *address = (void *) (((char *) this->base_addr_) + offset); void *shmem = ACE_OS::shmat (st[counter].shmid_, (char *) address, 0); if (shmem != address) ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p, shmem = %u, address = %u\n", "shmat", shmem, address), 0); } return 0; } // Handle SIGSEGV and SIGBUS signals to remap shared memory properly. int ACE_Shared_Memory_Pool::handle_signal (int , siginfo_t *siginfo, ucontext_t *) { ACE_TRACE ("ACE_Shared_Memory_Pool::handle_signal"); // ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("signal %S occurred\n"), signum)); #if defined (ACE_HAS_SIGINFO_T) && !defined (ACE_LACKS_SI_ADDR) off_t offset; // Make sure that the pointer causing the problem is within the // range of the backing store. if (siginfo != 0) { // ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("(%P|%t) si_signo = %d, si_code = %d, addr = %u\n"), siginfo->si_signo, siginfo->si_code, siginfo->si_addr)); size_t counter; if (this->in_use (offset, counter) == -1) ACE_ERROR ((LM_ERROR, ASYS_TEXT ("(%P|%t) %p\n"), ASYS_TEXT ("in_use"))); #if !defined(_UNICOS) else if (!(siginfo->si_code == SEGV_MAPERR && siginfo->si_addr < (((char *) this->base_addr_) + offset) && siginfo->si_addr >= ((char *) this->base_addr_))) ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) address %u out of range\n", siginfo->si_addr), -1); #else /* ! _UNICOS */ else if (!(siginfo->si_code == SEGV_MEMERR && siginfo->si_addr < (((unsigned long) this->base_addr_) + offset) && siginfo->si_addr >= ((unsigned long) this->base_addr_))) ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) address %u out of range\n", siginfo->si_addr), -1); #endif /* ! _UNICOS */ } // The above if case will check to see that the address is in the // proper range. Therefore there is a segment out there that the // pointer wants to point into. Find the segment that someone else // has used and attach to it (flabar@vais.net) size_t counter; // ret value to get shmid from the st table. #if !defined(_UNICOS) if (this->find_seg (siginfo->si_addr, offset, counter) == -1) #else /* ! _UNICOS */ if (this->find_seg ((const void *)siginfo->si_addr, offset, counter) == -1) #endif /* ! _UNICOS */ ACE_ERROR_RETURN ((LM_ERROR, ASYS_TEXT ("(%P|%t) %p\n"), ASYS_TEXT ("in_use")), -1); void *address = (void *) (((char *) this->base_addr_) + offset); SHM_TABLE *st = ACE_reinterpret_cast (SHM_TABLE *, this->base_addr_); void *shmem = ACE_OS::shmat (st[counter].shmid_, (char *) address, 0); if (shmem != address) ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p, shmem = %u, address = %u\n", "shmat", shmem, address), 0); // NOTE: this won't work if we dont have SIGINFO_T or SI_ADDR #else ACE_UNUSED_ARG (siginfo); #endif /* ACE_HAS_SIGINFO_T && !defined (ACE_LACKS_SI_ADDR) */ return 0; } ACE_Shared_Memory_Pool::ACE_Shared_Memory_Pool (LPCTSTR backing_store_name, const OPTIONS *options) : base_addr_ (0), file_perms_ (ACE_DEFAULT_FILE_PERMS), max_segments_ (ACE_DEFAULT_MAX_SEGMENTS), minimum_bytes_ (0), segment_size_ (ACE_DEFAULT_SEGMENT_SIZE) { ACE_TRACE ("ACE_Shared_Memory_Pool::ACE_Shared_Memory_Pool"); // Only change the defaults if != 0. if (options) { this->base_addr_ = (void *) options->base_addr_; this->max_segments_ = options->max_segments_; this->file_perms_ = options->file_perms_; this->minimum_bytes_ = options->minimum_bytes_; this->segment_size_ = options->segment_size_; } if (backing_store_name) { // Convert the string into a number that is used as the segment // key. int segment_key; int result = ::sscanf (backing_store_name, "%d", &segment_key); if (result == 0 || result == EOF) // The conversion to a number failed so hash with crc32 // ACE::crc32 is also used in . this->base_shm_key_ = (key_t) ACE::crc32 (backing_store_name); else this->base_shm_key_ = segment_key; if (this->base_shm_key_ == IPC_PRIVATE) // Make sure that the segment can be shared between unrelated // processes. this->base_shm_key_ = ACE_DEFAULT_SHM_KEY; } else this->base_shm_key_ = ACE_DEFAULT_SHM_KEY; if (this->signal_handler_.register_handler (SIGSEGV, this) == -1) ACE_ERROR ((LM_ERROR, ASYS_TEXT ("%p\n"), ASYS_TEXT ("ACE_Sig_Handler::register_handler"))); } // Ask system for more shared memory. void * ACE_Shared_Memory_Pool::acquire (size_t nbytes, size_t &rounded_bytes) { ACE_TRACE ("ACE_Shared_Memory_Pool::acquire"); rounded_bytes = this->round_up (nbytes); // ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("(%P|%t) acquiring more chunks, nbytes = %d, rounded_bytes = %d\n"), nbytes, rounded_bytes)); off_t offset; if (this->commit_backing_store_name (rounded_bytes, offset) == -1) return 0; // ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("(%P|%t) acquired more chunks, nbytes = %d, rounded_bytes = %d\n"), nbytes, rounded_bytes)); return ((char *) this->base_addr_) + offset; } // Ask system for initial chunk of shared memory. void * ACE_Shared_Memory_Pool::init_acquire (size_t nbytes, size_t &rounded_bytes, int &first_time) { ACE_TRACE ("ACE_Shared_Memory_Pool::init_acquire"); off_t shm_table_offset = ACE::round_to_pagesize (sizeof (SHM_TABLE)); rounded_bytes = this->round_up (nbytes > (size_t) this->minimum_bytes_ ? nbytes : (size_t) this->minimum_bytes_); // Acquire the semaphore to serialize initialization and prevent // race conditions. int shmid = ACE_OS::shmget (this->base_shm_key_, rounded_bytes + shm_table_offset, this->file_perms_ | IPC_CREAT | IPC_EXCL); if (shmid == -1) { if (errno != EEXIST) ACE_ERROR_RETURN ((LM_ERROR, ASYS_TEXT ("(%P|%t) %p\n"), ASYS_TEXT ("shmget")), 0); first_time = 0; shmid = ACE_OS::shmget (this->base_shm_key_, 0, 0); if (shmid == -1) ACE_ERROR_RETURN ((LM_ERROR, ASYS_TEXT ("(%P|%t) %p\n"), ASYS_TEXT ("shmget")), 0); // This implementation doesn't care if we don't get the key we // want... this->base_addr_ = ACE_OS::shmat (shmid, (char *) this->base_addr_, 0); if (this->base_addr_ == 0) ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p, base_addr = %u\n", "shmat", this->base_addr_), 0); } else { first_time = 1; // This implementation doesn't care if we don't get the key we // want... this->base_addr_ = ACE_OS::shmat (shmid, (char *) this->base_addr_, 0); if (this->base_addr_ == 0) ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p, base_addr = %u\n", "shmat", this->base_addr_), 0); SHM_TABLE *st = ACE_reinterpret_cast (SHM_TABLE *, this->base_addr_); st[0].key_ = this->base_shm_key_; st[0].shmid_ = shmid; st[0].used_ = 1; for (size_t counter = 1; // Skip over the first entry... counter < this->max_segments_; counter++) { st[counter].key_ = this->base_shm_key_ + counter; st[counter].shmid_ = 0; st[counter].used_ = 0; } } return (void *) (((char *) this->base_addr_) + shm_table_offset); } // Instruct the memory pool to release all of its resources. int ACE_Shared_Memory_Pool::release (void) { ACE_TRACE ("ACE_Shared_Memory_Pool::release"); int result = 0; SHM_TABLE *st = ACE_reinterpret_cast (SHM_TABLE *, this->base_addr_); for (size_t counter = 0; counter < this->max_segments_ && st[counter].used_ == 1; counter++) if (ACE_OS::shmctl (st[counter].shmid_, IPC_RMID, 0) == -1) result = -1; return result; } #endif /* !ACE_LACKS_SYSV_SHMEM */ #if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) template class ACE_Auto_Basic_Array_Ptr; template class ACE_Unbounded_Set; template class ACE_Unbounded_Set_Iterator; #elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) #pragma instantiate ACE_Auto_Basic_Array_Ptr #pragma instantiate ACE_Unbounded_Set #pragma instantiate ACE_Unbounded_Set_Iterator #endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */