diff options
Diffstat (limited to 'ACE/ace/Malloc.h')
-rw-r--r-- | ACE/ace/Malloc.h | 396 |
1 files changed, 396 insertions, 0 deletions
diff --git a/ACE/ace/Malloc.h b/ACE/ace/Malloc.h new file mode 100644 index 00000000000..5362c0baaf6 --- /dev/null +++ b/ACE/ace/Malloc.h @@ -0,0 +1,396 @@ +// -*- C++ -*- + +//========================================================================== +/** + * @file Malloc.h + * + * $Id$ + * + * @author Doug Schmidt and Irfan Pyarali + */ +//========================================================================== + +#ifndef ACE_MALLOC_H +#define ACE_MALLOC_H + +#include /**/ "ace/pre.h" + +#include "ace/ACE_export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Log_Msg.h" + +#if defined (ACE_HAS_MALLOC_STATS) +# include "ace/Atomic_Op.h" +# if defined (ACE_HAS_THREADS) +# include "ace/Process_Mutex.h" +# define ACE_PROCESS_MUTEX ACE_Process_Mutex +# else /* ACE_HAS_THREADS */ +# include "ace/SV_Semaphore_Simple.h" +# define ACE_PROCESS_MUTEX ACE_SV_Semaphore_Simple +# endif /* ACE_HAS_THREADS */ + + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +typedef ACE_Atomic_Op<ACE_PROCESS_MUTEX, int> ACE_INT; + +/****************************************************************** + +* Assume that ACE_MALLOC_ALIGN is the number of bytes of the alignment + of the platform. Usually, this will be 4 on most platforms. Some + platforms require this to be 8. In any case, this macro should + always be a 2's power. + +* Malloc_Header structure. + + Notice that sizeof (ACE_Malloc_Header) must be multiple of + ACE_MALLOC_ALIGN + + +-----------------------------------------+ + |MALLOC_HEADER_PTR *next_block_; | + | // Points to next free Malloc_Header | + | // in this chain. | + +-----------------------------------------+ + |size_t size_; | + | // Size of buffer associate with | + | // this Malloc_Header | + } // The size is in number of | + | // Malloc_Header (including this one.)| + +-----------------------------------------+ + |char paddings_[ACE_MALLOC_PADDING_SIZE]; | + | // Padding array. This purpose | + | // of this padding array is to adjust | + | // the sizeof (Malloc_Header) to be | + | // multiple of ACE_MALLOC_ALIGN. | + +-----------------------------------------+ + +* Name_Node + + ACE_Malloc allows searching thru it's allocated buffer using names. + Name_Node is an internal data structure that ACE_Malloc used to + maintain a linked list that manages this (name, buffer) mappings. + + +-----------------------------------------+ + |char *name_; | + | // Points to a dynamically allocated | + | // char buffer that holds the name | + | // of this node. This buffer is | + | // allocated from using this | + | // ACE_MALLOC instance that owns this | + | // Name_Node (so it always points to | + | // a buffer owned by its Malloc. | + +-----------------------------------------+ + |char *pointer_; | + | // Points to the content that <name_> | + | // referring to. Like <name_>, the | + | // context always resides within the | + | // Malloc. | + +-----------------------------------------+ + |NAME_NODE_PTR next_; | + +-----------------------------------------+ + |NAME_NODE_PTR prev_; | + | // Name Node linked list pointers. | + +-----------------------------------------+ + + +* Control_Block + + Only the first ACE_Malloc instance that uses + the shared memory will initialize the control block because all + later instances are supposed to share the memory with the first + instance. The following diagram shows the initial value of a + Control_Block. + + +-----------------------------------------+ + |NAME_NODE_PTR name_head_; |<---- NULL + | // Entry point for double-linked list.| + | // Initialized to NULL pointer to | + | // indicate an empty list. | + +-----------------------------------------+ + |MALLOC_HEADER_PTR freep_; | + | // Pointer to last un-allocated | + | // malloc_header linked list. |---+ + +-----------------------------------------+ | + |char lock_name_[MAXNAMELEN]; | | + | // The global name of the lock. | | + +-----------------------------------------+ | + |Malloc_Stats malloc_stats_; | | + | // (Optional statistic information. | | + | // Do not exist if | | + | // ACE_HAS_MALLOC_STATS is not | | + | // defined. | | + +-----------------------------------------+ | + |char align_[CONTROL_BLOCK_ALIGN_BYTES]; | | + | // | | + +-----------------------------------------+ | + |Malloc_Header base_; |<--+ + | // Dummy node used to anchor the | + | // freelist. |<--+ + | +-------------+ | + | |next_ |---+ + | +-------------+ + | |size_ |----> 0 + +-----------------------------------------+ + + The first ACE_Malloc initializes the control block by allocating a + memory block of size equal to or greater than sizeof (control block) + (rounded to the closest <rounded_bytes>) and invokes the placement + new's on to initialize the control block and its internal + pointers/data structures. If the extra memory (memory after the + <base_> in the following diagram) is enough to create a + Malloc_Header chain, one is created and added to the freelist list. + That is, if the memory size returned by init_acquire() is greater + than the sizeof Control_Block, the control block is initialized to + the following diagram: + + + +------------------------------------- + |name_head_; | + +-------------------------------------+ + |MALLOC_HEADER_PTR freep_; |--+ + +-------------------------------------+ | + |lock_name_[...]; | | + +-------------------------------------+ | + |malloc_stats_; (Optional) | | + +-------------------------------------+ | + |align_[...]; | | + +-------------------------------------+ | + |Malloc_Header base_; |<-+ + | +-----------+ + | |next_; |--+ + | +-----------+ | + | |size_ = 0; | | + +=====================================+ | + |Malloc_Header base_; |<-+ + | +-----------+ + | |next_; | + | +-----------+ + | |size_ = 3; | + +-------------------------------------+ + |Malloc_Header base_; | + | +-----------+ + | (Uninitialized) |next_; | + | +-----------+ + | |size_; | + +-------------------------------------+ + |Malloc_Header base_; | + | +-----------+ + | (Uninitialized) |next_; | + | +-----------+ + | |size_; | + +-------------------------------------+ + +***********************************************************/ + +/// This keeps stats on the usage of the memory manager. +struct ACE_Export ACE_Malloc_Stats +{ + ACE_Malloc_Stats (void); + void dump (void) const; + + /// Coarse-grained unit of allocation. + ACE_INT nchunks_; + + /// Fine-grained unit of allocation. + ACE_INT nblocks_; + + /// Number of blocks in use + ACE_INT ninuse_; +}; + +ACE_END_VERSIONED_NAMESPACE_DECL + +# define ACE_MALLOC_STATS(X) X +#else +# define ACE_MALLOC_STATS(X) +#endif /* ACE_HAS_MALLOC_STATS */ + +#if !defined (ACE_MALLOC_PADDING) +// ACE_MALLOC_PADDING allows you to insure that allocated regions are +// at least <ACE_MALLOC_PADDING> bytes long. It is especially useful +// when you want areas to be at least a page long, or 32K long, or +// something like that. + +# define ACE_MALLOC_PADDING 1 +#endif /* ACE_MALLOC_PADDING */ + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +union ACE_max_align_info +{ + int (*i)(); + void* p; + long l; + double d; +}; + +#if !defined (ACE_MALLOC_ALIGN) +// Align the malloc header size to a multiple of a double. +# define ACE_MALLOC_ALIGN (sizeof (ACE_max_align_info)) +#endif /* ACE_MALLOC_ALIGN */ + +#if !defined ACE_MALLOC_ROUNDUP +# define ACE_MALLOC_ROUNDUP(X, Y) ((X) + ((Y) - 1) & ~((Y) - 1)) +#endif + +// ACE_MALLOC_HEADER_SIZE is the normalized malloc header size. +#define ACE_MALLOC_HEADER_SIZE ACE_MALLOC_ROUNDUP(ACE_MALLOC_PADDING, ACE_MALLOC_ALIGN) + +/** + * @class ACE_Control_Block + * + * @brief This information is stored in memory allocated by the <Memory_Pool>. + * + * This class defines the "old" control block class for use in + * ACE_Malloc_T. This control block implementation is + * considerable more efficient than the "position independent" + * one below (ACE_PI_Control_Block) but if you are going to use + * it to construct a ACE_Malloc_T and access the memory from + * several different processes, you must "map" the underlying + * memory pool to the same address. + */ +class ACE_Export ACE_Control_Block +{ +public: + + /** + * @class ACE_Malloc_Header + * + * @brief This is the control block header. It's used by <ACE_Malloc> + * to keep track of each chunk of data when it's in the free + * list or in use. + */ + class ACE_Export ACE_Malloc_Header + { + public: + ACE_Malloc_Header (void); + + /// Points to next block if on free list. + ACE_Malloc_Header *next_block_; + + /// Initialize a malloc header pointer. + static void init_ptr (ACE_Malloc_Header **ptr, + ACE_Malloc_Header *init, + void *base_addr); + + /// Size of this header control block. + size_t size_; + +# if !defined (ACE_MALLOC_PADDING_SIZE) +# 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)) +# endif /* !ACE_MALLOC_PADDING_SIZE */ + char padding_[(ACE_MALLOC_PADDING_SIZE) ? ACE_MALLOC_PADDING_SIZE : ACE_MALLOC_ALIGN]; + + /// Dump the state of the object. + void dump (void) const; + }; + + /** + * @class ACE_Name_Node + * + * @brief This class supports "named memory regions" within ACE_Malloc. + * + * Internally, the named memory regions are stored as a + * doubly-linked list within the @c Memory_Pool. This makes + * it easy to iterate over the items in the list in both FIFO + * and LIFO order. + */ + class ACE_Export ACE_Name_Node + { + public: + // = Initialization methods. + /// Constructor. + ACE_Name_Node (const char *name, + char *name_ptr, + char *pointer, + ACE_Name_Node *head); + + /// Constructor. + ACE_Name_Node (void); + + /// Constructor. + ~ACE_Name_Node (void); + + /// Initialize a name node pointer. + static void init_ptr (ACE_Name_Node **ptr, + ACE_Name_Node *init, + void *base_addr); + + /// Return a pointer to the name of this node. + const char *name (void) const; + + /// Name of the Node. + char *name_; + + /// Pointer to the contents. + char *pointer_; + + /// Pointer to the next node in the doubly-linked list. + ACE_Name_Node *next_; + + /// Pointer to the previous node in the doubly-linked list. + ACE_Name_Node *prev_; + + /// Dump the state of the object. + void dump (void) const; + private: + /// Copy constructor. + ACE_Name_Node (const ACE_Name_Node &); + }; + + /// Print out a bunch of size info for debugging. + static void print_alignment_info (void); + + /// Reference counter. + int ref_counter_; + + /// Head of the linked list of Name Nodes. + ACE_Name_Node *name_head_; + + /// Current head of the freelist. + ACE_Malloc_Header *freep_; + + /// Name of lock thats ensures mutual exclusion. + char lock_name_[MAXNAMELEN]; + +#if defined (ACE_HAS_MALLOC_STATS) + /// Keep statistics about ACE_Malloc state and performance. + ACE_Malloc_Stats malloc_stats_; +#define ACE_CONTROL_BLOCK_SIZE ((int)(sizeof (ACE_Name_Node*) \ + + sizeof (ACE_Malloc_Header*) \ + + sizeof (int) \ + + MAXNAMELEN \ + + sizeof (ACE_Malloc_Stats))) +#else +#define ACE_CONTROL_BLOCK_SIZE ((int)(sizeof (ACE_Name_Node*) \ + + sizeof (ACE_Malloc_Header*) \ + + sizeof (int) \ + + MAXNAMELEN)) +#endif /* ACE_HAS_MALLOC_STATS */ + +# if !defined (ACE_CONTROL_BLOCK_ALIGN_BYTES) +# define ACE_CONTROL_BLOCK_ALIGN_BYTES \ + ACE_MALLOC_ROUNDUP (ACE_CONTROL_BLOCK_SIZE, ACE_MALLOC_ALIGN) - ACE_CONTROL_BLOCK_SIZE +# endif /* !ACE_CONTROL_BLOCK_ALIGN_BYTES */ + char align_[(ACE_CONTROL_BLOCK_ALIGN_BYTES) ? ACE_CONTROL_BLOCK_ALIGN_BYTES : ACE_MALLOC_ALIGN]; + + /// Dummy node used to anchor the freelist. This needs to come last... + ACE_Malloc_Header base_; + + /// Dump the state of the object. + void dump (void) const; +}; + +ACE_END_VERSIONED_NAMESPACE_DECL + +#if defined (__ACE_INLINE__) +#include "ace/Malloc.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* ACE_MALLOC_H */ |