00001
00002
00003
00004 #include "ace/MMAP_Memory_Pool.h"
00005 #include "ace/OS_NS_sys_mman.h"
00006 #include "ace/OS_NS_unistd.h"
00007 #include "ace/OS_NS_string.h"
00008 #include "ace/OS_NS_sys_stat.h"
00009 #include "ace/Log_Msg.h"
00010 #include "ace/Truncate.h"
00011
00012 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
00013 #include "ace/Based_Pointer_T.h"
00014 #include "ace/Based_Pointer_Repository.h"
00015 #endif
00016
00017 #if !defined (__ACE_INLINE__)
00018 #include "ace/MMAP_Memory_Pool.inl"
00019 #endif
00020
00021 ACE_RCSID(ace,
00022 MMAP_Memory_Pool,
00023 "$Id: MMAP_Memory_Pool.cpp 81704 2008-05-15 12:53:03Z mesnier_p $")
00024
00025 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00026
00027 ACE_ALLOC_HOOK_DEFINE(ACE_MMAP_Memory_Pool)
00028
00029 void
00030 ACE_MMAP_Memory_Pool::dump (void) const
00031 {
00032 #if defined (ACE_HAS_DUMP)
00033 ACE_TRACE ("ACE_MMAP_Memory_Pool::dump");
00034 #endif
00035 }
00036
00037 int
00038 ACE_MMAP_Memory_Pool::release (int destroy)
00039 {
00040 ACE_TRACE ("ACE_MMAP_Memory_Pool::release");
00041
00042 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
00043 ACE_BASED_POINTER_REPOSITORY::instance ()->unbind (this->mmap_.addr ());
00044 #endif
00045
00046 if (destroy)
00047 this->mmap_.remove ();
00048 else
00049 this->mmap_.close ();
00050 return 0;
00051 }
00052
00053 int
00054 ACE_MMAP_Memory_Pool::sync (size_t len, int flags)
00055 {
00056 ACE_TRACE ("ACE_MMAP_Memory_Pool::sync");
00057
00058 return this->mmap_.sync (len, flags);
00059 }
00060
00061 int
00062 ACE_MMAP_Memory_Pool::sync (int flags)
00063 {
00064 ACE_TRACE ("ACE_MMAP_Memory_Pool::sync");
00065
00066 size_t const len = ACE_Utils::truncate_cast<size_t> (
00067 ACE_OS::lseek (this->mmap_.handle (), 0, SEEK_END));
00068
00069 return this->mmap_.sync (len, flags);
00070 }
00071
00072
00073
00074
00075 int
00076 ACE_MMAP_Memory_Pool::sync (void *addr, size_t len, int flags)
00077 {
00078 ACE_TRACE ("ACE_MMAP_Memory_Pool::sync");
00079 return ACE_OS::msync (addr, len, flags);
00080 }
00081
00082
00083
00084
00085
00086 int
00087 ACE_MMAP_Memory_Pool::protect (size_t len, int prot)
00088 {
00089 ACE_TRACE ("ACE_MMAP_Memory_Pool::protect");
00090
00091 return this->mmap_.protect (len, prot);
00092 }
00093
00094 int
00095 ACE_MMAP_Memory_Pool::protect (int prot)
00096 {
00097 ACE_TRACE ("ACE_MMAP_Memory_Pool::protect");
00098
00099 size_t const len = ACE_Utils::truncate_cast<size_t> (
00100 ACE_OS::lseek (this->mmap_.handle (), 0, SEEK_END));
00101
00102 return this->mmap_.protect (len, prot);
00103 }
00104
00105
00106
00107
00108
00109 int
00110 ACE_MMAP_Memory_Pool::protect (void *addr, size_t len, int prot)
00111 {
00112 ACE_TRACE ("ACE_MMAP_Memory_Pool::protect");
00113 return ACE_OS::mprotect (addr, len, prot);
00114 }
00115
00116 ACE_MMAP_Memory_Pool::ACE_MMAP_Memory_Pool (
00117 const ACE_TCHAR *backing_store_name,
00118 const OPTIONS *options)
00119 : base_addr_ (0),
00120 use_fixed_addr_(0),
00121 flags_ (MAP_SHARED),
00122 write_each_page_ (false),
00123 minimum_bytes_ (0),
00124 sa_ (0),
00125 file_mode_ (ACE_DEFAULT_FILE_PERMS),
00126 install_signal_handler_ (true)
00127 {
00128 ACE_TRACE ("ACE_MMAP_Memory_Pool::ACE_MMAP_Memory_Pool");
00129
00130 #if (defined (ACE_HAS_SIGINFO_T) && !defined (ACE_LACKS_SI_ADDR)) || defined (ACE_WIN32)
00131
00132 guess_on_fault_ = false;
00133 #else
00134
00135
00136 if (options)
00137 guess_on_fault_ = options->guess_on_fault_;
00138 else
00139
00140 guess_on_fault_ = true;
00141 #endif
00142
00143
00144 if (options)
00145 {
00146 if (options->flags_ != 0)
00147 this->flags_ = options->flags_;
00148 use_fixed_addr_ = options->use_fixed_addr_;
00149
00150 if (use_fixed_addr_ == ACE_MMAP_Memory_Pool_Options::ALWAYS_FIXED)
00151 {
00152 this->base_addr_ = const_cast<void *> (options->base_addr_);
00153 ACE_SET_BITS (flags_, MAP_FIXED);
00154 }
00155 this->write_each_page_ = options->write_each_page_;
00156 this->minimum_bytes_ = options->minimum_bytes_;
00157 if (options->sa_ != 0)
00158 this->sa_ = options->sa_;
00159 this->file_mode_ = options->file_mode_;
00160 this->install_signal_handler_ = options->install_signal_handler_;
00161 }
00162
00163 if (backing_store_name == 0)
00164 {
00165
00166
00167 #if defined (ACE_DEFAULT_BACKING_STORE)
00168
00169 ACE_OS::strcpy (this->backing_store_name_,
00170 ACE_DEFAULT_BACKING_STORE);
00171 #else
00172 if (ACE::get_temp_dir (this->backing_store_name_,
00173 MAXPATHLEN - 17) == -1)
00174
00175 {
00176 ACE_ERROR ((LM_ERROR,
00177 ACE_TEXT ("Temporary path too long, ")
00178 ACE_TEXT ("defaulting to current directory\n")));
00179 this->backing_store_name_[0] = 0;
00180 }
00181
00182
00183 ACE_OS::strcat (this->backing_store_name_,
00184 ACE_TEXT ("ace-malloc-XXXXXX"));
00185
00186
00187 if (options && options->unique_)
00188 ACE_OS::mktemp(this->backing_store_name_);
00189 #endif
00190 }
00191 else
00192 ACE_OS::strsncpy (this->backing_store_name_,
00193 backing_store_name,
00194 (sizeof this->backing_store_name_ / sizeof (ACE_TCHAR)));
00195
00196 #if !defined (ACE_WIN32)
00197 if (this->install_signal_handler_)
00198 {
00199 if (this->signal_handler_.register_handler (SIGSEGV, this) == -1)
00200 ACE_ERROR ((LM_ERROR,
00201 "%p\n", this->backing_store_name_));
00202 }
00203 #endif
00204 }
00205
00206 ACE_MMAP_Memory_Pool::~ACE_MMAP_Memory_Pool (void)
00207 {
00208 }
00209
00210
00211
00212 int
00213 ACE_MMAP_Memory_Pool::commit_backing_store_name (size_t rounded_bytes,
00214 size_t & map_size)
00215 {
00216 ACE_TRACE ("ACE_MMAP_Memory_Pool::commit_backing_store_name");
00217
00218 #if defined (__Lynx__)
00219 map_size = rounded_bytes;
00220 #else
00221 size_t seek_len;
00222
00223 if (this->write_each_page_)
00224
00225
00226 seek_len = this->round_up (1);
00227 else
00228
00229 seek_len = rounded_bytes;
00230
00231
00232
00233
00234
00235 for (size_t cur_block = 0;
00236 cur_block < rounded_bytes;
00237 cur_block += seek_len)
00238 {
00239 map_size =
00240 ACE_Utils::truncate_cast<size_t> (
00241 ACE_OS::lseek (this->mmap_.handle (),
00242 static_cast<ACE_OFF_T> (seek_len - 1),
00243 SEEK_END));
00244
00245 if (map_size == static_cast<size_t> (-1)
00246 || ACE_OS::write (this->mmap_.handle (),
00247 "",
00248 1) == -1)
00249 ACE_ERROR_RETURN ((LM_ERROR,
00250 ACE_TEXT ("(%P|%t) %p\n"),
00251 this->backing_store_name_),
00252 -1);
00253 }
00254
00255 #if defined (ACE_OPENVMS)
00256 ::fsync(this->mmap_.handle());
00257 #endif
00258
00259
00260 ++map_size;
00261 #endif
00262 return 0;
00263 }
00264
00265
00266
00267 int
00268 ACE_MMAP_Memory_Pool::map_file (size_t map_size)
00269 {
00270 ACE_TRACE ("ACE_MMAP_Memory_Pool::map_file");
00271 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
00272 void* obase_addr = this->base_addr_;
00273 #endif
00274
00275
00276 this->mmap_.unmap ();
00277
00278 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
00279 if (use_fixed_addr_ == ACE_MMAP_Memory_Pool_Options::NEVER_FIXED)
00280 this->base_addr_ = 0;
00281 #endif
00282
00283
00284
00285
00286
00287 if (this->mmap_.map (map_size,
00288 PROT_RDWR,
00289 this->flags_,
00290 this->base_addr_,
00291 0,
00292 this->sa_) == -1
00293 || this->base_addr_ != 0
00294 #ifdef ACE_HAS_WINCE
00295 && this->mmap_.addr () == 0)
00296 #else
00297 && this->mmap_.addr () != this->base_addr_)
00298 #endif
00299 {
00300 #if 0
00301 ACE_ERROR ((LM_ERROR,
00302 ACE_TEXT ("(%P|%t) addr = %@, base_addr = %@, map_size = %B, %p\n"),
00303 this->mmap_.addr (),
00304 this->base_addr_,
00305 map_size,
00306 this->backing_store_name_));
00307 #endif
00308 return -1;
00309 }
00310 else
00311 {
00312 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
00313 this->base_addr_ = this->mmap_.addr ();
00314 if(obase_addr && this->base_addr_ != obase_addr)
00315 ACE_BASED_POINTER_REPOSITORY::instance ()->unbind (obase_addr);
00316 ACE_BASED_POINTER_REPOSITORY::instance ()->bind (this->base_addr_,
00317 map_size);
00318 #endif
00319 return 0;
00320 }
00321 }
00322
00323
00324
00325
00326
00327 void *
00328 ACE_MMAP_Memory_Pool::acquire (size_t nbytes,
00329 size_t &rounded_bytes)
00330 {
00331 ACE_TRACE ("ACE_MMAP_Memory_Pool::acquire");
00332 rounded_bytes = this->round_up (nbytes);
00333
00334
00335
00336
00337 size_t map_size;
00338
00339 if (this->commit_backing_store_name (rounded_bytes,
00340 map_size) == -1)
00341 return 0;
00342 else if (this->map_file (map_size) == -1)
00343 return 0;
00344
00345
00346
00347
00348
00349 return (void *) ((char *) this->mmap_.addr () + (this->mmap_.size () - rounded_bytes));
00350 }
00351
00352
00353
00354 void *
00355 ACE_MMAP_Memory_Pool::init_acquire (size_t nbytes,
00356 size_t &rounded_bytes,
00357 int &first_time)
00358 {
00359 ACE_TRACE ("ACE_MMAP_Memory_Pool::init_acquire");
00360
00361 first_time = 0;
00362
00363 if (nbytes < static_cast <size_t> (this->minimum_bytes_))
00364 nbytes = static_cast <size_t> (this->minimum_bytes_);
00365
00366 if (this->mmap_.open (this->backing_store_name_,
00367 O_RDWR | O_CREAT | O_TRUNC | O_EXCL,
00368 this->file_mode_, this->sa_) != -1)
00369 {
00370
00371 first_time = 1;
00372
00373 void *result = this->acquire (nbytes, rounded_bytes);
00374
00375
00376 if (use_fixed_addr_ == ACE_MMAP_Memory_Pool_Options::FIRSTCALL_FIXED)
00377 {
00378 ACE_SET_BITS (flags_, MAP_FIXED);
00379 }
00380 return result;
00381 }
00382 else if (errno == EEXIST)
00383 {
00384 errno = 0;
00385
00386 if (this->mmap_.map (this->backing_store_name_,
00387 static_cast<size_t> (-1),
00388 O_RDWR,
00389 this->file_mode_,
00390 PROT_RDWR,
00391 this->flags_,
00392 this->base_addr_,
00393 0,
00394 this->sa_) == -1)
00395 ACE_ERROR_RETURN ((LM_ERROR,
00396 ACE_TEXT ("%p\n"),
00397 ACE_TEXT ("MMAP_Memory_Pool::init_acquire, EEXIST")),
00398 0);
00399
00400
00401 if (use_fixed_addr_ == ACE_MMAP_Memory_Pool_Options::FIRSTCALL_FIXED)
00402 {
00403 ACE_SET_BITS (flags_, MAP_FIXED);
00404 }
00405 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
00406
00407 ACE_BASED_POINTER_REPOSITORY::instance ()->bind (this->mmap_.addr(),
00408 this->mmap_.size());
00409 #endif
00410
00411 return this->mmap_.addr ();
00412 }
00413 else
00414 ACE_ERROR_RETURN ((LM_ERROR,
00415 ACE_TEXT ("%p\n"),
00416 ACE_TEXT ("MMAP_Memory_Pool::init_acquire")),
00417 0);
00418 }
00419
00420 #if defined (ACE_WIN32)
00421 int
00422 ACE_MMAP_Memory_Pool::seh_selector (void *ep)
00423 {
00424 DWORD const ecode = ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionCode;
00425
00426 if (ecode == EXCEPTION_ACCESS_VIOLATION)
00427 {
00428 void * fault_addr = (void *)
00429 ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionInformation[1];
00430
00431 if (this->remap (fault_addr) == 0)
00432 return 1;
00433 }
00434
00435 return 0;
00436 }
00437 #endif
00438
00439 int
00440 ACE_MMAP_Memory_Pool::remap (void *addr)
00441 {
00442 ACE_TRACE ("ACE_MMAP_Memory_Pool::remap");
00443
00444 size_t const current_map_size =
00445 ACE_Utils::truncate_cast<size_t> (ACE_OS::filesize (this->mmap_.handle ()));
00446
00447
00448 if (!(addr < (void *) ((char *) this->mmap_.addr () + current_map_size)
00449 && addr >= this->mmap_.addr ()))
00450 return -1;
00451
00452
00453 return this->map_file (current_map_size);
00454 }
00455
00456 ACE_MMAP_Memory_Pool_Options::ACE_MMAP_Memory_Pool_Options (
00457 const void *base_addr,
00458 int use_fixed_addr,
00459 bool write_each_page,
00460 size_t minimum_bytes,
00461 u_int flags,
00462 bool guess_on_fault,
00463 LPSECURITY_ATTRIBUTES sa,
00464 mode_t file_mode,
00465 bool unique,
00466 bool install_signal_handler)
00467 : base_addr_ (base_addr),
00468 use_fixed_addr_ (use_fixed_addr),
00469 write_each_page_ (write_each_page),
00470 minimum_bytes_ (minimum_bytes),
00471 flags_ (flags),
00472 guess_on_fault_ (guess_on_fault),
00473 sa_ (sa),
00474 file_mode_ (file_mode),
00475 unique_ (unique),
00476 install_signal_handler_ (install_signal_handler)
00477 {
00478 ACE_TRACE ("ACE_MMAP_Memory_Pool_Options::ACE_MMAP_Memory_Pool_Options");
00479
00480 if (base_addr_ == 0 && use_fixed_addr_ == ALWAYS_FIXED)
00481 use_fixed_addr_ = FIRSTCALL_FIXED;
00482 }
00483
00484 #if !defined (ACE_WIN32)
00485 int
00486 ACE_MMAP_Memory_Pool::handle_signal (int signum, siginfo_t *siginfo, ucontext_t *)
00487 {
00488 if (signum != SIGSEGV)
00489 return -1;
00490 #if 0
00491 else
00492 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) received %S\n"), signum));
00493 #endif
00494
00495
00496 #if defined (ACE_HAS_SIGINFO_T) && !defined (ACE_LACKS_SI_ADDR)
00497
00498
00499
00500 if (siginfo != 0)
00501 {
00502
00503 if (this->remap ((void *) siginfo->si_addr) == -1)
00504 return -1;
00505
00506
00507 return 0;
00508 }
00509 #else
00510 ACE_UNUSED_ARG(siginfo);
00511 #endif
00512
00513
00514
00515
00516
00517
00518 if (guess_on_fault_)
00519 {
00520
00521 size_t const current_map_size =
00522 ACE_Utils::truncate_cast<size_t> (ACE_OS::filesize (this->mmap_.handle ()));
00523
00524 if (static_cast<size_t> (current_map_size) == this->mmap_.size ())
00525 {
00526
00527
00528
00529
00530 this->signal_handler_.remove_handler (SIGSEGV);
00531 return 0;
00532 }
00533
00534
00535 return this->map_file (current_map_size);
00536 }
00537 else
00538 return -1;
00539 }
00540 #endif
00541
00542 void *
00543 ACE_MMAP_Memory_Pool::base_addr (void) const
00544 {
00545 ACE_TRACE ("ACE_MMAP_Memory_Pool::base_addr");
00546 return this->base_addr_;
00547 }
00548
00549 size_t
00550 ACE_MMAP_Memory_Pool::round_up (size_t nbytes)
00551 {
00552 ACE_TRACE ("ACE_MMAP_Memory_Pool::round_up");
00553 return ACE::round_to_pagesize (nbytes);
00554 }
00555
00556 ACE_ALLOC_HOOK_DEFINE(ACE_Lite_MMAP_Memory_Pool)
00557
00558 ACE_Lite_MMAP_Memory_Pool::ACE_Lite_MMAP_Memory_Pool (const ACE_TCHAR *backing_store_name,
00559 const OPTIONS *options)
00560 : ACE_MMAP_Memory_Pool (backing_store_name, options)
00561 {
00562 ACE_TRACE ("ACE_Lite_MMAP_Memory_Pool::ACE_Lite_MMAP_Memory_Pool");
00563 }
00564
00565 ACE_Lite_MMAP_Memory_Pool::~ACE_Lite_MMAP_Memory_Pool (void)
00566 {
00567 }
00568
00569 int
00570 ACE_Lite_MMAP_Memory_Pool::sync (size_t, int)
00571 {
00572 ACE_TRACE ("ACE_Lite_MMAP_Memory_Pool::sync");
00573 return 0;
00574 }
00575
00576 int
00577 ACE_Lite_MMAP_Memory_Pool::sync (int)
00578 {
00579 ACE_TRACE ("ACE_Lite_MMAP_Memory_Pool::sync");
00580 return 0;
00581 }
00582
00583 int
00584 ACE_Lite_MMAP_Memory_Pool::sync (void *, size_t, int)
00585 {
00586 ACE_TRACE ("ACE_Lite_MMAP_Memory_Pool::sync");
00587 return 0;
00588 }
00589
00590 ACE_END_VERSIONED_NAMESPACE_DECL