00001 // -*- C++ -*- 00002 00003 //========================================================================== 00004 /** 00005 * @file Malloc.h 00006 * 00007 * $Id: Malloc.h 80826 2008-03-04 14:51:23Z wotte $ 00008 * 00009 * @author Doug Schmidt and Irfan Pyarali 00010 */ 00011 //========================================================================== 00012 00013 #ifndef ACE_MALLOC_H 00014 #define ACE_MALLOC_H 00015 00016 #include /**/ "ace/pre.h" 00017 00018 #include /**/ "ace/ACE_export.h" 00019 00020 #if !defined (ACE_LACKS_PRAGMA_ONCE) 00021 # pragma once 00022 #endif /* ACE_LACKS_PRAGMA_ONCE */ 00023 00024 #include "ace/Log_Msg.h" 00025 00026 #if defined (ACE_HAS_MALLOC_STATS) 00027 # include "ace/Atomic_Op.h" 00028 # if defined (ACE_HAS_THREADS) 00029 # include "ace/Process_Mutex.h" 00030 # define ACE_PROCESS_MUTEX ACE_Process_Mutex 00031 # else /* ACE_HAS_THREADS */ 00032 # include "ace/SV_Semaphore_Simple.h" 00033 # define ACE_PROCESS_MUTEX ACE_SV_Semaphore_Simple 00034 # endif /* ACE_HAS_THREADS */ 00035 00036 00037 ACE_BEGIN_VERSIONED_NAMESPACE_DECL 00038 00039 typedef ACE_Atomic_Op<ACE_PROCESS_MUTEX, int> ACE_INT; 00040 00041 /****************************************************************** 00042 00043 * Assume that ACE_MALLOC_ALIGN is the number of bytes of the alignment 00044 of the platform. Usually, this will be 4 on most platforms. Some 00045 platforms require this to be 8. In any case, this macro should 00046 always be a 2's power. 00047 00048 * Malloc_Header structure. 00049 00050 Notice that sizeof (ACE_Malloc_Header) must be multiple of 00051 ACE_MALLOC_ALIGN 00052 00053 +-----------------------------------------+ 00054 |MALLOC_HEADER_PTR *next_block_; | 00055 | // Points to next free Malloc_Header | 00056 | // in this chain. | 00057 +-----------------------------------------+ 00058 |size_t size_; | 00059 | // Size of buffer associate with | 00060 | // this Malloc_Header | 00061 } // The size is in number of | 00062 | // Malloc_Header (including this one.)| 00063 +-----------------------------------------+ 00064 |char paddings_[ACE_MALLOC_PADDING_SIZE]; | 00065 | // Padding array. This purpose | 00066 | // of this padding array is to adjust | 00067 | // the sizeof (Malloc_Header) to be | 00068 | // multiple of ACE_MALLOC_ALIGN. | 00069 +-----------------------------------------+ 00070 00071 * Name_Node 00072 00073 ACE_Malloc allows searching thru it's allocated buffer using names. 00074 Name_Node is an internal data structure that ACE_Malloc used to 00075 maintain a linked list that manages this (name, buffer) mappings. 00076 00077 +-----------------------------------------+ 00078 |char *name_; | 00079 | // Points to a dynamically allocated | 00080 | // char buffer that holds the name | 00081 | // of this node. This buffer is | 00082 | // allocated from using this | 00083 | // ACE_MALLOC instance that owns this | 00084 | // Name_Node (so it always points to | 00085 | // a buffer owned by its Malloc. | 00086 +-----------------------------------------+ 00087 |char *pointer_; | 00088 | // Points to the content that <name_> | 00089 | // referring to. Like <name_>, the | 00090 | // context always resides within the | 00091 | // Malloc. | 00092 +-----------------------------------------+ 00093 |NAME_NODE_PTR next_; | 00094 +-----------------------------------------+ 00095 |NAME_NODE_PTR prev_; | 00096 | // Name Node linked list pointers. | 00097 +-----------------------------------------+ 00098 00099 00100 * Control_Block 00101 00102 Only the first ACE_Malloc instance that uses 00103 the shared memory will initialize the control block because all 00104 later instances are supposed to share the memory with the first 00105 instance. The following diagram shows the initial value of a 00106 Control_Block. 00107 00108 +-----------------------------------------+ 00109 |NAME_NODE_PTR name_head_; |<---- NULL. 00110 | // Entry point for double-linked list.| 00111 | // Initialized to NULL pointer to | 00112 | // indicate an empty list. | 00113 +-----------------------------------------+ 00114 |MALLOC_HEADER_PTR freep_; | 00115 | // Pointer to last un-allocated | 00116 | // malloc_header linked list. |---+ 00117 +-----------------------------------------+ | 00118 |char lock_name_[MAXNAMELEN]; | | 00119 | // The global name of the lock. | | 00120 +-----------------------------------------+ | 00121 |Malloc_Stats malloc_stats_; | | 00122 | // (Optional statistic information. | | 00123 | // Do not exist if | | 00124 | // ACE_HAS_MALLOC_STATS is not | | 00125 | // defined. | | 00126 +-----------------------------------------+ | 00127 |char align_[CONTROL_BLOCK_ALIGN_BYTES]; | | 00128 | // | | 00129 +-----------------------------------------+ | 00130 |Malloc_Header base_; |<--+ 00131 | // Dummy node used to anchor the | 00132 | // freelist. |<--+ 00133 | +-------------+ | 00134 | |next_ |---+ 00135 | +-------------+ 00136 | |size_ |----> 0 00137 +-----------------------------------------+ 00138 00139 The first ACE_Malloc initializes the control block by allocating a 00140 memory block of size equal to or greater than sizeof (control block) 00141 (rounded to the closest <rounded_bytes>) and invokes the placement 00142 new's on to initialize the control block and its internal 00143 pointers/data structures. If the extra memory (memory after the 00144 <base_> in the following diagram) is enough to create a 00145 Malloc_Header chain, one is created and added to the freelist list. 00146 That is, if the memory size returned by init_acquire() is greater 00147 than the sizeof Control_Block, the control block is initialized to 00148 the following diagram: 00149 00150 00151 +------------------------------------- 00152 |name_head_; | 00153 +-------------------------------------+ 00154 |MALLOC_HEADER_PTR freep_; |--+ 00155 +-------------------------------------+ | 00156 |lock_name_[...]; | | 00157 +-------------------------------------+ | 00158 |malloc_stats_; (Optional) | | 00159 +-------------------------------------+ | 00160 |align_[...]; | | 00161 +-------------------------------------+ | 00162 |Malloc_Header base_; |<-+ 00163 | +-----------+ 00164 | |next_; |--+ 00165 | +-----------+ | 00166 | |size_ = 0; | | 00167 +=====================================+ | 00168 |Malloc_Header base_; |<-+ 00169 | +-----------+ 00170 | |next_; | 00171 | +-----------+ 00172 | |size_ = 3; | 00173 +-------------------------------------+ 00174 |Malloc_Header base_; | 00175 | +-----------+ 00176 | (Uninitialized) |next_; | 00177 | +-----------+ 00178 | |size_; | 00179 +-------------------------------------+ 00180 |Malloc_Header base_; | 00181 | +-----------+ 00182 | (Uninitialized) |next_; | 00183 | +-----------+ 00184 | |size_; | 00185 +-------------------------------------+ 00186 00187 ***********************************************************/ 00188 00189 /// This keeps stats on the usage of the memory manager. 00190 struct ACE_Export ACE_Malloc_Stats 00191 { 00192 ACE_Malloc_Stats (void); 00193 void dump (void) const; 00194 00195 /// Coarse-grained unit of allocation. 00196 ACE_INT nchunks_; 00197 00198 /// Fine-grained unit of allocation. 00199 ACE_INT nblocks_; 00200 00201 /// Number of blocks in use 00202 ACE_INT ninuse_; 00203 }; 00204 00205 ACE_END_VERSIONED_NAMESPACE_DECL 00206 00207 # define ACE_MALLOC_STATS(X) X 00208 #else 00209 # define ACE_MALLOC_STATS(X) 00210 #endif /* ACE_HAS_MALLOC_STATS */ 00211 00212 #if !defined (ACE_MALLOC_PADDING) 00213 // ACE_MALLOC_PADDING allows you to insure that allocated regions are 00214 // at least <ACE_MALLOC_PADDING> bytes long. It is especially useful 00215 // when you want areas to be at least a page long, or 32K long, or 00216 // something like that. 00217 00218 # define ACE_MALLOC_PADDING 1 00219 #endif /* ACE_MALLOC_PADDING */ 00220 00221 ACE_BEGIN_VERSIONED_NAMESPACE_DECL 00222 00223 union ACE_max_align_info 00224 { 00225 int (*i)(); 00226 void* p; 00227 long l; 00228 double d; 00229 }; 00230 00231 #if !defined (ACE_MALLOC_ALIGN) 00232 // Align the malloc header size to a multiple of a double. 00233 # define ACE_MALLOC_ALIGN (sizeof (ACE_max_align_info)) 00234 #endif /* ACE_MALLOC_ALIGN */ 00235 00236 #if !defined ACE_MALLOC_ROUNDUP 00237 # define ACE_MALLOC_ROUNDUP(X, Y) ((X) + ((Y) - 1) & ~((Y) - 1)) 00238 #endif 00239 00240 // ACE_MALLOC_HEADER_SIZE is the normalized malloc header size. 00241 #define ACE_MALLOC_HEADER_SIZE ACE_MALLOC_ROUNDUP(ACE_MALLOC_PADDING, ACE_MALLOC_ALIGN) 00242 00243 /** 00244 * @class ACE_Control_Block 00245 * 00246 * @brief This information is stored in memory allocated by the <Memory_Pool>. 00247 * 00248 * This class defines the "old" control block class for use in 00249 * ACE_Malloc_T. This control block implementation is 00250 * considerable more efficient than the "position independent" 00251 * one below (ACE_PI_Control_Block) but if you are going to use 00252 * it to construct a ACE_Malloc_T and access the memory from 00253 * several different processes, you must "map" the underlying 00254 * memory pool to the same address. 00255 */ 00256 class ACE_Export ACE_Control_Block 00257 { 00258 public: 00259 00260 /** 00261 * @class ACE_Malloc_Header 00262 * 00263 * @brief This is the control block header. It's used by <ACE_Malloc> 00264 * to keep track of each chunk of data when it's in the free 00265 * list or in use. 00266 */ 00267 class ACE_Export ACE_Malloc_Header 00268 { 00269 public: 00270 ACE_Malloc_Header (void); 00271 00272 /// Points to next block if on free list. 00273 ACE_Malloc_Header *next_block_; 00274 00275 /// Initialize a malloc header pointer. 00276 static void init_ptr (ACE_Malloc_Header **ptr, 00277 ACE_Malloc_Header *init, 00278 void *base_addr); 00279 00280 /// Size of this header control block. 00281 size_t size_; 00282 00283 # if !defined (ACE_MALLOC_PADDING_SIZE) 00284 # define ACE_MALLOC_PADDING_SIZE ACE_MALLOC_ROUNDUP (ACE_MALLOC_HEADER_SIZE + sizeof (ACE_Malloc_Header*) + sizeof (size_t), ACE_MALLOC_ALIGN) - (sizeof (ACE_Malloc_Header*) + sizeof (size_t)) 00285 # endif /* !ACE_MALLOC_PADDING_SIZE */ 00286 char padding_[(ACE_MALLOC_PADDING_SIZE) ? ACE_MALLOC_PADDING_SIZE : ACE_MALLOC_ALIGN]; 00287 00288 /// Dump the state of the object. 00289 void dump (void) const; 00290 }; 00291 00292 /** 00293 * @class ACE_Name_Node 00294 * 00295 * @brief This class supports "named memory regions" within ACE_Malloc. 00296 * 00297 * Internally, the named memory regions are stored as a 00298 * doubly-linked list within the @c Memory_Pool. This makes 00299 * it easy to iterate over the items in the list in both FIFO 00300 * and LIFO order. 00301 */ 00302 class ACE_Export ACE_Name_Node 00303 { 00304 public: 00305 // = Initialization methods. 00306 /// Constructor. 00307 ACE_Name_Node (const char *name, 00308 char *name_ptr, 00309 char *pointer, 00310 ACE_Name_Node *head); 00311 00312 /// Constructor. 00313 ACE_Name_Node (void); 00314 00315 /// Constructor. 00316 ~ACE_Name_Node (void); 00317 00318 /// Initialize a name node pointer. 00319 static void init_ptr (ACE_Name_Node **ptr, 00320 ACE_Name_Node *init, 00321 void *base_addr); 00322 00323 /// Return a pointer to the name of this node. 00324 const char *name (void) const; 00325 00326 /// Name of the Node. 00327 char *name_; 00328 00329 /// Pointer to the contents. 00330 char *pointer_; 00331 00332 /// Pointer to the next node in the doubly-linked list. 00333 ACE_Name_Node *next_; 00334 00335 /// Pointer to the previous node in the doubly-linked list. 00336 ACE_Name_Node *prev_; 00337 00338 /// Dump the state of the object. 00339 void dump (void) const; 00340 private: 00341 /// Copy constructor. 00342 ACE_Name_Node (const ACE_Name_Node &); 00343 }; 00344 00345 /// Print out a bunch of size info for debugging. 00346 static void print_alignment_info (void); 00347 00348 /// Reference counter. 00349 int ref_counter_; 00350 00351 /// Head of the linked list of Name Nodes. 00352 ACE_Name_Node *name_head_; 00353 00354 /// Current head of the freelist. 00355 ACE_Malloc_Header *freep_; 00356 00357 /// Name of lock thats ensures mutual exclusion. 00358 char lock_name_[MAXNAMELEN]; 00359 00360 #if defined (ACE_HAS_MALLOC_STATS) 00361 /// Keep statistics about ACE_Malloc state and performance. 00362 ACE_Malloc_Stats malloc_stats_; 00363 #define ACE_CONTROL_BLOCK_SIZE ((int)(sizeof (ACE_Name_Node*) \ 00364 + sizeof (ACE_Malloc_Header*) \ 00365 + sizeof (int) \ 00366 + MAXNAMELEN \ 00367 + sizeof (ACE_Malloc_Stats))) 00368 #else 00369 #define ACE_CONTROL_BLOCK_SIZE ((int)(sizeof (ACE_Name_Node*) \ 00370 + sizeof (ACE_Malloc_Header*) \ 00371 + sizeof (int) \ 00372 + MAXNAMELEN)) 00373 #endif /* ACE_HAS_MALLOC_STATS */ 00374 00375 # if !defined (ACE_CONTROL_BLOCK_ALIGN_BYTES) 00376 # define ACE_CONTROL_BLOCK_ALIGN_BYTES \ 00377 ACE_MALLOC_ROUNDUP (ACE_CONTROL_BLOCK_SIZE, ACE_MALLOC_ALIGN) - ACE_CONTROL_BLOCK_SIZE 00378 # endif /* !ACE_CONTROL_BLOCK_ALIGN_BYTES */ 00379 char align_[(ACE_CONTROL_BLOCK_ALIGN_BYTES) ? ACE_CONTROL_BLOCK_ALIGN_BYTES : ACE_MALLOC_ALIGN]; 00380 00381 /// Dummy node used to anchor the freelist. This needs to come last... 00382 ACE_Malloc_Header base_; 00383 00384 /// Dump the state of the object. 00385 void dump (void) const; 00386 }; 00387 00388 ACE_END_VERSIONED_NAMESPACE_DECL 00389 00390 #if defined (__ACE_INLINE__) 00391 #include "ace/Malloc.inl" 00392 #endif /* __ACE_INLINE__ */ 00393 00394 #include /**/ "ace/post.h" 00395 00396 #endif /* ACE_MALLOC_H */