summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorschmidt <douglascraigschmidt@users.noreply.github.com>1999-10-12 15:17:55 +0000
committerschmidt <douglascraigschmidt@users.noreply.github.com>1999-10-12 15:17:55 +0000
commit9a1bba1f2620891e9e8f26ea4c66482d757785ae (patch)
treedfbe7ae2384f92f552d162e8a4c18072d34d75d9
parent961f8786e9576fbc3a5905d88d0413ee46e8a1bf (diff)
downloadATCD-9a1bba1f2620891e9e8f26ea4c66482d757785ae.tar.gz
ChangeLogTag:Tue Oct 12 10:00:52 1999 Douglas C. Schmidt <schmidt@tango.cs.wustl.edu>
-rw-r--r--ChangeLog-99b5
-rw-r--r--ace/Memory_Pool.cpp307
-rw-r--r--ace/Memory_Pool.h136
-rw-r--r--ace/Memory_Pool.i16
-rw-r--r--ace/OS.h19
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 */
diff --git a/ace/OS.h b/ace/OS.h
index bf209c7f45e..5d4b5560108 100644
--- a/ace/OS.h
+++ b/ace/OS.h
@@ -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