diff options
author | schmidt <douglascraigschmidt@users.noreply.github.com> | 1999-10-12 15:17:55 +0000 |
---|---|---|
committer | schmidt <douglascraigschmidt@users.noreply.github.com> | 1999-10-12 15:17:55 +0000 |
commit | 9a1bba1f2620891e9e8f26ea4c66482d757785ae (patch) | |
tree | dfbe7ae2384f92f552d162e8a4c18072d34d75d9 | |
parent | 961f8786e9576fbc3a5905d88d0413ee46e8a1bf (diff) | |
download | ATCD-9a1bba1f2620891e9e8f26ea4c66482d757785ae.tar.gz |
ChangeLogTag:Tue Oct 12 10:00:52 1999 Douglas C. Schmidt <schmidt@tango.cs.wustl.edu>
-rw-r--r-- | ChangeLog-99b | 5 | ||||
-rw-r--r-- | ace/Memory_Pool.cpp | 307 | ||||
-rw-r--r-- | ace/Memory_Pool.h | 136 | ||||
-rw-r--r-- | ace/Memory_Pool.i | 16 | ||||
-rw-r--r-- | ace/OS.h | 19 |
5 files changed, 482 insertions, 1 deletions
diff --git a/ChangeLog-99b b/ChangeLog-99b index bbf6d00316c..68c70a4b228 100644 --- a/ChangeLog-99b +++ b/ChangeLog-99b @@ -1,3 +1,8 @@ +Tue Oct 12 10:00:52 1999 Douglas C. Schmidt <schmidt@tango.cs.wustl.edu> + + * ace/Memory_Pool: Added a new memory pool that uses the Win32 + page file. Thanks to Dieter Quehl for contributing this. + Mon Oct 11 17:07:46 1999 Douglas C. Schmidt <schmidt@tango.cs.wustl.edu> * ace/Message_Queue.cpp (enqueue): ACE fails to compile because of diff --git a/ace/Memory_Pool.cpp b/ace/Memory_Pool.cpp index 58a0892e568..66fcd19e068 100644 --- a/ace/Memory_Pool.cpp +++ b/ace/Memory_Pool.cpp @@ -925,6 +925,313 @@ ACE_Shared_Memory_Pool::release (void) } #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 (void) +{ + return this->unmap (); +} + +ACE_Pagefile_Memory_Pool::ACE_Pagefile_Memory_Pool (LPCTSTR backing_store_name, + const OPTIONS *options) + : shared_cb_ (0), + page_size_ (ACE_Pagefile_Memory_Pool::round_to_page_size (1)), + object_handle_ (0) +{ + // 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::strncpy (this->backing_store_name_, + backing_store_name, + (sizeof this->backing_store_name_ / sizeof (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_ + < (int) rounded_bytes) + { + int append = + rounded_bytes - this->shared_cb_->sh_.free_size_; + if (append < 0) + append = 0; + + 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_ + < (int) 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::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) +{ + ACE_BASED_POINTER_REPOSITORY::instance ()->unbind + (this->local_cb_.mapped_base_, + this->local_cb_.sh_.mapped_size_); + // 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, + int append_bytes) +{ + int mem_offset = 0; + int map_size; + void *map_addr; + + // Create file mapping, if not yet done + if (object_handle_ == 0) + { + // Allow access by all users. + SECURITY_ATTRIBUTES sa; + SECURITY_DESCRIPTOR sd; + ::InitializeSecurityDescriptor (&sd, + SECURITY_DESCRIPTOR_REVISION); + ::SetSecurityDescriptorDacl (&sd, + TRUE, + NULL, + FALSE); + sa.nLength = sizeof (SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = &sd; + sa.bInheritHandle = FALSE; + + // Get an object handle to the named reserved memory object. + object_handle_ = + ::CreateFileMapping ((HANDLE) 0xffffffff, + &sa, + PAGE_READWRITE | SEC_RESERVE, + 0, + this->local_cb_.sh_.max_size_, + 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); + + mem_offset = + this->local_cb_.sh_.mapped_size_; + 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_; + ACE_BASED_POINTER_REPOSITORY::instance ()->bind + (this->local_cb_.mapped_base_, + this->local_cb_.sh_.mapped_size_); + + 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 *>; diff --git a/ace/Memory_Pool.h b/ace/Memory_Pool.h index 58ad96ee9ba..2cfadafacc3 100644 --- a/ace/Memory_Pool.h +++ b/ace/Memory_Pool.h @@ -507,6 +507,142 @@ public: // Overwrite the default sync behavior with no-op }; +#if defined (ACE_WIN32) + +class ACE_Export ACE_Pagefile_Memory_Pool_Options +{ + // = TITLE + // Helper class for Pagefile Memory Pool constructor options. + // + // = DESCRIPTION + // This should be a nested class, but that breaks too many + // compilers. +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); + + void *base_addr_; + // Base address of the memory-mapped backing store. + + size_t max_size_; + // Maximum size the pool may grow. +}; + +class ACE_Export ACE_Pagefile_Memory_Pool +{ + // = TITLE + // Make a memory pool that is based on "anonymous" memory + // regions allocated from the Win32 page file. +public: + typedef ACE_Pagefile_Memory_Pool_Options OPTIONS; + + ACE_Pagefile_Memory_Pool (LPCTSTR backing_store_name = 0, + const OPTIONS *options = 0); + // Initialize the pool. + + void *init_acquire (size_t nbytes, + size_t &rounded_bytes, + int &first_time); + // Ask system for initial chunk of shared memory. + + void *acquire (size_t nbytes, + size_t &rounded_bytes); + // Acquire at least <nbytes> from the memory pool. <rounded_bytes> + // is the actual number of bytes allocated. + + int release (void); + // Instruct the memory pool to release all of its resources. + + int remap (void *addr); + // 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). + + size_t round_to_page_size (size_t nbytes); + // Round up to system page size. + + size_t round_to_chunk_size (size_t nbytes); + // Round up to the chunk size required by the operation system + + // = Don't need this methods here ... + int sync (ssize_t len = -1, int flags = MS_SYNC) { return 0; } + int sync (void *addr, size_t len, int flags = MS_SYNC) { return 0; } + int protect (ssize_t len = -1, int prot = PROT_RDWR) { return 0; }; + int protect (void *addr, size_t len, int prot = PROT_RDWR) { return 0; } + void dump (void) const {} + +protected: + + int map (int &firstTime, int appendBytes = 0); + // Map portions or the entire pool into the local virtual address + // space. To do this, we compute the new <file_offset> of the + // backing store and commit the memory. + + int unmap (void); + // Release the mapping. + +private: + + class Control_Block + { + // = TITLE + // Attributes that are meaningful in local storage only. + public: + void *req_base_; + // required base address + + void *mapped_base_; + // Base address returned from system call + + class Shared_Control_Block + { + // = TITLE + // Pool statistics + public: + size_t max_size_; + // Maximum size the pool may grow + + int mapped_size_; + // Size of mapped shared memory segment + + int free_offset_; + // Offset to mapped but not yet acquired address space + + int free_size_; + // Size of mapped but not yet acquired address space + }; + + 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. + + Control_Block local_cb_; + // Description of what our process mapped. + + Control_Block *shared_cb_; + // Shared memory pool statistics. + + ACE_HANDLE object_handle_; + // File mapping handle. + + size_t page_size_; + // System page size. + + TCHAR backing_store_name_[MAXPATHLEN]; + // Name of the backing store where the shared memory pool is kept. +}; + +#endif /* ACE_WIN32 */ + #if defined (__ACE_INLINE__) #include "ace/Memory_Pool.i" #endif /* __ACE_INLINE__ */ diff --git a/ace/Memory_Pool.i b/ace/Memory_Pool.i index d18ccb7afdd..75e778755a1 100644 --- a/ace/Memory_Pool.i +++ b/ace/Memory_Pool.i @@ -193,3 +193,19 @@ ACE_Sbrk_Memory_Pool::protect (void *, size_t, int) return 0; } #endif /* !ACE_LACKS_SBRK */ + +#if defined (ACE_WIN32) + +ACE_INLINE size_t +ACE_Page_File_Memory_Pool::round_to_chunk_size (size_t nbytes) +{ + return (nbytes + DEFAULT_PFPOOL_CHUNK -1) & (~(DEFAULT_PFPOOL_CHUNK-1)); +} + +ACE_INLINE size_t +ACE_Page_File_Memory_Pool::round_to_chunk_size (size_t nbytes) +{ + return (nBytes + DEFAULT_PFPOOL_CHUNK -1) & (~(DEFAULT_PFPOOL_CHUNK-1)); +} + +#endif /* ACE_WIN32 */ @@ -52,6 +52,22 @@ enum ACE_Recyclable_State // Unknown state. }; +#if !defined (ACE_DEFAULT_PAGEFILE_POOL_BASE) +#define ACE_DEFAULT_PAGEFILE_POOL_BASE (void *) 0 +#endif /* ACE_DEFAULT_PAGEFILE_POOL_BASE */ + +#if !defined (ACE_DEFAULT_PAGEFILE_POOL_SIZE) +#define ACE_DEFAULT_PAGEFILE_POOL_SIZE (size_t) 0x01000000 +#endif /* ACE_DEFAULT_PAGEFILE_POOL_SIZE */ + +#if !defined (ACE_DEFAULT_PAGEFILE_POOL_CHUNK) +#define ACE_DEFAULT_PAGEFILE_POOL_CHUNK (size_t) 0x00010000 +#endif /* ACE_DEFAULT_PAGEFILE_POOL_CHUNK */ + +#if !defined (ACE_DEFAULT_PAGEFILE_POOL_NAME) +#define ACE_DEFAULT_PAGEFILE_POOL_NAME ACE_TEXT ("Default_ACE_Pagefile_Memory_Pool") +#endif /* ACE_DEFAULT_PAGEFILE_POOL_NAME */ + #if !defined (ACE_DEFAULT_MESSAGE_BLOCK_PRIORITY) #define ACE_DEFAULT_MESSAGE_BLOCK_PRIORITY 0 #endif /* ACE_DEFAULT_MESSAGE_BLOCK_PRIORITY */ @@ -1641,6 +1657,7 @@ private: ACE_Time_Value *max_wait_time_; # define ACE_SBRK_MEMORY_POOL ACE_Sbrk_Memory_Pool # define ACE_SHARED_MEMORY_POOL ACE_Shared_Memory_Pool # define ACE_LOCAL_MEMORY_POOL ACE_Local_Memory_Pool +# define ACE_PAGEFILE_MEMORY_POOL ACE_Pagefile_Memory_Pool # else /* TEMPLATES are broken in some form or another (i.e., most C++ compilers) */ @@ -1716,7 +1733,7 @@ private: ACE_Time_Value *max_wait_time_; # define ACE_SBRK_MEMORY_POOL ACE_Sbrk_Memory_Pool, ACE_Sbrk_Memory_Pool_Options # define ACE_SHARED_MEMORY_POOL ACE_Shared_Memory_Pool, ACE_Shared_Memory_Pool_Options # define ACE_LOCAL_MEMORY_POOL ACE_Local_Memory_Pool, ACE_Local_Memory_Pool_Options - +# define ACE_PAGEFILE_MEMORY_POOL ACE_Pagefile_Memory_Pool, ACE_Pagefile_Memory_Pool_Options # endif /* ACE_HAS_TEMPLATE_TYPEDEFS */ // These two are only for backward compatibility. You should avoid |