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