Removed ACE_HAS_BSTRING, not used
[ACE_TAO.git] / ACE / ace / MMAP_Memory_Pool.cpp
blobc0a02bac81cd9dc47ec7388295da223a5565af85
1 // MMAP_Memory_Pool.cpp
2 #include "ace/MMAP_Memory_Pool.h"
3 #include "ace/OS_NS_sys_mman.h"
4 #include "ace/OS_NS_unistd.h"
5 #include "ace/OS_NS_string.h"
6 #include "ace/OS_NS_sys_stat.h"
7 #include "ace/Log_Category.h"
8 #include "ace/Truncate.h"
9 #include "ace/Lib_Find.h"
11 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
12 #include "ace/Based_Pointer_T.h"
13 #include "ace/Based_Pointer_Repository.h"
14 #endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
16 #if !defined (__ACE_INLINE__)
17 #include "ace/MMAP_Memory_Pool.inl"
18 #endif /* __ACE_INLINE__ */
20 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
22 ACE_ALLOC_HOOK_DEFINE(ACE_MMAP_Memory_Pool)
24 void
25 ACE_MMAP_Memory_Pool::dump (void) const
27 #if defined (ACE_HAS_DUMP)
28 ACE_TRACE ("ACE_MMAP_Memory_Pool::dump");
29 #endif /* ACE_HAS_DUMP */
32 int
33 ACE_MMAP_Memory_Pool::release (int destroy)
35 ACE_TRACE ("ACE_MMAP_Memory_Pool::release");
37 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
38 ACE_BASED_POINTER_REPOSITORY::instance ()->unbind (this->mmap_.addr ());
39 #endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
41 if (destroy)
42 this->mmap_.remove ();
43 else
44 this->mmap_.close ();
45 return 0;
48 int
49 ACE_MMAP_Memory_Pool::sync (size_t len, int flags)
51 ACE_TRACE ("ACE_MMAP_Memory_Pool::sync");
53 return this->mmap_.sync (len, flags);
56 int
57 ACE_MMAP_Memory_Pool::sync (int flags)
59 ACE_TRACE ("ACE_MMAP_Memory_Pool::sync");
61 size_t const len = ACE_Utils::truncate_cast<size_t> (
62 ACE_OS::lseek (this->mmap_.handle (), 0, SEEK_END));
64 return this->mmap_.sync (len, flags);
67 /// Sync @a len bytes of the memory region to the backing store starting
68 /// at <addr_>.
69 int
70 ACE_MMAP_Memory_Pool::sync (void *addr, size_t len, int flags)
72 ACE_TRACE ("ACE_MMAP_Memory_Pool::sync");
73 return ACE_OS::msync (addr, len, flags);
76 // Change the protection of the pages of the mapped region to <prot>
77 // starting at <this->base_addr_> up to <len> bytes.
78 // Change protection of all pages in the mapped region.
80 int
81 ACE_MMAP_Memory_Pool::protect (size_t len, int prot)
83 ACE_TRACE ("ACE_MMAP_Memory_Pool::protect");
85 return this->mmap_.protect (len, prot);
88 int
89 ACE_MMAP_Memory_Pool::protect (int prot)
91 ACE_TRACE ("ACE_MMAP_Memory_Pool::protect");
93 size_t const len = ACE_Utils::truncate_cast<size_t> (
94 ACE_OS::lseek (this->mmap_.handle (), 0, SEEK_END));
96 return this->mmap_.protect (len, prot);
100 // Change the protection of the pages of the mapped region to <prot>
101 // starting at <addr> up to <len> bytes.
104 ACE_MMAP_Memory_Pool::protect (void *addr, size_t len, int prot)
106 ACE_TRACE ("ACE_MMAP_Memory_Pool::protect");
107 return ACE_OS::mprotect (addr, len, prot);
110 ACE_MMAP_Memory_Pool::ACE_MMAP_Memory_Pool (
111 const ACE_TCHAR *backing_store_name,
112 const OPTIONS *options)
113 : base_addr_ (0),
114 use_fixed_addr_(0),
115 flags_ (MAP_SHARED),
116 write_each_page_ (false),
117 minimum_bytes_ (0),
118 sa_ (0),
119 file_mode_ (ACE_DEFAULT_FILE_PERMS),
120 install_signal_handler_ (true)
122 ACE_TRACE ("ACE_MMAP_Memory_Pool::ACE_MMAP_Memory_Pool");
124 #if (defined (ACE_HAS_SIGINFO_T) && !defined (ACE_LACKS_SI_ADDR)) || defined (ACE_WIN32)
125 // For plaforms that give the faulting address.
126 guess_on_fault_ = false;
127 #else
128 // For plaforms that do NOT give the faulting address, let the
129 // options decide whether to guess or not.
130 if (options)
131 guess_on_fault_ = options->guess_on_fault_;
132 else
133 // If no options are specified, default to true.
134 guess_on_fault_ = true;
135 #endif /* (defined (ACE_HAS_SIGINFO_T) && !defined (ACE_LACKS_SI_ADDR)) || defined (ACE_WIN32) */
137 // Only change the defaults if <options> != 0.
138 if (options)
140 if (options->flags_ != 0)
141 this->flags_ = options->flags_;
142 use_fixed_addr_ = options->use_fixed_addr_;
144 if (use_fixed_addr_ == ACE_MMAP_Memory_Pool_Options::ALWAYS_FIXED)
146 this->base_addr_ = const_cast<void *> (options->base_addr_);
147 ACE_SET_BITS (flags_, MAP_FIXED);
149 this->write_each_page_ = options->write_each_page_;
150 this->minimum_bytes_ = options->minimum_bytes_;
151 if (options->sa_ != 0)
152 this->sa_ = options->sa_;
153 this->file_mode_ = options->file_mode_;
154 this->install_signal_handler_ = options->install_signal_handler_;
157 if (backing_store_name == 0)
159 // Only create a new unique filename for the backing store file
160 // if the user didn't supply one...
161 #if defined (ACE_DEFAULT_BACKING_STORE)
162 // Create a temporary file.
163 ACE_OS::strcpy (this->backing_store_name_,
164 ACE_DEFAULT_BACKING_STORE);
165 #else /* ACE_DEFAULT_BACKING_STORE */
166 if (ACE::get_temp_dir (this->backing_store_name_,
167 MAXPATHLEN - 17) == -1)
168 // -17 for ace-malloc-XXXXXX
170 ACELIB_ERROR ((LM_ERROR,
171 ACE_TEXT ("Temporary path too long, ")
172 ACE_TEXT ("defaulting to current directory\n")));
173 this->backing_store_name_[0] = 0;
176 // Add the filename to the end
177 ACE_OS::strcat (this->backing_store_name_,
178 ACE_TEXT ("ace-malloc-XXXXXX"));
180 // If requested an unique filename, use mktemp to get a random file.
181 if (options && options->unique_)
182 # if defined (ACE_DISABLE_MKTEMP)
184 ACELIB_ERROR ((LM_ERROR,
185 ACE_TEXT ("mktemp disabled; ")
186 ACE_TEXT ("can't generate unique name")));
187 this->backing_store_name_[0] = 0;
189 # else
190 ACE_OS::mktemp(this->backing_store_name_);
191 # endif /* ACE_DISABLE_MKTEMP */
192 #endif /* ACE_DEFAULT_BACKING_STORE */
194 else
195 ACE_OS::strsncpy (this->backing_store_name_,
196 backing_store_name,
197 (sizeof this->backing_store_name_ / sizeof (ACE_TCHAR)));
199 #if !defined (ACE_WIN32)
200 if (this->install_signal_handler_)
202 if (this->signal_handler_.register_handler (SIGSEGV, this) == -1)
203 ACELIB_ERROR ((LM_ERROR,
204 ACE_TEXT("%p\n"), this->backing_store_name_));
206 #endif /* ACE_WIN32 */
209 ACE_MMAP_Memory_Pool::~ACE_MMAP_Memory_Pool (void)
213 // Compute the new map_size of the backing store and commit the
214 // memory.
216 ACE_MMAP_Memory_Pool::commit_backing_store_name (size_t rounded_bytes,
217 size_t & map_size)
219 ACE_TRACE ("ACE_MMAP_Memory_Pool::commit_backing_store_name");
221 #if defined (__Lynx__)
222 map_size = rounded_bytes;
223 #else
224 size_t seek_len;
226 if (this->write_each_page_)
227 // Write to the end of every block to ensure that we have enough
228 // space in the backing store.
229 seek_len = this->round_up (1); // round_up(1) is one page.
230 else
231 // We're willing to risk it all in the name of efficiency...
232 seek_len = rounded_bytes;
234 // The following loop will execute multiple times (if
235 // this->write_each_page == 1) or just once (if
236 // this->write_each_page == 0).
238 for (size_t cur_block = 0;
239 cur_block < rounded_bytes;
240 cur_block += seek_len)
242 map_size =
243 ACE_Utils::truncate_cast<size_t> (
244 ACE_OS::lseek (this->mmap_.handle (),
245 static_cast<ACE_OFF_T> (seek_len - 1),
246 SEEK_END));
248 if (map_size == static_cast<size_t> (-1)
249 || ACE_OS::write (this->mmap_.handle (),
251 1) == -1)
252 ACELIB_ERROR_RETURN ((LM_ERROR,
253 ACE_TEXT ("(%P|%t) %p\n"),
254 this->backing_store_name_),
255 -1);
258 #if defined (ACE_OPENVMS)
259 ::fsync(this->mmap_.handle());
260 #endif
262 // Increment by one to put us at the beginning of the next chunk...
263 ++map_size;
264 #endif /* __Lynx__ */
265 return 0;
268 // Memory map the file up to <map_size> bytes.
271 ACE_MMAP_Memory_Pool::map_file (size_t map_size)
273 ACE_TRACE ("ACE_MMAP_Memory_Pool::map_file");
274 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
275 void* obase_addr = this->base_addr_;
276 #endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
278 // Unmap the existing mapping.
279 this->mmap_.unmap ();
281 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
282 if (use_fixed_addr_ == ACE_MMAP_Memory_Pool_Options::NEVER_FIXED)
283 this->base_addr_ = 0;
284 #endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
286 // Remap the file; try to stay at the same location as a previous mapping
287 // but do not force it with MAP_FIXED. Doing so will give the OS permission
288 // to map locations currently holding other things (such as the heap, or
289 // the C library) into the map file, producing very unexpected results.
290 if (this->mmap_.map (map_size,
291 PROT_RDWR,
292 this->flags_,
293 this->base_addr_,
295 this->sa_) == -1
296 || (this->base_addr_ != 0
297 #ifdef ACE_HAS_WINCE
298 && this->mmap_.addr () == 0)) // WinCE does not allow users to specify alloc addr.
299 #else
300 && this->mmap_.addr () != this->base_addr_))
301 #endif // ACE_HAS_WINCE
303 #if 0
304 ACELIB_ERROR ((LM_ERROR,
305 ACE_TEXT ("(%P|%t) addr = %@, base_addr = %@, map_size = %B, %p\n"),
306 this->mmap_.addr (),
307 this->base_addr_,
308 map_size,
309 this->backing_store_name_));
310 #endif /* 0 */
311 return -1;
313 else
315 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
316 this->base_addr_ = this->mmap_.addr ();
318 if (obase_addr && this->base_addr_ != obase_addr)
320 ACE_BASED_POINTER_REPOSITORY::instance ()->unbind (obase_addr);
323 ACE_BASED_POINTER_REPOSITORY::instance ()->bind (this->base_addr_,
324 map_size);
325 #endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
326 return 0;
330 // Ask operating system for more shared memory, increasing the mapping
331 // accordingly. Note that this routine assumes that the appropriate
332 // locks are held when it is called.
334 void *
335 ACE_MMAP_Memory_Pool::acquire (size_t nbytes,
336 size_t &rounded_bytes)
338 ACE_TRACE ("ACE_MMAP_Memory_Pool::acquire");
339 rounded_bytes = this->round_up (nbytes);
341 // ACELIB_DEBUG ((LM_DEBUG, "(%P|%t) acquiring more chunks, nbytes =
342 // %B, rounded_bytes = %B\n", nbytes, rounded_bytes));
344 size_t map_size;
346 if (this->commit_backing_store_name (rounded_bytes,
347 map_size) == -1)
348 return 0;
349 else if (this->map_file (map_size) == -1)
350 return 0;
352 // ACELIB_DEBUG ((LM_DEBUG, "(%P|%t) acquired more chunks, nbytes = %B,
353 // rounded_bytes = %B, map_size = %B\n", nbytes, rounded_bytes,
354 // map_size));
356 return (void *) ((char *) this->mmap_.addr () + (this->mmap_.size () - rounded_bytes));
359 // Ask system for initial chunk of shared memory.
361 void *
362 ACE_MMAP_Memory_Pool::init_acquire (size_t nbytes,
363 size_t &rounded_bytes,
364 int &first_time)
366 ACE_TRACE ("ACE_MMAP_Memory_Pool::init_acquire");
368 first_time = 0;
370 if (nbytes < static_cast <size_t> (this->minimum_bytes_))
371 nbytes = static_cast <size_t> (this->minimum_bytes_);
373 if (this->mmap_.open (this->backing_store_name_,
374 O_RDWR | O_CREAT | O_TRUNC | O_EXCL,
375 this->file_mode_, this->sa_) != -1)
377 // First time in, so need to acquire memory.
378 first_time = 1;
380 void *result = this->acquire (nbytes, rounded_bytes);
381 // After the first time, reset the flag so that subsequent calls
382 // will use MAP_FIXED
383 if (this->use_fixed_addr_ == ACE_MMAP_Memory_Pool_Options::FIRSTCALL_FIXED)
385 ACE_SET_BITS (flags_, MAP_FIXED);
387 return result;
389 else if (errno == EEXIST)
391 errno = 0;
392 // Reopen file *without* using O_EXCL...
393 if (this->mmap_.map (this->backing_store_name_,
394 static_cast<size_t> (-1),
395 O_RDWR,
396 this->file_mode_,
397 PROT_RDWR,
398 this->flags_,
399 this->base_addr_,
401 this->sa_) == -1)
402 ACELIB_ERROR_RETURN ((LM_ERROR,
403 ACE_TEXT ("%p\n"),
404 ACE_TEXT ("MMAP_Memory_Pool::init_acquire, EEXIST")),
406 // After the first time, reset the flag so that subsequent calls
407 // will use MAP_FIXED
408 if (use_fixed_addr_ == ACE_MMAP_Memory_Pool_Options::FIRSTCALL_FIXED)
410 ACE_SET_BITS (flags_, MAP_FIXED);
412 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
413 // Update the mapped segment information
414 ACE_BASED_POINTER_REPOSITORY::instance ()->bind (this->mmap_.addr(),
415 this->mmap_.size());
416 #endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
418 return this->mmap_.addr ();
420 else
421 ACELIB_ERROR_RETURN ((LM_ERROR,
422 ACE_TEXT ("%p\n"),
423 ACE_TEXT ("MMAP_Memory_Pool::init_acquire")),
427 #if defined (ACE_WIN32)
429 ACE_MMAP_Memory_Pool::seh_selector (void *ep)
431 DWORD const ecode = ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionCode;
433 if (ecode == EXCEPTION_ACCESS_VIOLATION)
435 void * fault_addr = (void *)
436 ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionInformation[1];
438 if (this->remap (fault_addr) == 0)
439 return 1;
442 return 0;
444 #endif /* ACE_WIN32 */
447 ACE_MMAP_Memory_Pool::remap (void *addr)
449 ACE_TRACE ("ACE_MMAP_Memory_Pool::remap");
450 // ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("Remapping with fault address at: %@\n"), addr));
451 size_t const current_map_size =
452 ACE_Utils::truncate_cast<size_t> (ACE_OS::filesize (this->mmap_.handle ()));
453 // ACE_OS::lseek (this->mmap_.handle (), 0, SEEK_END);
455 if (!(addr < (void *) ((char *) this->mmap_.addr () + current_map_size)
456 && addr >= this->mmap_.addr ()))
457 return -1;
459 // Extend the mapping to cover the size of the backing store.
460 return this->map_file (current_map_size);
463 ACE_MMAP_Memory_Pool_Options::ACE_MMAP_Memory_Pool_Options (
464 const void *base_addr,
465 int use_fixed_addr,
466 bool write_each_page,
467 size_t minimum_bytes,
468 u_int flags,
469 bool guess_on_fault,
470 LPSECURITY_ATTRIBUTES sa,
471 mode_t file_mode,
472 bool unique,
473 bool install_signal_handler)
474 : base_addr_ (base_addr),
475 use_fixed_addr_ (use_fixed_addr),
476 write_each_page_ (write_each_page),
477 minimum_bytes_ (minimum_bytes),
478 flags_ (flags),
479 guess_on_fault_ (guess_on_fault),
480 sa_ (sa),
481 file_mode_ (file_mode),
482 unique_ (unique),
483 install_signal_handler_ (install_signal_handler)
485 ACE_TRACE ("ACE_MMAP_Memory_Pool_Options::ACE_MMAP_Memory_Pool_Options");
486 // for backwards compatibility
487 if (base_addr_ == 0 && use_fixed_addr_ == ALWAYS_FIXED)
488 use_fixed_addr_ = FIRSTCALL_FIXED;
491 #if !defined (ACE_WIN32)
493 ACE_MMAP_Memory_Pool::handle_signal (int signum, siginfo_t *siginfo, ucontext_t *)
495 if (signum != SIGSEGV)
496 return -1;
497 #if 0
498 else
499 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) received %S\n"), signum));
500 #endif
501 // ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) new mapping address = %@\n"), (char *) this->base_addr_ + current_map_size));
503 #if defined (ACE_HAS_SIGINFO_T) && !defined (ACE_LACKS_SI_ADDR)
504 // Make sure that the pointer causing the problem is within the
505 // range of the backing store.
507 if (siginfo != 0)
509 // ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) si_signo = %d, si_code = %d, addr = %@\n"), siginfo->si_signo, siginfo->si_code, siginfo->si_addr));
510 if (this->remap ((void *) siginfo->si_addr) == -1)
511 return -1;
512 // ACELIB_ERROR_RETURN ((LM_ERROR, "(%P|%t) address %@ out of range\n",
513 // siginfo->si_addr), -1);
514 return 0;
516 #else
517 ACE_UNUSED_ARG(siginfo);
518 #endif /* ACE_HAS_SIGINFO_T && !defined ACE_LACKS_SI_ADDR */
519 // If guess_on_fault_ is true, then we want to try to remap without
520 // knowing the faulting address. guess_on_fault_ can only be true
521 // on platforms that do not provide the faulting address through
522 // signals or exceptions. We check to see if the mapping is up to
523 // date. If it is, then this fault isn't due to this mapping and we
524 // pass it on.
525 if (guess_on_fault_)
527 // Check if the current mapping is up to date.
528 size_t const current_map_size =
529 ACE_Utils::truncate_cast<size_t> (ACE_OS::filesize (this->mmap_.handle ()));
531 if (static_cast<size_t> (current_map_size) == this->mmap_.size ())
533 // The mapping is up to date so this really is a bad
534 // address. Thus, remove current signal handler so process
535 // will fail with default action and core file will be
536 // written.
537 this->signal_handler_.remove_handler (SIGSEGV);
538 return 0;
541 // Extend the mapping to cover the size of the backing store.
542 return this->map_file (current_map_size);
544 else
545 return -1;
547 #endif
549 void *
550 ACE_MMAP_Memory_Pool::base_addr (void) const
552 ACE_TRACE ("ACE_MMAP_Memory_Pool::base_addr");
553 return this->base_addr_;
556 size_t
557 ACE_MMAP_Memory_Pool::round_up (size_t nbytes)
559 ACE_TRACE ("ACE_MMAP_Memory_Pool::round_up");
560 return ACE::round_to_pagesize (nbytes);
563 ACE_ALLOC_HOOK_DEFINE(ACE_Lite_MMAP_Memory_Pool)
565 ACE_Lite_MMAP_Memory_Pool::ACE_Lite_MMAP_Memory_Pool (const ACE_TCHAR *backing_store_name,
566 const OPTIONS *options)
567 : ACE_MMAP_Memory_Pool (backing_store_name, options)
569 ACE_TRACE ("ACE_Lite_MMAP_Memory_Pool::ACE_Lite_MMAP_Memory_Pool");
572 ACE_Lite_MMAP_Memory_Pool::~ACE_Lite_MMAP_Memory_Pool (void)
577 ACE_Lite_MMAP_Memory_Pool::sync (size_t, int)
579 ACE_TRACE ("ACE_Lite_MMAP_Memory_Pool::sync");
580 return 0;
584 ACE_Lite_MMAP_Memory_Pool::sync (int)
586 ACE_TRACE ("ACE_Lite_MMAP_Memory_Pool::sync");
587 return 0;
591 ACE_Lite_MMAP_Memory_Pool::sync (void *, size_t, int)
593 ACE_TRACE ("ACE_Lite_MMAP_Memory_Pool::sync");
594 return 0;
597 ACE_END_VERSIONED_NAMESPACE_DECL