Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

Memory_Pool.cpp

Go to the documentation of this file.
00001 #include "ace_pch.h"
00002 // $Id: Memory_Pool.cpp,v 1.1.1.4.2.2 2003/04/16 16:41:14 taoadmin Exp $
00003 
00004 // Memory_Pool.cpp
00005 #include "ace/Memory_Pool.h"
00006 #include "ace/Log_Msg.h"
00007 
00008 #if !defined (__ACE_INLINE__)
00009 #include "ace/Memory_Pool.i"
00010 #endif /* __ACE_INLINE__ */
00011 
00012 #include "ace/Auto_Ptr.h"
00013 
00014 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
00015 #include "ace/Based_Pointer_T.h"
00016 #include "ace/Based_Pointer_Repository.h"
00017 #endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1  */
00018 
00019 ACE_RCSID(ace, Memory_Pool, "Memory_Pool.cpp,v 4.79 2001/09/02 22:33:16 schmidt Exp")
00020 
00021 ACE_ALLOC_HOOK_DEFINE(ACE_Local_Memory_Pool)
00022 
00023 void
00024 ACE_Local_Memory_Pool::dump (void) const
00025 {
00026   ACE_TRACE ("ACE_Local_Memory_Pool::dump");
00027 }
00028 
00029 ACE_Local_Memory_Pool::ACE_Local_Memory_Pool (const ACE_TCHAR *,
00030                                               const OPTIONS *)
00031 {
00032   ACE_TRACE ("ACE_Local_Memory_Pool::ACE_Local_Memory_Pool");
00033 }
00034 
00035 void *
00036 ACE_Local_Memory_Pool::acquire (size_t nbytes,
00037                                 size_t &rounded_bytes)
00038 {
00039   ACE_TRACE ("ACE_Local_Memory_Pool::acquire");
00040   rounded_bytes = this->round_up (nbytes);
00041 
00042   char *temp = 0;
00043   ACE_NEW_RETURN (temp,
00044                   char[rounded_bytes],
00045                   0);
00046 
00047   ACE_Auto_Basic_Array_Ptr<char> cp (temp);
00048 
00049   if (this->allocated_chunks_.insert (cp.get ()) != 0)
00050     ACE_ERROR_RETURN ((LM_ERROR,
00051                        ACE_LIB_TEXT ("(%P|%t) insertion into set failed\n")),
00052                       0);
00053 
00054   return cp.release ();
00055 }
00056 
00057 int
00058 ACE_Local_Memory_Pool::release (int)
00059 {
00060   ACE_TRACE ("ACE_Local_Memory_Pool::release");
00061 
00062   // Zap the memory we allocated.
00063   for (ACE_Unbounded_Set<char *>::iterator i = this->allocated_chunks_.begin ();
00064        i != this->allocated_chunks_.end ();
00065        ++i)
00066     delete [] *i;
00067   this->allocated_chunks_.reset ();
00068   return 0;
00069 }
00070 
00071 #if defined (ACE_WIN32)
00072 int
00073 ACE_Local_Memory_Pool::seh_selector (void *)
00074 {
00075   return 0;
00076   // Continue propagate the structural exception up.
00077 }
00078 #endif /* ACE_WIN32 */
00079 
00080 int
00081 ACE_Local_Memory_Pool::remap (void *)
00082 {
00083   return 0;
00084   // Not much can be done.
00085 }
00086 
00087 ACE_ALLOC_HOOK_DEFINE(ACE_MMAP_Memory_Pool)
00088 
00089 void
00090 ACE_MMAP_Memory_Pool::dump (void) const
00091 {
00092   ACE_TRACE ("ACE_MMAP_Memory_Pool::dump");
00093 }
00094 
00095 int
00096 ACE_MMAP_Memory_Pool::release (int destroy)
00097 {
00098   ACE_TRACE ("ACE_MMAP_Memory_Pool::release");
00099 
00100 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
00101   ACE_BASED_POINTER_REPOSITORY::instance ()->unbind (this->mmap_.addr ());
00102 #endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
00103 
00104   if (destroy)
00105   this->mmap_.remove ();
00106   else
00107     this->mmap_.close ();
00108   return 0;
00109 }
00110 
00111 int
00112 ACE_MMAP_Memory_Pool::sync (ssize_t len, int flags)
00113 {
00114   ACE_TRACE ("ACE_MMAP_Memory_Pool::sync");
00115 
00116   if (len < 0)
00117     len = ACE_OS::lseek (this->mmap_.handle (), 0, SEEK_END);
00118 
00119   return this->mmap_.sync (len, flags);
00120 }
00121 
00122 // Sync <len> bytes of the memory region to the backing store starting
00123 // at <addr_>.
00124 
00125 int
00126 ACE_MMAP_Memory_Pool::sync (void *addr, size_t len, int flags)
00127 {
00128   ACE_TRACE ("ACE_MMAP_Memory_Pool::sync");
00129   return ACE_OS::msync (addr, len, flags);
00130 }
00131 
00132 // Change the protection of the pages of the mapped region to <prot>
00133 // starting at <this->base_addr_> up to <len> bytes.  If <len> == -1
00134 // then change protection of all pages in the mapped region.
00135 
00136 int
00137 ACE_MMAP_Memory_Pool::protect (ssize_t len, int prot)
00138 {
00139   ACE_TRACE ("ACE_MMAP_Memory_Pool::protect");
00140 
00141   if (len < 0)
00142     len = ACE_OS::lseek (this->mmap_.handle (), 0, SEEK_END);
00143 
00144   return this->mmap_.protect (len, prot);
00145 }
00146 
00147 // Change the protection of the pages of the mapped region to <prot>
00148 // starting at <addr> up to <len> bytes.
00149 
00150 int
00151 ACE_MMAP_Memory_Pool::protect (void *addr, size_t len, int prot)
00152 {
00153   ACE_TRACE ("ACE_MMAP_Memory_Pool::protect");
00154   return ACE_OS::mprotect (addr, len, prot);
00155 }
00156 
00157 ACE_MMAP_Memory_Pool::ACE_MMAP_Memory_Pool (const ACE_TCHAR *backing_store_name,
00158                                             const OPTIONS *options)
00159   : base_addr_ (0),
00160     use_fixed_addr_(0),
00161     flags_ (MAP_SHARED),
00162     write_each_page_ (0),
00163     minimum_bytes_ (0),
00164     sa_ (0),
00165     file_mode_ (ACE_DEFAULT_FILE_PERMS)
00166 {
00167   ACE_TRACE ("ACE_MMAP_Memory_Pool::ACE_MMAP_Memory_Pool");
00168 
00169 #if (defined (ACE_HAS_SIGINFO_T) && !defined (ACE_LACKS_SI_ADDR)) || defined (ACE_WIN32)
00170       // For plaforms that give the faulting address.
00171       guess_on_fault_ = 0;
00172 #else
00173       // For plaforms that do NOT give the faulting address, let the
00174       // options decide whether to guess or not.
00175       if (options)
00176         guess_on_fault_ = options->guess_on_fault_;
00177       else
00178         // If no options are specified, default to true.
00179         guess_on_fault_ = 1;
00180 #endif /* (defined (ACE_HAS_SIGINFO_T) && !defined (ACE_LACKS_SI_ADDR)) || defined (ACE_WIN32) */
00181 
00182   // Only change the defaults if <options> != 0.
00183   if (options)
00184     {
00185       if (options->flags_ != 0)
00186         this->flags_ = options->flags_;
00187       use_fixed_addr_ = options->use_fixed_addr_;
00188 
00189       if (use_fixed_addr_ == ACE_MMAP_Memory_Pool_Options::ALWAYS_FIXED)
00190         {
00191           this->base_addr_ = ACE_const_cast (void *, options->base_addr_);
00192           ACE_SET_BITS (flags_, MAP_FIXED);
00193         }
00194       this->write_each_page_ = options->write_each_page_;
00195       this->minimum_bytes_ = options->minimum_bytes_;
00196       if (options->sa_ != 0)
00197         this->sa_ = options->sa_;
00198       this->file_mode_ = options->file_mode_;
00199     }
00200 
00201   if (backing_store_name == 0)
00202     {
00203       // Only create a new unique filename for the backing store file
00204       // if the user didn't supply one...
00205 #if defined (ACE_DEFAULT_BACKING_STORE)
00206       // Create a temporary file.
00207       ACE_OS::strcpy (this->backing_store_name_,
00208                       ACE_DEFAULT_BACKING_STORE);
00209 #else /* ACE_DEFAULT_BACKING_STORE */
00210       if (ACE_Lib_Find::get_temp_dir (this->backing_store_name_,
00211                                       MAXPATHLEN - 17) == -1)
00212         // -17 for ace-malloc-XXXXXX
00213         {
00214           ACE_ERROR ((LM_ERROR,
00215                       ACE_LIB_TEXT ("Temporary path too long, ")
00216                       ACE_LIB_TEXT ("defaulting to current directory\n")));
00217           this->backing_store_name_[0] = 0;
00218         }
00219 
00220       // Add the filename to the end
00221       ACE_OS::strcat (this->backing_store_name_,
00222                       ACE_LIB_TEXT ("ace-malloc-XXXXXX"));
00223 
00224 #endif /* ACE_DEFAULT_BACKING_STORE */
00225     }
00226   else
00227     ACE_OS::strsncpy (this->backing_store_name_,
00228                       backing_store_name,
00229                       (sizeof this->backing_store_name_ / sizeof (ACE_TCHAR)));
00230 
00231 #if !defined (ACE_WIN32) && !defined (CHORUS)
00232   if (this->signal_handler_.register_handler (SIGSEGV, this) == -1)
00233     ACE_ERROR ((LM_ERROR,
00234                 "%p\n", this->backing_store_name_));
00235 #endif /* ACE_WIN32 */
00236 }
00237 
00238 // Compute the new map_size of the backing store and commit the
00239 // memory.
00240 int
00241 ACE_MMAP_Memory_Pool::commit_backing_store_name (size_t rounded_bytes,
00242                                                  off_t &map_size)
00243 {
00244   ACE_TRACE ("ACE_MMAP_Memory_Pool::commit_backing_store_name");
00245 
00246 #if defined (CHORUS)
00247   map_size = rounded_bytes;
00248 #else
00249   size_t seek_len;
00250 
00251   if (this->write_each_page_)
00252     // Write to the end of every block to ensure that we have enough
00253     // space in the backing store.
00254     seek_len = this->round_up (1); // round_up(1) is one page.
00255   else
00256     // We're willing to risk it all in the name of efficiency...
00257     seek_len = rounded_bytes;
00258 
00259   // The following loop will execute multiple times (if
00260   // this->write_each_page == 1) or just once (if
00261   // this->write_each_page == 0).
00262 
00263   for (size_t cur_block = 0;
00264        cur_block < rounded_bytes;
00265        cur_block += seek_len)
00266     {
00267       map_size = ACE_OS::lseek (this->mmap_.handle (),
00268                                 ACE_static_cast (off_t, seek_len - 1),
00269                                 SEEK_END);
00270 
00271       if (map_size == -1
00272           || ACE_OS::write (this->mmap_.handle (),
00273                             "",
00274                             1) == -1)
00275         ACE_ERROR_RETURN ((LM_ERROR,
00276                            ACE_LIB_TEXT ("(%P|%t) %p\n"),
00277                            this->backing_store_name_),
00278                           -1);
00279     }
00280 
00281   // Increment by one to put us at the beginning of the next chunk...
00282   map_size++;
00283 #endif /* CHORUS */
00284   return 0;
00285 }
00286 
00287 // Memory map the file up to <map_size> bytes.
00288 
00289 int
00290 ACE_MMAP_Memory_Pool::map_file (off_t map_size)
00291 {
00292   ACE_TRACE ("ACE_MMAP_Memory_Pool::map_file");
00293 
00294   // Unmap the existing mapping.
00295   this->mmap_.unmap ();
00296 
00297 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
00298   if(use_fixed_addr_ == ACE_MMAP_Memory_Pool_Options::NEVER_FIXED)
00299     this->base_addr_ = 0;
00300 #endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
00301 
00302   // Remap the file.
00303   if (this->mmap_.map (map_size,
00304                        PROT_RDWR,
00305                        this->flags_,
00306                        this->base_addr_,
00307                        0,
00308                        this->sa_) == -1
00309       || this->base_addr_ != 0
00310 #ifdef ACE_HAS_WINCE
00311       && this->mmap_.addr () == 0)  // WinCE does not allow users to specify alloc addr.
00312 #else
00313       && this->mmap_.addr () != this->base_addr_)
00314 #endif  // ACE_HAS_WINCE
00315     {
00316 #if 0
00317       ACE_ERROR ((LM_ERROR,
00318                   ACE_LIB_TEXT ("(%P|%t) addr = %u, base_addr = %u, map_size = %u, %p\n"),
00319                   this->mmap_.addr (),
00320                   this->base_addr_,
00321                   map_size,
00322                   this->backing_store_name_));
00323 #endif /* 0 */
00324       return -1;
00325     }
00326   else
00327     {
00328 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
00329       this->base_addr_ = this->mmap_.addr ();
00330       ACE_BASED_POINTER_REPOSITORY::instance ()->bind (this->base_addr_,
00331                                                        map_size);
00332 #endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
00333       return 0;
00334     }
00335 }
00336 
00337 // Ask operating system for more shared memory, increasing the mapping
00338 // accordingly.  Note that this routine assumes that the appropriate
00339 // locks are held when it is called.
00340 
00341 void *
00342 ACE_MMAP_Memory_Pool::acquire (size_t nbytes,
00343                                size_t &rounded_bytes)
00344 {
00345   ACE_TRACE ("ACE_MMAP_Memory_Pool::acquire");
00346   rounded_bytes = this->round_up (nbytes);
00347 
00348   // ACE_DEBUG ((LM_DEBUG, "(%P|%t) acquiring more chunks, nbytes =
00349   // %d, rounded_bytes = %d\n", nbytes, rounded_bytes));
00350 
00351   off_t map_size;
00352 
00353   if (this->commit_backing_store_name (rounded_bytes,
00354                                        map_size) == -1)
00355     return 0;
00356   else if (this->map_file (map_size) == -1)
00357     return 0;
00358 
00359   // ACE_DEBUG ((LM_DEBUG, "(%P|%t) acquired more chunks, nbytes = %d,
00360   // rounded_bytes = %d, map_size = %d\n", nbytes, rounded_bytes,
00361   // map_size));
00362 
00363   return (void *) ((char *) this->mmap_.addr () + (this->mmap_.size () - rounded_bytes));
00364 }
00365 
00366 // Ask system for initial chunk of shared memory.
00367 
00368 void *
00369 ACE_MMAP_Memory_Pool::init_acquire (size_t nbytes,
00370                                     size_t &rounded_bytes,
00371                                     int &first_time)
00372 {
00373   ACE_TRACE ("ACE_MMAP_Memory_Pool::init_acquire");
00374 
00375   first_time = 0;
00376 
00377   if (nbytes < (size_t) this->minimum_bytes_)
00378     nbytes = this->minimum_bytes_;
00379 
00380   if (this->mmap_.open (this->backing_store_name_,
00381                         O_RDWR | O_CREAT | O_TRUNC | O_EXCL,
00382                         this->file_mode_, this->sa_) != -1)
00383     {
00384       // First time in, so need to acquire memory.
00385       first_time = 1;
00386       return this->acquire (nbytes, rounded_bytes);
00387     }
00388   else if (errno == EEXIST)
00389     {
00390       errno = 0;
00391       // Reopen file *without* using O_EXCL...
00392       if (this->mmap_.map (this->backing_store_name_,
00393 #if defined (CHORUS)
00394                            nbytes,
00395 #else
00396                            -1,
00397 #endif /* CHORUS */
00398                            O_RDWR,
00399                            this->file_mode_,
00400                            PROT_RDWR,
00401                            this->flags_,
00402                            this->base_addr_,
00403                            0,
00404                            this->sa_) == -1)
00405         ACE_ERROR_RETURN ((LM_ERROR,
00406                            ACE_LIB_TEXT ("%p\n"),
00407                            ACE_LIB_TEXT ("open")),
00408                           0);
00409 
00410       return this->mmap_.addr ();
00411     }
00412   else
00413     ACE_ERROR_RETURN ((LM_ERROR,
00414                        ACE_LIB_TEXT ("%p\n"),
00415                        ACE_LIB_TEXT ("open")),
00416                       0);
00417 }
00418 
00419 #if defined (ACE_WIN32)
00420 int
00421 ACE_MMAP_Memory_Pool::seh_selector (void *ep)
00422 {
00423   DWORD ecode = ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionCode;
00424 
00425   if (ecode == EXCEPTION_ACCESS_VIOLATION)
00426     {
00427       void * fault_addr = (void *)
00428         ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionInformation[1];
00429 
00430       if (this->remap (fault_addr) == 0)
00431         return 1;
00432     }
00433 
00434   return 0;
00435 }
00436 #endif /* ACE_WIN32 */
00437 
00438 int
00439 ACE_MMAP_Memory_Pool::remap (void *addr)
00440 {
00441   ACE_TRACE ("ACE_MMAP_Memory_Pool::remap");
00442   //  ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("Remapping with fault address at: %X\n"), addr));
00443   off_t current_map_size = ACE_OS::filesize (this->mmap_.handle ());
00444   // ACE_OS::lseek (this->mmap_.handle (), 0, SEEK_END);
00445 
00446   if (!(addr < (void *) ((char *) this->mmap_.addr () + current_map_size)
00447         && addr >= this->mmap_.addr ()))
00448     return -1;
00449 
00450   // Extend the mapping to cover the size of the backing store.
00451   return this->map_file (current_map_size);
00452 }
00453 
00454 ACE_MMAP_Memory_Pool_Options::ACE_MMAP_Memory_Pool_Options (const void *base_addr,
00455                                                             int use_fixed_addr,
00456                                                             int write_each_page,
00457                                                             off_t minimum_bytes,
00458                                                             u_int flags,
00459                                                             int guess_on_fault,
00460                                                             LPSECURITY_ATTRIBUTES sa,
00461                                                             mode_t file_mode)
00462   : base_addr_ (base_addr),
00463     use_fixed_addr_ (use_fixed_addr),
00464     write_each_page_ (write_each_page),
00465     minimum_bytes_ (minimum_bytes),
00466     flags_ (flags),
00467     guess_on_fault_ (guess_on_fault),
00468     sa_ (sa),
00469     file_mode_ (file_mode)
00470 {
00471   ACE_TRACE ("ACE_MMAP_Memory_Pool_Options::ACE_MMAP_Memory_Pool_Options");
00472   // for backwards compatability
00473   if (base_addr_ == 0 && use_fixed_addr_ == ALWAYS_FIXED)
00474     use_fixed_addr_ = FIRSTCALL_FIXED;
00475 
00476   // HP-UX 11, 64-bit bug workaround.
00477 #if defined (__hpux) && defined (__LP64__)
00478   long temp = ACE_DEFAULT_BASE_ADDRL;
00479   base_addr_ = (void *) temp;
00480 #endif /* defined (__hpux) && defined (__LP64__) */
00481 }
00482 
00483 // Handle SIGSEGV and SIGBUS signals to remap memory properly.  When a
00484 // process reads or writes to non-mapped memory a signal (SIGBUS or
00485 // SIGSEGV) will be triggered.  At that point, the ACE_Sig_Handler
00486 // (which is part of the ACE_Reactor) will catch the signal and
00487 // dispatch the handle_signal() method defined here.  If the SIGSEGV
00488 // signal occurred due to the fact that the mapping wasn't uptodate
00489 // with respect to the backing store, the handler method below will
00490 // update the mapping accordingly.  When the signal handler returns,
00491 // the instruction should be restarted and the operation should work.
00492 
00493 int
00494 ACE_MMAP_Memory_Pool::handle_signal (int signum, siginfo_t *siginfo, ucontext_t *)
00495 {
00496   if (signum != SIGSEGV)
00497     return -1;
00498   else
00499     ; // ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("(%P|%t) received %S\n"), signum));
00500 
00501   // ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("(%P|%t) new mapping address = %u\n"), (char *) this->base_addr_ + current_map_size));
00502 
00503 #if defined (ACE_HAS_SIGINFO_T) && !defined (ACE_LACKS_SI_ADDR)
00504   // Make sure that the pointer causing the problem is within the
00505   // range of the backing store.
00506 
00507   if (siginfo != 0)
00508     {
00509       // ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("(%P|%t) si_signo = %d, si_code = %d, addr = %u\n"), siginfo->si_signo, siginfo->si_code, siginfo->si_addr));
00510       if (this->remap ((void *) siginfo->si_addr) == -1)
00511         return -1;
00512       // ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) address %u out of range\n",
00513       // siginfo->si_addr), -1);
00514       return 0;
00515     }
00516 #else
00517   ACE_UNUSED_ARG(siginfo);
00518 #endif /* ACE_HAS_SIGINFO_T && !defined ACE_LACKS_SI_ADDR */
00519   // If guess_on_fault_ is true, then we want to try to remap without
00520   // knowing the faulting address.  guess_on_fault_ can only be true
00521   // on platforms that do not provide the faulting address through
00522   // signals or exceptions.  We check to see if the mapping is up to
00523   // date. If it is, then this fault isn't due to this mapping and we
00524   // pass it on.
00525   if (guess_on_fault_)
00526     {
00527       // Check if the current mapping is up to date.
00528       off_t current_map_size = ACE_OS::filesize (this->mmap_.handle ());
00529 
00530       if (ACE_static_cast (size_t, current_map_size) == this->mmap_.size ())
00531         {
00532           // The mapping is up to date so this really is a bad
00533           // address.  Thus, remove current signal handler so process
00534           // will fail with default action and core file will be
00535           // written.
00536           this->signal_handler_.remove_handler (SIGSEGV);
00537           return 0;
00538         }
00539 
00540       // Extend the mapping to cover the size of the backing store.
00541       return this->map_file (current_map_size);
00542     }
00543   else
00544     return -1;
00545 }
00546 
00547 ACE_ALLOC_HOOK_DEFINE(ACE_Lite_MMAP_Memory_Pool)
00548 
00549 ACE_Lite_MMAP_Memory_Pool::ACE_Lite_MMAP_Memory_Pool (const ACE_TCHAR *backing_store_name,
00550                                                       const OPTIONS *options)
00551   : ACE_MMAP_Memory_Pool (backing_store_name, options)
00552 {
00553   ACE_TRACE ("ACE_Lite_MMAP_Memory_Pool::ACE_Lite_MMAP_Memory_Pool");
00554 }
00555 
00556 int
00557 ACE_Lite_MMAP_Memory_Pool::sync (ssize_t, int)
00558 {
00559   ACE_TRACE ("ACE_Lite_MMAP_Memory_Pool::sync");
00560   return 0;
00561 }
00562 
00563 int
00564 ACE_Lite_MMAP_Memory_Pool::sync (void *, size_t, int)
00565 {
00566   ACE_TRACE ("ACE_Lite_MMAP_Memory_Pool::sync");
00567   return 0;
00568 }
00569 
00570 #if !defined (ACE_LACKS_SBRK)
00571 ACE_ALLOC_HOOK_DEFINE(ACE_Sbrk_Memory_Pool)
00572 
00573 // Ask system for more local memory via sbrk(2).
00574 
00575 void *
00576 ACE_Sbrk_Memory_Pool::acquire (size_t nbytes,
00577                                size_t &rounded_bytes)
00578 {
00579   ACE_TRACE ("ACE_Sbrk_Memory_Pool::acquire");
00580   rounded_bytes = this->round_up (nbytes);
00581   // ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("(%P|%t) acquiring more chunks, nbytes = %d, rounded_bytes = %d\n"), nbytes, rounded_bytes));
00582   void *cp = ACE_OS::sbrk (rounded_bytes);
00583 
00584   if (cp == MAP_FAILED)
00585     ACE_ERROR_RETURN ((LM_ERROR,
00586                        "(%P|%t) cp = %u\n",
00587                        cp),
00588                       0);
00589   else
00590     // ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("(%P|%t) acquired more chunks, nbytes = %d, rounded_bytes = %d, new break = %u\n"), nbytes, rounded_bytes, cp));
00591   return cp;
00592 }
00593 
00594 void
00595 ACE_Sbrk_Memory_Pool::dump (void) const
00596 {
00597   ACE_TRACE ("ACE_Sbrk_Memory_Pool::dump");
00598 }
00599 
00600 ACE_Sbrk_Memory_Pool::ACE_Sbrk_Memory_Pool (const ACE_TCHAR *,
00601                                             const OPTIONS *)
00602 {
00603   ACE_TRACE ("ACE_Sbrk_Memory_Pool::ACE_Sbrk_Memory_Pool");
00604 }
00605 #endif /* !ACE_LACKS_SBRK */
00606 
00607 #if !defined (ACE_LACKS_SYSV_SHMEM)
00608 ACE_ALLOC_HOOK_DEFINE(ACE_Shared_Memory_Pool)
00609 
00610 ACE_Shared_Memory_Pool_Options::ACE_Shared_Memory_Pool_Options (const char *base_addr,
00611                                                                 size_t max_segments,
00612                                                                 size_t file_perms,
00613                                                                 off_t minimum_bytes,
00614                                                                 size_t segment_size)
00615   : base_addr_ (base_addr),
00616     max_segments_ (max_segments),
00617     minimum_bytes_ (minimum_bytes),
00618     file_perms_ (file_perms),
00619     segment_size_ (segment_size)
00620 {
00621   ACE_TRACE ("ACE_Shared_Memory_Pool_Options::ACE_Shared_Memory_Pool_Options");
00622   // HP-UX 11, 64-bit bug workaround
00623 #if defined (__hpux) && defined (__LP64__)
00624   long temp = ACE_DEFAULT_BASE_ADDRL;
00625   base_addr_ = (char *) temp;
00626 #endif /* defined (__hpux) && defined (__LP64__) */
00627 }
00628 
00629 void
00630 ACE_Shared_Memory_Pool::dump (void) const
00631 {
00632   ACE_TRACE ("ACE_Shared_Memory_Pool::dump");
00633 }
00634 
00635 int
00636 ACE_Shared_Memory_Pool::in_use (off_t &offset,
00637                                 size_t &counter)
00638 {
00639   offset = 0;
00640   SHM_TABLE *st = ACE_reinterpret_cast (SHM_TABLE *,
00641                                         this->base_addr_);
00642   shmid_ds buf;
00643 
00644   for (counter = 0;
00645        counter < this->max_segments_ && st[counter].used_ == 1;
00646        counter++)
00647     {
00648       if (ACE_OS::shmctl (st[counter].shmid_, IPC_STAT, &buf) == -1)
00649         ACE_ERROR_RETURN ((LM_ERROR,
00650                            ACE_LIB_TEXT ("(%P|%t) %p\n"),
00651                            ACE_LIB_TEXT ("shmctl")),
00652                           -1);
00653       offset += buf.shm_segsz;
00654       // ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("(%P|%t) segment size = %d, offset = %d\n"), buf.shm_segsz, offset));
00655     }
00656 
00657   return 0;
00658 }
00659 
00660 int
00661 ACE_Shared_Memory_Pool::find_seg (const void* const searchPtr,
00662                                   off_t &offset,
00663                                   size_t &counter)
00664 {
00665   offset = 0;
00666   SHM_TABLE *st = ACE_reinterpret_cast (SHM_TABLE *,
00667                                         this->base_addr_);
00668   shmid_ds buf;
00669 
00670   for (counter = 0;
00671        counter < this->max_segments_
00672          && st[counter].used_ == 1;
00673        counter++)
00674     {
00675       if (ACE_OS::shmctl (st[counter].shmid_, IPC_STAT, &buf) == -1)
00676         ACE_ERROR_RETURN ((LM_ERROR,
00677                            ACE_LIB_TEXT ("(%P|%t) %p\n"),
00678                            ACE_LIB_TEXT ("shmctl")),
00679                           -1);
00680       offset += buf.shm_segsz;
00681 
00682       // If segment 'counter' starts at a location greater than the
00683       // place we are searching for. We then decrement the offset to
00684       // the start of counter-1. (flabar@vais.net)
00685       if (((ptrdiff_t) offset + (ptrdiff_t) (this->base_addr_)) > (ptrdiff_t) searchPtr)
00686         {
00687           --counter;
00688           offset -= buf.shm_segsz;
00689           return 0;
00690         }
00691       // ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("(%P|%t) segment size = %d, offset = %d\n"), buf.shm_segsz, offset));
00692     }
00693 
00694   return 0;
00695 }
00696 
00697 int
00698 ACE_Shared_Memory_Pool::commit_backing_store_name (size_t rounded_bytes,
00699                                                    off_t &offset)
00700 {
00701   ACE_TRACE ("ACE_Shared_Memory_Pool::commit_backing_store_name");
00702 
00703   size_t counter;
00704   SHM_TABLE *st = ACE_reinterpret_cast (SHM_TABLE *,
00705                                         this->base_addr_);
00706 
00707   if (this->in_use (offset, counter) == -1)
00708     return -1;
00709 
00710   if (counter == this->max_segments_)
00711     ACE_ERROR_RETURN ((LM_ERROR,
00712                       "exceeded max number of segments = %d, base = %u, offset = %u\n",
00713                        counter,
00714                        this->base_addr_,
00715                        offset),
00716                       -1);
00717   else
00718     {
00719       int shmid = ACE_OS::shmget (st[counter].key_,
00720                                   rounded_bytes,
00721                                   this->file_perms_ | IPC_CREAT | IPC_EXCL);
00722       if (shmid == -1)
00723         ACE_ERROR_RETURN ((LM_ERROR,
00724                            ACE_LIB_TEXT ("(%P|%t) %p\n"),
00725                            ACE_LIB_TEXT ("shmget")),
00726                           0);
00727       st[counter].shmid_ = shmid;
00728       st[counter].used_ = 1;
00729 
00730       void *address = (void *) (((char *) this->base_addr_) + offset);
00731       void *shmem = ACE_OS::shmat (st[counter].shmid_,
00732                                    (char *) address,
00733                                    0);
00734 
00735       if (shmem != address)
00736         ACE_ERROR_RETURN ((LM_ERROR,
00737                            "(%P|%t) %p, shmem = %u, address = %u\n",
00738                            "shmat",
00739                            shmem,
00740                            address),
00741                           0);
00742     }
00743   return 0;
00744 }
00745 
00746 // Handle SIGSEGV and SIGBUS signals to remap shared memory properly.
00747 
00748 int
00749 ACE_Shared_Memory_Pool::handle_signal (int , siginfo_t *siginfo, ucontext_t *)
00750 {
00751   ACE_TRACE ("ACE_Shared_Memory_Pool::handle_signal");
00752   // ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("signal %S occurred\n"), signum));
00753 
00754 #if defined (ACE_HAS_SIGINFO_T) && !defined (ACE_LACKS_SI_ADDR)
00755   off_t offset;
00756   // Make sure that the pointer causing the problem is within the
00757   // range of the backing store.
00758 
00759   if (siginfo != 0)
00760     {
00761       // ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("(%P|%t) si_signo = %d, si_code = %d, addr = %u\n"), siginfo->si_signo, siginfo->si_code, siginfo->si_addr));
00762       size_t counter;
00763       if (this->in_use (offset, counter) == -1)
00764         ACE_ERROR ((LM_ERROR,
00765                     ACE_LIB_TEXT ("(%P|%t) %p\n"),
00766                     ACE_LIB_TEXT ("in_use")));
00767 #if !defined(_UNICOS)
00768       else if (!(siginfo->si_code == SEGV_MAPERR
00769            && siginfo->si_addr < (((char *) this->base_addr_) + offset)
00770            && siginfo->si_addr >= ((char *) this->base_addr_)))
00771         ACE_ERROR_RETURN ((LM_ERROR,
00772                            "(%P|%t) address %u out of range\n",
00773                            siginfo->si_addr),
00774                           -1);
00775 #else /* ! _UNICOS */
00776       else if (!(siginfo->si_code == SEGV_MEMERR
00777            && siginfo->si_addr < (((unsigned long) this->base_addr_) + offset)
00778            && siginfo->si_addr >= ((unsigned long) this->base_addr_)))
00779         ACE_ERROR_RETURN ((LM_ERROR,
00780                            "(%P|%t) address %u out of range\n",
00781                            siginfo->si_addr),
00782                           -1);
00783 #endif /* ! _UNICOS */
00784     }
00785 
00786   // The above if case will check to see that the address is in the
00787   // proper range.  Therefore there is a segment out there that the
00788   // pointer wants to point into.  Find the segment that someone else
00789   // has used and attach to it (flabar@vais.net)
00790 
00791   size_t counter; // ret value to get shmid from the st table.
00792 
00793 #if !defined(_UNICOS)
00794   if (this->find_seg (siginfo->si_addr, offset, counter) == -1)
00795 #else /* ! _UNICOS */
00796   if (this->find_seg ((const void *)siginfo->si_addr, offset, counter) == -1)
00797 #endif /* ! _UNICOS */
00798       ACE_ERROR_RETURN ((LM_ERROR,
00799                          ACE_LIB_TEXT ("(%P|%t) %p\n"),
00800                          ACE_LIB_TEXT ("in_use")),
00801                         -1);
00802 
00803   void *address = (void *) (((char *) this->base_addr_) + offset);
00804   SHM_TABLE *st = ACE_reinterpret_cast (SHM_TABLE *,
00805                                         this->base_addr_);
00806 
00807   void *shmem = ACE_OS::shmat (st[counter].shmid_, (char *) address, 0);
00808 
00809   if (shmem != address)
00810       ACE_ERROR_RETURN ((LM_ERROR,
00811                          "(%P|%t) %p, shmem = %u, address = %u\n",
00812                          "shmat",
00813                          shmem,
00814                          address),
00815                         0);
00816 
00817   // NOTE: this won't work if we dont have SIGINFO_T or SI_ADDR
00818 #else
00819   ACE_UNUSED_ARG (siginfo);
00820 #endif /* ACE_HAS_SIGINFO_T && !defined (ACE_LACKS_SI_ADDR) */
00821 
00822   return 0;
00823 }
00824 
00825 ACE_Shared_Memory_Pool::ACE_Shared_Memory_Pool (const ACE_TCHAR *backing_store_name,
00826                                                 const OPTIONS *options)
00827   : base_addr_ (0),
00828     file_perms_ (ACE_DEFAULT_FILE_PERMS),
00829     max_segments_ (ACE_DEFAULT_MAX_SEGMENTS),
00830     minimum_bytes_ (0),
00831     segment_size_ (ACE_DEFAULT_SEGMENT_SIZE)
00832 {
00833   ACE_TRACE ("ACE_Shared_Memory_Pool::ACE_Shared_Memory_Pool");
00834 
00835   // Only change the defaults if <options> != 0.
00836   if (options)
00837     {
00838       this->base_addr_ =
00839         ACE_reinterpret_cast (void *,
00840                               ACE_const_cast (char *,
00841                                               options->base_addr_));
00842       this->max_segments_ = options->max_segments_;
00843       this->file_perms_ = options->file_perms_;
00844       this->minimum_bytes_ = options->minimum_bytes_;
00845       this->segment_size_ = options->segment_size_;
00846     }
00847 
00848   if (backing_store_name)
00849     {
00850       // Convert the string into a number that is used as the segment
00851       // key.
00852 
00853       int segment_key;
00854       int result = ::sscanf (backing_store_name,
00855                              "%d",
00856                              &segment_key);
00857 
00858       if (result == 0 || result == EOF)
00859         // The conversion to a number failed so hash with crc32
00860         // ACE::crc32 is also used in <SV_Semaphore_Simple>.
00861         this->base_shm_key_ = (key_t) ACE::crc32 (backing_store_name);
00862       else
00863         this->base_shm_key_ = segment_key;
00864 
00865       if (this->base_shm_key_ == IPC_PRIVATE)
00866         // Make sure that the segment can be shared between unrelated
00867         // processes.
00868         this->base_shm_key_ = ACE_DEFAULT_SHM_KEY;
00869     }
00870   else
00871     this->base_shm_key_ = ACE_DEFAULT_SHM_KEY;
00872 
00873   if (this->signal_handler_.register_handler (SIGSEGV, this) == -1)
00874     ACE_ERROR ((LM_ERROR,
00875                 ACE_LIB_TEXT ("%p\n"),
00876                 ACE_LIB_TEXT ("ACE_Sig_Handler::register_handler")));
00877 }
00878 
00879 // Ask system for more shared memory.
00880 
00881 void *
00882 ACE_Shared_Memory_Pool::acquire (size_t nbytes,
00883                                  size_t &rounded_bytes)
00884 {
00885   ACE_TRACE ("ACE_Shared_Memory_Pool::acquire");
00886 
00887   rounded_bytes = this->round_up (nbytes);
00888 
00889   // ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("(%P|%t) acquiring more chunks, nbytes = %d, rounded_bytes = %d\n"), nbytes, rounded_bytes));
00890 
00891   off_t offset;
00892 
00893   if (this->commit_backing_store_name (rounded_bytes, offset) == -1)
00894     return 0;
00895 
00896   // ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("(%P|%t) acquired more chunks, nbytes = %d, rounded_bytes = %d\n"), nbytes, rounded_bytes));
00897   return ((char *) this->base_addr_) + offset;
00898 }
00899 
00900 // Ask system for initial chunk of shared memory.
00901 
00902 void *
00903 ACE_Shared_Memory_Pool::init_acquire (size_t nbytes,
00904                                       size_t &rounded_bytes,
00905                                       int &first_time)
00906 {
00907   ACE_TRACE ("ACE_Shared_Memory_Pool::init_acquire");
00908 
00909   off_t shm_table_offset = ACE::round_to_pagesize (sizeof (SHM_TABLE));
00910   rounded_bytes = this->round_up (nbytes > (size_t) this->minimum_bytes_
00911                                   ? nbytes
00912                                   : (size_t) this->minimum_bytes_);
00913 
00914   // Acquire the semaphore to serialize initialization and prevent
00915   // race conditions.
00916 
00917   int shmid = ACE_OS::shmget (this->base_shm_key_,
00918                               rounded_bytes + shm_table_offset,
00919                               this->file_perms_ | IPC_CREAT | IPC_EXCL);
00920   if (shmid == -1)
00921     {
00922       if (errno != EEXIST)
00923         ACE_ERROR_RETURN ((LM_ERROR,
00924                            ACE_LIB_TEXT ("(%P|%t) %p\n"),
00925                            ACE_LIB_TEXT ("shmget")),
00926                           0);
00927       first_time = 0;
00928 
00929       shmid = ACE_OS::shmget (this->base_shm_key_, 0, 0);
00930 
00931       if (shmid == -1)
00932         ACE_ERROR_RETURN ((LM_ERROR,
00933                            ACE_LIB_TEXT ("(%P|%t) %p\n"),
00934                            ACE_LIB_TEXT ("shmget")),
00935                           0);
00936 
00937       // This implementation doesn't care if we don't get the key we
00938       // want...
00939       this->base_addr_ =
00940         ACE_OS::shmat (shmid,
00941                        ACE_reinterpret_cast (char *,
00942                                              this->base_addr_),
00943                        0);
00944       if (this->base_addr_ == ACE_reinterpret_cast (void *, -1))
00945         ACE_ERROR_RETURN ((LM_ERROR,
00946                            "(%P|%t) %p, base_addr = %u\n",
00947                            "shmat",
00948                            this->base_addr_),
00949                           0);
00950     }
00951   else
00952     {
00953       first_time = 1;
00954 
00955       // This implementation doesn't care if we don't get the key we
00956       // want...
00957       this->base_addr_ =
00958         ACE_OS::shmat (shmid,
00959                        ACE_reinterpret_cast (char *,
00960                                              this->base_addr_),
00961                        0);
00962       if (this->base_addr_ == ACE_reinterpret_cast (char *, -1))
00963         ACE_ERROR_RETURN ((LM_ERROR,
00964                            "(%P|%t) %p, base_addr = %u\n",
00965                            "shmat",
00966                            this->base_addr_), 0);
00967 
00968       SHM_TABLE *st = ACE_reinterpret_cast (SHM_TABLE *,
00969                                             this->base_addr_);
00970       st[0].key_ = this->base_shm_key_;
00971       st[0].shmid_ = shmid;
00972 
00973       st[0].used_ = 1;
00974 
00975       for (size_t counter = 1; // Skip over the first entry...
00976            counter < this->max_segments_;
00977            counter++)
00978         {
00979           st[counter].key_ = this->base_shm_key_ + counter;
00980           st[counter].shmid_ = 0;
00981           st[counter].used_ = 0;
00982         }
00983     }
00984 
00985   return (void *) (((char *) this->base_addr_) + shm_table_offset);
00986 }
00987 
00988 // Instruct the memory pool to release all of its resources.
00989 
00990 int
00991 ACE_Shared_Memory_Pool::release (int)
00992 {
00993   ACE_TRACE ("ACE_Shared_Memory_Pool::release");
00994 
00995   int result = 0;
00996   SHM_TABLE *st = ACE_reinterpret_cast (SHM_TABLE *,
00997                                         this->base_addr_);
00998 
00999   for (size_t counter = 0;
01000        counter < this->max_segments_ && st[counter].used_ == 1;
01001        counter++)
01002     if (ACE_OS::shmctl (st[counter].shmid_, IPC_RMID, 0) == -1)
01003       result = -1;
01004 
01005   return result;
01006 }
01007 #endif /* !ACE_LACKS_SYSV_SHMEM */
01008 
01009 #if defined (ACE_WIN32)
01010 #if !defined (ACE_HAS_WINCE)
01011 #define ACE_MAP_FILE(_hnd, _access, _offHigh, _offLow, _nBytes, _baseAdd)\
01012   MapViewOfFileEx (_hnd, _access, _offHigh, _offLow, _nBytes, _baseAdd)
01013 #else //if !defined (ACE_HAS_WINCE)
01014 #define ACE_MAP_FILE(_hnd, _access, _offHigh, _offLow, _nBytes, _baseAdd)\
01015   MapViewOfFile (_hnd, _access, _offHigh, _offLow, _nBytes)
01016 #endif /* !defined (ACE_HAS_WINCE) */
01017 
01018 ACE_Pagefile_Memory_Pool_Options::ACE_Pagefile_Memory_Pool_Options (void *base_addr,
01019                                                                     size_t max_size)
01020   : base_addr_ (base_addr),
01021     max_size_ (max_size)
01022 {
01023 }
01024 
01025 int
01026 ACE_Pagefile_Memory_Pool::release (int)
01027 {
01028   return this->unmap ();
01029 }
01030 
01031 ACE_Pagefile_Memory_Pool::ACE_Pagefile_Memory_Pool (const ACE_TCHAR *backing_store_name,
01032                                                     const OPTIONS *options)
01033   : shared_cb_ (0),
01034     object_handle_ (0),
01035     page_size_ (ACE_Pagefile_Memory_Pool::round_to_page_size (1))
01036 {
01037   // Initialize local copy of pool statistics.
01038   if (options != 0)
01039     {
01040       this->local_cb_.req_base_ = options->base_addr_;
01041       this->local_cb_.mapped_base_ = 0;
01042       this->local_cb_.sh_.max_size_ =
01043         options->max_size_;
01044       this->local_cb_.sh_.mapped_size_ = 0;
01045       this->local_cb_.sh_.free_offset_ =
01046         this->local_cb_.sh_.mapped_size_;
01047       this->local_cb_.sh_.free_size_ = 0;
01048     }
01049 
01050   if (backing_store_name == 0)
01051     // Only create a new unique filename for the backing store file if
01052     // the user didn't supply one...
01053     backing_store_name = ACE_DEFAULT_PAGEFILE_POOL_NAME;
01054 
01055   ACE_OS::strsncpy (this->backing_store_name_,
01056                     backing_store_name,
01057                     (sizeof this->backing_store_name_ / sizeof (ACE_TCHAR)));
01058 }
01059 
01060 void *
01061 ACE_Pagefile_Memory_Pool::acquire (size_t nbytes,
01062                                    size_t &rounded_bytes)
01063 {
01064   rounded_bytes = round_to_page_size (nbytes);
01065   void *result = 0;
01066   int first_time = 0;
01067 
01068   // Check local_cb_ for consistency.  Remap, if extra space is too
01069   // small and/or we didn't map the whole shared memory section
01070   if (this->shared_cb_->sh_.mapped_size_
01071       > this->local_cb_.sh_.mapped_size_
01072       || this->shared_cb_->sh_.free_size_ < rounded_bytes)
01073     {
01074       size_t append = 0;
01075       if (rounded_bytes > this->shared_cb_->sh_.free_size_)
01076         append = rounded_bytes - this->shared_cb_->sh_.free_size_;
01077 
01078       if (this->map (first_time, append) < 0)
01079         return result;
01080     }
01081 
01082   // Get the block from extra space and update shared and local
01083   // control block
01084   if (this->shared_cb_->sh_.free_size_ < rounded_bytes)
01085     return result;
01086 
01087   result = (void *)((char *) this->local_cb_.mapped_base_
01088                     + this->shared_cb_->sh_.free_offset_);
01089   this->shared_cb_->sh_.free_offset_ += rounded_bytes;
01090   this->shared_cb_->sh_.free_size_ -= rounded_bytes;
01091   this->local_cb_.sh_ = this->shared_cb_->sh_;
01092 
01093   return result;
01094 }
01095 
01096 void *
01097 ACE_Pagefile_Memory_Pool::init_acquire (size_t nbytes,
01098                                         size_t &rounded_bytes,
01099                                         int &first_time)
01100 {
01101   // Map the shared memory and get information, if we created the
01102   // shared memory.
01103   if (this->map (first_time) < 0)
01104     return 0;
01105 
01106   if (first_time != 0)
01107     // We created the shared memory. So we have to allocate the
01108     // requested memory.
01109     return this->acquire (nbytes, rounded_bytes);
01110   else
01111     // We just mapped the memory and return the base address
01112     return (void *)((char *) this->local_cb_.mapped_base_
01113                     + ACE_Pagefile_Memory_Pool::round_to_page_size
01114                     ((int) sizeof (Control_Block)));
01115 }
01116 
01117 int
01118 ACE_Pagefile_Memory_Pool::seh_selector (void *ep)
01119 {
01120   DWORD ecode = ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionCode;
01121 
01122   if (ecode == EXCEPTION_ACCESS_VIOLATION)
01123     {
01124       void * fault_addr = (void *)
01125         ((EXCEPTION_POINTERS *) ep)->ExceptionRecord->ExceptionInformation[1];
01126 
01127       if (this->remap (fault_addr) == 0)
01128         return 1;
01129     }
01130 
01131   return 0;
01132 }
01133 
01134 int
01135 ACE_Pagefile_Memory_Pool::remap (void *addr)
01136 {
01137   // If the shared memory is not mapped or the address, that caused
01138   // the memory fault is outside of the commited range of chunks, we
01139   // return.
01140   if (this->shared_cb_ == 0
01141       || addr < this->local_cb_.mapped_base_
01142       || addr >= (void *)((char *) this->local_cb_.mapped_base_
01143                           + this->shared_cb_->sh_.mapped_size_))
01144     return -1;
01145 
01146   // We can solve the problem by committing additional chunks.
01147   int first_time = 0;
01148   return this->map (first_time);
01149 }
01150 
01151 int
01152 ACE_Pagefile_Memory_Pool::unmap (void)
01153 {
01154 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
01155   ACE_BASED_POINTER_REPOSITORY::instance ()->unbind
01156     (this->local_cb_.mapped_base_);
01157 #endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
01158 
01159   // Cleanup cached pool pointer.
01160   this->shared_cb_ = 0;
01161 
01162   if (this->local_cb_.sh_.mapped_size_ > 0)
01163     ::UnmapViewOfFile (this->local_cb_.mapped_base_);
01164 
01165   // Reset local pool statistics.
01166   this->local_cb_.req_base_ =
01167     ACE_DEFAULT_PAGEFILE_POOL_BASE;
01168   this->local_cb_.mapped_base_ = 0;
01169   this->local_cb_.sh_.max_size_ =
01170     ACE_DEFAULT_PAGEFILE_POOL_SIZE;
01171   this->local_cb_.sh_.mapped_size_ = 0;
01172   this->local_cb_.sh_.free_offset_ =
01173     this->local_cb_.sh_.mapped_size_;
01174   this->local_cb_.sh_.free_size_ = 0;
01175 
01176   // Release the pool
01177   if (this->object_handle_ != 0)
01178     {
01179       ::CloseHandle (this->object_handle_);
01180       this->object_handle_ = 0;
01181     }
01182   return 0;
01183 }
01184 
01185 int
01186 ACE_Pagefile_Memory_Pool::map (int &first_time,
01187                                size_t append_bytes)
01188 {
01189   size_t map_size;
01190   void *map_addr;
01191 
01192   // Create file mapping, if not yet done
01193   if (object_handle_ == 0)
01194     {
01195 #if (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0))
01196       // Allow access by all users.
01197       SECURITY_ATTRIBUTES sa;
01198       SECURITY_DESCRIPTOR sd;
01199       ::InitializeSecurityDescriptor (&sd,
01200                                       SECURITY_DESCRIPTOR_REVISION);
01201       ::SetSecurityDescriptorDacl (&sd,
01202                                    TRUE,
01203                                    0,
01204                                    FALSE);
01205       sa.nLength = sizeof (SECURITY_ATTRIBUTES);
01206       sa.lpSecurityDescriptor = &sd;
01207       sa.bInheritHandle = FALSE;
01208 #endif /* (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) */
01209 
01210       // Get an object handle to the named reserved memory object.
01211       DWORD size_high;
01212       DWORD size_low;
01213 #if defined (ACE_WIN64)
01214       size_high = ACE_static_cast (DWORD,
01215                                    this->local_cb_.sh_.max_size_ >> 32);
01216       size_low  = ACE_static_cast (DWORD,
01217                                    this->local_cb_.sh_.max_size_ & 0xFFFFFFFF);
01218 #else
01219       size_high = 0;
01220       size_low = this->local_cb_.sh_.max_size_;
01221 #endif
01222 
01223       object_handle_ =
01224         ACE_TEXT_CreateFileMapping (INVALID_HANDLE_VALUE,
01225 #if (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0))
01226                                     &sa,
01227 #else
01228                                     0,
01229 #endif /* (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) */
01230                                     PAGE_READWRITE | SEC_RESERVE,
01231                                     size_high,
01232                                     size_low,
01233                                     this->backing_store_name_);
01234       if (object_handle_ == 0)
01235         return -1;
01236       first_time =
01237         ::GetLastError () == ERROR_ALREADY_EXISTS
01238         ? 0
01239         : 1;
01240     }
01241 
01242   // Do the initial mapping.
01243   if (this->shared_cb_ == 0)
01244     {
01245       // Map a view to the shared memory.  Note: <MapViewOfFile[Ex]>
01246       // does *not* commit the pages!
01247       this->shared_cb_ = (ACE_Pagefile_Memory_Pool::Control_Block *)
01248         ACE_MAP_FILE (this->object_handle_,
01249                       FILE_MAP_WRITE,
01250                       0,
01251                       0,
01252                       this->local_cb_.sh_.max_size_,
01253                       this->local_cb_.req_base_);
01254       if (this->shared_cb_ == 0)
01255         return -1;
01256 
01257       // There was no previous mapping, so we map the first chunk and
01258       // initialize the shared pool statistics.
01259       if (first_time)
01260         {
01261           // 1st block is used to keep shared memory statistics.
01262           map_size =
01263             ACE_Pagefile_Memory_Pool::round_to_chunk_size
01264             (ACE_Pagefile_Memory_Pool::round_to_page_size
01265              ((int) sizeof(Control_Block))
01266              + append_bytes);
01267 
01268           if (::VirtualAlloc ((void *) this->shared_cb_,
01269                               map_size,
01270                               MEM_COMMIT,
01271                               PAGE_READWRITE) == 0)
01272             return -1;
01273 
01274           this->shared_cb_->req_base_ = 0;
01275           this->shared_cb_->mapped_base_ = 0;
01276           this->local_cb_.mapped_base_ = this->shared_cb_;
01277           this->local_cb_.sh_.mapped_size_ = map_size;
01278           this->local_cb_.sh_.free_offset_ =
01279             round_to_page_size ((int) sizeof (Control_Block));
01280           this->local_cb_.sh_.free_size_ =
01281             this->local_cb_.sh_.mapped_size_ -
01282             this->local_cb_.sh_.free_offset_;
01283           this->shared_cb_->sh_ = this->local_cb_.sh_;
01284         }
01285 
01286       // The shared memory exists, so we map the first chunk to the
01287       // base address of the pool to get the shared pool statistics.
01288       else
01289         {
01290           // 1st block is used to keep shared memory statistics.
01291           map_size =
01292             ACE_Pagefile_Memory_Pool::round_to_chunk_size
01293             ((int) sizeof (Control_Block));
01294 
01295           if (::VirtualAlloc ((void *) this->shared_cb_,
01296                               map_size,
01297                               MEM_COMMIT,
01298                               PAGE_READWRITE) == 0)
01299             return -1;
01300           this->local_cb_.mapped_base_ = this->shared_cb_;
01301           this->local_cb_.sh_.mapped_size_ = map_size;
01302         }
01303     }
01304 
01305   // If the shared memory is larger than the part we've already
01306   // committed, we have to remap it.
01307   if (this->shared_cb_->sh_.mapped_size_ >
01308       this->local_cb_.sh_.mapped_size_
01309       || append_bytes > 0)
01310     {
01311       map_size =
01312         (this->shared_cb_->sh_.mapped_size_ -
01313          this->local_cb_.sh_.mapped_size_)
01314         + ACE_Pagefile_Memory_Pool::round_to_chunk_size
01315         (append_bytes);
01316 
01317       map_addr = (void *)((char *) this->shared_cb_ +
01318                           this->local_cb_.sh_.mapped_size_);
01319 
01320       if (::VirtualAlloc (map_addr,
01321                           map_size,
01322                           MEM_COMMIT,
01323                           PAGE_READWRITE) == 0)
01324         return -1;
01325       else if (append_bytes > 0)
01326         {
01327           this->shared_cb_->sh_.mapped_size_ +=
01328             round_to_chunk_size (append_bytes);
01329           this->shared_cb_->sh_.free_size_ =
01330             this->shared_cb_->sh_.mapped_size_ -
01331             this->shared_cb_->sh_.free_offset_;
01332         }
01333     }
01334 
01335   // Update local copy of the shared memory statistics.
01336   this->local_cb_.sh_ =
01337     this->shared_cb_->sh_;
01338 #if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
01339   ACE_BASED_POINTER_REPOSITORY::instance ()->bind
01340     (this->local_cb_.mapped_base_,
01341      this->local_cb_.sh_.mapped_size_);
01342 #endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
01343 
01344   return 0;
01345 }
01346 
01347 #endif /* ACE_WIN32 */
01348 
01349 #if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
01350 template class ACE_Auto_Basic_Array_Ptr<char>;
01351 template class ACE_Unbounded_Set<char *>;
01352 template class ACE_Unbounded_Set_Iterator<char *>;
01353 #elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
01354 #pragma instantiate ACE_Auto_Basic_Array_Ptr<char>
01355 #pragma instantiate ACE_Unbounded_Set<char *>
01356 #pragma instantiate ACE_Unbounded_Set_Iterator<char *>
01357 #endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */

Generated on Mon Jun 16 11:20:19 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002