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 (
30 : base_addr_ (base_addr
),
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
)
45 page_size_ (ACE_Pagefile_Memory_Pool::round_to_page_size (1))
47 // Initialize local copy of pool statistics.
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;
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_
,
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_
,
85 ACE_Pagefile_Memory_Pool::acquire (size_t nbytes
,
86 size_t &rounded_bytes
)
88 rounded_bytes
= round_to_page_size (nbytes
);
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
)
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)
106 // Get the block from extra space and update shared and local
108 if (this->shared_cb_
->sh_
.free_size_
< rounded_bytes
)
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_
;
121 ACE_Pagefile_Memory_Pool::init_acquire (size_t nbytes
,
122 size_t &rounded_bytes
,
125 // Map the shared memory and get information, if we created the
127 if (this->map (first_time
) < 0)
131 // We created the shared memory. So we have to allocate the
133 return this->acquire (nbytes
, rounded_bytes
);
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)
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
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_
))
170 // We can solve the problem by committing additional chunks.
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;
201 if (this->object_handle_
!= 0)
203 ::CloseHandle (this->object_handle_
);
204 this->object_handle_
= 0;
210 ACE_Pagefile_Memory_Pool::map (int &first_time
,
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
,
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.
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);
240 size_low
= ACE_Utils::truncate_cast
<DWORD
> (this->local_cb_
.sh_
.max_size_
);
244 ACE_TEXT_CreateFileMapping (INVALID_HANDLE_VALUE
,
246 PAGE_READWRITE
| SEC_RESERVE
,
249 this->backing_store_name_
);
250 if (object_handle_
== 0)
253 ::GetLastError () == ERROR_ALREADY_EXISTS
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_
,
268 this->local_cb_
.sh_
.max_size_
,
269 this->local_cb_
.req_base_
);
270 if (this->shared_cb_
== 0)
273 // There was no previous mapping, so we map the first chunk and
274 // initialize the shared pool statistics.
277 // 1st block is used to keep shared memory statistics.
279 ACE_Pagefile_Memory_Pool::round_to_chunk_size
280 (ACE_Pagefile_Memory_Pool::round_to_page_size
281 ((int) sizeof(Control_Block
))
284 if (::VirtualAlloc ((void *) this->shared_cb_
,
287 PAGE_READWRITE
) == 0)
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.
306 // 1st block is used to keep shared memory statistics.
308 ACE_Pagefile_Memory_Pool::round_to_chunk_size
309 ((int) sizeof (Control_Block
));
311 if (::VirtualAlloc ((void *) this->shared_cb_
,
314 PAGE_READWRITE
) == 0)
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_
328 (this->shared_cb_
->sh_
.mapped_size_
-
329 this->local_cb_
.sh_
.mapped_size_
)
330 + ACE_Pagefile_Memory_Pool::round_to_chunk_size
333 map_addr
= (void *)((char *) this->shared_cb_
+
334 this->local_cb_
.sh_
.mapped_size_
);
336 if (::VirtualAlloc (map_addr
,
339 PAGE_READWRITE
) == 0)
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 */
363 ACE_END_VERSIONED_NAMESPACE_DECL
365 #endif /* ACE_WIN32 */