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 (
38 : base_addr_ (base_addr
),
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
)
53 page_size_ (ACE_Pagefile_Memory_Pool::round_to_page_size (1))
55 // Initialize local copy of pool statistics.
58 this->local_cb_
.req_base_
= options
->base_addr_
;
59 this->local_cb_
.mapped_base_
= 0;
60 this->local_cb_
.sh_
.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;
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_
,
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_
,
96 ACE_Pagefile_Memory_Pool::~ACE_Pagefile_Memory_Pool (void)
101 ACE_Pagefile_Memory_Pool::acquire (size_t nbytes
,
102 size_t &rounded_bytes
)
104 rounded_bytes
= round_to_page_size (nbytes
);
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
)
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)
122 // Get the block from extra space and update shared and local
124 if (this->shared_cb_
->sh_
.free_size_
< rounded_bytes
)
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_
;
137 ACE_Pagefile_Memory_Pool::init_acquire (size_t nbytes
,
138 size_t &rounded_bytes
,
141 // Map the shared memory and get information, if we created the
143 if (this->map (first_time
) < 0)
147 // We created the shared memory. So we have to allocate the
149 return this->acquire (nbytes
, rounded_bytes
);
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)
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
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_
))
186 // We can solve the problem by committing additional chunks.
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;
217 if (this->object_handle_
!= 0)
219 ::CloseHandle (this->object_handle_
);
220 this->object_handle_
= 0;
226 ACE_Pagefile_Memory_Pool::map (int &first_time
,
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
,
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.
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);
258 size_low
= ACE_Utils::truncate_cast
<DWORD
> (this->local_cb_
.sh_
.max_size_
);
262 ACE_TEXT_CreateFileMapping (INVALID_HANDLE_VALUE
,
263 #if !defined (ACE_LACKS_WIN32_SECURITY_DESCRIPTORS)
267 #endif /* !ACE_LACKS_WIN32_SECURITY_DESCRIPTORS */
268 PAGE_READWRITE
| SEC_RESERVE
,
271 this->backing_store_name_
);
272 if (object_handle_
== 0)
275 ::GetLastError () == ERROR_ALREADY_EXISTS
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_
,
290 this->local_cb_
.sh_
.max_size_
,
291 this->local_cb_
.req_base_
);
292 if (this->shared_cb_
== 0)
295 // There was no previous mapping, so we map the first chunk and
296 // initialize the shared pool statistics.
299 // 1st block is used to keep shared memory statistics.
301 ACE_Pagefile_Memory_Pool::round_to_chunk_size
302 (ACE_Pagefile_Memory_Pool::round_to_page_size
303 ((int) sizeof(Control_Block
))
306 if (::VirtualAlloc ((void *) this->shared_cb_
,
309 PAGE_READWRITE
) == 0)
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.
328 // 1st block is used to keep shared memory statistics.
330 ACE_Pagefile_Memory_Pool::round_to_chunk_size
331 ((int) sizeof (Control_Block
));
333 if (::VirtualAlloc ((void *) this->shared_cb_
,
336 PAGE_READWRITE
) == 0)
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_
350 (this->shared_cb_
->sh_
.mapped_size_
-
351 this->local_cb_
.sh_
.mapped_size_
)
352 + ACE_Pagefile_Memory_Pool::round_to_chunk_size
355 map_addr
= (void *)((char *) this->shared_cb_
+
356 this->local_cb_
.sh_
.mapped_size_
);
358 if (::VirtualAlloc (map_addr
,
361 PAGE_READWRITE
) == 0)
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 */
385 ACE_END_VERSIONED_NAMESPACE_DECL
387 #endif /* ACE_WIN32 && !ACE_HAS_PHARLAP */