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