00001
00002
00003
00004 #include "ace/Pagefile_Memory_Pool.h"
00005
00006 #if !defined (__ACE_INLINE__)
00007 #include "ace/Pagefile_Memory_Pool.inl"
00008 #endif
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 #include "ace/Truncate.h"
00018
00019 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
00020 #include "ace/Based_Pointer_T.h"
00021 #include "ace/Based_Pointer_Repository.h"
00022 #endif
00023
00024 ACE_RCSID(ace, Pagefile_Memory_Pool, "$Id: Pagefile_Memory_Pool.cpp 85318 2009-05-11 18:17:14Z johnnyw $")
00025
00026 #if defined (ACE_WIN32) && !defined (ACE_HAS_PHARLAP)
00027 #if !defined (ACE_HAS_WINCE)
00028 #define ACE_MAP_FILE(_hnd, _access, _offHigh, _offLow, _nBytes, _baseAdd)\
00029 MapViewOfFileEx (_hnd, _access, _offHigh, _offLow, _nBytes, _baseAdd)
00030 #else //if !defined (ACE_HAS_WINCE)
00031 #define ACE_MAP_FILE(_hnd, _access, _offHigh, _offLow, _nBytes, _baseAdd)\
00032 MapViewOfFile (_hnd, _access, _offHigh, _offLow, _nBytes)
00033 #endif
00034
00035 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00036
00037 ACE_Pagefile_Memory_Pool_Options::ACE_Pagefile_Memory_Pool_Options (
00038 void *base_addr,
00039 size_t max_size)
00040 : base_addr_ (base_addr),
00041 max_size_ (max_size)
00042 {
00043 }
00044
00045 int
00046 ACE_Pagefile_Memory_Pool::release (int)
00047 {
00048 return this->unmap ();
00049 }
00050
00051 ACE_Pagefile_Memory_Pool::ACE_Pagefile_Memory_Pool (const ACE_TCHAR *backing_store_name,
00052 const OPTIONS *options)
00053 : shared_cb_ (0),
00054 object_handle_ (0),
00055 page_size_ (ACE_Pagefile_Memory_Pool::round_to_page_size (1))
00056 {
00057
00058 if (options != 0)
00059 {
00060 this->local_cb_.req_base_ = options->base_addr_;
00061 this->local_cb_.mapped_base_ = 0;
00062 this->local_cb_.sh_.max_size_ =
00063 options->max_size_;
00064 this->local_cb_.sh_.mapped_size_ = 0;
00065 this->local_cb_.sh_.free_offset_ =
00066 this->local_cb_.sh_.mapped_size_;
00067 this->local_cb_.sh_.free_size_ = 0;
00068 }
00069 else
00070 {
00071 this->local_cb_.req_base_ = 0;
00072 this->local_cb_.mapped_base_ = 0;
00073 this->local_cb_.sh_.max_size_ =
00074 this->round_to_chunk_size (page_size_) ;
00075 this->local_cb_.sh_.mapped_size_ = 0;
00076 this->local_cb_.sh_.free_offset_ =
00077 this->local_cb_.sh_.mapped_size_;
00078 this->local_cb_.sh_.free_size_ = 0;
00079 }
00080
00081 int update_backing_store_name = backing_store_name == 0 ? 0 : 1;
00082
00083 if (backing_store_name == 0)
00084
00085
00086 backing_store_name = ACE_DEFAULT_PAGEFILE_POOL_NAME;
00087
00088 ACE_OS::strsncpy (this->backing_store_name_,
00089 backing_store_name,
00090 (sizeof this->backing_store_name_ / sizeof (ACE_TCHAR)));
00091
00092 if (update_backing_store_name
00093 && ACE_OS::strlen (this->backing_store_name_) < sizeof this->backing_store_name_)
00094 ACE_OS::strcat (this->backing_store_name_,
00095 ACE_TEXT ("_"));
00096 }
00097
00098 ACE_Pagefile_Memory_Pool::~ACE_Pagefile_Memory_Pool (void)
00099 {
00100 }
00101
00102 void *
00103 ACE_Pagefile_Memory_Pool::acquire (size_t nbytes,
00104 size_t &rounded_bytes)
00105 {
00106 rounded_bytes = round_to_page_size (nbytes);
00107 void *result = 0;
00108 int first_time = 0;
00109
00110
00111
00112 if (this->shared_cb_->sh_.mapped_size_
00113 > this->local_cb_.sh_.mapped_size_
00114 || this->shared_cb_->sh_.free_size_ < rounded_bytes)
00115 {
00116 size_t append = 0;
00117 if (rounded_bytes > this->shared_cb_->sh_.free_size_)
00118 append = rounded_bytes - this->shared_cb_->sh_.free_size_;
00119
00120 if (this->map (first_time, append) < 0)
00121 return result;
00122 }
00123
00124
00125
00126 if (this->shared_cb_->sh_.free_size_ < rounded_bytes)
00127 return result;
00128
00129 result = (void *)((char *) this->local_cb_.mapped_base_
00130 + this->shared_cb_->sh_.free_offset_);
00131 this->shared_cb_->sh_.free_offset_ += rounded_bytes;
00132 this->shared_cb_->sh_.free_size_ -= rounded_bytes;
00133 this->local_cb_.sh_ = this->shared_cb_->sh_;
00134
00135 return result;
00136 }
00137
00138 void *
00139 ACE_Pagefile_Memory_Pool::init_acquire (size_t nbytes,
00140 size_t &rounded_bytes,
00141 int &first_time)
00142 {
00143
00144
00145 if (this->map (first_time) < 0)
00146 return 0;
00147
00148 if (first_time != 0)
00149
00150
00151 return this->acquire (nbytes, rounded_bytes);
00152 else
00153
00154 return (void *)((char *) this->local_cb_.mapped_base_
00155 + ACE_Pagefile_Memory_Pool::round_to_page_size
00156 ((int) sizeof (Control_Block)));
00157 }
00158
00159 int
00160 ACE_Pagefile_Memory_Pool::seh_selector (void *ep)
00161 {
00162 DWORD ecode = ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionCode;
00163
00164 if (ecode == EXCEPTION_ACCESS_VIOLATION)
00165 {
00166 void * fault_addr = (void *)
00167 ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionInformation[1];
00168
00169 if (this->remap (fault_addr) == 0)
00170 return 1;
00171 }
00172
00173 return 0;
00174 }
00175
00176 int
00177 ACE_Pagefile_Memory_Pool::remap (void *addr)
00178 {
00179
00180
00181
00182 if (this->shared_cb_ == 0
00183 || addr < this->local_cb_.mapped_base_
00184 || addr >= (void *)((char *) this->local_cb_.mapped_base_
00185 + this->shared_cb_->sh_.mapped_size_))
00186 return -1;
00187
00188
00189 int first_time = 0;
00190 return this->map (first_time);
00191 }
00192
00193 int
00194 ACE_Pagefile_Memory_Pool::unmap (void)
00195 {
00196 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
00197 ACE_BASED_POINTER_REPOSITORY::instance ()->unbind
00198 (this->local_cb_.mapped_base_);
00199 #endif
00200
00201
00202 this->shared_cb_ = 0;
00203
00204 if (this->local_cb_.sh_.mapped_size_ > 0)
00205 ::UnmapViewOfFile (this->local_cb_.mapped_base_);
00206
00207
00208 this->local_cb_.req_base_ =
00209 ACE_DEFAULT_PAGEFILE_POOL_BASE;
00210 this->local_cb_.mapped_base_ = 0;
00211 this->local_cb_.sh_.max_size_ =
00212 ACE_DEFAULT_PAGEFILE_POOL_SIZE;
00213 this->local_cb_.sh_.mapped_size_ = 0;
00214 this->local_cb_.sh_.free_offset_ =
00215 this->local_cb_.sh_.mapped_size_;
00216 this->local_cb_.sh_.free_size_ = 0;
00217
00218
00219 if (this->object_handle_ != 0)
00220 {
00221 ::CloseHandle (this->object_handle_);
00222 this->object_handle_ = 0;
00223 }
00224 return 0;
00225 }
00226
00227 int
00228 ACE_Pagefile_Memory_Pool::map (int &first_time,
00229 size_t append_bytes)
00230 {
00231 size_t map_size;
00232 void *map_addr;
00233
00234
00235 if (object_handle_ == 0)
00236 {
00237 #if !defined (ACE_LACKS_WIN32_SECURITY_DESCRIPTORS)
00238
00239 SECURITY_ATTRIBUTES sa;
00240 SECURITY_DESCRIPTOR sd;
00241 ::InitializeSecurityDescriptor (&sd,
00242 SECURITY_DESCRIPTOR_REVISION);
00243 ::SetSecurityDescriptorDacl (&sd,
00244 TRUE,
00245 0,
00246 FALSE);
00247 sa.nLength = sizeof (SECURITY_ATTRIBUTES);
00248 sa.lpSecurityDescriptor = &sd;
00249 sa.bInheritHandle = FALSE;
00250 #endif
00251
00252
00253 DWORD size_high;
00254 DWORD size_low;
00255 #if defined (ACE_WIN64)
00256 size_high = static_cast<DWORD> (this->local_cb_.sh_.max_size_ >> 32);
00257 size_low = static_cast<DWORD> (this->local_cb_.sh_.max_size_ & 0xFFFFFFFF);
00258 #else
00259 size_high = 0;
00260 size_low = ACE_Utils::truncate_cast<DWORD> (this->local_cb_.sh_.max_size_);
00261 #endif
00262
00263 object_handle_ =
00264 ACE_TEXT_CreateFileMapping (INVALID_HANDLE_VALUE,
00265 #if !defined (ACE_LACKS_WIN32_SECURITY_DESCRIPTORS)
00266 &sa,
00267 #else
00268 0,
00269 #endif
00270 PAGE_READWRITE | SEC_RESERVE,
00271 size_high,
00272 size_low,
00273 this->backing_store_name_);
00274 if (object_handle_ == 0)
00275 return -1;
00276 first_time =
00277 ::GetLastError () == ERROR_ALREADY_EXISTS
00278 ? 0
00279 : 1;
00280 }
00281
00282
00283 if (this->shared_cb_ == 0)
00284 {
00285
00286
00287 this->shared_cb_ = (ACE_Pagefile_Memory_Pool::Control_Block *)
00288 ACE_MAP_FILE (this->object_handle_,
00289 FILE_MAP_WRITE,
00290 0,
00291 0,
00292 this->local_cb_.sh_.max_size_,
00293 this->local_cb_.req_base_);
00294 if (this->shared_cb_ == 0)
00295 return -1;
00296
00297
00298
00299 if (first_time)
00300 {
00301
00302 map_size =
00303 ACE_Pagefile_Memory_Pool::round_to_chunk_size
00304 (ACE_Pagefile_Memory_Pool::round_to_page_size
00305 ((int) sizeof(Control_Block))
00306 + append_bytes);
00307
00308 if (::VirtualAlloc ((void *) this->shared_cb_,
00309 map_size,
00310 MEM_COMMIT,
00311 PAGE_READWRITE) == 0)
00312 return -1;
00313
00314 this->shared_cb_->req_base_ = 0;
00315 this->shared_cb_->mapped_base_ = 0;
00316 this->local_cb_.mapped_base_ = this->shared_cb_;
00317 this->local_cb_.sh_.mapped_size_ = map_size;
00318 this->local_cb_.sh_.free_offset_ =
00319 round_to_page_size ((int) sizeof (Control_Block));
00320 this->local_cb_.sh_.free_size_ =
00321 this->local_cb_.sh_.mapped_size_ -
00322 this->local_cb_.sh_.free_offset_;
00323 this->shared_cb_->sh_ = this->local_cb_.sh_;
00324 }
00325
00326
00327
00328 else
00329 {
00330
00331 map_size =
00332 ACE_Pagefile_Memory_Pool::round_to_chunk_size
00333 ((int) sizeof (Control_Block));
00334
00335 if (::VirtualAlloc ((void *) this->shared_cb_,
00336 map_size,
00337 MEM_COMMIT,
00338 PAGE_READWRITE) == 0)
00339 return -1;
00340 this->local_cb_.mapped_base_ = this->shared_cb_;
00341 this->local_cb_.sh_.mapped_size_ = map_size;
00342 }
00343 }
00344
00345
00346
00347 if (this->shared_cb_->sh_.mapped_size_ >
00348 this->local_cb_.sh_.mapped_size_
00349 || append_bytes > 0)
00350 {
00351 map_size =
00352 (this->shared_cb_->sh_.mapped_size_ -
00353 this->local_cb_.sh_.mapped_size_)
00354 + ACE_Pagefile_Memory_Pool::round_to_chunk_size
00355 (append_bytes);
00356
00357 map_addr = (void *)((char *) this->shared_cb_ +
00358 this->local_cb_.sh_.mapped_size_);
00359
00360 if (::VirtualAlloc (map_addr,
00361 map_size,
00362 MEM_COMMIT,
00363 PAGE_READWRITE) == 0)
00364 return -1;
00365 else if (append_bytes > 0)
00366 {
00367 this->shared_cb_->sh_.mapped_size_ +=
00368 round_to_chunk_size (append_bytes);
00369 this->shared_cb_->sh_.free_size_ =
00370 this->shared_cb_->sh_.mapped_size_ -
00371 this->shared_cb_->sh_.free_offset_;
00372 }
00373 }
00374
00375
00376 this->local_cb_.sh_ =
00377 this->shared_cb_->sh_;
00378 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
00379 ACE_BASED_POINTER_REPOSITORY::instance ()->bind
00380 (this->local_cb_.mapped_base_,
00381 this->local_cb_.sh_.mapped_size_);
00382 #endif
00383
00384 return 0;
00385 }
00386
00387 ACE_END_VERSIONED_NAMESPACE_DECL
00388
00389 #endif