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
00018 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
00019 #include "ace/Based_Pointer_T.h"
00020 #include "ace/Based_Pointer_Repository.h"
00021 #endif
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
00030 #define ACE_MAP_FILE(_hnd, _access, _offHigh, _offLow, _nBytes, _baseAdd)\
00031 MapViewOfFile (_hnd, _access, _offHigh, _offLow, _nBytes)
00032 #endif
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
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
00084
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
00106
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
00120
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
00139
00140 if (this->map (first_time) < 0)
00141 return 0;
00142
00143 if (first_time != 0)
00144
00145
00146 return this->acquire (nbytes, rounded_bytes);
00147 else
00148
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
00175
00176
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
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
00195
00196
00197 this->shared_cb_ = 0;
00198
00199 if (this->local_cb_.sh_.mapped_size_ > 0)
00200 ::UnmapViewOfFile (this->local_cb_.mapped_base_);
00201
00202
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
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
00230 if (object_handle_ == 0)
00231 {
00232 #if (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0))
00233
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
00246
00247
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
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
00278 if (this->shared_cb_ == 0)
00279 {
00280
00281
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
00293
00294 if (first_time)
00295 {
00296
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
00322
00323 else
00324 {
00325
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
00341
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
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
00378
00379 return 0;
00380 }
00381
00382 ACE_END_VERSIONED_NAMESPACE_DECL
00383
00384 #endif
00385