Pagefile_Memory_Pool.cpp

Go to the documentation of this file.
00001 // Pagefile_Memory_Pool.cpp,v 4.3 2005/10/28 16:14:54 ossama Exp
00002 
00003 // Pagefile_Memory_Pool.cpp
00004 #include "ace/Pagefile_Memory_Pool.h"
00005 
00006 #if !defined (__ACE_INLINE__)
00007 #include "ace/Pagefile_Memory_Pool.inl"
00008 #endif /* __ACE_INLINE__ */
00009 
00010 #include "ace/Log_Msg.h"
00011 #include "ace/Auto_Ptr.h"
00012 #include "ace/RW_Thread_Mutex.h"
00013 #include "ace/OS_NS_sys_mman.h"
00014 #include "ace/OS_NS_string.h"
00015 #include "ace/OS_NS_sys_stat.h"
00016 #include "ace/OS_NS_unistd.h"
00017 
00018 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
00019 #include "ace/Based_Pointer_T.h"
00020 #include "ace/Based_Pointer_Repository.h"
00021 #endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1  */
00022 
00023 ACE_RCSID(ace, Pagefile_Memory_Pool, "Pagefile_Memory_Pool.cpp,v 4.3 2005/10/28 16:14:54 ossama Exp")
00024 
00025 #if defined (ACE_WIN32)
00026 #if !defined (ACE_HAS_WINCE)
00027 #define ACE_MAP_FILE(_hnd, _access, _offHigh, _offLow, _nBytes, _baseAdd)\
00028   MapViewOfFileEx (_hnd, _access, _offHigh, _offLow, _nBytes, _baseAdd)
00029 #else //if !defined (ACE_HAS_WINCE)
00030 #define ACE_MAP_FILE(_hnd, _access, _offHigh, _offLow, _nBytes, _baseAdd)\
00031   MapViewOfFile (_hnd, _access, _offHigh, _offLow, _nBytes)
00032 #endif /* !ACE_HAS_WINCE */
00033 
00034 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00035 
00036 ACE_Pagefile_Memory_Pool_Options::ACE_Pagefile_Memory_Pool_Options (
00037   void *base_addr,
00038   size_t max_size)
00039   : base_addr_ (base_addr),
00040     max_size_ (max_size)
00041 {
00042 }
00043 
00044 int
00045 ACE_Pagefile_Memory_Pool::release (int)
00046 {
00047   return this->unmap ();
00048 }
00049 
00050 ACE_Pagefile_Memory_Pool::ACE_Pagefile_Memory_Pool (const ACE_TCHAR *backing_store_name,
00051                                                     const OPTIONS *options)
00052   : shared_cb_ (0),
00053     object_handle_ (0),
00054     page_size_ (ACE_Pagefile_Memory_Pool::round_to_page_size (1))
00055 {
00056   // Initialize local copy of pool statistics.
00057   if (options != 0)
00058     {
00059       this->local_cb_.req_base_ = options->base_addr_;
00060       this->local_cb_.mapped_base_ = 0;
00061       this->local_cb_.sh_.max_size_ =
00062         options->max_size_;
00063       this->local_cb_.sh_.mapped_size_ = 0;
00064       this->local_cb_.sh_.free_offset_ =
00065         this->local_cb_.sh_.mapped_size_;
00066       this->local_cb_.sh_.free_size_ = 0;
00067     }
00068   else
00069     {
00070       this->local_cb_.req_base_ = 0;
00071       this->local_cb_.mapped_base_ = 0;
00072       this->local_cb_.sh_.max_size_ =
00073         this->round_to_chunk_size (page_size_) ;
00074       this->local_cb_.sh_.mapped_size_ = 0;
00075       this->local_cb_.sh_.free_offset_ =
00076         this->local_cb_.sh_.mapped_size_;
00077       this->local_cb_.sh_.free_size_ = 0;
00078     }
00079 
00080   int update_backing_store_name = backing_store_name == 0 ? 0 : 1;
00081 
00082   if (backing_store_name == 0)
00083     // Only create a new unique filename for the backing store file if
00084     // the user didn't supply one...
00085     backing_store_name = ACE_DEFAULT_PAGEFILE_POOL_NAME;
00086 
00087   ACE_OS::strsncpy (this->backing_store_name_,
00088                     backing_store_name,
00089                     (sizeof this->backing_store_name_ / sizeof (ACE_TCHAR)));
00090 
00091   if (update_backing_store_name
00092       && ACE_OS::strlen (this->backing_store_name_) < sizeof this->backing_store_name_)
00093       ACE_OS::strcat (this->backing_store_name_,
00094                       ACE_LIB_TEXT ("_"));
00095 }
00096 
00097 void *
00098 ACE_Pagefile_Memory_Pool::acquire (size_t nbytes,
00099                                    size_t &rounded_bytes)
00100 {
00101   rounded_bytes = round_to_page_size (nbytes);
00102   void *result = 0;
00103   int first_time = 0;
00104 
00105   // Check local_cb_ for consistency.  Remap, if extra space is too
00106   // small and/or we didn't map the whole shared memory section
00107   if (this->shared_cb_->sh_.mapped_size_
00108       > this->local_cb_.sh_.mapped_size_
00109       || this->shared_cb_->sh_.free_size_ < rounded_bytes)
00110     {
00111       size_t append = 0;
00112       if (rounded_bytes > this->shared_cb_->sh_.free_size_)
00113         append = rounded_bytes - this->shared_cb_->sh_.free_size_;
00114 
00115       if (this->map (first_time, append) < 0)
00116         return result;
00117     }
00118 
00119   // Get the block from extra space and update shared and local
00120   // control block
00121   if (this->shared_cb_->sh_.free_size_ < rounded_bytes)
00122     return result;
00123 
00124   result = (void *)((char *) this->local_cb_.mapped_base_
00125                     + this->shared_cb_->sh_.free_offset_);
00126   this->shared_cb_->sh_.free_offset_ += rounded_bytes;
00127   this->shared_cb_->sh_.free_size_ -= rounded_bytes;
00128   this->local_cb_.sh_ = this->shared_cb_->sh_;
00129 
00130   return result;
00131 }
00132 
00133 void *
00134 ACE_Pagefile_Memory_Pool::init_acquire (size_t nbytes,
00135                                         size_t &rounded_bytes,
00136                                         int &first_time)
00137 {
00138   // Map the shared memory and get information, if we created the
00139   // shared memory.
00140   if (this->map (first_time) < 0)
00141     return 0;
00142 
00143   if (first_time != 0)
00144     // We created the shared memory. So we have to allocate the
00145     // requested memory.
00146     return this->acquire (nbytes, rounded_bytes);
00147   else
00148     // We just mapped the memory and return the base address
00149     return (void *)((char *) this->local_cb_.mapped_base_
00150                     + ACE_Pagefile_Memory_Pool::round_to_page_size
00151                     ((int) sizeof (Control_Block)));
00152 }
00153 
00154 int
00155 ACE_Pagefile_Memory_Pool::seh_selector (void *ep)
00156 {
00157   DWORD ecode = ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionCode;
00158 
00159   if (ecode == EXCEPTION_ACCESS_VIOLATION)
00160     {
00161       void * fault_addr = (void *)
00162         ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionInformation[1];
00163 
00164       if (this->remap (fault_addr) == 0)
00165         return 1;
00166     }
00167 
00168   return 0;
00169 }
00170 
00171 int
00172 ACE_Pagefile_Memory_Pool::remap (void *addr)
00173 {
00174   // If the shared memory is not mapped or the address, that caused
00175   // the memory fault is outside of the commited range of chunks, we
00176   // return.
00177   if (this->shared_cb_ == 0
00178       || addr < this->local_cb_.mapped_base_
00179       || addr >= (void *)((char *) this->local_cb_.mapped_base_
00180                           + this->shared_cb_->sh_.mapped_size_))
00181     return -1;
00182 
00183   // We can solve the problem by committing additional chunks.
00184   int first_time = 0;
00185   return this->map (first_time);
00186 }
00187 
00188 int
00189 ACE_Pagefile_Memory_Pool::unmap (void)
00190 {
00191 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
00192   ACE_BASED_POINTER_REPOSITORY::instance ()->unbind
00193     (this->local_cb_.mapped_base_);
00194 #endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
00195 
00196   // Cleanup cached pool pointer.
00197   this->shared_cb_ = 0;
00198 
00199   if (this->local_cb_.sh_.mapped_size_ > 0)
00200     ::UnmapViewOfFile (this->local_cb_.mapped_base_);
00201 
00202   // Reset local pool statistics.
00203   this->local_cb_.req_base_ =
00204     ACE_DEFAULT_PAGEFILE_POOL_BASE;
00205   this->local_cb_.mapped_base_ = 0;
00206   this->local_cb_.sh_.max_size_ =
00207     ACE_DEFAULT_PAGEFILE_POOL_SIZE;
00208   this->local_cb_.sh_.mapped_size_ = 0;
00209   this->local_cb_.sh_.free_offset_ =
00210     this->local_cb_.sh_.mapped_size_;
00211   this->local_cb_.sh_.free_size_ = 0;
00212 
00213   // Release the pool
00214   if (this->object_handle_ != 0)
00215     {
00216       ::CloseHandle (this->object_handle_);
00217       this->object_handle_ = 0;
00218     }
00219   return 0;
00220 }
00221 
00222 int
00223 ACE_Pagefile_Memory_Pool::map (int &first_time,
00224                                size_t append_bytes)
00225 {
00226   size_t map_size;
00227   void *map_addr;
00228 
00229   // Create file mapping, if not yet done
00230   if (object_handle_ == 0)
00231     {
00232 #if (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0))
00233       // Allow access by all users.
00234       SECURITY_ATTRIBUTES sa;
00235       SECURITY_DESCRIPTOR sd;
00236       ::InitializeSecurityDescriptor (&sd,
00237                                       SECURITY_DESCRIPTOR_REVISION);
00238       ::SetSecurityDescriptorDacl (&sd,
00239                                    TRUE,
00240                                    0,
00241                                    FALSE);
00242       sa.nLength = sizeof (SECURITY_ATTRIBUTES);
00243       sa.lpSecurityDescriptor = &sd;
00244       sa.bInheritHandle = FALSE;
00245 #endif /* (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) */
00246 
00247       // Get an object handle to the named reserved memory object.
00248       DWORD size_high;
00249       DWORD size_low;
00250 #if defined (ACE_WIN64)
00251       size_high = static_cast<DWORD> (this->local_cb_.sh_.max_size_ >> 32);
00252       size_low  = static_cast<DWORD> (this->local_cb_.sh_.max_size_ & 0xFFFFFFFF);
00253 #else
00254       size_high = 0;
00255       size_low = this->local_cb_.sh_.max_size_;
00256 #endif
00257 
00258       object_handle_ =
00259         ACE_TEXT_CreateFileMapping (INVALID_HANDLE_VALUE,
00260 #if (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0))
00261                                     &sa,
00262 #else
00263                                     0,
00264 #endif /* (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) */
00265                                     PAGE_READWRITE | SEC_RESERVE,
00266                                     size_high,
00267                                     size_low,
00268                                     this->backing_store_name_);
00269       if (object_handle_ == 0)
00270         return -1;
00271       first_time =
00272         ::GetLastError () == ERROR_ALREADY_EXISTS
00273         ? 0
00274         : 1;
00275     }
00276 
00277   // Do the initial mapping.
00278   if (this->shared_cb_ == 0)
00279     {
00280       // Map a view to the shared memory.  Note: <MapViewOfFile[Ex]>
00281       // does *not* commit the pages!
00282       this->shared_cb_ = (ACE_Pagefile_Memory_Pool::Control_Block *)
00283         ACE_MAP_FILE (this->object_handle_,
00284                       FILE_MAP_WRITE,
00285                       0,
00286                       0,
00287                       this->local_cb_.sh_.max_size_,
00288                       this->local_cb_.req_base_);
00289       if (this->shared_cb_ == 0)
00290         return -1;
00291 
00292       // There was no previous mapping, so we map the first chunk and
00293       // initialize the shared pool statistics.
00294       if (first_time)
00295         {
00296           // 1st block is used to keep shared memory statistics.
00297           map_size =
00298             ACE_Pagefile_Memory_Pool::round_to_chunk_size
00299             (ACE_Pagefile_Memory_Pool::round_to_page_size
00300              ((int) sizeof(Control_Block))
00301              + append_bytes);
00302 
00303           if (::VirtualAlloc ((void *) this->shared_cb_,
00304                               map_size,
00305                               MEM_COMMIT,
00306                               PAGE_READWRITE) == 0)
00307             return -1;
00308 
00309           this->shared_cb_->req_base_ = 0;
00310           this->shared_cb_->mapped_base_ = 0;
00311           this->local_cb_.mapped_base_ = this->shared_cb_;
00312           this->local_cb_.sh_.mapped_size_ = map_size;
00313           this->local_cb_.sh_.free_offset_ =
00314             round_to_page_size ((int) sizeof (Control_Block));
00315           this->local_cb_.sh_.free_size_ =
00316             this->local_cb_.sh_.mapped_size_ -
00317             this->local_cb_.sh_.free_offset_;
00318           this->shared_cb_->sh_ = this->local_cb_.sh_;
00319         }
00320 
00321       // The shared memory exists, so we map the first chunk to the
00322       // base address of the pool to get the shared pool statistics.
00323       else
00324         {
00325           // 1st block is used to keep shared memory statistics.
00326           map_size =
00327             ACE_Pagefile_Memory_Pool::round_to_chunk_size
00328             ((int) sizeof (Control_Block));
00329 
00330           if (::VirtualAlloc ((void *) this->shared_cb_,
00331                               map_size,
00332                               MEM_COMMIT,
00333                               PAGE_READWRITE) == 0)
00334             return -1;
00335           this->local_cb_.mapped_base_ = this->shared_cb_;
00336           this->local_cb_.sh_.mapped_size_ = map_size;
00337         }
00338     }
00339 
00340   // If the shared memory is larger than the part we've already
00341   // committed, we have to remap it.
00342   if (this->shared_cb_->sh_.mapped_size_ >
00343       this->local_cb_.sh_.mapped_size_
00344       || append_bytes > 0)
00345     {
00346       map_size =
00347         (this->shared_cb_->sh_.mapped_size_ -
00348          this->local_cb_.sh_.mapped_size_)
00349         + ACE_Pagefile_Memory_Pool::round_to_chunk_size
00350         (append_bytes);
00351 
00352       map_addr = (void *)((char *) this->shared_cb_ +
00353                           this->local_cb_.sh_.mapped_size_);
00354 
00355       if (::VirtualAlloc (map_addr,
00356                           map_size,
00357                           MEM_COMMIT,
00358                           PAGE_READWRITE) == 0)
00359         return -1;
00360       else if (append_bytes > 0)
00361         {
00362           this->shared_cb_->sh_.mapped_size_ +=
00363             round_to_chunk_size (append_bytes);
00364           this->shared_cb_->sh_.free_size_ =
00365             this->shared_cb_->sh_.mapped_size_ -
00366             this->shared_cb_->sh_.free_offset_;
00367         }
00368     }
00369 
00370   // Update local copy of the shared memory statistics.
00371   this->local_cb_.sh_ =
00372     this->shared_cb_->sh_;
00373 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
00374   ACE_BASED_POINTER_REPOSITORY::instance ()->bind
00375     (this->local_cb_.mapped_base_,
00376      this->local_cb_.sh_.mapped_size_);
00377 #endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
00378 
00379   return 0;
00380 }
00381 
00382 ACE_END_VERSIONED_NAMESPACE_DECL
00383 
00384 #endif /* ACE_WIN32 */
00385 

Generated on Thu Nov 9 09:41:59 2006 for ACE by doxygen 1.3.6