Make a memory pool that is based on System V shared memory (shmget(2) etc.). This implementation allows memory to be shared between processes. If your platform doesn't support System V shared memory (e.g., Win32 and many RTOS platforms do not) then you should use ACE_MMAP_Memory_Pool instead of this class. In fact, you should probably use ACE_MMAP_Memory_Pool on platforms that *do* support System V shared memory since it provides more powerful features, such as persistent backing store and greatly scalability. More...
#include <Shared_Memory_Pool.h>
Classes | |
struct | SHM_TABLE |
Keeps track of all the segments being used. More... | |
Public Types | |
typedef ACE_Shared_Memory_Pool_Options | OPTIONS |
Public Member Functions | |
ACE_Shared_Memory_Pool (const ACE_TCHAR *backing_store_name=0, const OPTIONS *options=0) | |
Initialize the pool. | |
virtual | ~ACE_Shared_Memory_Pool (void) |
virtual void * | init_acquire (size_t nbytes, size_t &rounded_bytes, int &first_time) |
Ask system for initial chunk of local memory. | |
virtual void * | acquire (size_t nbytes, size_t &rounded_bytes) |
virtual int | release (int destroy=1) |
Instruct the memory pool to release all of its resources. | |
virtual int | sync (ssize_t len=-1, int flags=MS_SYNC) |
virtual int | sync (void *addr, size_t len, int flags=MS_SYNC) |
Sync the memory region to the backing store starting at addr. | |
virtual int | protect (ssize_t len=-1, int prot=PROT_RDWR) |
virtual int | protect (void *addr, size_t len, int prot=PROT_RDWR) |
virtual void * | base_addr (void) const |
virtual void | dump (void) const |
Dump the state of an object. | |
Public Attributes | |
ACE_ALLOC_HOOK_DECLARE | |
Declare the dynamic allocation hooks. | |
Protected Member Functions | |
virtual size_t | round_up (size_t nbytes) |
virtual int | commit_backing_store_name (size_t rounded_bytes, ACE_OFF_T &offset) |
virtual int | find_seg (const void *const searchPtr, ACE_OFF_T &offset, size_t &counter) |
Find the segment that contains the searchPtr. | |
virtual int | in_use (ACE_OFF_T &offset, size_t &counter) |
Determine how much memory is currently in use. | |
virtual int | handle_signal (int signum, siginfo_t *, ucontext_t *) |
Protected Attributes | |
void * | base_addr_ |
size_t | file_perms_ |
File permissions to use when creating/opening a segment. | |
size_t | max_segments_ |
Number of shared memory segments in the <SHM_TABLE> table. | |
ACE_OFF_T | minimum_bytes_ |
What the minimim bytes of the initial segment should be. | |
size_t | segment_size_ |
Shared memory segment size. | |
key_t | base_shm_key_ |
Base shared memory key for the segment. | |
ACE_Sig_Handler | signal_handler_ |
Handles SIGSEGV. |
Make a memory pool that is based on System V shared memory (shmget(2) etc.). This implementation allows memory to be shared between processes. If your platform doesn't support System V shared memory (e.g., Win32 and many RTOS platforms do not) then you should use ACE_MMAP_Memory_Pool instead of this class. In fact, you should probably use ACE_MMAP_Memory_Pool on platforms that *do* support System V shared memory since it provides more powerful features, such as persistent backing store and greatly scalability.
Definition at line 82 of file Shared_Memory_Pool.h.
Definition at line 85 of file Shared_Memory_Pool.h.
ACE_Shared_Memory_Pool::ACE_Shared_Memory_Pool | ( | const ACE_TCHAR * | backing_store_name = 0 , |
|
const OPTIONS * | options = 0 | |||
) |
Initialize the pool.
Definition at line 228 of file Shared_Memory_Pool.cpp.
: 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 <options> != 0. if (options) { this->base_addr_ = reinterpret_cast<void *> (const_cast<char *> (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 (ACE_TEXT_ALWAYS_CHAR (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 <SV_Semaphore_Simple>. this->base_shm_key_ = (key_t) ACE::crc32 (ACE_TEXT_ALWAYS_CHAR (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, ACE_TEXT ("%p\n"), ACE_TEXT ("ACE_Sig_Handler::register_handler"))); }
ACE_Shared_Memory_Pool::~ACE_Shared_Memory_Pool | ( | void | ) | [virtual] |
Definition at line 282 of file Shared_Memory_Pool.cpp.
{ }
void * ACE_Shared_Memory_Pool::acquire | ( | size_t | nbytes, | |
size_t & | rounded_bytes | |||
) | [virtual] |
Acquire at least nbytes from the memory pool. rounded_byes is the actual number of bytes allocated. Also acquires an internal semaphore that ensures proper serialization of Memory_Pool initialization across processes.
Definition at line 289 of file Shared_Memory_Pool.cpp.
{ ACE_TRACE ("ACE_Shared_Memory_Pool::acquire"); rounded_bytes = this->round_up (nbytes); // ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) acquiring more chunks, nbytes = %d, rounded_bytes = %d\n"), nbytes, rounded_bytes)); ACE_OFF_T offset; if (this->commit_backing_store_name (rounded_bytes, offset) == -1) return 0; // ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) acquired more chunks, nbytes = %d, rounded_bytes = %d\n"), nbytes, rounded_bytes)); return ((char *) this->base_addr_) + offset; }
void * ACE_Shared_Memory_Pool::base_addr | ( | void | ) | const [virtual] |
Return the base address of this memory pool, 0 if base_addr never changes.
Definition at line 440 of file Shared_Memory_Pool.cpp.
{ ACE_TRACE ("ACE_Shared_Memory_Pool::base_addr"); return this->base_addr_; }
int ACE_Shared_Memory_Pool::commit_backing_store_name | ( | size_t | rounded_bytes, | |
ACE_OFF_T & | offset | |||
) | [protected, virtual] |
Commits a new shared memory segment if necessary after an <acquire> or a signal. offset is set to the new offset into the backing store.
Definition at line 100 of file Shared_Memory_Pool.cpp.
{ ACE_TRACE ("ACE_Shared_Memory_Pool::commit_backing_store_name"); size_t counter; SHM_TABLE *st = 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, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("shmget")), -1); 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, ACE_TEXT("(%P|%t) %p, shmem = %u, address = %u\n"), ACE_TEXT("shmat"), shmem, address), -1); } return 0; }
void ACE_Shared_Memory_Pool::dump | ( | void | ) | const [virtual] |
Dump the state of an object.
Definition at line 32 of file Shared_Memory_Pool.cpp.
{ #if defined (ACE_HAS_DUMP) ACE_TRACE ("ACE_Shared_Memory_Pool::dump"); #endif /* ACE_HAS_DUMP */ }
int ACE_Shared_Memory_Pool::find_seg | ( | const void *const | searchPtr, | |
ACE_OFF_T & | offset, | |||
size_t & | counter | |||
) | [protected, virtual] |
Find the segment that contains the searchPtr.
Definition at line 64 of file Shared_Memory_Pool.cpp.
{ offset = 0; SHM_TABLE *st = 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, ACE_TEXT ("(%P|%t) %p\n"), ACE_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 (((ptrdiff_t) offset + (ptrdiff_t) (this->base_addr_)) > (ptrdiff_t) searchPtr) { --counter; offset -= buf.shm_segsz; return 0; } // ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) segment size = %d, offset = %d\n"), buf.shm_segsz, offset)); } return 0; }
int ACE_Shared_Memory_Pool::handle_signal | ( | int | signum, | |
siginfo_t * | siginfo, | |||
ucontext_t * | ||||
) | [protected, virtual] |
Handle SIGSEGV and SIGBUS signals to remap shared memory properly.
Reimplemented from ACE_Event_Handler.
Definition at line 150 of file Shared_Memory_Pool.cpp.
{ ACE_TRACE ("ACE_Shared_Memory_Pool::handle_signal"); // ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("signal %S occurred\n"), signum)); // While FreeBSD 5.X has a siginfo_t struct with a si_addr field, // it does not define SEGV_MAPERR. #if defined (ACE_HAS_SIGINFO_T) && !defined (ACE_LACKS_SI_ADDR) && \ (defined (SEGV_MAPERR) || defined (SEGV_MEMERR)) ACE_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, ACE_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, ACE_TEXT ("(%P|%t) %p\n"), ACE_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, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("in_use")), -1); void *address = (void *) (((char *) this->base_addr_) + offset); SHM_TABLE *st = 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, ACE_TEXT("(%P|%t) %p, shmem = %u, address = %u\n"), ACE_TEXT("shmat"), shmem, address), -1); // 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; }
int ACE_Shared_Memory_Pool::in_use | ( | ACE_OFF_T & | offset, | |
size_t & | counter | |||
) | [protected, virtual] |
Determine how much memory is currently in use.
Definition at line 40 of file Shared_Memory_Pool.cpp.
{ offset = 0; SHM_TABLE *st = 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, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("shmctl")), -1); offset += buf.shm_segsz; // ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) segment size = %d, offset = %d\n"), buf.shm_segsz, offset)); } return 0; }
void * ACE_Shared_Memory_Pool::init_acquire | ( | size_t | nbytes, | |
size_t & | rounded_bytes, | |||
int & | first_time | |||
) | [virtual] |
Ask system for initial chunk of local memory.
Definition at line 310 of file Shared_Memory_Pool.cpp.
{ ACE_TRACE ("ACE_Shared_Memory_Pool::init_acquire"); ACE_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, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("shmget")), 0); first_time = 0; shmid = ACE_OS::shmget (this->base_shm_key_, 0, 0); if (shmid == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("shmget")), 0); // This implementation doesn't care if we don't get the key we // want... this->base_addr_ = ACE_OS::shmat (shmid, reinterpret_cast<char *> (this->base_addr_), 0); if (this->base_addr_ == reinterpret_cast<void *> (-1)) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT("(%P|%t) %p, base_addr = %u\n"), ACE_TEXT("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, reinterpret_cast<char *> (this->base_addr_), 0); if (this->base_addr_ == reinterpret_cast<char *> (-1)) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT("(%P|%t) %p, base_addr = %u\n"), ACE_TEXT("shmat"), this->base_addr_), 0); SHM_TABLE *st = 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); }
int ACE_Shared_Memory_Pool::protect | ( | ssize_t | len = -1 , |
|
int | prot = PROT_RDWR | |||
) | [virtual] |
Change the protection of the pages of the mapped region to prot starting at this->base_addr_
up to len bytes. If len == -1 then change protection of all pages in the mapped region.
Definition at line 426 of file Shared_Memory_Pool.cpp.
{ ACE_TRACE ("ACE_Shared_Memory_Pool::protect"); return 0; }
int ACE_Shared_Memory_Pool::protect | ( | void * | addr, | |
size_t | len, | |||
int | prot = PROT_RDWR | |||
) | [virtual] |
Change the protection of the pages of the mapped region to prot starting at addr up to len bytes.
Definition at line 433 of file Shared_Memory_Pool.cpp.
{ ACE_TRACE ("ACE_Shared_Memory_Pool::protect"); return 0; }
int ACE_Shared_Memory_Pool::release | ( | int | destroy = 1 |
) | [virtual] |
Instruct the memory pool to release all of its resources.
Definition at line 395 of file Shared_Memory_Pool.cpp.
{ ACE_TRACE ("ACE_Shared_Memory_Pool::release"); int result = 0; SHM_TABLE *st = 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; }
size_t ACE_Shared_Memory_Pool::round_up | ( | size_t | nbytes | ) | [protected, virtual] |
Implement the algorithm for rounding up the request to an appropriate chunksize.
Definition at line 450 of file Shared_Memory_Pool.cpp.
{ ACE_TRACE ("ACE_Shared_Memory_Pool::round_up"); if (nbytes < this->segment_size_) nbytes = this->segment_size_; return ACE::round_to_pagesize (nbytes); }
int ACE_Shared_Memory_Pool::sync | ( | void * | addr, | |
size_t | len, | |||
int | flags = MS_SYNC | |||
) | [virtual] |
Sync the memory region to the backing store starting at addr.
Definition at line 419 of file Shared_Memory_Pool.cpp.
{ ACE_TRACE ("ACE_Shared_Memory_Pool::sync"); return 0; }
int ACE_Shared_Memory_Pool::sync | ( | ssize_t | len = -1 , |
|
int | flags = MS_SYNC | |||
) | [virtual] |
Sync the memory region to the backing store starting at this->base_addr_
.
Definition at line 412 of file Shared_Memory_Pool.cpp.
{ ACE_TRACE ("ACE_Shared_Memory_Pool::sync"); return 0; }
Declare the dynamic allocation hooks.
Definition at line 136 of file Shared_Memory_Pool.h.
void* ACE_Shared_Memory_Pool::base_addr_ [protected] |
Base address of the shared memory segment. If this has the value of 0 then the OS is free to select any address, otherwise this value is what the OS must try to use to map the shared memory segment.
Definition at line 170 of file Shared_Memory_Pool.h.
key_t ACE_Shared_Memory_Pool::base_shm_key_ [protected] |
Base shared memory key for the segment.
Definition at line 185 of file Shared_Memory_Pool.h.
size_t ACE_Shared_Memory_Pool::file_perms_ [protected] |
File permissions to use when creating/opening a segment.
Definition at line 173 of file Shared_Memory_Pool.h.
size_t ACE_Shared_Memory_Pool::max_segments_ [protected] |
Number of shared memory segments in the <SHM_TABLE> table.
Definition at line 176 of file Shared_Memory_Pool.h.
ACE_OFF_T ACE_Shared_Memory_Pool::minimum_bytes_ [protected] |
What the minimim bytes of the initial segment should be.
Definition at line 179 of file Shared_Memory_Pool.h.
size_t ACE_Shared_Memory_Pool::segment_size_ [protected] |
Shared memory segment size.
Definition at line 182 of file Shared_Memory_Pool.h.
Handles SIGSEGV.
Definition at line 197 of file Shared_Memory_Pool.h.