server/dep/ACE_wrappers/ace/Pagefile_Memory_Pool.cpp
Neo2003 23c920ca4b [10643] Update the ACE part we use to 5.8.2
Signed-off-by: Neo2003 <Neo.2003@Hotmail.fr>
2010-10-25 20:36:51 +02:00

389 lines
12 KiB
C++

// $Id: Pagefile_Memory_Pool.cpp 91286 2010-08-05 09:04:31Z johnnyw $
// 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"
#include "ace/Truncate.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 */
#if defined (ACE_WIN32) && !defined (ACE_HAS_PHARLAP)
#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 /* !ACE_HAS_WINCE */
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
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;
}
else
{
this->local_cb_.req_base_ = 0;
this->local_cb_.mapped_base_ = 0;
this->local_cb_.sh_.max_size_ =
this->round_to_chunk_size (page_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;
}
int update_backing_store_name = backing_store_name == 0 ? 0 : 1;
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)));
if (update_backing_store_name
&& ACE_OS::strlen (this->backing_store_name_) < sizeof this->backing_store_name_)
ACE_OS::strcat (this->backing_store_name_,
ACE_TEXT ("_"));
}
ACE_Pagefile_Memory_Pool::~ACE_Pagefile_Memory_Pool (void)
{
}
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_LACKS_WIN32_SECURITY_DESCRIPTORS)
// 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 /* ACE_LACKS_WIN32_SECURITY_DESCRIPTORS */
// 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 = ACE_Utils::truncate_cast<DWORD> (this->local_cb_.sh_.max_size_);
#endif
object_handle_ =
ACE_TEXT_CreateFileMapping (INVALID_HANDLE_VALUE,
#if !defined (ACE_LACKS_WIN32_SECURITY_DESCRIPTORS)
&sa,
#else
0,
#endif /* !ACE_LACKS_WIN32_SECURITY_DESCRIPTORS */
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;
}
ACE_END_VERSIONED_NAMESPACE_DECL
#endif /* ACE_WIN32 && !ACE_HAS_PHARLAP */