Need double escape
[ACE_TAO.git] / ACE / ace / Pagefile_Memory_Pool.cpp
blobb536f8d1a3fc9bb11a14f81328b106a6d349e7f4
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/RW_Thread_Mutex.h"
10 #include "ace/OS_NS_sys_mman.h"
11 #include "ace/OS_NS_string.h"
12 #include "ace/OS_NS_sys_stat.h"
13 #include "ace/OS_NS_unistd.h"
14 #include "ace/Truncate.h"
16 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
17 #include "ace/Based_Pointer_T.h"
18 #include "ace/Based_Pointer_Repository.h"
19 #endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
21 #if defined (ACE_WIN32)
22 #define ACE_MAP_FILE(_hnd, _access, _offHigh, _offLow, _nBytes, _baseAdd) \
23 MapViewOfFileEx (_hnd, _access, _offHigh, _offLow, _nBytes, _baseAdd)
25 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
27 ACE_Pagefile_Memory_Pool_Options::ACE_Pagefile_Memory_Pool_Options (
28 void *base_addr,
29 size_t max_size)
30 : base_addr_ (base_addr),
31 max_size_ (max_size)
35 int
36 ACE_Pagefile_Memory_Pool::release (int)
38 return this->unmap ();
41 ACE_Pagefile_Memory_Pool::ACE_Pagefile_Memory_Pool (const ACE_TCHAR *backing_store_name,
42 const OPTIONS *options)
43 : shared_cb_ (0),
44 object_handle_ (0),
45 page_size_ (ACE_Pagefile_Memory_Pool::round_to_page_size (1))
47 // Initialize local copy of pool statistics.
48 if (options != 0)
50 this->local_cb_.req_base_ = options->base_addr_;
51 this->local_cb_.mapped_base_ = 0;
52 this->local_cb_.sh_.max_size_ = options->max_size_;
53 this->local_cb_.sh_.mapped_size_ = 0;
54 this->local_cb_.sh_.free_offset_ = this->local_cb_.sh_.mapped_size_;
55 this->local_cb_.sh_.free_size_ = 0;
57 else
59 this->local_cb_.req_base_ = 0;
60 this->local_cb_.mapped_base_ = 0;
61 this->local_cb_.sh_.max_size_ = this->round_to_chunk_size (page_size_) ;
62 this->local_cb_.sh_.mapped_size_ = 0;
63 this->local_cb_.sh_.free_offset_ = this->local_cb_.sh_.mapped_size_;
64 this->local_cb_.sh_.free_size_ = 0;
67 int const update_backing_store_name = backing_store_name == 0 ? 0 : 1;
69 if (backing_store_name == 0)
70 // Only create a new unique filename for the backing store file if
71 // the user didn't supply one...
72 backing_store_name = ACE_DEFAULT_PAGEFILE_POOL_NAME;
74 ACE_OS::strsncpy (this->backing_store_name_,
75 backing_store_name,
76 (sizeof this->backing_store_name_ / sizeof (ACE_TCHAR)));
78 if (update_backing_store_name
79 && ACE_OS::strlen (this->backing_store_name_) < sizeof this->backing_store_name_)
80 ACE_OS::strcat (this->backing_store_name_,
81 ACE_TEXT ("_"));
84 void *
85 ACE_Pagefile_Memory_Pool::acquire (size_t nbytes,
86 size_t &rounded_bytes)
88 rounded_bytes = round_to_page_size (nbytes);
89 void *result = 0;
90 int first_time = 0;
92 // Check local_cb_ for consistency. Remap, if extra space is too
93 // small and/or we didn't map the whole shared memory section
94 if (this->shared_cb_->sh_.mapped_size_
95 > this->local_cb_.sh_.mapped_size_
96 || this->shared_cb_->sh_.free_size_ < rounded_bytes)
98 size_t append = 0;
99 if (rounded_bytes > this->shared_cb_->sh_.free_size_)
100 append = rounded_bytes - this->shared_cb_->sh_.free_size_;
102 if (this->map (first_time, append) < 0)
103 return result;
106 // Get the block from extra space and update shared and local
107 // control block
108 if (this->shared_cb_->sh_.free_size_ < rounded_bytes)
109 return result;
111 result = (void *)((char *) this->local_cb_.mapped_base_
112 + this->shared_cb_->sh_.free_offset_);
113 this->shared_cb_->sh_.free_offset_ += rounded_bytes;
114 this->shared_cb_->sh_.free_size_ -= rounded_bytes;
115 this->local_cb_.sh_ = this->shared_cb_->sh_;
117 return result;
120 void *
121 ACE_Pagefile_Memory_Pool::init_acquire (size_t nbytes,
122 size_t &rounded_bytes,
123 int &first_time)
125 // Map the shared memory and get information, if we created the
126 // shared memory.
127 if (this->map (first_time) < 0)
128 return 0;
130 if (first_time != 0)
131 // We created the shared memory. So we have to allocate the
132 // requested memory.
133 return this->acquire (nbytes, rounded_bytes);
134 else
135 // We just mapped the memory and return the base address
136 return (void *)((char *) this->local_cb_.mapped_base_
137 + ACE_Pagefile_Memory_Pool::round_to_page_size
138 ((int) sizeof (Control_Block)));
142 ACE_Pagefile_Memory_Pool::seh_selector (void *ep)
144 DWORD ecode = ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionCode;
146 if (ecode == EXCEPTION_ACCESS_VIOLATION)
148 void * fault_addr = (void *)
149 ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionInformation[1];
151 if (this->remap (fault_addr) == 0)
152 return 1;
155 return 0;
159 ACE_Pagefile_Memory_Pool::remap (void *addr)
161 // If the shared memory is not mapped or the address, that caused
162 // the memory fault is outside of the commited range of chunks, we
163 // return.
164 if (this->shared_cb_ == 0
165 || addr < this->local_cb_.mapped_base_
166 || addr >= (void *)((char *) this->local_cb_.mapped_base_
167 + this->shared_cb_->sh_.mapped_size_))
168 return -1;
170 // We can solve the problem by committing additional chunks.
171 int first_time = 0;
172 return this->map (first_time);
176 ACE_Pagefile_Memory_Pool::unmap ()
178 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
179 ACE_BASED_POINTER_REPOSITORY::instance ()->unbind
180 (this->local_cb_.mapped_base_);
181 #endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
183 // Cleanup cached pool pointer.
184 this->shared_cb_ = 0;
186 if (this->local_cb_.sh_.mapped_size_ > 0)
187 ::UnmapViewOfFile (this->local_cb_.mapped_base_);
189 // Reset local pool statistics.
190 this->local_cb_.req_base_ =
191 ACE_DEFAULT_PAGEFILE_POOL_BASE;
192 this->local_cb_.mapped_base_ = 0;
193 this->local_cb_.sh_.max_size_ =
194 ACE_DEFAULT_PAGEFILE_POOL_SIZE;
195 this->local_cb_.sh_.mapped_size_ = 0;
196 this->local_cb_.sh_.free_offset_ =
197 this->local_cb_.sh_.mapped_size_;
198 this->local_cb_.sh_.free_size_ = 0;
200 // Release the pool
201 if (this->object_handle_ != 0)
203 ::CloseHandle (this->object_handle_);
204 this->object_handle_ = 0;
206 return 0;
210 ACE_Pagefile_Memory_Pool::map (int &first_time,
211 size_t append_bytes)
213 size_t map_size;
214 void *map_addr;
216 // Create file mapping, if not yet done
217 if (object_handle_ == 0)
219 // Allow access by all users.
220 SECURITY_ATTRIBUTES sa;
221 SECURITY_DESCRIPTOR sd;
222 ::InitializeSecurityDescriptor (&sd,
223 SECURITY_DESCRIPTOR_REVISION);
224 ::SetSecurityDescriptorDacl (&sd,
225 TRUE,
227 FALSE);
228 sa.nLength = sizeof (SECURITY_ATTRIBUTES);
229 sa.lpSecurityDescriptor = &sd;
230 sa.bInheritHandle = FALSE;
232 // Get an object handle to the named reserved memory object.
233 DWORD size_high;
234 DWORD size_low;
235 #if defined (ACE_WIN64)
236 size_high = static_cast<DWORD> (this->local_cb_.sh_.max_size_ >> 32);
237 size_low = static_cast<DWORD> (this->local_cb_.sh_.max_size_ & 0xFFFFFFFF);
238 #else
239 size_high = 0;
240 size_low = ACE_Utils::truncate_cast<DWORD> (this->local_cb_.sh_.max_size_);
241 #endif
243 object_handle_ =
244 ACE_TEXT_CreateFileMapping (INVALID_HANDLE_VALUE,
245 &sa,
246 PAGE_READWRITE | SEC_RESERVE,
247 size_high,
248 size_low,
249 this->backing_store_name_);
250 if (object_handle_ == 0)
251 return -1;
252 first_time =
253 ::GetLastError () == ERROR_ALREADY_EXISTS
255 : 1;
258 // Do the initial mapping.
259 if (this->shared_cb_ == 0)
261 // Map a view to the shared memory. Note: <MapViewOfFile[Ex]>
262 // does *not* commit the pages!
263 this->shared_cb_ = (ACE_Pagefile_Memory_Pool::Control_Block *)
264 ACE_MAP_FILE (this->object_handle_,
265 FILE_MAP_WRITE,
268 this->local_cb_.sh_.max_size_,
269 this->local_cb_.req_base_);
270 if (this->shared_cb_ == 0)
271 return -1;
273 // There was no previous mapping, so we map the first chunk and
274 // initialize the shared pool statistics.
275 if (first_time)
277 // 1st block is used to keep shared memory statistics.
278 map_size =
279 ACE_Pagefile_Memory_Pool::round_to_chunk_size
280 (ACE_Pagefile_Memory_Pool::round_to_page_size
281 ((int) sizeof(Control_Block))
282 + append_bytes);
284 if (::VirtualAlloc ((void *) this->shared_cb_,
285 map_size,
286 MEM_COMMIT,
287 PAGE_READWRITE) == 0)
288 return -1;
290 this->shared_cb_->req_base_ = 0;
291 this->shared_cb_->mapped_base_ = 0;
292 this->local_cb_.mapped_base_ = this->shared_cb_;
293 this->local_cb_.sh_.mapped_size_ = map_size;
294 this->local_cb_.sh_.free_offset_ =
295 round_to_page_size ((int) sizeof (Control_Block));
296 this->local_cb_.sh_.free_size_ =
297 this->local_cb_.sh_.mapped_size_ -
298 this->local_cb_.sh_.free_offset_;
299 this->shared_cb_->sh_ = this->local_cb_.sh_;
302 // The shared memory exists, so we map the first chunk to the
303 // base address of the pool to get the shared pool statistics.
304 else
306 // 1st block is used to keep shared memory statistics.
307 map_size =
308 ACE_Pagefile_Memory_Pool::round_to_chunk_size
309 ((int) sizeof (Control_Block));
311 if (::VirtualAlloc ((void *) this->shared_cb_,
312 map_size,
313 MEM_COMMIT,
314 PAGE_READWRITE) == 0)
315 return -1;
316 this->local_cb_.mapped_base_ = this->shared_cb_;
317 this->local_cb_.sh_.mapped_size_ = map_size;
321 // If the shared memory is larger than the part we've already
322 // committed, we have to remap it.
323 if (this->shared_cb_->sh_.mapped_size_ >
324 this->local_cb_.sh_.mapped_size_
325 || append_bytes > 0)
327 map_size =
328 (this->shared_cb_->sh_.mapped_size_ -
329 this->local_cb_.sh_.mapped_size_)
330 + ACE_Pagefile_Memory_Pool::round_to_chunk_size
331 (append_bytes);
333 map_addr = (void *)((char *) this->shared_cb_ +
334 this->local_cb_.sh_.mapped_size_);
336 if (::VirtualAlloc (map_addr,
337 map_size,
338 MEM_COMMIT,
339 PAGE_READWRITE) == 0)
340 return -1;
341 else if (append_bytes > 0)
343 this->shared_cb_->sh_.mapped_size_ +=
344 round_to_chunk_size (append_bytes);
345 this->shared_cb_->sh_.free_size_ =
346 this->shared_cb_->sh_.mapped_size_ -
347 this->shared_cb_->sh_.free_offset_;
351 // Update local copy of the shared memory statistics.
352 this->local_cb_.sh_ =
353 this->shared_cb_->sh_;
354 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
355 ACE_BASED_POINTER_REPOSITORY::instance ()->bind
356 (this->local_cb_.mapped_base_,
357 this->local_cb_.sh_.mapped_size_);
358 #endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
360 return 0;
363 ACE_END_VERSIONED_NAMESPACE_DECL
365 #endif /* ACE_WIN32 */