diff options
author | jtc <jtc@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2004-10-11 18:46:56 +0000 |
---|---|---|
committer | jtc <jtc@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2004-10-11 18:46:56 +0000 |
commit | a060cde8d37b75e0f52a971e785173fbebdfbdc8 (patch) | |
tree | 66e9a4720d3b3596dc27eff38ee6b6ed7f67658a | |
parent | 1dae2ac679b1e4dbbf27e394111d7f45f39fb409 (diff) | |
download | ATCD-a060cde8d37b75e0f52a971e785173fbebdfbdc8.tar.gz |
ChangeLogTag: Mon Oct 11 10:14:36 2004 J.T. Conklin <jtc@acorntoolworks.com>
-rw-r--r-- | ChangeLog | 40 | ||||
-rw-r--r-- | ace/Local_Memory_Pool.cpp | 148 | ||||
-rw-r--r-- | ace/Local_Memory_Pool.h | 128 | ||||
-rw-r--r-- | ace/MMAP_Memory_Pool.cpp | 518 | ||||
-rw-r--r-- | ace/MMAP_Memory_Pool.h | 288 | ||||
-rw-r--r-- | ace/Makefile.am | 15 | ||||
-rw-r--r-- | ace/Memory_Pool.cpp | 1352 | ||||
-rw-r--r-- | ace/Memory_Pool.h | 794 | ||||
-rw-r--r-- | ace/Memory_Pool.inl | 269 | ||||
-rw-r--r-- | ace/Pagefile_Memory_Pool.cpp | 362 | ||||
-rw-r--r-- | ace/Pagefile_Memory_Pool.h | 192 | ||||
-rw-r--r-- | ace/Pagefile_Memory_Pool.inl | 48 | ||||
-rw-r--r-- | ace/Sbrk_Memory_Pool.cpp | 119 | ||||
-rw-r--r-- | ace/Sbrk_Memory_Pool.h | 107 | ||||
-rw-r--r-- | ace/Shared_Memory_Pool.cpp | 449 | ||||
-rw-r--r-- | ace/Shared_Memory_Pool.h | 200 | ||||
-rw-r--r-- | ace/ace.mpc | 6 | ||||
-rw-r--r-- | examples/System_V_IPC/SV_Semaphores/Semaphores_1.cpp | 1 | ||||
-rw-r--r-- | tests/SV_Shared_Memory_Test.cpp | 3 |
19 files changed, 2625 insertions, 2414 deletions
diff --git a/ChangeLog b/ChangeLog index 0d7d4425907..911a2c9838b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,43 @@ +Mon Oct 11 10:14:36 2004 J.T. Conklin <jtc@acorntoolworks.com> + + * examples/System_V_IPC/SV_Semaphores/Semaphores_1.cpp: + * tests/SV_Shared_Memory_Test.cpp: + + Changed to #include ace/SV_Sempahore_Complex.h, which had been + implicitly included via Memory_Pool.h, even though it was not + needed by the interface or implementation. + + * ace/Makefile.am: + * ace/ace.mpc: + + Updated. + + * ace/Local_Memory_Pool.cpp: + * ace/Local_Memory_Pool.h: + * ace/MMAP_Memory_Pool.cpp: + * ace/MMAP_Memory_Pool.h: + * ace/Pagefile_Memory_Pool.cpp: + * ace/Pagefile_Memory_Pool.h: + * ace/Pagefile_Memory_Pool.inl: + * ace/Sbrk_Memory_Pool.cpp: + * ace/Sbrk_Memory_Pool.h: + * ace/Shared_Memory_Pool.cpp: + * ace/Shared_Memory_Pool.h: + + New files. + + * ace/Memory_Pool.cpp: + * ace/Memory_Pool.inl: + * ace/Memory_Pool.h: + + Split apart Memory_Pool.{cpp,h,inl} into a separate set of files + for each class and "outlining" inlined virtual functions. Since + the implementations are related by interface, not inheritance; + locating them all in the same file typically results in static + footprint bloat. + + Removed Memory_Pool.{cpp,inl}. + Mon Oct 10 12:48:03 2004 Martin Corino <mcorino@remedy.nl> * ace/config-hpux-11.00.h: diff --git a/ace/Local_Memory_Pool.cpp b/ace/Local_Memory_Pool.cpp new file mode 100644 index 00000000000..8f12592e871 --- /dev/null +++ b/ace/Local_Memory_Pool.cpp @@ -0,0 +1,148 @@ +// $Id$ + +// Local_Memory_Pool.cpp +#include "ace/Local_Memory_Pool.h" +#include "ace/Auto_Ptr.h" + +ACE_RCSID(ace, Local_Memory_Pool, "$Id$") + +ACE_ALLOC_HOOK_DEFINE(ACE_Local_Memory_Pool) + +void +ACE_Local_Memory_Pool::dump (void) const +{ +#if defined (ACE_HAS_DUMP) + ACE_TRACE ("ACE_Local_Memory_Pool::dump"); +#endif /* ACE_HAS_DUMP */ +} + +ACE_Local_Memory_Pool::ACE_Local_Memory_Pool (const ACE_TCHAR *, + const OPTIONS *) +{ + ACE_TRACE ("ACE_Local_Memory_Pool::ACE_Local_Memory_Pool"); +} + +ACE_Local_Memory_Pool::~ACE_Local_Memory_Pool (void) +{ + // Free up all memory allocated by this pool. + this->release (); +} + +// Ask system for initial chunk of local memory. +void * +ACE_Local_Memory_Pool::init_acquire (size_t nbytes, + size_t &rounded_bytes, + int &first_time) +{ + ACE_TRACE ("ACE_Local_Memory_Pool::init_acquire"); + // Note that we assume that when ACE_Local_Memory_Pool is used, + // ACE_Malloc's constructor will only get called once. If this + // assumption doesn't hold, we are in deep trouble! + + first_time = 1; + return this->acquire (nbytes, rounded_bytes); +} + +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<char> cp (temp); + + if (this->allocated_chunks_.insert (cp.get ()) != 0) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_LIB_TEXT ("(%P|%t) insertion into set failed\n")), + 0); + + return cp.release (); +} + +int +ACE_Local_Memory_Pool::release (int) +{ + ACE_TRACE ("ACE_Local_Memory_Pool::release"); + + // Zap the memory we allocated. + for (ACE_Unbounded_Set<char *>::iterator i = this->allocated_chunks_.begin (); + i != this->allocated_chunks_.end (); + ++i) + delete [] *i; + this->allocated_chunks_.reset (); + return 0; +} + +int +ACE_Local_Memory_Pool::sync (ssize_t, int) +{ + ACE_TRACE ("ACE_Local_Memory_Pool::sync"); + return 0; +} + +int +ACE_Local_Memory_Pool::sync (void *, size_t, int) +{ + ACE_TRACE ("ACE_Local_Memory_Pool::sync"); + return 0; +} + +int +ACE_Local_Memory_Pool::protect (ssize_t, int) +{ + ACE_TRACE ("ACE_Local_Memory_Pool::protect"); + return 0; +} + +int +ACE_Local_Memory_Pool::protect (void *, size_t, int) +{ + ACE_TRACE ("ACE_Local_Memory_Pool::protect"); + return 0; +} + +#if defined (ACE_WIN32) +int +ACE_Local_Memory_Pool::seh_selector (void *) +{ + return 0; + // Continue propagate the structural exception up. +} +#endif /* ACE_WIN32 */ + +int +ACE_Local_Memory_Pool::remap (void *) +{ + return 0; + // Not much can be done. +} + +void * +ACE_Local_Memory_Pool::base_addr (void) const +{ + return 0; +} + +// Let the underlying new operator figure out the alignment... +size_t +ACE_Local_Memory_Pool::round_up (size_t nbytes) +{ + ACE_TRACE ("ACE_Local_Memory_Pool::round_up"); + return ACE::round_to_pagesize (static_cast<off_t> (nbytes)); +} + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +template class ACE_Auto_Basic_Array_Ptr<char>; +template class ACE_Unbounded_Set<char *>; +template class ACE_Unbounded_Set_Iterator<char *>; +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +#pragma instantiate ACE_Auto_Basic_Array_Ptr<char> +#pragma instantiate ACE_Unbounded_Set<char *> +#pragma instantiate ACE_Unbounded_Set_Iterator<char *> +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/ace/Local_Memory_Pool.h b/ace/Local_Memory_Pool.h new file mode 100644 index 00000000000..a4a0add9ff6 --- /dev/null +++ b/ace/Local_Memory_Pool.h @@ -0,0 +1,128 @@ +/* -*- C++ -*- */ + +//============================================================================= +/** + * @file Memory_Pool.h + * + * $Id$ + * + * @author Dougls C. Schmidt <schmidt@cs.wustl.edu> + * @author Prashant Jain <pjain@cs.wustl.edu> + */ +//============================================================================= + +#ifndef ACE_LOCAL_MEMORY_POOL_H +#define ACE_LOCAL_MEMORY_POOL_H +#include /**/ "ace/pre.h" + +#include "ace/ACE.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Unbounded_Set.h" + +/** + * @class ACE_Local_Memory_Pool_Options + * + * @brief Helper class for Local Memory Pool constructor options. + * + * This should be a nested class, but that breaks too many + * compilers. + */ +class ACE_Export ACE_Local_Memory_Pool_Options +{ +}; + +/** + * @class ACE_Local_Memory_Pool + * + * @brief Make a memory pool that is based on C++ new/delete. This is + * useful for integrating existing components that use new/delete + * into the ACE Malloc scheme... + */ +class ACE_Export ACE_Local_Memory_Pool +{ +public: + typedef ACE_Local_Memory_Pool_Options OPTIONS; + + /// Initialize the pool. + ACE_Local_Memory_Pool (const ACE_TCHAR *backing_store_name = 0, + const OPTIONS *options = 0); + + virtual ~ACE_Local_Memory_Pool (void); + + /// Ask system for initial chunk of local memory. + virtual void *init_acquire (size_t nbytes, + size_t &rounded_bytes, + int &first_time); + + /// Acquire at least @a nbytes from the memory pool. @a rounded_bytes is + /// the actual number of bytes allocated. + virtual void *acquire (size_t nbytes, + size_t &rounded_bytes); + + /// Instruct the memory pool to release all of its resources. + virtual int release (int destroy = 1); + + /** + * Sync <len> bytes of the memory region to the backing store + * starting at <this->base_addr_>. If <len> == -1 then sync the + * whole region. + */ + virtual int sync (ssize_t len = -1, int flags = MS_SYNC); + + /// Sync <len> bytes of the memory region to the backing store + /// starting at <addr_>. + virtual int sync (void *addr, size_t len, int flags = MS_SYNC); + + /** + * 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. + */ + virtual int protect (ssize_t len = -1, int prot = PROT_RDWR); + + /// Change the protection of the pages of the mapped region to <prot> + /// starting at <addr> up to <len> bytes. + virtual int protect (void *addr, size_t len, int prot = PROT_RDWR); + +#if defined (ACE_WIN32) + /** + * Win32 Structural exception selector. The return value decides + * how to handle memory pool related structural exceptions. Returns + * 1, 0, or , -1. + */ + virtual int seh_selector (void *); +#endif /* ACE_WIN32 */ + + /** + * Try to extend the virtual address space so that <addr> is now + * covered by the address mapping. Always returns 0 since we can't + * remap a local memory pool. + */ + virtual int remap (void *addr); + + /// Return the base address of this memory pool, 0 if base_addr + /// never changes. + virtual void *base_addr (void) const; + + /// Dump the state of an object. + virtual void dump (void) const; + + /// Declare the dynamic allocation hooks. + ACE_ALLOC_HOOK_DECLARE; + +protected: + /// List of memory that we have allocated. + ACE_Unbounded_Set<char *> allocated_chunks_; + + /// Implement the algorithm for rounding up the request to an + /// appropriate chunksize. + virtual size_t round_up (size_t nbytes); + +}; + +#include /**/ "ace/post.h" +#endif /* ACE_LOCAL_MEMORY_POOL_H */ diff --git a/ace/MMAP_Memory_Pool.cpp b/ace/MMAP_Memory_Pool.cpp new file mode 100644 index 00000000000..85800b3ecd8 --- /dev/null +++ b/ace/MMAP_Memory_Pool.cpp @@ -0,0 +1,518 @@ +// $Id$ + +// MMAP_Memory_Pool.cpp +#include "ace/MMAP_Memory_Pool.h" +#include "ace/OS_NS_sys_mman.h" +#include "ace/OS_NS_unistd.h" + +#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1) +#include "ace/Based_Pointer_T.h" +#include "ace/Based_Pointer_Repository.h" +#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */ + +ACE_RCSID(ace, MMAP_Memory_Pool, "$Id$") + +ACE_ALLOC_HOOK_DEFINE(ACE_MMAP_Memory_Pool) + +void +ACE_MMAP_Memory_Pool::dump (void) const +{ +#if defined (ACE_HAS_DUMP) + ACE_TRACE ("ACE_MMAP_Memory_Pool::dump"); +#endif /* ACE_HAS_DUMP */ +} + +int +ACE_MMAP_Memory_Pool::release (int destroy) +{ + ACE_TRACE ("ACE_MMAP_Memory_Pool::release"); + +#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1) + ACE_BASED_POINTER_REPOSITORY::instance ()->unbind (this->mmap_.addr ()); +#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */ + + if (destroy) + this->mmap_.remove (); + else + this->mmap_.close (); + 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 <len> bytes of the memory region to the backing store starting +// at <addr_>. + +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 <prot> +// starting at <this->base_addr_> up to <len> bytes. If <len> == -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 <prot> +// starting at <addr> up to <len> 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 (const ACE_TCHAR *backing_store_name, + const OPTIONS *options) + : base_addr_ (0), + use_fixed_addr_(0), + flags_ (MAP_SHARED), + write_each_page_ (0), + minimum_bytes_ (0), + sa_ (0), + file_mode_ (ACE_DEFAULT_FILE_PERMS) +{ + 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 /* (defined (ACE_HAS_SIGINFO_T) && !defined (ACE_LACKS_SI_ADDR)) || defined (ACE_WIN32) */ + + // Only change the defaults if <options> != 0. + if (options) + { + if (options->flags_ != 0) + this->flags_ = options->flags_; + use_fixed_addr_ = options->use_fixed_addr_; + + if (use_fixed_addr_ == ACE_MMAP_Memory_Pool_Options::ALWAYS_FIXED) + { + this->base_addr_ = const_cast<void *> (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->sa_ != 0) + this->sa_ = options->sa_; + this->file_mode_ = options->file_mode_; + } + + if (backing_store_name == 0) + { + // Only create a new unique filename for the backing store file + // if the user didn't supply one... +#if defined (ACE_DEFAULT_BACKING_STORE) + // Create a temporary file. + ACE_OS::strcpy (this->backing_store_name_, + ACE_DEFAULT_BACKING_STORE); +#else /* ACE_DEFAULT_BACKING_STORE */ + if (ACE::get_temp_dir (this->backing_store_name_, + MAXPATHLEN - 17) == -1) + // -17 for ace-malloc-XXXXXX + { + ACE_ERROR ((LM_ERROR, + ACE_LIB_TEXT ("Temporary path too long, ") + ACE_LIB_TEXT ("defaulting to current directory\n"))); + this->backing_store_name_[0] = 0; + } + + // Add the filename to the end + ACE_OS::strcat (this->backing_store_name_, + ACE_LIB_TEXT ("ace-malloc-XXXXXX")); + +#endif /* ACE_DEFAULT_BACKING_STORE */ + } + else + ACE_OS::strsncpy (this->backing_store_name_, + backing_store_name, + (sizeof this->backing_store_name_ / sizeof (ACE_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 */ +} + +ACE_MMAP_Memory_Pool::~ACE_MMAP_Memory_Pool (void) +{ +} + +// 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 (), + static_cast<off_t> (seek_len - 1), + SEEK_END); + + if (map_size == -1 + || ACE_OS::write (this->mmap_.handle (), + "", + 1) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_LIB_TEXT ("(%P|%t) %p\n"), + this->backing_store_name_), + -1); + } + +#if defined (ACE_OPENVMS) + ::fsync(this->mmap_.handle()); +#endif + + // 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 <map_size> 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 (); + +#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1) + if(use_fixed_addr_ == ACE_MMAP_Memory_Pool_Options::NEVER_FIXED) + this->base_addr_ = 0; +#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */ + + // Remap the file. + if (this->mmap_.map (map_size, + PROT_RDWR, + this->flags_, + this->base_addr_, + 0, + this->sa_) == -1 + || this->base_addr_ != 0 +#ifdef ACE_HAS_WINCE + && this->mmap_.addr () == 0) // WinCE does not allow users to specify alloc addr. +#else + && this->mmap_.addr () != this->base_addr_) +#endif // ACE_HAS_WINCE + { +#if 0 + ACE_ERROR ((LM_ERROR, + ACE_LIB_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 (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1) + this->base_addr_ = this->mmap_.addr (); + ACE_BASED_POINTER_REPOSITORY::instance ()->bind (this->base_addr_, + map_size); +#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */ + 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, + this->file_mode_, 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, + this->file_mode_, + PROT_RDWR, + this->flags_, + this->base_addr_, + 0, + this->sa_) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_LIB_TEXT ("%p\n"), + ACE_LIB_TEXT ("open")), + 0); + + return this->mmap_.addr (); + } + else + ACE_ERROR_RETURN ((LM_ERROR, + ACE_LIB_TEXT ("%p\n"), + ACE_LIB_TEXT ("open")), + 0); +} + +#if defined (ACE_WIN32) +int +ACE_MMAP_Memory_Pool::seh_selector (void *ep) +{ + DWORD ecode = ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionCode; + + if (ecode == EXCEPTION_ACCESS_VIOLATION) + { + void * fault_addr = (void *) + ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionInformation[1]; + + if (this->remap (fault_addr) == 0) + return 1; + } + + return 0; +} +#endif /* ACE_WIN32 */ + +int +ACE_MMAP_Memory_Pool::remap (void *addr) +{ + ACE_TRACE ("ACE_MMAP_Memory_Pool::remap"); + // ACE_DEBUG ((LM_DEBUG, ACE_LIB_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 (const 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, + mode_t file_mode) + : 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), + file_mode_ (file_mode) +{ + ACE_TRACE ("ACE_MMAP_Memory_Pool_Options::ACE_MMAP_Memory_Pool_Options"); + // for backwards compatability + if (base_addr_ == 0 && use_fixed_addr_ == ALWAYS_FIXED) + use_fixed_addr_ = FIRSTCALL_FIXED; +} + +// 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, ACE_LIB_TEXT ("(%P|%t) received %S\n"), signum)); + + // ACE_DEBUG ((LM_DEBUG, ACE_LIB_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, ACE_LIB_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 (static_cast<size_t> (current_map_size) == this->mmap_.size ()) + { + // The mapping is up to date so this really is a bad + // address. Thus, remove current signal handler so process + // will fail with default action and core file will be + // written. + this->signal_handler_.remove_handler (SIGSEGV); + return 0; + } + + // Extend the mapping to cover the size of the backing store. + return this->map_file (current_map_size); + } + else + return -1; +} + +void * +ACE_MMAP_Memory_Pool::base_addr (void) const +{ + ACE_TRACE ("ACE_MMAP_Memory_Pool::base_addr"); + return this->base_addr_; +} + +size_t +ACE_MMAP_Memory_Pool::round_up (size_t nbytes) +{ + ACE_TRACE ("ACE_MMAP_Memory_Pool::round_up"); + return ACE::round_to_pagesize (static_cast<off_t> (nbytes)); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Lite_MMAP_Memory_Pool) + +ACE_Lite_MMAP_Memory_Pool::ACE_Lite_MMAP_Memory_Pool (const ACE_TCHAR *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"); +} + +ACE_Lite_MMAP_Memory_Pool::~ACE_Lite_MMAP_Memory_Pool (void) +{ +} + +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; +} diff --git a/ace/MMAP_Memory_Pool.h b/ace/MMAP_Memory_Pool.h new file mode 100644 index 00000000000..864bea00cbf --- /dev/null +++ b/ace/MMAP_Memory_Pool.h @@ -0,0 +1,288 @@ +/* -*- C++ -*- */ + +//============================================================================= +/** + * @file Memory_Pool.h + * + * $Id$ + * + * @author Dougls C. Schmidt <schmidt@cs.wustl.edu> + * @author Prashant Jain <pjain@cs.wustl.edu> + */ +//============================================================================= + +#ifndef ACE_MMAP_MEMORY_POOL_H +#define ACE_MMAP_MEMORY_POOL_H +#include /**/ "ace/pre.h" + +#include "ace/ACE.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Event_Handler.h" +#include "ace/Signal.h" +#include "ace/Mem_Map.h" + +/** + * @class ACE_MMAP_Memory_Pool_Options + * + * @brief Helper class for MMAP Memory Pool constructor options. + * + * This should be a nested class, but that breaks too many + * compilers. + */ +class ACE_Export ACE_MMAP_Memory_Pool_Options +{ +public: + enum + { + /** + * The base address from the first call to mmap will be used for subsequent + * calls to mmap. + */ + FIRSTCALL_FIXED = 0, + + /** + * The base address specified in base_addr will be used in all calls to + * mmap. + */ + ALWAYS_FIXED = 1, + + /** + * The base address will be selected by the OS for each call to mmap. + * Caution should be used with this mode since a call that requires the + * backing store to grow may change pointers that are cached by the + * application. + */ + NEVER_FIXED = 2 + }; + + // = Initialization method. + ACE_MMAP_Memory_Pool_Options (const void *base_addr = ACE_DEFAULT_BASE_ADDR, + int use_fixed_addr = ALWAYS_FIXED, + int write_each_page = 1, + off_t minimum_bytes = 0, + u_int flags = 0, + int guess_on_fault = 1, + LPSECURITY_ATTRIBUTES sa = 0, + mode_t file_mode = ACE_DEFAULT_FILE_PERMS); + + /// Base address of the memory-mapped backing store. + const void *base_addr_; + + /** + * Determines whether we set @c base_addr_ or if mmap(2) selects it + * FIRSTCALL_FIXED The base address from the first call to mmap + * will be used for subsequent calls to mmap + * ALWAYS_FIXED The base address specified in base_addr will be + * used in all calls to mmap. + * NEVER_FIXED The base address will be selected by the OS for + * each call to mmap. Caution should be used with + * this mode since a call that requires the backing + * store to grow may change pointers that are + * cached by the application. + */ + int use_fixed_addr_; + + /// Should each page be written eagerly to avoid surprises later + /// on? + int write_each_page_; + + /// What the minimim bytes of the initial segment should be. + off_t minimum_bytes_; + + /// Any special flags that need to be used for @c mmap. + u_int flags_; + + /** + * Try to remap without knowing the faulting address. This + * parameter is ignored on platforms that know the faulting address + * (UNIX with SI_ADDR and Win32). + */ + int guess_on_fault_; + + /// Pointer to a security attributes object. Only used on NT. + LPSECURITY_ATTRIBUTES sa_; + + /// File mode for mmaped file, if it is created. + mode_t file_mode_; +}; + +/** + * @class ACE_MMAP_Memory_Pool + * + * @brief Make a memory pool that is based on @c mmap(2). This + * implementation allows memory to be shared between processes. + */ +class ACE_Export ACE_MMAP_Memory_Pool : public ACE_Event_Handler +{ +public: + typedef ACE_MMAP_Memory_Pool_Options OPTIONS; + + // = Initialization and termination methods. + + /// Initialize the pool. + ACE_MMAP_Memory_Pool (const ACE_TCHAR *backing_store_name = 0, + const OPTIONS *options = 0); + + /// Destructor. + virtual ~ACE_MMAP_Memory_Pool (void); + + /// Ask system for initial chunk of shared memory. + virtual void *init_acquire (size_t nbytes, + size_t &rounded_bytes, + int &first_time); + + /** + * Acquire at least @a nbytes from the memory pool. @a rounded_bytes + * is the actual number of bytes allocated. Also acquires an + * internal semaphore that ensures proper serialization of + * ACE_MMAP_Memory_Pool initialization across processes. + */ + virtual void *acquire (size_t nbytes, + size_t &rounded_bytes); + + /// Instruct the memory pool to release all of its resources. + virtual int release (int destroy = 1); + + /// Sync the memory region to the backing store starting at + /// @c this->base_addr_. + virtual int sync (ssize_t len = -1, int flags = MS_SYNC); + + /// Sync the memory region to the backing store starting at @a addr. + virtual int sync (void *addr, size_t len, int flags = MS_SYNC); + + /** + * 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. + */ + virtual int protect (ssize_t len = -1, int prot = PROT_RDWR); + + /// Change the protection of the pages of the mapped region to @a prot + /// starting at @a addr up to @a len bytes. + virtual int protect (void *addr, size_t len, int prot = PROT_RDWR); + +#if defined (ACE_WIN32) + /** + * Win32 Structural exception selector. The return value decides + * how to handle memory pool related structural exceptions. Returns + * 1, 0, or , -1. + */ + virtual int seh_selector (void *); +#endif /* ACE_WIN32 */ + + /** + * Try to extend the virtual address space so that @a addr is now + * covered by the address mapping. The method succeeds and returns + * 0 if the backing store has adequate memory to cover this address. + * Otherwise, it returns -1. This method is typically called by a + * UNIX signal handler for SIGSEGV or a Win32 structured exception + * when another process has grown the backing store (and its + * mapping) and our process now incurs a fault because our mapping + * isn't in range (yet). + */ + virtual int remap (void *addr); + + /// Return the base address of this memory pool. + virtual void *base_addr (void) const; + + /// Dump the state of an object. + virtual void dump (void) const; + + /// Declare the dynamic allocation hooks. + ACE_ALLOC_HOOK_DECLARE; + +protected: + /// Implement the algorithm for rounding up the request to an + /// appropriate chunksize. + virtual size_t round_up (size_t nbytes); + + /// Compute the new @a map_size of the backing store and commit the + /// memory. + virtual int commit_backing_store_name (size_t rounded_bytes, + off_t &map_size); + + /// Memory map the file up to @a map_size bytes. + virtual int map_file (off_t map_size); + + /// Handle SIGSEGV and SIGBUS signals to remap shared memory + /// properly. + virtual int handle_signal (int signum, siginfo_t *, ucontext_t *); + + /// Handles SIGSEGV. + ACE_Sig_Handler signal_handler_; + + /// Memory-mapping object. + ACE_Mem_Map mmap_; + + /** + * Base of mapped region. If this has the value of 0 then the OS is + * free to select any address to map the file, otherwise this value + * is what the OS must try to use to mmap the file. + */ + void *base_addr_; + + /// Must we use the @c base_addr_ or can we let mmap(2) select it? + int use_fixed_addr_; + + /// Flags passed into <ACE_OS::mmap>. + int flags_; + + /// Should we write a byte to each page to forceably allocate memory + /// for this backing store? + int write_each_page_; + + /// What the minimum bytes of the initial segment should be. + off_t minimum_bytes_; + + /// Name of the backing store where the shared memory pool is kept. + ACE_TCHAR backing_store_name_[MAXPATHLEN + 1]; + + /** + * Try to remap without knowing the faulting address. This + * parameter is ignored on platforms that know the faulting address + * (UNIX with SI_ADDR and Win32). + */ + int guess_on_fault_; + + /// Security attributes object, only used on NT. + LPSECURITY_ATTRIBUTES sa_; + + /// Protection mode for mmaped file. + mode_t file_mode_; +}; + +/** + * @class ACE_Lite_MMAP_Memory_Pool + * + * @brief Make a ``lighter-weight'' memory pool based <ACE_Mem_Map>. + * + * This implementation allows memory to be shared between + * processes. However, unlike the <ACE_MMAP_Memory_Pool> + * the <sync> methods are no-ops, which means that we don't pay + * for the price of flushing the memory to the backing store on + * every update. Naturally, this trades off increased + * performance for less reliability if the machine crashes. + */ +class ACE_Export ACE_Lite_MMAP_Memory_Pool : public ACE_MMAP_Memory_Pool +{ +public: + /// Initialize the pool. + ACE_Lite_MMAP_Memory_Pool (const ACE_TCHAR *backing_store_name = 0, + const OPTIONS *options = 0); + + /// Destructor. + virtual ~ACE_Lite_MMAP_Memory_Pool (void); + + /// Overwrite the default sync behavior with no-op + virtual int sync (ssize_t len = -1, int flags = MS_SYNC); + + /// Overwrite the default sync behavior with no-op + virtual int sync (void *addr, size_t len, int flags = MS_SYNC); +}; + +#include /**/ "ace/post.h" +#endif /* ACE_MMAP_MEMORY_POOL_H */ diff --git a/ace/Makefile.am b/ace/Makefile.am index ad77a83e45c..0fb01af0677 100644 --- a/ace/Makefile.am +++ b/ace/Makefile.am @@ -316,18 +316,22 @@ Streams = \ Memory = \ Based_Pointer_Repository.cpp \ + Local_Memory_Pool.cpp \ + MMAP_Memory_Pool.cpp \ Malloc.cpp \ Malloc_Allocator.cpp \ Malloc_Instantiations.cpp \ Mem_Map.cpp \ - Memory_Pool.cpp \ Obchunk.cpp \ Obstack.cpp \ + Pagefile_Memory_Pool.cpp \ PI_Malloc.cpp \ Read_Buffer.cpp \ + Sbrk_Memory_Pool.cpp \ Shared_Memory.cpp \ Shared_Memory_MM.cpp \ - Shared_Memory_SV.cpp + Shared_Memory_SV.cpp \ + Shared_Memory_Pool.cpp Timer = \ Basic_Stats.cpp \ @@ -510,6 +514,7 @@ nobase_include_HEADERS = \ LSOCK_Dgram.h \ LSOCK_Stream.h \ Lib_Find.h \ + Local_Memory_Pool.h \ Local_Name_Space.h \ Local_Name_Space_T.h \ Local_Tokens.h \ @@ -530,6 +535,7 @@ nobase_include_HEADERS = \ MEM_IO.h \ MEM_SAP.h \ MEM_Stream.h \ + MMAP_Memory_Pool.h \ Malloc.h \ Malloc_Allocator.h \ Malloc_Base.h \ @@ -615,6 +621,7 @@ nobase_include_HEADERS = \ POSIX_Asynch_IO.h \ POSIX_CB_Proactor.h \ POSIX_Proactor.h \ + Pagefile_Memory_Pool.h \ Pair.h \ Pair_T.h \ Parse_Node.h \ @@ -673,6 +680,7 @@ nobase_include_HEADERS = \ SV_Semaphore_Simple.h \ SV_Shared_Memory.h \ Sample_History.h \ + Sbrk_Memory_Pool.h \ Sched_Params.h \ Select_Reactor.h \ Select_Reactor_Base.h \ @@ -687,6 +695,7 @@ nobase_include_HEADERS = \ Shared_Memory.h \ Shared_Memory_MM.h \ Shared_Memory_SV.h \ + Shared_Memory_Pool.h \ Shared_Object.h \ Signal.h \ Singleton.h \ @@ -984,7 +993,6 @@ nobase_include_HEADERS = \ Map_Manager.inl \ Map_T.inl \ Mem_Map.inl \ - Memory_Pool.inl \ Message_Block.inl \ Message_Block_T.inl \ Message_Queue.inl \ @@ -1039,6 +1047,7 @@ nobase_include_HEADERS = \ PI_Malloc.inl \ POSIX_CB_Proactor.inl \ POSIX_Proactor.inl \ + Pagefile_Memory_Pool.inl \ Pair_T.inl \ Parse_Node.inl \ Ping_Socket.inl \ diff --git a/ace/Memory_Pool.cpp b/ace/Memory_Pool.cpp deleted file mode 100644 index e5de1f19fdf..00000000000 --- a/ace/Memory_Pool.cpp +++ /dev/null @@ -1,1352 +0,0 @@ -// $Id$ - -// Memory_Pool.cpp -#include "ace/Memory_Pool.h" - -#if !defined (__ACE_INLINE__) -#include "ace/Memory_Pool.inl" -#endif /* __ACE_INLINE__ */ - -#include "ace/Log_Msg.h" -#include "ace/Auto_Ptr.h" -#include "ace/RW_Thread_Mutex.h" -#include "ace/OS_NS_sys_mman.h" -#include "ace/OS_NS_string.h" -#include "ace/OS_NS_sys_stat.h" -#include "ace/OS_NS_sys_shm.h" -#include "ace/OS_NS_unistd.h" - -#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1) -#include "ace/Based_Pointer_T.h" -#include "ace/Based_Pointer_Repository.h" -#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */ - -ACE_RCSID(ace, Memory_Pool, "$Id$") - -ACE_ALLOC_HOOK_DEFINE(ACE_Local_Memory_Pool) - -void -ACE_Local_Memory_Pool::dump (void) const -{ -#if defined (ACE_HAS_DUMP) - ACE_TRACE ("ACE_Local_Memory_Pool::dump"); -#endif /* ACE_HAS_DUMP */ -} - -ACE_Local_Memory_Pool::ACE_Local_Memory_Pool (const ACE_TCHAR *, - 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<char> cp (temp); - - if (this->allocated_chunks_.insert (cp.get ()) != 0) - ACE_ERROR_RETURN ((LM_ERROR, - ACE_LIB_TEXT ("(%P|%t) insertion into set failed\n")), - 0); - - return cp.release (); -} - -int -ACE_Local_Memory_Pool::release (int) -{ - ACE_TRACE ("ACE_Local_Memory_Pool::release"); - - // Zap the memory we allocated. - for (ACE_Unbounded_Set<char *>::iterator i = this->allocated_chunks_.begin (); - i != this->allocated_chunks_.end (); - ++i) - delete [] *i; - this->allocated_chunks_.reset (); - return 0; -} - -#if defined (ACE_WIN32) -int -ACE_Local_Memory_Pool::seh_selector (void *) -{ - return 0; - // Continue propagate the structural exception up. -} -#endif /* ACE_WIN32 */ - -int -ACE_Local_Memory_Pool::remap (void *) -{ - return 0; - // Not much can be done. -} - -ACE_ALLOC_HOOK_DEFINE(ACE_MMAP_Memory_Pool) - -void -ACE_MMAP_Memory_Pool::dump (void) const -{ -#if defined (ACE_HAS_DUMP) - ACE_TRACE ("ACE_MMAP_Memory_Pool::dump"); -#endif /* ACE_HAS_DUMP */ -} - -int -ACE_MMAP_Memory_Pool::release (int destroy) -{ - ACE_TRACE ("ACE_MMAP_Memory_Pool::release"); - -#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1) - ACE_BASED_POINTER_REPOSITORY::instance ()->unbind (this->mmap_.addr ()); -#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */ - - if (destroy) - this->mmap_.remove (); - else - this->mmap_.close (); - 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 <len> bytes of the memory region to the backing store starting -// at <addr_>. - -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 <prot> -// starting at <this->base_addr_> up to <len> bytes. If <len> == -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 <prot> -// starting at <addr> up to <len> 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 (const ACE_TCHAR *backing_store_name, - const OPTIONS *options) - : base_addr_ (0), - use_fixed_addr_(0), - flags_ (MAP_SHARED), - write_each_page_ (0), - minimum_bytes_ (0), - sa_ (0), - file_mode_ (ACE_DEFAULT_FILE_PERMS) -{ - 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 /* (defined (ACE_HAS_SIGINFO_T) && !defined (ACE_LACKS_SI_ADDR)) || defined (ACE_WIN32) */ - - // Only change the defaults if <options> != 0. - if (options) - { - if (options->flags_ != 0) - this->flags_ = options->flags_; - use_fixed_addr_ = options->use_fixed_addr_; - - if (use_fixed_addr_ == ACE_MMAP_Memory_Pool_Options::ALWAYS_FIXED) - { - this->base_addr_ = const_cast<void *> (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->sa_ != 0) - this->sa_ = options->sa_; - this->file_mode_ = options->file_mode_; - } - - if (backing_store_name == 0) - { - // Only create a new unique filename for the backing store file - // if the user didn't supply one... -#if defined (ACE_DEFAULT_BACKING_STORE) - // Create a temporary file. - ACE_OS::strcpy (this->backing_store_name_, - ACE_DEFAULT_BACKING_STORE); -#else /* ACE_DEFAULT_BACKING_STORE */ - if (ACE::get_temp_dir (this->backing_store_name_, - MAXPATHLEN - 17) == -1) - // -17 for ace-malloc-XXXXXX - { - ACE_ERROR ((LM_ERROR, - ACE_LIB_TEXT ("Temporary path too long, ") - ACE_LIB_TEXT ("defaulting to current directory\n"))); - this->backing_store_name_[0] = 0; - } - - // Add the filename to the end - ACE_OS::strcat (this->backing_store_name_, - ACE_LIB_TEXT ("ace-malloc-XXXXXX")); - -#endif /* ACE_DEFAULT_BACKING_STORE */ - } - else - ACE_OS::strsncpy (this->backing_store_name_, - backing_store_name, - (sizeof this->backing_store_name_ / sizeof (ACE_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 (), - static_cast<off_t> (seek_len - 1), - SEEK_END); - - if (map_size == -1 - || ACE_OS::write (this->mmap_.handle (), - "", - 1) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - ACE_LIB_TEXT ("(%P|%t) %p\n"), - this->backing_store_name_), - -1); - } - -#if defined (ACE_OPENVMS) - ::fsync(this->mmap_.handle()); -#endif - - // 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 <map_size> 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 (); - -#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1) - if(use_fixed_addr_ == ACE_MMAP_Memory_Pool_Options::NEVER_FIXED) - this->base_addr_ = 0; -#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */ - - // Remap the file. - if (this->mmap_.map (map_size, - PROT_RDWR, - this->flags_, - this->base_addr_, - 0, - this->sa_) == -1 - || this->base_addr_ != 0 -#ifdef ACE_HAS_WINCE - && this->mmap_.addr () == 0) // WinCE does not allow users to specify alloc addr. -#else - && this->mmap_.addr () != this->base_addr_) -#endif // ACE_HAS_WINCE - { -#if 0 - ACE_ERROR ((LM_ERROR, - ACE_LIB_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 (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1) - this->base_addr_ = this->mmap_.addr (); - ACE_BASED_POINTER_REPOSITORY::instance ()->bind (this->base_addr_, - map_size); -#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */ - 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, - this->file_mode_, 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, - this->file_mode_, - PROT_RDWR, - this->flags_, - this->base_addr_, - 0, - this->sa_) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - ACE_LIB_TEXT ("%p\n"), - ACE_LIB_TEXT ("open")), - 0); - - return this->mmap_.addr (); - } - else - ACE_ERROR_RETURN ((LM_ERROR, - ACE_LIB_TEXT ("%p\n"), - ACE_LIB_TEXT ("open")), - 0); -} - -#if defined (ACE_WIN32) -int -ACE_MMAP_Memory_Pool::seh_selector (void *ep) -{ - DWORD ecode = ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionCode; - - if (ecode == EXCEPTION_ACCESS_VIOLATION) - { - void * fault_addr = (void *) - ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionInformation[1]; - - if (this->remap (fault_addr) == 0) - return 1; - } - - return 0; -} -#endif /* ACE_WIN32 */ - -int -ACE_MMAP_Memory_Pool::remap (void *addr) -{ - ACE_TRACE ("ACE_MMAP_Memory_Pool::remap"); - // ACE_DEBUG ((LM_DEBUG, ACE_LIB_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 (const 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, - mode_t file_mode) - : 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), - file_mode_ (file_mode) -{ - ACE_TRACE ("ACE_MMAP_Memory_Pool_Options::ACE_MMAP_Memory_Pool_Options"); - // for backwards compatability - if (base_addr_ == 0 && use_fixed_addr_ == ALWAYS_FIXED) - use_fixed_addr_ = FIRSTCALL_FIXED; -} - -// 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, ACE_LIB_TEXT ("(%P|%t) received %S\n"), signum)); - - // ACE_DEBUG ((LM_DEBUG, ACE_LIB_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, ACE_LIB_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 (static_cast<size_t> (current_map_size) == this->mmap_.size ()) - { - // The mapping is up to date so this really is a bad - // address. Thus, remove current signal handler so process - // will fail with default action and core file will be - // written. - this->signal_handler_.remove_handler (SIGSEGV); - return 0; - } - - // 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 (const ACE_TCHAR *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, ACE_LIB_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, ACE_LIB_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 -{ -#if defined (ACE_HAS_DUMP) - ACE_TRACE ("ACE_Sbrk_Memory_Pool::dump"); -#endif /* ACE_HAS_DUMP */ -} - -ACE_Sbrk_Memory_Pool::ACE_Sbrk_Memory_Pool (const ACE_TCHAR *, - 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 (const 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"); -} - -void -ACE_Shared_Memory_Pool::dump (void) const -{ -#if defined (ACE_HAS_DUMP) - ACE_TRACE ("ACE_Shared_Memory_Pool::dump"); -#endif /* ACE_HAS_DUMP */ -} - -int -ACE_Shared_Memory_Pool::in_use (off_t &offset, - size_t &counter) -{ - 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_LIB_TEXT ("(%P|%t) %p\n"), - ACE_LIB_TEXT ("shmctl")), - -1); - offset += buf.shm_segsz; - // ACE_DEBUG ((LM_DEBUG, ACE_LIB_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 = 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_LIB_TEXT ("(%P|%t) %p\n"), - ACE_LIB_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_LIB_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::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_LIB_TEXT ("(%P|%t) %p\n"), - ACE_LIB_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, - "(%P|%t) %p, shmem = %u, address = %u\n", - "shmat", - shmem, - address), - -1); - } - 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, ACE_LIB_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, ACE_LIB_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_LIB_TEXT ("(%P|%t) %p\n"), - ACE_LIB_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_LIB_TEXT ("(%P|%t) %p\n"), - ACE_LIB_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, - "(%P|%t) %p, shmem = %u, address = %u\n", - "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; -} - -ACE_Shared_Memory_Pool::ACE_Shared_Memory_Pool (const ACE_TCHAR *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 <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_LIB_TEXT ("%p\n"), - ACE_LIB_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, ACE_LIB_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, ACE_LIB_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, - ACE_LIB_TEXT ("(%P|%t) %p\n"), - ACE_LIB_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_LIB_TEXT ("(%P|%t) %p\n"), - ACE_LIB_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, - "(%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, - reinterpret_cast<char *> (this->base_addr_), - 0); - if (this->base_addr_ == reinterpret_cast<char *> (-1)) - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) %p, base_addr = %u\n", - "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); -} - -// Instruct the memory pool to release all of its resources. - -int -ACE_Shared_Memory_Pool::release (int) -{ - 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; -} -#endif /* !ACE_LACKS_SYSV_SHMEM */ - -#if defined (ACE_WIN32) -#if !defined (ACE_HAS_WINCE) -#define ACE_MAP_FILE(_hnd, _access, _offHigh, _offLow, _nBytes, _baseAdd)\ - MapViewOfFileEx (_hnd, _access, _offHigh, _offLow, _nBytes, _baseAdd) -#else //if !defined (ACE_HAS_WINCE) -#define ACE_MAP_FILE(_hnd, _access, _offHigh, _offLow, _nBytes, _baseAdd)\ - MapViewOfFile (_hnd, _access, _offHigh, _offLow, _nBytes) -#endif /* !defined (ACE_HAS_WINCE) */ - -ACE_Pagefile_Memory_Pool_Options::ACE_Pagefile_Memory_Pool_Options (void *base_addr, - size_t max_size) - : base_addr_ (base_addr), - max_size_ (max_size) -{ -} - -int -ACE_Pagefile_Memory_Pool::release (int) -{ - return this->unmap (); -} - -ACE_Pagefile_Memory_Pool::ACE_Pagefile_Memory_Pool (const ACE_TCHAR *backing_store_name, - const OPTIONS *options) - : shared_cb_ (0), - object_handle_ (0), - page_size_ (ACE_Pagefile_Memory_Pool::round_to_page_size (1)) -{ - // Initialize local copy of pool statistics. - if (options != 0) - { - this->local_cb_.req_base_ = options->base_addr_; - this->local_cb_.mapped_base_ = 0; - this->local_cb_.sh_.max_size_ = - options->max_size_; - this->local_cb_.sh_.mapped_size_ = 0; - this->local_cb_.sh_.free_offset_ = - this->local_cb_.sh_.mapped_size_; - this->local_cb_.sh_.free_size_ = 0; - } - - 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_PAGEFILE_POOL_NAME; - - ACE_OS::strsncpy (this->backing_store_name_, - backing_store_name, - (sizeof this->backing_store_name_ / sizeof (ACE_TCHAR))); -} - -void * -ACE_Pagefile_Memory_Pool::acquire (size_t nbytes, - size_t &rounded_bytes) -{ - rounded_bytes = round_to_page_size (nbytes); - void *result = 0; - int first_time = 0; - - // Check local_cb_ for consistency. Remap, if extra space is too - // small and/or we didn't map the whole shared memory section - if (this->shared_cb_->sh_.mapped_size_ - > this->local_cb_.sh_.mapped_size_ - || this->shared_cb_->sh_.free_size_ < rounded_bytes) - { - size_t append = 0; - if (rounded_bytes > this->shared_cb_->sh_.free_size_) - append = rounded_bytes - this->shared_cb_->sh_.free_size_; - - if (this->map (first_time, append) < 0) - return result; - } - - // Get the block from extra space and update shared and local - // control block - if (this->shared_cb_->sh_.free_size_ < rounded_bytes) - return result; - - result = (void *)((char *) this->local_cb_.mapped_base_ - + this->shared_cb_->sh_.free_offset_); - this->shared_cb_->sh_.free_offset_ += rounded_bytes; - this->shared_cb_->sh_.free_size_ -= rounded_bytes; - this->local_cb_.sh_ = this->shared_cb_->sh_; - - return result; -} - -void * -ACE_Pagefile_Memory_Pool::init_acquire (size_t nbytes, - size_t &rounded_bytes, - int &first_time) -{ - // Map the shared memory and get information, if we created the - // shared memory. - if (this->map (first_time) < 0) - return 0; - - if (first_time != 0) - // We created the shared memory. So we have to allocate the - // requested memory. - return this->acquire (nbytes, rounded_bytes); - else - // We just mapped the memory and return the base address - return (void *)((char *) this->local_cb_.mapped_base_ - + ACE_Pagefile_Memory_Pool::round_to_page_size - ((int) sizeof (Control_Block))); -} - -int -ACE_Pagefile_Memory_Pool::seh_selector (void *ep) -{ - DWORD ecode = ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionCode; - - if (ecode == EXCEPTION_ACCESS_VIOLATION) - { - void * fault_addr = (void *) - ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionInformation[1]; - - if (this->remap (fault_addr) == 0) - return 1; - } - - return 0; -} - -int -ACE_Pagefile_Memory_Pool::remap (void *addr) -{ - // If the shared memory is not mapped or the address, that caused - // the memory fault is outside of the commited range of chunks, we - // return. - if (this->shared_cb_ == 0 - || addr < this->local_cb_.mapped_base_ - || addr >= (void *)((char *) this->local_cb_.mapped_base_ - + this->shared_cb_->sh_.mapped_size_)) - return -1; - - // We can solve the problem by committing additional chunks. - int first_time = 0; - return this->map (first_time); -} - -int -ACE_Pagefile_Memory_Pool::unmap (void) -{ -#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1) - ACE_BASED_POINTER_REPOSITORY::instance ()->unbind - (this->local_cb_.mapped_base_); -#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */ - - // Cleanup cached pool pointer. - this->shared_cb_ = 0; - - if (this->local_cb_.sh_.mapped_size_ > 0) - ::UnmapViewOfFile (this->local_cb_.mapped_base_); - - // Reset local pool statistics. - this->local_cb_.req_base_ = - ACE_DEFAULT_PAGEFILE_POOL_BASE; - this->local_cb_.mapped_base_ = 0; - this->local_cb_.sh_.max_size_ = - ACE_DEFAULT_PAGEFILE_POOL_SIZE; - this->local_cb_.sh_.mapped_size_ = 0; - this->local_cb_.sh_.free_offset_ = - this->local_cb_.sh_.mapped_size_; - this->local_cb_.sh_.free_size_ = 0; - - // Release the pool - if (this->object_handle_ != 0) - { - ::CloseHandle (this->object_handle_); - this->object_handle_ = 0; - } - return 0; -} - -int -ACE_Pagefile_Memory_Pool::map (int &first_time, - size_t append_bytes) -{ - size_t map_size; - void *map_addr; - - // Create file mapping, if not yet done - if (object_handle_ == 0) - { -#if (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) - // Allow access by all users. - SECURITY_ATTRIBUTES sa; - SECURITY_DESCRIPTOR sd; - ::InitializeSecurityDescriptor (&sd, - SECURITY_DESCRIPTOR_REVISION); - ::SetSecurityDescriptorDacl (&sd, - TRUE, - 0, - FALSE); - sa.nLength = sizeof (SECURITY_ATTRIBUTES); - sa.lpSecurityDescriptor = &sd; - sa.bInheritHandle = FALSE; -#endif /* (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) */ - - // Get an object handle to the named reserved memory object. - DWORD size_high; - DWORD size_low; -#if defined (ACE_WIN64) - size_high = static_cast<DWORD> (this->local_cb_.sh_.max_size_ >> 32); - size_low = static_cast<DWORD> (this->local_cb_.sh_.max_size_ & 0xFFFFFFFF); -#else - size_high = 0; - size_low = this->local_cb_.sh_.max_size_; -#endif - - object_handle_ = - ACE_TEXT_CreateFileMapping (INVALID_HANDLE_VALUE, -#if (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) - &sa, -#else - 0, -#endif /* (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) */ - PAGE_READWRITE | SEC_RESERVE, - size_high, - size_low, - this->backing_store_name_); - if (object_handle_ == 0) - return -1; - first_time = - ::GetLastError () == ERROR_ALREADY_EXISTS - ? 0 - : 1; - } - - // Do the initial mapping. - if (this->shared_cb_ == 0) - { - // Map a view to the shared memory. Note: <MapViewOfFile[Ex]> - // does *not* commit the pages! - this->shared_cb_ = (ACE_Pagefile_Memory_Pool::Control_Block *) - ACE_MAP_FILE (this->object_handle_, - FILE_MAP_WRITE, - 0, - 0, - this->local_cb_.sh_.max_size_, - this->local_cb_.req_base_); - if (this->shared_cb_ == 0) - return -1; - - // There was no previous mapping, so we map the first chunk and - // initialize the shared pool statistics. - if (first_time) - { - // 1st block is used to keep shared memory statistics. - map_size = - ACE_Pagefile_Memory_Pool::round_to_chunk_size - (ACE_Pagefile_Memory_Pool::round_to_page_size - ((int) sizeof(Control_Block)) - + append_bytes); - - if (::VirtualAlloc ((void *) this->shared_cb_, - map_size, - MEM_COMMIT, - PAGE_READWRITE) == 0) - return -1; - - this->shared_cb_->req_base_ = 0; - this->shared_cb_->mapped_base_ = 0; - this->local_cb_.mapped_base_ = this->shared_cb_; - this->local_cb_.sh_.mapped_size_ = map_size; - this->local_cb_.sh_.free_offset_ = - round_to_page_size ((int) sizeof (Control_Block)); - this->local_cb_.sh_.free_size_ = - this->local_cb_.sh_.mapped_size_ - - this->local_cb_.sh_.free_offset_; - this->shared_cb_->sh_ = this->local_cb_.sh_; - } - - // The shared memory exists, so we map the first chunk to the - // base address of the pool to get the shared pool statistics. - else - { - // 1st block is used to keep shared memory statistics. - map_size = - ACE_Pagefile_Memory_Pool::round_to_chunk_size - ((int) sizeof (Control_Block)); - - if (::VirtualAlloc ((void *) this->shared_cb_, - map_size, - MEM_COMMIT, - PAGE_READWRITE) == 0) - return -1; - this->local_cb_.mapped_base_ = this->shared_cb_; - this->local_cb_.sh_.mapped_size_ = map_size; - } - } - - // If the shared memory is larger than the part we've already - // committed, we have to remap it. - if (this->shared_cb_->sh_.mapped_size_ > - this->local_cb_.sh_.mapped_size_ - || append_bytes > 0) - { - map_size = - (this->shared_cb_->sh_.mapped_size_ - - this->local_cb_.sh_.mapped_size_) - + ACE_Pagefile_Memory_Pool::round_to_chunk_size - (append_bytes); - - map_addr = (void *)((char *) this->shared_cb_ + - this->local_cb_.sh_.mapped_size_); - - if (::VirtualAlloc (map_addr, - map_size, - MEM_COMMIT, - PAGE_READWRITE) == 0) - return -1; - else if (append_bytes > 0) - { - this->shared_cb_->sh_.mapped_size_ += - round_to_chunk_size (append_bytes); - this->shared_cb_->sh_.free_size_ = - this->shared_cb_->sh_.mapped_size_ - - this->shared_cb_->sh_.free_offset_; - } - } - - // Update local copy of the shared memory statistics. - this->local_cb_.sh_ = - this->shared_cb_->sh_; -#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1) - ACE_BASED_POINTER_REPOSITORY::instance ()->bind - (this->local_cb_.mapped_base_, - this->local_cb_.sh_.mapped_size_); -#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */ - - return 0; -} - -#endif /* ACE_WIN32 */ - -#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) -template class ACE_Auto_Basic_Array_Ptr<char>; -template class ACE_Unbounded_Set<char *>; -template class ACE_Unbounded_Set_Iterator<char *>; -#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) -#pragma instantiate ACE_Auto_Basic_Array_Ptr<char> -#pragma instantiate ACE_Unbounded_Set<char *> -#pragma instantiate ACE_Unbounded_Set_Iterator<char *> -#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/ace/Memory_Pool.h b/ace/Memory_Pool.h index 521378370b6..628a6e09c24 100644 --- a/ace/Memory_Pool.h +++ b/ace/Memory_Pool.h @@ -21,795 +21,11 @@ # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ -#include "ace/Event_Handler.h" -#include "ace/Signal.h" -#include "ace/Mem_Map.h" -#if !defined (ACE_WIN32) -#include "ace/SV_Semaphore_Complex.h" -#endif /* !ACE_WIN32 */ - -#include "ace/Unbounded_Set.h" - -#if !defined (ACE_LACKS_SBRK) -/** - * @class ACE_Sbrk_Memory_Pool_Options - * - * @brief Helper class for Sbrk Memory Pool constructor options. - * - * This should be a nested class, but that breaks too many - * compilers. - */ -class ACE_Export ACE_Sbrk_Memory_Pool_Options -{ -}; - -/** - * @class ACE_Sbrk_Memory_Pool - * - * @brief Make a memory pool that is based on <sbrk(2)>. - */ -class ACE_Export ACE_Sbrk_Memory_Pool -{ -public: - typedef ACE_Sbrk_Memory_Pool_Options OPTIONS; - - /// Initialize the pool. - ACE_Sbrk_Memory_Pool (const ACE_TCHAR *backing_store_name = 0, - const OPTIONS *options = 0); - - virtual ~ACE_Sbrk_Memory_Pool (void); - - // = Implementor operations. - /// Ask system for initial chunk of local memory. - virtual void *init_acquire (size_t nbytes, - size_t &rounded_bytes, - int &first_time); - - /// Acquire at least @a nbytes from the memory pool. @a rounded_bytes is - /// the actual number of bytes allocated. - virtual void *acquire (size_t nbytes, - size_t &rounded_bytes); - - /// Instruct the memory pool to release all of its resources. - virtual int release (int destroy = 1); - - /** - * Sync @a len bytes of the memory region to the backing store - * starting at @c this->base_addr_. If @a len == -1 then sync the - * whole region. - */ - virtual int sync (ssize_t len = -1, int flags = MS_SYNC); - - /// Sync @a len bytes of the memory region to the backing store - /// starting at @a addr. - virtual int sync (void *addr, size_t len, int flags = MS_SYNC); - - /** - * Change the protection of the pages of the mapped region to <prot> - * starting at @c this->base_addr_ up to @a len bytes. If @a len == -1 - * then change protection of all pages in the mapped region. - */ - virtual int protect (ssize_t len = -1, int prot = PROT_RDWR); - - /// Change the protection of the pages of the mapped region to @a prot - /// starting at @a addr up to @a len bytes. - virtual int protect (void *addr, size_t len, int prot = PROT_RDWR); - - /// Dump the state of an object. - virtual void dump (void) const; - - /// Return the base address of this memory pool, 0 if base_addr - /// never changes. - virtual void *base_addr (void) const; - - /// Declare the dynamic allocation hooks. - ACE_ALLOC_HOOK_DECLARE; - -protected: - /// Implement the algorithm for rounding up the request to an - /// appropriate chunksize. - virtual size_t round_up (size_t nbytes); -}; -#endif /* !ACE_LACKS_SBRK */ - -#if !defined (ACE_LACKS_SYSV_SHMEM) - -/** - * @class ACE_Shared_Memory_Pool_Options - * - * @brief Helper class for Shared Memory Pool constructor options. - * - * This should be a nested class, but that breaks too many - * compilers. - */ -class ACE_Export ACE_Shared_Memory_Pool_Options -{ -public: - /// Initialization method. - ACE_Shared_Memory_Pool_Options (const char *base_addr = ACE_DEFAULT_BASE_ADDR, - size_t max_segments = ACE_DEFAULT_MAX_SEGMENTS, - size_t file_perms = ACE_DEFAULT_FILE_PERMS, - off_t minimum_bytes = 0, - size_t segment_size = ACE_DEFAULT_SEGMENT_SIZE); - - /// Base address of the memory-mapped backing store. - const char *base_addr_; - - /// Number of shared memory segments to allocate. - size_t max_segments_; - - /// What the minimum bytes of the initial segment should be. - off_t minimum_bytes_; - - /// File permissions to use when creating/opening a segment. - size_t file_perms_; - - /// Shared memory segment size. - size_t segment_size_; -}; - -/** - * @class ACE_Shared_Memory_Pool - * - * @brief 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. - */ -class ACE_Export ACE_Shared_Memory_Pool : public ACE_Event_Handler -{ -public: - typedef ACE_Shared_Memory_Pool_Options OPTIONS; - - /// Initialize the pool. - ACE_Shared_Memory_Pool (const ACE_TCHAR *backing_store_name = 0, - const OPTIONS *options = 0); - - virtual ~ACE_Shared_Memory_Pool (void); - - /// Ask system for initial chunk of local memory. - virtual void *init_acquire (size_t nbytes, - size_t &rounded_bytes, - int &first_time); - - /** - * Acquire at least @a nbytes from the memory pool. @a rounded_byes is - * the actual number of bytes allocated. Also acquires an internal - * semaphore that ensures proper serialization of Memory_Pool - * initialization across processes. - */ - virtual void *acquire (size_t nbytes, - size_t &rounded_bytes); - - /// Instruct the memory pool to release all of its resources. - virtual int release (int destroy = 1); - - /// Sync the memory region to the backing store starting at - /// @c this->base_addr_. - virtual int sync (ssize_t len = -1, int flags = MS_SYNC); - - /// Sync the memory region to the backing store starting at @a addr. - virtual int sync (void *addr, size_t len, int flags = MS_SYNC); - - /** - * Change the protection of the pages of the mapped region to <prot> - * starting at @c this->base_addr_ up to @a len bytes. If @a len == -1 - * then change protection of all pages in the mapped region. - */ - virtual int protect (ssize_t len = -1, int prot = PROT_RDWR); - - /// Change the protection of the pages of the mapped region to <prot> - /// starting at <addr> up to <len> bytes. - virtual int protect (void *addr, size_t len, int prot = PROT_RDWR); - - /// Return the base address of this memory pool, 0 if base_addr - /// never changes. - virtual void *base_addr (void) const; - - /// Dump the state of an object. - virtual void dump (void) const; - - /// Declare the dynamic allocation hooks. - ACE_ALLOC_HOOK_DECLARE; - -protected: - /// Implement the algorithm for rounding up the request to an - /// appropriate chunksize. - virtual size_t round_up (size_t nbytes); - - /** - * 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. - */ - virtual int commit_backing_store_name (size_t rounded_bytes, - off_t &offset); - - /// Keeps track of all the segments being used. - struct SHM_TABLE - { - /// Shared memory segment key. - key_t key_; - - /// Shared memory segment internal id. - int shmid_; - - /// Is the segment currently used.; - int used_; - }; - - /** - * 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. - */ - void *base_addr_; - - /// File permissions to use when creating/opening a segment. - size_t file_perms_; - - /// Number of shared memory segments in the <SHM_TABLE> table. - size_t max_segments_; - - /// What the minimim bytes of the initial segment should be. - off_t minimum_bytes_; - - /// Shared memory segment size. - size_t segment_size_; - - /// Base shared memory key for the segment. - key_t base_shm_key_; - - /// Find the segment that contains the @a searchPtr - virtual int find_seg (const void *const searchPtr, - off_t &offset, - size_t &counter); - - /// Determine how much memory is currently in use. - virtual int in_use (off_t &offset, - size_t &counter); - - /// Handles SIGSEGV. - ACE_Sig_Handler signal_handler_; - - /// Handle SIGSEGV and SIGBUS signals to remap shared memory - /// properly. - virtual int handle_signal (int signum, siginfo_t *, ucontext_t *); -}; -#endif /* !ACE_LACKS_SYSV_SHMEM */ - -/** - * @class ACE_Local_Memory_Pool_Options - * - * @brief Helper class for Local Memory Pool constructor options. - * - * This should be a nested class, but that breaks too many - * compilers. - */ -class ACE_Export ACE_Local_Memory_Pool_Options -{ -}; - -/** - * @class ACE_Local_Memory_Pool - * - * @brief Make a memory pool that is based on C++ new/delete. This is - * useful for integrating existing components that use new/delete - * into the ACE Malloc scheme... - */ -class ACE_Export ACE_Local_Memory_Pool -{ -public: - typedef ACE_Local_Memory_Pool_Options OPTIONS; - - /// Initialize the pool. - ACE_Local_Memory_Pool (const ACE_TCHAR *backing_store_name = 0, - const OPTIONS *options = 0); - - virtual ~ACE_Local_Memory_Pool (void); - - /// Ask system for initial chunk of local memory. - virtual void *init_acquire (size_t nbytes, - size_t &rounded_bytes, - int &first_time); - - /// Acquire at least @a nbytes from the memory pool. @a rounded_bytes is - /// the actual number of bytes allocated. - virtual void *acquire (size_t nbytes, - size_t &rounded_bytes); - - /// Instruct the memory pool to release all of its resources. - virtual int release (int destroy = 1); - - /** - * Sync <len> bytes of the memory region to the backing store - * starting at <this->base_addr_>. If <len> == -1 then sync the - * whole region. - */ - virtual int sync (ssize_t len = -1, int flags = MS_SYNC); - - /// Sync <len> bytes of the memory region to the backing store - /// starting at <addr_>. - virtual int sync (void *addr, size_t len, int flags = MS_SYNC); - - /** - * 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. - */ - virtual int protect (ssize_t len = -1, int prot = PROT_RDWR); - - /// Change the protection of the pages of the mapped region to <prot> - /// starting at <addr> up to <len> bytes. - virtual int protect (void *addr, size_t len, int prot = PROT_RDWR); - -#if defined (ACE_WIN32) - /** - * Win32 Structural exception selector. The return value decides - * how to handle memory pool related structural exceptions. Returns - * 1, 0, or , -1. - */ - virtual int seh_selector (void *); -#endif /* ACE_WIN32 */ - - /** - * Try to extend the virtual address space so that <addr> is now - * covered by the address mapping. Always returns 0 since we can't - * remap a local memory pool. - */ - virtual int remap (void *addr); - - /// Return the base address of this memory pool, 0 if base_addr - /// never changes. - virtual void *base_addr (void) const; - - /// Dump the state of an object. - virtual void dump (void) const; - - /// Declare the dynamic allocation hooks. - ACE_ALLOC_HOOK_DECLARE; - -protected: - /// List of memory that we have allocated. - ACE_Unbounded_Set<char *> allocated_chunks_; - - /// Implement the algorithm for rounding up the request to an - /// appropriate chunksize. - virtual size_t round_up (size_t nbytes); - -}; - -/** - * @class ACE_MMAP_Memory_Pool_Options - * - * @brief Helper class for MMAP Memory Pool constructor options. - * - * This should be a nested class, but that breaks too many - * compilers. - */ -class ACE_Export ACE_MMAP_Memory_Pool_Options -{ -public: - enum - { - /** - * The base address from the first call to mmap will be used for subsequent - * calls to mmap. - */ - FIRSTCALL_FIXED = 0, - - /** - * The base address specified in base_addr will be used in all calls to - * mmap. - */ - ALWAYS_FIXED = 1, - - /** - * The base address will be selected by the OS for each call to mmap. - * Caution should be used with this mode since a call that requires the - * backing store to grow may change pointers that are cached by the - * application. - */ - NEVER_FIXED = 2 - }; - - // = Initialization method. - ACE_MMAP_Memory_Pool_Options (const void *base_addr = ACE_DEFAULT_BASE_ADDR, - int use_fixed_addr = ALWAYS_FIXED, - int write_each_page = 1, - off_t minimum_bytes = 0, - u_int flags = 0, - int guess_on_fault = 1, - LPSECURITY_ATTRIBUTES sa = 0, - mode_t file_mode = ACE_DEFAULT_FILE_PERMS); - - /// Base address of the memory-mapped backing store. - const void *base_addr_; - - /** - * Determines whether we set @c base_addr_ or if mmap(2) selects it - * FIRSTCALL_FIXED The base address from the first call to mmap - * will be used for subsequent calls to mmap - * ALWAYS_FIXED The base address specified in base_addr will be - * used in all calls to mmap. - * NEVER_FIXED The base address will be selected by the OS for - * each call to mmap. Caution should be used with - * this mode since a call that requires the backing - * store to grow may change pointers that are - * cached by the application. - */ - int use_fixed_addr_; - - /// Should each page be written eagerly to avoid surprises later - /// on? - int write_each_page_; - - /// What the minimim bytes of the initial segment should be. - off_t minimum_bytes_; - - /// Any special flags that need to be used for @c mmap. - u_int flags_; - - /** - * Try to remap without knowing the faulting address. This - * parameter is ignored on platforms that know the faulting address - * (UNIX with SI_ADDR and Win32). - */ - int guess_on_fault_; - - /// Pointer to a security attributes object. Only used on NT. - LPSECURITY_ATTRIBUTES sa_; - - /// File mode for mmaped file, if it is created. - mode_t file_mode_; -}; - -/** - * @class ACE_MMAP_Memory_Pool - * - * @brief Make a memory pool that is based on @c mmap(2). This - * implementation allows memory to be shared between processes. - */ -class ACE_Export ACE_MMAP_Memory_Pool : public ACE_Event_Handler -{ -public: - typedef ACE_MMAP_Memory_Pool_Options OPTIONS; - - // = Initialization and termination methods. - - /// Initialize the pool. - ACE_MMAP_Memory_Pool (const ACE_TCHAR *backing_store_name = 0, - const OPTIONS *options = 0); - - /// Destructor. - virtual ~ACE_MMAP_Memory_Pool (void); - - /// Ask system for initial chunk of shared memory. - virtual void *init_acquire (size_t nbytes, - size_t &rounded_bytes, - int &first_time); - - /** - * Acquire at least @a nbytes from the memory pool. @a rounded_bytes - * is the actual number of bytes allocated. Also acquires an - * internal semaphore that ensures proper serialization of - * ACE_MMAP_Memory_Pool initialization across processes. - */ - virtual void *acquire (size_t nbytes, - size_t &rounded_bytes); - - /// Instruct the memory pool to release all of its resources. - virtual int release (int destroy = 1); - - /// Sync the memory region to the backing store starting at - /// @c this->base_addr_. - virtual int sync (ssize_t len = -1, int flags = MS_SYNC); - - /// Sync the memory region to the backing store starting at @a addr. - virtual int sync (void *addr, size_t len, int flags = MS_SYNC); - - /** - * 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. - */ - virtual int protect (ssize_t len = -1, int prot = PROT_RDWR); - - /// Change the protection of the pages of the mapped region to @a prot - /// starting at @a addr up to @a len bytes. - virtual int protect (void *addr, size_t len, int prot = PROT_RDWR); - -#if defined (ACE_WIN32) - /** - * Win32 Structural exception selector. The return value decides - * how to handle memory pool related structural exceptions. Returns - * 1, 0, or , -1. - */ - virtual int seh_selector (void *); -#endif /* ACE_WIN32 */ - - /** - * Try to extend the virtual address space so that @a addr is now - * covered by the address mapping. The method succeeds and returns - * 0 if the backing store has adequate memory to cover this address. - * Otherwise, it returns -1. This method is typically called by a - * UNIX signal handler for SIGSEGV or a Win32 structured exception - * when another process has grown the backing store (and its - * mapping) and our process now incurs a fault because our mapping - * isn't in range (yet). - */ - virtual int remap (void *addr); - - /// Return the base address of this memory pool. - virtual void *base_addr (void) const; - - /// Dump the state of an object. - virtual void dump (void) const; - - /// Declare the dynamic allocation hooks. - ACE_ALLOC_HOOK_DECLARE; - -protected: - /// Implement the algorithm for rounding up the request to an - /// appropriate chunksize. - virtual size_t round_up (size_t nbytes); - - /// Compute the new @a map_size of the backing store and commit the - /// memory. - virtual int commit_backing_store_name (size_t rounded_bytes, - off_t &map_size); - - /// Memory map the file up to @a map_size bytes. - virtual int map_file (off_t map_size); - - /// Handle SIGSEGV and SIGBUS signals to remap shared memory - /// properly. - virtual int handle_signal (int signum, siginfo_t *, ucontext_t *); - - /// Handles SIGSEGV. - ACE_Sig_Handler signal_handler_; - - /// Memory-mapping object. - ACE_Mem_Map mmap_; - - /** - * Base of mapped region. If this has the value of 0 then the OS is - * free to select any address to map the file, otherwise this value - * is what the OS must try to use to mmap the file. - */ - void *base_addr_; - - /// Must we use the @c base_addr_ or can we let mmap(2) select it? - int use_fixed_addr_; - - /// Flags passed into <ACE_OS::mmap>. - int flags_; - - /// Should we write a byte to each page to forceably allocate memory - /// for this backing store? - int write_each_page_; - - /// What the minimum bytes of the initial segment should be. - off_t minimum_bytes_; - - /// Name of the backing store where the shared memory pool is kept. - ACE_TCHAR backing_store_name_[MAXPATHLEN + 1]; - - /** - * Try to remap without knowing the faulting address. This - * parameter is ignored on platforms that know the faulting address - * (UNIX with SI_ADDR and Win32). - */ - int guess_on_fault_; - - /// Security attributes object, only used on NT. - LPSECURITY_ATTRIBUTES sa_; - - /// Protection mode for mmaped file. - mode_t file_mode_; -}; - -/** - * @class ACE_Lite_MMAP_Memory_Pool - * - * @brief Make a ``lighter-weight'' memory pool based <ACE_Mem_Map>. - * - * This implementation allows memory to be shared between - * processes. However, unlike the <ACE_MMAP_Memory_Pool> - * the <sync> methods are no-ops, which means that we don't pay - * for the price of flushing the memory to the backing store on - * every update. Naturally, this trades off increased - * performance for less reliability if the machine crashes. - */ -class ACE_Export ACE_Lite_MMAP_Memory_Pool : public ACE_MMAP_Memory_Pool -{ -public: - /// Initialize the pool. - ACE_Lite_MMAP_Memory_Pool (const ACE_TCHAR *backing_store_name = 0, - const OPTIONS *options = 0); - - /// Destructor. - virtual ~ACE_Lite_MMAP_Memory_Pool (void); - - /// Overwrite the default sync behavior with no-op - virtual int sync (ssize_t len = -1, int flags = MS_SYNC); - - /// Overwrite the default sync behavior with no-op - virtual int sync (void *addr, size_t len, int flags = MS_SYNC); -}; - -#if defined (ACE_WIN32) - -/** - * @class ACE_Pagefile_Memory_Pool_Options - * - * @brief Helper class for Pagefile Memory Pool constructor options. - * - * This should be a nested class, but that breaks too many - * compilers. - */ -class ACE_Export ACE_Pagefile_Memory_Pool_Options -{ -public: - /// Initialization method. - ACE_Pagefile_Memory_Pool_Options (void *base_addr = ACE_DEFAULT_PAGEFILE_POOL_BASE, - size_t max_size = ACE_DEFAULT_PAGEFILE_POOL_SIZE); - - /// Base address of the memory-mapped backing store. - void *base_addr_; - - /// Maximum size the pool may grow. - size_t max_size_; -}; - -/** - * @class ACE_Pagefile_Memory_Pool - * - * @brief Make a memory pool that is based on "anonymous" memory - * regions allocated from the Win32 page file. - */ -class ACE_Export ACE_Pagefile_Memory_Pool -{ -public: - typedef ACE_Pagefile_Memory_Pool_Options OPTIONS; - - /// Initialize the pool. - ACE_Pagefile_Memory_Pool (const ACE_TCHAR *backing_store_name = 0, - const OPTIONS *options = 0); - - /// Ask system for initial chunk of shared memory. - void *init_acquire (size_t nbytes, - size_t &rounded_bytes, - int &first_time); - - /// Acquire at least <nbytes> from the memory pool. <rounded_bytes> - /// is the actual number of bytes allocated. - void *acquire (size_t nbytes, - size_t &rounded_bytes); - - /// Instruct the memory pool to release all of its resources. - int release (int destroy = 1); - - /** - * Win32 Structural exception selector. The return value decides - * how to handle memory pool related structural exceptions. Returns - * 1, 0, or , -1. - */ - virtual int seh_selector (void *); - - /** - * Try to extend the virtual address space so that <addr> is now - * covered by the address mapping. The method succeeds and returns - * 0 if the backing store has adequate memory to cover this address. - * Otherwise, it returns -1. This method is typically called by an - * exception handler for a Win32 structured exception when another - * process has grown the backing store (and its mapping) and our - * process now incurs a fault because our mapping isn't in range - * (yet). - */ - int remap (void *addr); - - /// Round up to system page size. - size_t round_to_page_size (size_t nbytes); - - /// Round up to the chunk size required by the operation system - size_t round_to_chunk_size (size_t nbytes); - - // = Don't need this methods here ... - int sync (ssize_t = -1, int = MS_SYNC); - int sync (void *, size_t, int = MS_SYNC); - int protect (ssize_t = -1, int = PROT_RDWR); - int protect (void *, size_t, int = PROT_RDWR); - - /// Return the base address of this memory pool, 0 if base_addr - /// never changes. - virtual void *base_addr (void) const; - - void dump (void) const {} - -protected: - - /** - * Map portions or the entire pool into the local virtual address - * space. To do this, we compute the new @c file_offset of the - * backing store and commit the memory. - */ - int map (int &firstTime, size_t appendBytes = 0); - - /// Release the mapping. - int unmap (void); - -private: - - /** - * @class Control_Block - * - * @brief Attributes that are meaningful in local storage only. - */ - class Control_Block - { - public: - /// Required base address - void *req_base_; - - /// Base address returned from system call - void *mapped_base_; - - /** - * @class Shared_Control_Block - * - * @brief Pool statistics - */ - class Shared_Control_Block - { - public: - /// Maximum size the pool may grow - size_t max_size_; - - /// Size of mapped shared memory segment - size_t mapped_size_; - - /// Offset to mapped but not yet acquired address space - ptrdiff_t free_offset_; - - /// Size of mapped but not yet acquired address space - size_t free_size_; - }; - - Shared_Control_Block sh_; - }; - - // Base of mapped region. If this has the value of 0 then the OS is - // free to select any address to map the file, otherwise this value - // is what the OS must try to use to mmap the file. - - /// Description of what our process mapped. - Control_Block local_cb_; - - /// Shared memory pool statistics. - Control_Block *shared_cb_; - - /// File mapping handle. - ACE_HANDLE object_handle_; - - /// System page size. - size_t page_size_; - - /// Name of the backing store where the shared memory pool is kept. - ACE_TCHAR backing_store_name_[MAXPATHLEN]; -}; - -#endif /* ACE_WIN32 */ - -#if defined (__ACE_INLINE__) -#include "ace/Memory_Pool.inl" -#endif /* __ACE_INLINE__ */ +#include "ace/Local_Memory_Pool.h" +#include "ace/MMAP_Memory_Pool.h" +#include "ace/Sbrk_Memory_Pool.h" +#include "ace/Shared_Memory_Pool.h" +#include "ace/Pagefile_Memory_Pool.h" #include /**/ "ace/post.h" #endif /* ACE_MEMORY_POOL_H */ diff --git a/ace/Memory_Pool.inl b/ace/Memory_Pool.inl deleted file mode 100644 index de87de3b331..00000000000 --- a/ace/Memory_Pool.inl +++ /dev/null @@ -1,269 +0,0 @@ -/* -*- C++ -*- */ -// $Id$ - -ACE_INLINE -ACE_Local_Memory_Pool::~ACE_Local_Memory_Pool (void) -{ - // Free up all memory allocated by this pool. - this->release (); -} - -ACE_INLINE int -ACE_Local_Memory_Pool::sync (ssize_t, int) -{ - ACE_TRACE ("ACE_Local_Memory_Pool::sync"); - return 0; -} - -ACE_INLINE int -ACE_Local_Memory_Pool::sync (void *, size_t, int) -{ - ACE_TRACE ("ACE_Local_Memory_Pool::sync"); - return 0; -} - -ACE_INLINE int -ACE_Local_Memory_Pool::protect (ssize_t, int) -{ - ACE_TRACE ("ACE_Local_Memory_Pool::protect"); - return 0; -} - -ACE_INLINE int -ACE_Local_Memory_Pool::protect (void *, size_t, int) -{ - ACE_TRACE ("ACE_Local_Memory_Pool::protect"); - return 0; -} - -ACE_INLINE void * -ACE_Local_Memory_Pool::base_addr (void) const -{ - return 0; -} - -ACE_INLINE -ACE_MMAP_Memory_Pool::~ACE_MMAP_Memory_Pool (void) -{ -} - -ACE_INLINE -ACE_Lite_MMAP_Memory_Pool::~ACE_Lite_MMAP_Memory_Pool (void) -{ -} - -ACE_INLINE size_t -ACE_MMAP_Memory_Pool::round_up (size_t nbytes) -{ - ACE_TRACE ("ACE_MMAP_Memory_Pool::round_up"); - return ACE::round_to_pagesize (static_cast<off_t> (nbytes)); -} - -ACE_INLINE void * -ACE_MMAP_Memory_Pool::base_addr (void) const -{ - ACE_TRACE ("ACE_MMAP_Memory_Pool::base_addr"); - return this->base_addr_; -} - -// Ask system for initial chunk of local memory. - -ACE_INLINE void * -ACE_Local_Memory_Pool::init_acquire (size_t nbytes, - size_t &rounded_bytes, - int &first_time) -{ - ACE_TRACE ("ACE_Local_Memory_Pool::init_acquire"); - // Note that we assume that when ACE_Local_Memory_Pool is used, - // ACE_Malloc's constructor will only get called once. If this - // assumption doesn't hold, we are in deep trouble! - - first_time = 1; - return this->acquire (nbytes, rounded_bytes); -} - -// Let the underlying new operator figure out the alignment... - -ACE_INLINE size_t -ACE_Local_Memory_Pool::round_up (size_t nbytes) -{ - ACE_TRACE ("ACE_Local_Memory_Pool::round_up"); - return ACE::round_to_pagesize (static_cast<off_t> (nbytes)); -} - -#if !defined (ACE_LACKS_SYSV_SHMEM) -// Implement the algorithm for rounding up the request to an -// appropriate chunksize. - -ACE_INLINE -ACE_Shared_Memory_Pool::~ACE_Shared_Memory_Pool (void) -{ -} - -ACE_INLINE size_t -ACE_Shared_Memory_Pool::round_up (size_t nbytes) -{ - ACE_TRACE ("ACE_Shared_Memory_Pool::round_up"); - if (nbytes < this->segment_size_) - nbytes = this->segment_size_; - - return ACE::round_to_pagesize (nbytes); -} - -ACE_INLINE int -ACE_Shared_Memory_Pool::sync (ssize_t, int) -{ - ACE_TRACE ("ACE_Shared_Memory_Pool::sync"); - return 0; -} - -ACE_INLINE int -ACE_Shared_Memory_Pool::sync (void *, size_t, int) -{ - ACE_TRACE ("ACE_Shared_Memory_Pool::sync"); - return 0; -} - -ACE_INLINE int -ACE_Shared_Memory_Pool::protect (ssize_t, int) -{ - ACE_TRACE ("ACE_Shared_Memory_Pool::protect"); - return 0; -} - -ACE_INLINE int -ACE_Shared_Memory_Pool::protect (void *, size_t, int) -{ - ACE_TRACE ("ACE_Shared_Memory_Pool::protect"); - return 0; -} - -ACE_INLINE void * -ACE_Shared_Memory_Pool::base_addr (void) const -{ - ACE_TRACE ("ACE_Shared_Memory_Pool::base_addr"); - return this->base_addr_; -} -#endif /* !ACE_LACKS_SYSV_SHMEM */ - -#if !defined (ACE_LACKS_SBRK) - -ACE_INLINE -ACE_Sbrk_Memory_Pool::~ACE_Sbrk_Memory_Pool (void) -{ -} - -ACE_INLINE void * -ACE_Sbrk_Memory_Pool::base_addr (void) const -{ - return 0; -} - -// Ask system for initial chunk of local memory. - -ACE_INLINE void * -ACE_Sbrk_Memory_Pool::init_acquire (size_t nbytes, - size_t &rounded_bytes, - int &first_time) -{ - ACE_TRACE ("ACE_Sbrk_Memory_Pool::init_acquire"); - // Note that we assume that when ACE_Sbrk_Memory_Pool is used, - // ACE_Malloc's constructor will only get called once. If this - // assumption doesn't hold, we are in deep trouble! - - first_time = 1; - return this->acquire (nbytes, rounded_bytes); -} - -// Round up the request to a multiple of the page size. - -ACE_INLINE size_t -ACE_Sbrk_Memory_Pool::round_up (size_t nbytes) -{ - ACE_TRACE ("ACE_Sbrk_Memory_Pool::round_up"); - return ACE::round_to_pagesize (nbytes); -} - -/* No-op for now... */ - -ACE_INLINE int -ACE_Sbrk_Memory_Pool::release (int) -{ - ACE_TRACE ("ACE_Sbrk_Memory_Pool::release"); - return 0; -} - -ACE_INLINE int -ACE_Sbrk_Memory_Pool::sync (ssize_t, int) -{ - ACE_TRACE ("ACE_Sbrk_Memory_Pool::sync"); - return 0; -} - -ACE_INLINE int -ACE_Sbrk_Memory_Pool::sync (void *, size_t, int) -{ - ACE_TRACE ("ACE_Sbrk_Memory_Pool::sync"); - return 0; -} - -ACE_INLINE int -ACE_Sbrk_Memory_Pool::protect (ssize_t, int) -{ - ACE_TRACE ("ACE_Sbrk_Memory_Pool::protect"); - return 0; -} - -ACE_INLINE int -ACE_Sbrk_Memory_Pool::protect (void *, size_t, int) -{ - ACE_TRACE ("ACE_Sbrk_Memory_Pool::protect"); - return 0; -} -#endif /* !ACE_LACKS_SBRK */ - -#if defined (ACE_WIN32) - -ACE_INLINE size_t -ACE_Pagefile_Memory_Pool::round_to_chunk_size (size_t nbytes) -{ - return (nbytes + ACE_DEFAULT_PAGEFILE_POOL_CHUNK - 1) - & (~(ACE_DEFAULT_PAGEFILE_POOL_CHUNK - 1)); -} - -ACE_INLINE size_t -ACE_Pagefile_Memory_Pool::round_to_page_size (size_t nbytes) -{ - return ACE::round_to_pagesize (static_cast<off_t> (nbytes)); -} - -ACE_INLINE int -ACE_Pagefile_Memory_Pool::sync (ssize_t, int) -{ - return 0; -} - -ACE_INLINE int -ACE_Pagefile_Memory_Pool::sync (void *, size_t, int) -{ - return 0; -} - -ACE_INLINE int -ACE_Pagefile_Memory_Pool::protect (ssize_t, int) -{ - return 0; -} - -ACE_INLINE int -ACE_Pagefile_Memory_Pool::protect (void *, size_t, int) -{ - return 0; -} - -ACE_INLINE void * -ACE_Pagefile_Memory_Pool::base_addr (void) const -{ - return 0; -} -#endif /* ACE_WIN32 */ diff --git a/ace/Pagefile_Memory_Pool.cpp b/ace/Pagefile_Memory_Pool.cpp new file mode 100644 index 00000000000..99a80760893 --- /dev/null +++ b/ace/Pagefile_Memory_Pool.cpp @@ -0,0 +1,362 @@ +// $Id$ + +// Pagefile_Memory_Pool.cpp +#include "ace/Pagefile_Memory_Pool.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Pagefile_Memory_Pool.inl" +#endif /* __ACE_INLINE__ */ + +#include "ace/Log_Msg.h" +#include "ace/Auto_Ptr.h" +#include "ace/RW_Thread_Mutex.h" +#include "ace/OS_NS_sys_mman.h" +#include "ace/OS_NS_string.h" +#include "ace/OS_NS_sys_stat.h" +#include "ace/OS_NS_unistd.h" + +#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1) +#include "ace/Based_Pointer_T.h" +#include "ace/Based_Pointer_Repository.h" +#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */ + +ACE_RCSID(ace, Pagefile_Memory_Pool, "$Id$") + +#if defined (ACE_WIN32) +#if !defined (ACE_HAS_WINCE) +#define ACE_MAP_FILE(_hnd, _access, _offHigh, _offLow, _nBytes, _baseAdd)\ + MapViewOfFileEx (_hnd, _access, _offHigh, _offLow, _nBytes, _baseAdd) +#else //if !defined (ACE_HAS_WINCE) +#define ACE_MAP_FILE(_hnd, _access, _offHigh, _offLow, _nBytes, _baseAdd)\ + MapViewOfFile (_hnd, _access, _offHigh, _offLow, _nBytes) +#endif /* !defined (ACE_HAS_WINCE) */ + +ACE_Pagefile_Memory_Pool_Options::ACE_Pagefile_Memory_Pool_Options (void *base_addr, + size_t max_size) + : base_addr_ (base_addr), + max_size_ (max_size) +{ +} + +int +ACE_Pagefile_Memory_Pool::release (int) +{ + return this->unmap (); +} + +ACE_Pagefile_Memory_Pool::ACE_Pagefile_Memory_Pool (const ACE_TCHAR *backing_store_name, + const OPTIONS *options) + : shared_cb_ (0), + object_handle_ (0), + page_size_ (ACE_Pagefile_Memory_Pool::round_to_page_size (1)) +{ + // Initialize local copy of pool statistics. + if (options != 0) + { + this->local_cb_.req_base_ = options->base_addr_; + this->local_cb_.mapped_base_ = 0; + this->local_cb_.sh_.max_size_ = + options->max_size_; + this->local_cb_.sh_.mapped_size_ = 0; + this->local_cb_.sh_.free_offset_ = + this->local_cb_.sh_.mapped_size_; + this->local_cb_.sh_.free_size_ = 0; + } + + 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_PAGEFILE_POOL_NAME; + + ACE_OS::strsncpy (this->backing_store_name_, + backing_store_name, + (sizeof this->backing_store_name_ / sizeof (ACE_TCHAR))); +} + +void * +ACE_Pagefile_Memory_Pool::acquire (size_t nbytes, + size_t &rounded_bytes) +{ + rounded_bytes = round_to_page_size (nbytes); + void *result = 0; + int first_time = 0; + + // Check local_cb_ for consistency. Remap, if extra space is too + // small and/or we didn't map the whole shared memory section + if (this->shared_cb_->sh_.mapped_size_ + > this->local_cb_.sh_.mapped_size_ + || this->shared_cb_->sh_.free_size_ < rounded_bytes) + { + size_t append = 0; + if (rounded_bytes > this->shared_cb_->sh_.free_size_) + append = rounded_bytes - this->shared_cb_->sh_.free_size_; + + if (this->map (first_time, append) < 0) + return result; + } + + // Get the block from extra space and update shared and local + // control block + if (this->shared_cb_->sh_.free_size_ < rounded_bytes) + return result; + + result = (void *)((char *) this->local_cb_.mapped_base_ + + this->shared_cb_->sh_.free_offset_); + this->shared_cb_->sh_.free_offset_ += rounded_bytes; + this->shared_cb_->sh_.free_size_ -= rounded_bytes; + this->local_cb_.sh_ = this->shared_cb_->sh_; + + return result; +} + +void * +ACE_Pagefile_Memory_Pool::init_acquire (size_t nbytes, + size_t &rounded_bytes, + int &first_time) +{ + // Map the shared memory and get information, if we created the + // shared memory. + if (this->map (first_time) < 0) + return 0; + + if (first_time != 0) + // We created the shared memory. So we have to allocate the + // requested memory. + return this->acquire (nbytes, rounded_bytes); + else + // We just mapped the memory and return the base address + return (void *)((char *) this->local_cb_.mapped_base_ + + ACE_Pagefile_Memory_Pool::round_to_page_size + ((int) sizeof (Control_Block))); +} + +int +ACE_Pagefile_Memory_Pool::seh_selector (void *ep) +{ + DWORD ecode = ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionCode; + + if (ecode == EXCEPTION_ACCESS_VIOLATION) + { + void * fault_addr = (void *) + ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionInformation[1]; + + if (this->remap (fault_addr) == 0) + return 1; + } + + return 0; +} + +int +ACE_Pagefile_Memory_Pool::remap (void *addr) +{ + // If the shared memory is not mapped or the address, that caused + // the memory fault is outside of the commited range of chunks, we + // return. + if (this->shared_cb_ == 0 + || addr < this->local_cb_.mapped_base_ + || addr >= (void *)((char *) this->local_cb_.mapped_base_ + + this->shared_cb_->sh_.mapped_size_)) + return -1; + + // We can solve the problem by committing additional chunks. + int first_time = 0; + return this->map (first_time); +} + +int +ACE_Pagefile_Memory_Pool::unmap (void) +{ +#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1) + ACE_BASED_POINTER_REPOSITORY::instance ()->unbind + (this->local_cb_.mapped_base_); +#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */ + + // Cleanup cached pool pointer. + this->shared_cb_ = 0; + + if (this->local_cb_.sh_.mapped_size_ > 0) + ::UnmapViewOfFile (this->local_cb_.mapped_base_); + + // Reset local pool statistics. + this->local_cb_.req_base_ = + ACE_DEFAULT_PAGEFILE_POOL_BASE; + this->local_cb_.mapped_base_ = 0; + this->local_cb_.sh_.max_size_ = + ACE_DEFAULT_PAGEFILE_POOL_SIZE; + this->local_cb_.sh_.mapped_size_ = 0; + this->local_cb_.sh_.free_offset_ = + this->local_cb_.sh_.mapped_size_; + this->local_cb_.sh_.free_size_ = 0; + + // Release the pool + if (this->object_handle_ != 0) + { + ::CloseHandle (this->object_handle_); + this->object_handle_ = 0; + } + return 0; +} + +int +ACE_Pagefile_Memory_Pool::map (int &first_time, + size_t append_bytes) +{ + size_t map_size; + void *map_addr; + + // Create file mapping, if not yet done + if (object_handle_ == 0) + { +#if (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) + // Allow access by all users. + SECURITY_ATTRIBUTES sa; + SECURITY_DESCRIPTOR sd; + ::InitializeSecurityDescriptor (&sd, + SECURITY_DESCRIPTOR_REVISION); + ::SetSecurityDescriptorDacl (&sd, + TRUE, + 0, + FALSE); + sa.nLength = sizeof (SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = &sd; + sa.bInheritHandle = FALSE; +#endif /* (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) */ + + // Get an object handle to the named reserved memory object. + DWORD size_high; + DWORD size_low; +#if defined (ACE_WIN64) + size_high = static_cast<DWORD> (this->local_cb_.sh_.max_size_ >> 32); + size_low = static_cast<DWORD> (this->local_cb_.sh_.max_size_ & 0xFFFFFFFF); +#else + size_high = 0; + size_low = this->local_cb_.sh_.max_size_; +#endif + + object_handle_ = + ACE_TEXT_CreateFileMapping (INVALID_HANDLE_VALUE, +#if (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) + &sa, +#else + 0, +#endif /* (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) */ + PAGE_READWRITE | SEC_RESERVE, + size_high, + size_low, + this->backing_store_name_); + if (object_handle_ == 0) + return -1; + first_time = + ::GetLastError () == ERROR_ALREADY_EXISTS + ? 0 + : 1; + } + + // Do the initial mapping. + if (this->shared_cb_ == 0) + { + // Map a view to the shared memory. Note: <MapViewOfFile[Ex]> + // does *not* commit the pages! + this->shared_cb_ = (ACE_Pagefile_Memory_Pool::Control_Block *) + ACE_MAP_FILE (this->object_handle_, + FILE_MAP_WRITE, + 0, + 0, + this->local_cb_.sh_.max_size_, + this->local_cb_.req_base_); + if (this->shared_cb_ == 0) + return -1; + + // There was no previous mapping, so we map the first chunk and + // initialize the shared pool statistics. + if (first_time) + { + // 1st block is used to keep shared memory statistics. + map_size = + ACE_Pagefile_Memory_Pool::round_to_chunk_size + (ACE_Pagefile_Memory_Pool::round_to_page_size + ((int) sizeof(Control_Block)) + + append_bytes); + + if (::VirtualAlloc ((void *) this->shared_cb_, + map_size, + MEM_COMMIT, + PAGE_READWRITE) == 0) + return -1; + + this->shared_cb_->req_base_ = 0; + this->shared_cb_->mapped_base_ = 0; + this->local_cb_.mapped_base_ = this->shared_cb_; + this->local_cb_.sh_.mapped_size_ = map_size; + this->local_cb_.sh_.free_offset_ = + round_to_page_size ((int) sizeof (Control_Block)); + this->local_cb_.sh_.free_size_ = + this->local_cb_.sh_.mapped_size_ - + this->local_cb_.sh_.free_offset_; + this->shared_cb_->sh_ = this->local_cb_.sh_; + } + + // The shared memory exists, so we map the first chunk to the + // base address of the pool to get the shared pool statistics. + else + { + // 1st block is used to keep shared memory statistics. + map_size = + ACE_Pagefile_Memory_Pool::round_to_chunk_size + ((int) sizeof (Control_Block)); + + if (::VirtualAlloc ((void *) this->shared_cb_, + map_size, + MEM_COMMIT, + PAGE_READWRITE) == 0) + return -1; + this->local_cb_.mapped_base_ = this->shared_cb_; + this->local_cb_.sh_.mapped_size_ = map_size; + } + } + + // If the shared memory is larger than the part we've already + // committed, we have to remap it. + if (this->shared_cb_->sh_.mapped_size_ > + this->local_cb_.sh_.mapped_size_ + || append_bytes > 0) + { + map_size = + (this->shared_cb_->sh_.mapped_size_ - + this->local_cb_.sh_.mapped_size_) + + ACE_Pagefile_Memory_Pool::round_to_chunk_size + (append_bytes); + + map_addr = (void *)((char *) this->shared_cb_ + + this->local_cb_.sh_.mapped_size_); + + if (::VirtualAlloc (map_addr, + map_size, + MEM_COMMIT, + PAGE_READWRITE) == 0) + return -1; + else if (append_bytes > 0) + { + this->shared_cb_->sh_.mapped_size_ += + round_to_chunk_size (append_bytes); + this->shared_cb_->sh_.free_size_ = + this->shared_cb_->sh_.mapped_size_ - + this->shared_cb_->sh_.free_offset_; + } + } + + // Update local copy of the shared memory statistics. + this->local_cb_.sh_ = + this->shared_cb_->sh_; +#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1) + ACE_BASED_POINTER_REPOSITORY::instance ()->bind + (this->local_cb_.mapped_base_, + this->local_cb_.sh_.mapped_size_); +#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */ + + return 0; +} + +#endif /* ACE_WIN32 */ + diff --git a/ace/Pagefile_Memory_Pool.h b/ace/Pagefile_Memory_Pool.h new file mode 100644 index 00000000000..004582523d2 --- /dev/null +++ b/ace/Pagefile_Memory_Pool.h @@ -0,0 +1,192 @@ +/* -*- C++ -*- */ + +//============================================================================= +/** + * @file Memory_Pool.h + * + * $Id$ + * + * @author Dougls C. Schmidt <schmidt@cs.wustl.edu> + * @author Prashant Jain <pjain@cs.wustl.edu> + */ +//============================================================================= + +#ifndef ACE_PAGEFILE_MEMORY_POOL_H +#define ACE_PAGEFILE_MEMORY_POOL_H +#include /**/ "ace/pre.h" + +#include "ace/ACE.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#if defined (ACE_WIN32) + +/** + * @class ACE_Pagefile_Memory_Pool_Options + * + * @brief Helper class for Pagefile Memory Pool constructor options. + * + * This should be a nested class, but that breaks too many + * compilers. + */ +class ACE_Export ACE_Pagefile_Memory_Pool_Options +{ +public: + /// Initialization method. + ACE_Pagefile_Memory_Pool_Options (void *base_addr = ACE_DEFAULT_PAGEFILE_POOL_BASE, + size_t max_size = ACE_DEFAULT_PAGEFILE_POOL_SIZE); + + /// Base address of the memory-mapped backing store. + void *base_addr_; + + /// Maximum size the pool may grow. + size_t max_size_; +}; + +/** + * @class ACE_Pagefile_Memory_Pool + * + * @brief Make a memory pool that is based on "anonymous" memory + * regions allocated from the Win32 page file. + */ +class ACE_Export ACE_Pagefile_Memory_Pool +{ +public: + typedef ACE_Pagefile_Memory_Pool_Options OPTIONS; + + /// Initialize the pool. + ACE_Pagefile_Memory_Pool (const ACE_TCHAR *backing_store_name = 0, + const OPTIONS *options = 0); + + /// Ask system for initial chunk of shared memory. + void *init_acquire (size_t nbytes, + size_t &rounded_bytes, + int &first_time); + + /// Acquire at least <nbytes> from the memory pool. <rounded_bytes> + /// is the actual number of bytes allocated. + void *acquire (size_t nbytes, + size_t &rounded_bytes); + + /// Instruct the memory pool to release all of its resources. + int release (int destroy = 1); + + /** + * Win32 Structural exception selector. The return value decides + * how to handle memory pool related structural exceptions. Returns + * 1, 0, or , -1. + */ + virtual int seh_selector (void *); + + /** + * Try to extend the virtual address space so that <addr> is now + * covered by the address mapping. The method succeeds and returns + * 0 if the backing store has adequate memory to cover this address. + * Otherwise, it returns -1. This method is typically called by an + * exception handler for a Win32 structured exception when another + * process has grown the backing store (and its mapping) and our + * process now incurs a fault because our mapping isn't in range + * (yet). + */ + int remap (void *addr); + + /// Round up to system page size. + size_t round_to_page_size (size_t nbytes); + + /// Round up to the chunk size required by the operation system + size_t round_to_chunk_size (size_t nbytes); + + // = Don't need this methods here ... + int sync (ssize_t = -1, int = MS_SYNC); + int sync (void *, size_t, int = MS_SYNC); + int protect (ssize_t = -1, int = PROT_RDWR); + int protect (void *, size_t, int = PROT_RDWR); + + /// Return the base address of this memory pool, 0 if base_addr + /// never changes. + virtual void *base_addr (void) const; + + void dump (void) const {} + +protected: + + /** + * Map portions or the entire pool into the local virtual address + * space. To do this, we compute the new @c file_offset of the + * backing store and commit the memory. + */ + int map (int &firstTime, size_t appendBytes = 0); + + /// Release the mapping. + int unmap (void); + +private: + + /** + * @class Control_Block + * + * @brief Attributes that are meaningful in local storage only. + */ + class Control_Block + { + public: + /// Required base address + void *req_base_; + + /// Base address returned from system call + void *mapped_base_; + + /** + * @class Shared_Control_Block + * + * @brief Pool statistics + */ + class Shared_Control_Block + { + public: + /// Maximum size the pool may grow + size_t max_size_; + + /// Size of mapped shared memory segment + size_t mapped_size_; + + /// Offset to mapped but not yet acquired address space + ptrdiff_t free_offset_; + + /// Size of mapped but not yet acquired address space + size_t free_size_; + }; + + Shared_Control_Block sh_; + }; + + // Base of mapped region. If this has the value of 0 then the OS is + // free to select any address to map the file, otherwise this value + // is what the OS must try to use to mmap the file. + + /// Description of what our process mapped. + Control_Block local_cb_; + + /// Shared memory pool statistics. + Control_Block *shared_cb_; + + /// File mapping handle. + ACE_HANDLE object_handle_; + + /// System page size. + size_t page_size_; + + /// Name of the backing store where the shared memory pool is kept. + ACE_TCHAR backing_store_name_[MAXPATHLEN]; +}; + +#endif /* ACE_WIN32 */ + +#if defined (__ACE_INLINE__) +#include "ace/Pagefile_Memory_Pool.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" +#endif /* ACE_MEMORY_POOL_H */ diff --git a/ace/Pagefile_Memory_Pool.inl b/ace/Pagefile_Memory_Pool.inl new file mode 100644 index 00000000000..db8d7a00aa4 --- /dev/null +++ b/ace/Pagefile_Memory_Pool.inl @@ -0,0 +1,48 @@ +/* -*- C++ -*- */ +// $Id$ + +#if defined (ACE_WIN32) + +ACE_INLINE size_t +ACE_Pagefile_Memory_Pool::round_to_chunk_size (size_t nbytes) +{ + return (nbytes + ACE_DEFAULT_PAGEFILE_POOL_CHUNK - 1) + & (~(ACE_DEFAULT_PAGEFILE_POOL_CHUNK - 1)); +} + +ACE_INLINE size_t +ACE_Pagefile_Memory_Pool::round_to_page_size (size_t nbytes) +{ + return ACE::round_to_pagesize (static_cast<off_t> (nbytes)); +} + +ACE_INLINE int +ACE_Pagefile_Memory_Pool::sync (ssize_t, int) +{ + return 0; +} + +ACE_INLINE int +ACE_Pagefile_Memory_Pool::sync (void *, size_t, int) +{ + return 0; +} + +ACE_INLINE int +ACE_Pagefile_Memory_Pool::protect (ssize_t, int) +{ + return 0; +} + +ACE_INLINE int +ACE_Pagefile_Memory_Pool::protect (void *, size_t, int) +{ + return 0; +} + +ACE_INLINE void * +ACE_Pagefile_Memory_Pool::base_addr (void) const +{ + return 0; +} +#endif /* ACE_WIN32 */ diff --git a/ace/Sbrk_Memory_Pool.cpp b/ace/Sbrk_Memory_Pool.cpp new file mode 100644 index 00000000000..70c6f7c4891 --- /dev/null +++ b/ace/Sbrk_Memory_Pool.cpp @@ -0,0 +1,119 @@ +// $Id$ + +// Memory_Pool.cpp +#include "ace/Sbrk_Memory_Pool.h" +#include "ace/Log_Msg.h" + +ACE_RCSID(ace, Sbrk_Memory_Pool, "$Id$") + +#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, ACE_LIB_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, ACE_LIB_TEXT ("(%P|%t) acquired more chunks, nbytes = %d, rounded_bytes = %d, new break = %u\n"), nbytes, rounded_bytes, cp)); + return cp; +} + +/* No-op for now... */ + +int +ACE_Sbrk_Memory_Pool::release (int) +{ + ACE_TRACE ("ACE_Sbrk_Memory_Pool::release"); + return 0; +} + +int +ACE_Sbrk_Memory_Pool::sync (ssize_t, int) +{ + ACE_TRACE ("ACE_Sbrk_Memory_Pool::sync"); + return 0; +} + +int +ACE_Sbrk_Memory_Pool::sync (void *, size_t, int) +{ + ACE_TRACE ("ACE_Sbrk_Memory_Pool::sync"); + return 0; +} + +int +ACE_Sbrk_Memory_Pool::protect (ssize_t, int) +{ + ACE_TRACE ("ACE_Sbrk_Memory_Pool::protect"); + return 0; +} + +int +ACE_Sbrk_Memory_Pool::protect (void *, size_t, int) +{ + ACE_TRACE ("ACE_Sbrk_Memory_Pool::protect"); + return 0; +} + +// Ask system for initial chunk of local memory. + +void * +ACE_Sbrk_Memory_Pool::init_acquire (size_t nbytes, + size_t &rounded_bytes, + int &first_time) +{ + ACE_TRACE ("ACE_Sbrk_Memory_Pool::init_acquire"); + // Note that we assume that when ACE_Sbrk_Memory_Pool is used, + // ACE_Malloc's constructor will only get called once. If this + // assumption doesn't hold, we are in deep trouble! + + first_time = 1; + return this->acquire (nbytes, rounded_bytes); +} + +void +ACE_Sbrk_Memory_Pool::dump (void) const +{ +#if defined (ACE_HAS_DUMP) + ACE_TRACE ("ACE_Sbrk_Memory_Pool::dump"); +#endif /* ACE_HAS_DUMP */ +} + +ACE_Sbrk_Memory_Pool::ACE_Sbrk_Memory_Pool (const ACE_TCHAR *, + const OPTIONS *) +{ + ACE_TRACE ("ACE_Sbrk_Memory_Pool::ACE_Sbrk_Memory_Pool"); +} + +ACE_Sbrk_Memory_Pool::~ACE_Sbrk_Memory_Pool (void) +{ +} + +void * +ACE_Sbrk_Memory_Pool::base_addr (void) const +{ + return 0; +} + + +// Round up the request to a multiple of the page size. + +size_t +ACE_Sbrk_Memory_Pool::round_up (size_t nbytes) +{ + ACE_TRACE ("ACE_Sbrk_Memory_Pool::round_up"); + return ACE::round_to_pagesize (nbytes); +} +#endif /* !ACE_LACKS_SBRK */ diff --git a/ace/Sbrk_Memory_Pool.h b/ace/Sbrk_Memory_Pool.h new file mode 100644 index 00000000000..07893057659 --- /dev/null +++ b/ace/Sbrk_Memory_Pool.h @@ -0,0 +1,107 @@ +/* -*- C++ -*- */ + +//============================================================================= +/** + * @file Memory_Pool.h + * + * $Id$ + * + * @author Dougls C. Schmidt <schmidt@cs.wustl.edu> + * @author Prashant Jain <pjain@cs.wustl.edu> + */ +//============================================================================= + +#ifndef ACE_SBRK_MEMORY_POOL_H +#define ACE_SBRK_MEMORY_POOL_H +#include /**/ "ace/pre.h" + +#include "ace/ACE.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#if !defined (ACE_LACKS_SBRK) +/** + * @class ACE_Sbrk_Memory_Pool_Options + * + * @brief Helper class for Sbrk Memory Pool constructor options. + * + * This should be a nested class, but that breaks too many + * compilers. + */ +class ACE_Export ACE_Sbrk_Memory_Pool_Options +{ +}; + +/** + * @class ACE_Sbrk_Memory_Pool + * + * @brief Make a memory pool that is based on <sbrk(2)>. + */ +class ACE_Export ACE_Sbrk_Memory_Pool +{ +public: + typedef ACE_Sbrk_Memory_Pool_Options OPTIONS; + + /// Initialize the pool. + ACE_Sbrk_Memory_Pool (const ACE_TCHAR *backing_store_name = 0, + const OPTIONS *options = 0); + + virtual ~ACE_Sbrk_Memory_Pool (void); + + // = Implementor operations. + /// Ask system for initial chunk of local memory. + virtual void *init_acquire (size_t nbytes, + size_t &rounded_bytes, + int &first_time); + + /// Acquire at least @a nbytes from the memory pool. @a rounded_bytes is + /// the actual number of bytes allocated. + virtual void *acquire (size_t nbytes, + size_t &rounded_bytes); + + /// Instruct the memory pool to release all of its resources. + virtual int release (int destroy = 1); + + /** + * Sync @a len bytes of the memory region to the backing store + * starting at @c this->base_addr_. If @a len == -1 then sync the + * whole region. + */ + virtual int sync (ssize_t len = -1, int flags = MS_SYNC); + + /// Sync @a len bytes of the memory region to the backing store + /// starting at @a addr. + virtual int sync (void *addr, size_t len, int flags = MS_SYNC); + + /** + * Change the protection of the pages of the mapped region to <prot> + * starting at @c this->base_addr_ up to @a len bytes. If @a len == -1 + * then change protection of all pages in the mapped region. + */ + virtual int protect (ssize_t len = -1, int prot = PROT_RDWR); + + /// Change the protection of the pages of the mapped region to @a prot + /// starting at @a addr up to @a len bytes. + virtual int protect (void *addr, size_t len, int prot = PROT_RDWR); + + /// Dump the state of an object. + virtual void dump (void) const; + + /// Return the base address of this memory pool, 0 if base_addr + /// never changes. + virtual void *base_addr (void) const; + + /// Declare the dynamic allocation hooks. + ACE_ALLOC_HOOK_DECLARE; + +protected: + /// Implement the algorithm for rounding up the request to an + /// appropriate chunksize. + virtual size_t round_up (size_t nbytes); +}; +#endif /* !ACE_LACKS_SBRK */ + +#include /**/ "ace/post.h" +#endif /* ACE_SBRK_MEMORY_POOL_H */ diff --git a/ace/Shared_Memory_Pool.cpp b/ace/Shared_Memory_Pool.cpp new file mode 100644 index 00000000000..34a790a6110 --- /dev/null +++ b/ace/Shared_Memory_Pool.cpp @@ -0,0 +1,449 @@ +// $Id$ + +// Shared_Memory_Pool.cpp +#include "ace/Shared_Memory_Pool.h" +#include "ace/OS_NS_sys_shm.h" + +ACE_RCSID(ace, Shared_Memory_Pool, "$Id$") + +#if !defined (ACE_LACKS_SYSV_SHMEM) +ACE_ALLOC_HOOK_DEFINE(ACE_Shared_Memory_Pool) + +ACE_Shared_Memory_Pool_Options::ACE_Shared_Memory_Pool_Options (const 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"); +} + +void +ACE_Shared_Memory_Pool::dump (void) const +{ +#if defined (ACE_HAS_DUMP) + ACE_TRACE ("ACE_Shared_Memory_Pool::dump"); +#endif /* ACE_HAS_DUMP */ +} + +int +ACE_Shared_Memory_Pool::in_use (off_t &offset, + size_t &counter) +{ + 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_LIB_TEXT ("(%P|%t) %p\n"), + ACE_LIB_TEXT ("shmctl")), + -1); + offset += buf.shm_segsz; + // ACE_DEBUG ((LM_DEBUG, ACE_LIB_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 = 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_LIB_TEXT ("(%P|%t) %p\n"), + ACE_LIB_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_LIB_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::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_LIB_TEXT ("(%P|%t) %p\n"), + ACE_LIB_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, + "(%P|%t) %p, shmem = %u, address = %u\n", + "shmat", + shmem, + address), + -1); + } + 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, ACE_LIB_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, ACE_LIB_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_LIB_TEXT ("(%P|%t) %p\n"), + ACE_LIB_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_LIB_TEXT ("(%P|%t) %p\n"), + ACE_LIB_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, + "(%P|%t) %p, shmem = %u, address = %u\n", + "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; +} + +ACE_Shared_Memory_Pool::ACE_Shared_Memory_Pool (const ACE_TCHAR *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 <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_LIB_TEXT ("%p\n"), + ACE_LIB_TEXT ("ACE_Sig_Handler::register_handler"))); +} + +ACE_Shared_Memory_Pool::~ACE_Shared_Memory_Pool (void) +{ +} + +// 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, ACE_LIB_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, ACE_LIB_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, + ACE_LIB_TEXT ("(%P|%t) %p\n"), + ACE_LIB_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_LIB_TEXT ("(%P|%t) %p\n"), + ACE_LIB_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, + "(%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, + reinterpret_cast<char *> (this->base_addr_), + 0); + if (this->base_addr_ == reinterpret_cast<char *> (-1)) + ACE_ERROR_RETURN ((LM_ERROR, + "(%P|%t) %p, base_addr = %u\n", + "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); +} + +// Instruct the memory pool to release all of its resources. + +int +ACE_Shared_Memory_Pool::release (int) +{ + 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; +} + +int +ACE_Shared_Memory_Pool::sync (ssize_t, int) +{ + ACE_TRACE ("ACE_Shared_Memory_Pool::sync"); + return 0; +} + +int +ACE_Shared_Memory_Pool::sync (void *, size_t, int) +{ + ACE_TRACE ("ACE_Shared_Memory_Pool::sync"); + return 0; +} + +int +ACE_Shared_Memory_Pool::protect (ssize_t, int) +{ + ACE_TRACE ("ACE_Shared_Memory_Pool::protect"); + return 0; +} + +int +ACE_Shared_Memory_Pool::protect (void *, size_t, int) +{ + ACE_TRACE ("ACE_Shared_Memory_Pool::protect"); + return 0; +} + +void * +ACE_Shared_Memory_Pool::base_addr (void) const +{ + ACE_TRACE ("ACE_Shared_Memory_Pool::base_addr"); + return this->base_addr_; +} + +// Implement the algorithm for rounding up the request to an +// appropriate chunksize. + +size_t +ACE_Shared_Memory_Pool::round_up (size_t nbytes) +{ + ACE_TRACE ("ACE_Shared_Memory_Pool::round_up"); + if (nbytes < this->segment_size_) + nbytes = this->segment_size_; + + return ACE::round_to_pagesize (nbytes); +} +#endif /* !ACE_LACKS_SYSV_SHMEM */ diff --git a/ace/Shared_Memory_Pool.h b/ace/Shared_Memory_Pool.h new file mode 100644 index 00000000000..e252d06f4b3 --- /dev/null +++ b/ace/Shared_Memory_Pool.h @@ -0,0 +1,200 @@ +/* -*- C++ -*- */ + +//============================================================================= +/** + * @file Memory_Pool.h + * + * $Id$ + * + * @author Dougls C. Schmidt <schmidt@cs.wustl.edu> + * @author Prashant Jain <pjain@cs.wustl.edu> + */ +//============================================================================= + +#ifndef ACE_SHARED_MEMORY_POOL_H +#define ACE_SHARED_MEMORY_POOL_H +#include /**/ "ace/pre.h" + +#include "ace/ACE.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Event_Handler.h" +#include "ace/Signal.h" + +#if !defined (ACE_LACKS_SYSV_SHMEM) + +/** + * @class ACE_Shared_Memory_Pool_Options + * + * @brief Helper class for Shared Memory Pool constructor options. + * + * This should be a nested class, but that breaks too many + * compilers. + */ +class ACE_Export ACE_Shared_Memory_Pool_Options +{ +public: + /// Initialization method. + ACE_Shared_Memory_Pool_Options (const char *base_addr = ACE_DEFAULT_BASE_ADDR, + size_t max_segments = ACE_DEFAULT_MAX_SEGMENTS, + size_t file_perms = ACE_DEFAULT_FILE_PERMS, + off_t minimum_bytes = 0, + size_t segment_size = ACE_DEFAULT_SEGMENT_SIZE); + + /// Base address of the memory-mapped backing store. + const char *base_addr_; + + /// Number of shared memory segments to allocate. + size_t max_segments_; + + /// What the minimum bytes of the initial segment should be. + off_t minimum_bytes_; + + /// File permissions to use when creating/opening a segment. + size_t file_perms_; + + /// Shared memory segment size. + size_t segment_size_; +}; + +/** + * @class ACE_Shared_Memory_Pool + * + * @brief 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. + */ +class ACE_Export ACE_Shared_Memory_Pool : public ACE_Event_Handler +{ +public: + typedef ACE_Shared_Memory_Pool_Options OPTIONS; + + /// Initialize the pool. + ACE_Shared_Memory_Pool (const ACE_TCHAR *backing_store_name = 0, + const OPTIONS *options = 0); + + virtual ~ACE_Shared_Memory_Pool (void); + + /// Ask system for initial chunk of local memory. + virtual void *init_acquire (size_t nbytes, + size_t &rounded_bytes, + int &first_time); + + /** + * Acquire at least @a nbytes from the memory pool. @a rounded_byes is + * the actual number of bytes allocated. Also acquires an internal + * semaphore that ensures proper serialization of Memory_Pool + * initialization across processes. + */ + virtual void *acquire (size_t nbytes, + size_t &rounded_bytes); + + /// Instruct the memory pool to release all of its resources. + virtual int release (int destroy = 1); + + /// Sync the memory region to the backing store starting at + /// @c this->base_addr_. + virtual int sync (ssize_t len = -1, int flags = MS_SYNC); + + /// Sync the memory region to the backing store starting at @a addr. + virtual int sync (void *addr, size_t len, int flags = MS_SYNC); + + /** + * Change the protection of the pages of the mapped region to <prot> + * starting at @c this->base_addr_ up to @a len bytes. If @a len == -1 + * then change protection of all pages in the mapped region. + */ + virtual int protect (ssize_t len = -1, int prot = PROT_RDWR); + + /// Change the protection of the pages of the mapped region to <prot> + /// starting at <addr> up to <len> bytes. + virtual int protect (void *addr, size_t len, int prot = PROT_RDWR); + + /// Return the base address of this memory pool, 0 if base_addr + /// never changes. + virtual void *base_addr (void) const; + + /// Dump the state of an object. + virtual void dump (void) const; + + /// Declare the dynamic allocation hooks. + ACE_ALLOC_HOOK_DECLARE; + +protected: + /// Implement the algorithm for rounding up the request to an + /// appropriate chunksize. + virtual size_t round_up (size_t nbytes); + + /** + * 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. + */ + virtual int commit_backing_store_name (size_t rounded_bytes, + off_t &offset); + + /// Keeps track of all the segments being used. + struct SHM_TABLE + { + /// Shared memory segment key. + key_t key_; + + /// Shared memory segment internal id. + int shmid_; + + /// Is the segment currently used.; + int used_; + }; + + /** + * 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. + */ + void *base_addr_; + + /// File permissions to use when creating/opening a segment. + size_t file_perms_; + + /// Number of shared memory segments in the <SHM_TABLE> table. + size_t max_segments_; + + /// What the minimim bytes of the initial segment should be. + off_t minimum_bytes_; + + /// Shared memory segment size. + size_t segment_size_; + + /// Base shared memory key for the segment. + key_t base_shm_key_; + + /// Find the segment that contains the @a searchPtr + virtual int find_seg (const void *const searchPtr, + off_t &offset, + size_t &counter); + + /// Determine how much memory is currently in use. + virtual int in_use (off_t &offset, + size_t &counter); + + /// Handles SIGSEGV. + ACE_Sig_Handler signal_handler_; + + /// Handle SIGSEGV and SIGBUS signals to remap shared memory + /// properly. + virtual int handle_signal (int signum, siginfo_t *, ucontext_t *); +}; +#endif /* !ACE_LACKS_SYSV_SHMEM */ + +#include /**/ "ace/post.h" +#endif /* ACE_SHARED_MEMORY_POOL_H */ diff --git a/ace/ace.mpc b/ace/ace.mpc index 427d28fe50a..1a7e8a68266 100644 --- a/ace/ace.mpc +++ b/ace/ace.mpc @@ -282,16 +282,20 @@ project(ACE) : acedefaults, aceversion, core, qt_reactor, other, codecs, token, Based_Pointer_Repository.cpp Malloc.cpp PI_Malloc.cpp + Local_Memory_Pool.cpp + MMAP_Memory_Pool.cpp Malloc_Allocator.cpp Malloc_Instantiations.cpp Mem_Map.cpp - Memory_Pool.cpp Obchunk.cpp Obstack.cpp + Pagefile_Memory_Pool.cpp Read_Buffer.cpp + Sbrk_Memory_Pool.cpp Shared_Memory.cpp Shared_Memory_MM.cpp Shared_Memory_SV.cpp + Shared_Memory_Pool.cpp } Timer { diff --git a/examples/System_V_IPC/SV_Semaphores/Semaphores_1.cpp b/examples/System_V_IPC/SV_Semaphores/Semaphores_1.cpp index 1dba56c734c..ef88e2fa3e0 100644 --- a/examples/System_V_IPC/SV_Semaphores/Semaphores_1.cpp +++ b/examples/System_V_IPC/SV_Semaphores/Semaphores_1.cpp @@ -2,6 +2,7 @@ #include "ace/SV_Shared_Memory.h" #include "ace/SV_Semaphore_Simple.h" +#include "ace/SV_Semaphore_Complex.h" #include "ace/Malloc.h" #include "ace/OS_NS_unistd.h" diff --git a/tests/SV_Shared_Memory_Test.cpp b/tests/SV_Shared_Memory_Test.cpp index 7f22a2da468..1b5ae80060d 100644 --- a/tests/SV_Shared_Memory_Test.cpp +++ b/tests/SV_Shared_Memory_Test.cpp @@ -24,8 +24,11 @@ #include "test_config.h" #include "ace/Malloc.h" +#include "ace/SV_Semaphore_Simple.h" +#include "ace/SV_Semaphore_Complex.h" #include "ace/OS_NS_unistd.h" + ACE_RCSID(tests, SV_Shared_Memory_Test, "$Id$") #if defined (ACE_HAS_SYSV_IPC) && !defined(ACE_LACKS_SYSV_SHMEM) |