Correct feature names
[ACE_TAO.git] / ACE / ace / Pagefile_Memory_Pool.cpp
blobba803872c3578857747b350d3ca137337653d14a
1 // Pagefile_Memory_Pool.cpp
2 #include "ace/Pagefile_Memory_Pool.h"
4 #if !defined (__ACE_INLINE__)
5 #include "ace/Pagefile_Memory_Pool.inl"
6 #endif /* __ACE_INLINE__ */
8 #include "ace/Log_Category.h"
9 #include "ace/Auto_Ptr.h"
10 #include "ace/RW_Thread_Mutex.h"
11 #include "ace/OS_NS_sys_mman.h"
12 #include "ace/OS_NS_string.h"
13 #include "ace/OS_NS_sys_stat.h"
14 #include "ace/OS_NS_unistd.h"
15 #include "ace/Truncate.h"
17 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
18 #include "ace/Based_Pointer_T.h"
19 #include "ace/Based_Pointer_Repository.h"
20 #endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
24 #if defined (ACE_WIN32) && !defined (ACE_HAS_PHARLAP)
25 #if !defined (ACE_HAS_WINCE)
26 #define ACE_MAP_FILE(_hnd, _access, _offHigh, _offLow, _nBytes, _baseAdd)\
27 MapViewOfFileEx (_hnd, _access, _offHigh, _offLow, _nBytes, _baseAdd)
28 #else //if !defined (ACE_HAS_WINCE)
29 #define ACE_MAP_FILE(_hnd, _access, _offHigh, _offLow, _nBytes, _baseAdd)\
30 MapViewOfFile (_hnd, _access, _offHigh, _offLow, _nBytes)
31 #endif /* !ACE_HAS_WINCE */
33 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
35 ACE_Pagefile_Memory_Pool_Options::ACE_Pagefile_Memory_Pool_Options (
36 void *base_addr,
37 size_t max_size)
38 : base_addr_ (base_addr),
39 max_size_ (max_size)
43 int
44 ACE_Pagefile_Memory_Pool::release (int)
46 return this->unmap ();
49 ACE_Pagefile_Memory_Pool::ACE_Pagefile_Memory_Pool (const ACE_TCHAR *backing_store_name,
50 const OPTIONS *options)
51 : shared_cb_ (0),
52 object_handle_ (0),
53 page_size_ (ACE_Pagefile_Memory_Pool::round_to_page_size (1))
55 // Initialize local copy of pool statistics.
56 if (options != 0)
58 this->local_cb_.req_base_ = options->base_addr_;
59 this->local_cb_.mapped_base_ = 0;
60 this->local_cb_.sh_.max_size_ =
61 options->max_size_;
62 this->local_cb_.sh_.mapped_size_ = 0;
63 this->local_cb_.sh_.free_offset_ =
64 this->local_cb_.sh_.mapped_size_;
65 this->local_cb_.sh_.free_size_ = 0;
67 else
69 this->local_cb_.req_base_ = 0;
70 this->local_cb_.mapped_base_ = 0;
71 this->local_cb_.sh_.max_size_ =
72 this->round_to_chunk_size (page_size_) ;
73 this->local_cb_.sh_.mapped_size_ = 0;
74 this->local_cb_.sh_.free_offset_ =
75 this->local_cb_.sh_.mapped_size_;
76 this->local_cb_.sh_.free_size_ = 0;
79 int update_backing_store_name = backing_store_name == 0 ? 0 : 1;
81 if (backing_store_name == 0)
82 // Only create a new unique filename for the backing store file if
83 // the user didn't supply one...
84 backing_store_name = ACE_DEFAULT_PAGEFILE_POOL_NAME;
86 ACE_OS::strsncpy (this->backing_store_name_,
87 backing_store_name,
88 (sizeof this->backing_store_name_ / sizeof (ACE_TCHAR)));
90 if (update_backing_store_name
91 && ACE_OS::strlen (this->backing_store_name_) < sizeof this->backing_store_name_)
92 ACE_OS::strcat (this->backing_store_name_,
93 ACE_TEXT ("_"));
96 ACE_Pagefile_Memory_Pool::~ACE_Pagefile_Memory_Pool (void)
100 void *
101 ACE_Pagefile_Memory_Pool::acquire (size_t nbytes,
102 size_t &rounded_bytes)
104 rounded_bytes = round_to_page_size (nbytes);
105 void *result = 0;
106 int first_time = 0;
108 // Check local_cb_ for consistency. Remap, if extra space is too
109 // small and/or we didn't map the whole shared memory section
110 if (this->shared_cb_->sh_.mapped_size_
111 > this->local_cb_.sh_.mapped_size_
112 || this->shared_cb_->sh_.free_size_ < rounded_bytes)
114 size_t append = 0;
115 if (rounded_bytes > this->shared_cb_->sh_.free_size_)
116 append = rounded_bytes - this->shared_cb_->sh_.free_size_;
118 if (this->map (first_time, append) < 0)
119 return result;
122 // Get the block from extra space and update shared and local
123 // control block
124 if (this->shared_cb_->sh_.free_size_ < rounded_bytes)
125 return result;
127 result = (void *)((char *) this->local_cb_.mapped_base_
128 + this->shared_cb_->sh_.free_offset_);
129 this->shared_cb_->sh_.free_offset_ += rounded_bytes;
130 this->shared_cb_->sh_.free_size_ -= rounded_bytes;
131 this->local_cb_.sh_ = this->shared_cb_->sh_;
133 return result;
136 void *
137 ACE_Pagefile_Memory_Pool::init_acquire (size_t nbytes,
138 size_t &rounded_bytes,
139 int &first_time)
141 // Map the shared memory and get information, if we created the
142 // shared memory.
143 if (this->map (first_time) < 0)
144 return 0;
146 if (first_time != 0)
147 // We created the shared memory. So we have to allocate the
148 // requested memory.
149 return this->acquire (nbytes, rounded_bytes);
150 else
151 // We just mapped the memory and return the base address
152 return (void *)((char *) this->local_cb_.mapped_base_
153 + ACE_Pagefile_Memory_Pool::round_to_page_size
154 ((int) sizeof (Control_Block)));
158 ACE_Pagefile_Memory_Pool::seh_selector (void *ep)
160 DWORD ecode = ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionCode;
162 if (ecode == EXCEPTION_ACCESS_VIOLATION)
164 void * fault_addr = (void *)
165 ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionInformation[1];
167 if (this->remap (fault_addr) == 0)
168 return 1;
171 return 0;
175 ACE_Pagefile_Memory_Pool::remap (void *addr)
177 // If the shared memory is not mapped or the address, that caused
178 // the memory fault is outside of the commited range of chunks, we
179 // return.
180 if (this->shared_cb_ == 0
181 || addr < this->local_cb_.mapped_base_
182 || addr >= (void *)((char *) this->local_cb_.mapped_base_
183 + this->shared_cb_->sh_.mapped_size_))
184 return -1;
186 // We can solve the problem by committing additional chunks.
187 int first_time = 0;
188 return this->map (first_time);
192 ACE_Pagefile_Memory_Pool::unmap (void)
194 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
195 ACE_BASED_POINTER_REPOSITORY::instance ()->unbind
196 (this->local_cb_.mapped_base_);
197 #endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
199 // Cleanup cached pool pointer.
200 this->shared_cb_ = 0;
202 if (this->local_cb_.sh_.mapped_size_ > 0)
203 ::UnmapViewOfFile (this->local_cb_.mapped_base_);
205 // Reset local pool statistics.
206 this->local_cb_.req_base_ =
207 ACE_DEFAULT_PAGEFILE_POOL_BASE;
208 this->local_cb_.mapped_base_ = 0;
209 this->local_cb_.sh_.max_size_ =
210 ACE_DEFAULT_PAGEFILE_POOL_SIZE;
211 this->local_cb_.sh_.mapped_size_ = 0;
212 this->local_cb_.sh_.free_offset_ =
213 this->local_cb_.sh_.mapped_size_;
214 this->local_cb_.sh_.free_size_ = 0;
216 // Release the pool
217 if (this->object_handle_ != 0)
219 ::CloseHandle (this->object_handle_);
220 this->object_handle_ = 0;
222 return 0;
226 ACE_Pagefile_Memory_Pool::map (int &first_time,
227 size_t append_bytes)
229 size_t map_size;
230 void *map_addr;
232 // Create file mapping, if not yet done
233 if (object_handle_ == 0)
235 #if !defined (ACE_LACKS_WIN32_SECURITY_DESCRIPTORS)
236 // Allow access by all users.
237 SECURITY_ATTRIBUTES sa;
238 SECURITY_DESCRIPTOR sd;
239 ::InitializeSecurityDescriptor (&sd,
240 SECURITY_DESCRIPTOR_REVISION);
241 ::SetSecurityDescriptorDacl (&sd,
242 TRUE,
244 FALSE);
245 sa.nLength = sizeof (SECURITY_ATTRIBUTES);
246 sa.lpSecurityDescriptor = &sd;
247 sa.bInheritHandle = FALSE;
248 #endif /* ACE_LACKS_WIN32_SECURITY_DESCRIPTORS */
250 // Get an object handle to the named reserved memory object.
251 DWORD size_high;
252 DWORD size_low;
253 #if defined (ACE_WIN64)
254 size_high = static_cast<DWORD> (this->local_cb_.sh_.max_size_ >> 32);
255 size_low = static_cast<DWORD> (this->local_cb_.sh_.max_size_ & 0xFFFFFFFF);
256 #else
257 size_high = 0;
258 size_low = ACE_Utils::truncate_cast<DWORD> (this->local_cb_.sh_.max_size_);
259 #endif
261 object_handle_ =
262 ACE_TEXT_CreateFileMapping (INVALID_HANDLE_VALUE,
263 #if !defined (ACE_LACKS_WIN32_SECURITY_DESCRIPTORS)
264 &sa,
265 #else
267 #endif /* !ACE_LACKS_WIN32_SECURITY_DESCRIPTORS */
268 PAGE_READWRITE | SEC_RESERVE,
269 size_high,
270 size_low,
271 this->backing_store_name_);
272 if (object_handle_ == 0)
273 return -1;
274 first_time =
275 ::GetLastError () == ERROR_ALREADY_EXISTS
277 : 1;
280 // Do the initial mapping.
281 if (this->shared_cb_ == 0)
283 // Map a view to the shared memory. Note: <MapViewOfFile[Ex]>
284 // does *not* commit the pages!
285 this->shared_cb_ = (ACE_Pagefile_Memory_Pool::Control_Block *)
286 ACE_MAP_FILE (this->object_handle_,
287 FILE_MAP_WRITE,
290 this->local_cb_.sh_.max_size_,
291 this->local_cb_.req_base_);
292 if (this->shared_cb_ == 0)
293 return -1;
295 // There was no previous mapping, so we map the first chunk and
296 // initialize the shared pool statistics.
297 if (first_time)
299 // 1st block is used to keep shared memory statistics.
300 map_size =
301 ACE_Pagefile_Memory_Pool::round_to_chunk_size
302 (ACE_Pagefile_Memory_Pool::round_to_page_size
303 ((int) sizeof(Control_Block))
304 + append_bytes);
306 if (::VirtualAlloc ((void *) this->shared_cb_,
307 map_size,
308 MEM_COMMIT,
309 PAGE_READWRITE) == 0)
310 return -1;
312 this->shared_cb_->req_base_ = 0;
313 this->shared_cb_->mapped_base_ = 0;
314 this->local_cb_.mapped_base_ = this->shared_cb_;
315 this->local_cb_.sh_.mapped_size_ = map_size;
316 this->local_cb_.sh_.free_offset_ =
317 round_to_page_size ((int) sizeof (Control_Block));
318 this->local_cb_.sh_.free_size_ =
319 this->local_cb_.sh_.mapped_size_ -
320 this->local_cb_.sh_.free_offset_;
321 this->shared_cb_->sh_ = this->local_cb_.sh_;
324 // The shared memory exists, so we map the first chunk to the
325 // base address of the pool to get the shared pool statistics.
326 else
328 // 1st block is used to keep shared memory statistics.
329 map_size =
330 ACE_Pagefile_Memory_Pool::round_to_chunk_size
331 ((int) sizeof (Control_Block));
333 if (::VirtualAlloc ((void *) this->shared_cb_,
334 map_size,
335 MEM_COMMIT,
336 PAGE_READWRITE) == 0)
337 return -1;
338 this->local_cb_.mapped_base_ = this->shared_cb_;
339 this->local_cb_.sh_.mapped_size_ = map_size;
343 // If the shared memory is larger than the part we've already
344 // committed, we have to remap it.
345 if (this->shared_cb_->sh_.mapped_size_ >
346 this->local_cb_.sh_.mapped_size_
347 || append_bytes > 0)
349 map_size =
350 (this->shared_cb_->sh_.mapped_size_ -
351 this->local_cb_.sh_.mapped_size_)
352 + ACE_Pagefile_Memory_Pool::round_to_chunk_size
353 (append_bytes);
355 map_addr = (void *)((char *) this->shared_cb_ +
356 this->local_cb_.sh_.mapped_size_);
358 if (::VirtualAlloc (map_addr,
359 map_size,
360 MEM_COMMIT,
361 PAGE_READWRITE) == 0)
362 return -1;
363 else if (append_bytes > 0)
365 this->shared_cb_->sh_.mapped_size_ +=
366 round_to_chunk_size (append_bytes);
367 this->shared_cb_->sh_.free_size_ =
368 this->shared_cb_->sh_.mapped_size_ -
369 this->shared_cb_->sh_.free_offset_;
373 // Update local copy of the shared memory statistics.
374 this->local_cb_.sh_ =
375 this->shared_cb_->sh_;
376 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
377 ACE_BASED_POINTER_REPOSITORY::instance ()->bind
378 (this->local_cb_.mapped_base_,
379 this->local_cb_.sh_.mapped_size_);
380 #endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
382 return 0;
385 ACE_END_VERSIONED_NAMESPACE_DECL
387 #endif /* ACE_WIN32 && !ACE_HAS_PHARLAP */