00001 // Filename: memoryHook.I 00002 // Created by: drose (28Jun07) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 00016 //////////////////////////////////////////////////////////////////// 00017 // Function: MemoryHook::inc_heap 00018 // Access: Public 00019 // Description: Called by our alternative malloc implementations 00020 // (dlmalloc and ptmalloc2) to indicate they have 00021 // requested size bytes from the system for the heap. 00022 //////////////////////////////////////////////////////////////////// 00023 INLINE void MemoryHook:: 00024 inc_heap(size_t size) { 00025 #ifdef DO_MEMORY_USAGE 00026 AtomicAdjust::add(_requested_heap_size, (AtomicAdjust::Integer)size); 00027 #endif // DO_MEMORY_USAGE 00028 } 00029 00030 //////////////////////////////////////////////////////////////////// 00031 // Function: MemoryHook::dec_heap 00032 // Access: Public 00033 // Description: Called by our alternative malloc implementations 00034 // (dlmalloc and ptmalloc2) to indicate they have 00035 // returned size bytes to the system from the heap. 00036 //////////////////////////////////////////////////////////////////// 00037 INLINE void MemoryHook:: 00038 dec_heap(size_t size) { 00039 #ifdef DO_MEMORY_USAGE 00040 //assert((int)size <= _requested_heap_size); 00041 AtomicAdjust::add(_requested_heap_size, -(AtomicAdjust::Integer)size); 00042 #endif // DO_MEMORY_USAGE 00043 } 00044 00045 //////////////////////////////////////////////////////////////////// 00046 // Function: MemoryHook::get_memory_alignment 00047 // Access: Public, Static 00048 // Description: Returns the global memory alignment. This is the 00049 // number of bytes at which each allocated memory 00050 // pointer will be aligned. 00051 //////////////////////////////////////////////////////////////////// 00052 INLINE size_t MemoryHook:: 00053 get_memory_alignment() { 00054 #ifdef LINMATH_ALIGN 00055 // We require 16-byte alignment of certain structures, to support 00056 // SSE2. We don't strictly have to align *everything*, but it's just 00057 // easier to do so. 00058 const size_t alignment_size = 16; 00059 #else 00060 // Otherwise, use word alignment. 00061 const size_t alignment_size = sizeof(void *); 00062 #endif 00063 return alignment_size; 00064 } 00065 00066 //////////////////////////////////////////////////////////////////// 00067 // Function: MemoryHook::get_header_reserved_bytes 00068 // Access: Public, Static 00069 // Description: Returns the number of additional bytes that are 00070 // reserved at the beginning of every allocated block to 00071 // store a size_t. 00072 //////////////////////////////////////////////////////////////////// 00073 INLINE size_t MemoryHook:: 00074 get_header_reserved_bytes() { 00075 // We need to figure out the minimum amount of additional space we 00076 // need in order to place a single word at the start of each 00077 // allocated block, to store the size of the block. 00078 00079 #ifdef LINMATH_ALIGN 00080 // If we're doing SSE2 alignment, we must reserve a full 16-byte 00081 // block, since anything less than that will spoil the alignment. 00082 static const size_t header_reserved_bytes = 16; 00083 00084 #elif defined(MEMORY_HOOK_DO_ALIGN) 00085 // If we're just aligning to words, we reserve a block as big as two 00086 // words, to allow us wiggle room to align the word precisely within 00087 // that block. 00088 static const size_t header_reserved_bytes = sizeof(size_t) + sizeof(size_t); 00089 00090 #else 00091 // If we're not aligning, we just need space for the word itself. 00092 static const size_t header_reserved_bytes = sizeof(size_t); 00093 #endif 00094 00095 return header_reserved_bytes; 00096 } 00097 00098 //////////////////////////////////////////////////////////////////// 00099 // Function: MemoryHook::get_page_size 00100 // Access: Public 00101 // Description: Returns the operating system page size. This is the 00102 // minimum granularity required for calls to 00103 // mmap_alloc(). Also see round_up_to_page_size(). 00104 //////////////////////////////////////////////////////////////////// 00105 INLINE size_t MemoryHook:: 00106 get_page_size() const { 00107 return _page_size; 00108 } 00109 00110 //////////////////////////////////////////////////////////////////// 00111 // Function: MemoryHook::round_up_to_page_size 00112 // Access: Public 00113 // Description: Rounds the indicated size request up to the next 00114 // larger multiple of page_size, to qualify it for a 00115 // call to mmap_alloc(). 00116 //////////////////////////////////////////////////////////////////// 00117 INLINE size_t MemoryHook:: 00118 round_up_to_page_size(size_t size) const { 00119 return ((size + _page_size - 1) / _page_size) * _page_size; 00120 } 00121 00122 //////////////////////////////////////////////////////////////////// 00123 // Function: MemoryHook::inflate_size 00124 // Access: Private, Static 00125 // Description: Increments the amount of requested size as necessary 00126 // to accommodate the extra data we might piggyback on 00127 // each allocated block. 00128 //////////////////////////////////////////////////////////////////// 00129 INLINE size_t MemoryHook:: 00130 inflate_size(size_t size) { 00131 #if defined(MEMORY_HOOK_DO_ALIGN) 00132 // If we're aligning, we need to request the header size, plus extra 00133 // bytes to give us wiggle room to adjust the pointer. 00134 return size + get_header_reserved_bytes() + get_memory_alignment() - 1; 00135 #elif defined(DO_MEMORY_USAGE) 00136 // If we're not aligning, but we're tracking memory allocations, we 00137 // just need the header size extra (this gives us a place to store 00138 // the size of the allocated block). 00139 return size + get_header_reserved_bytes(); 00140 #else 00141 // If we're not doing any of that, we can just allocate the precise 00142 // requested amount. 00143 return size; 00144 #endif // DO_MEMORY_USAGE 00145 } 00146 00147 //////////////////////////////////////////////////////////////////// 00148 // Function: MemoryHook::alloc_to_ptr 00149 // Access: Private, Static 00150 // Description: Converts an allocated pointer to a pointer returnable 00151 // to the application. Stuffs size in the first n bytes 00152 // of the allocated space. 00153 //////////////////////////////////////////////////////////////////// 00154 INLINE void *MemoryHook:: 00155 alloc_to_ptr(void *alloc, size_t size) { 00156 #if defined(MEMORY_HOOK_DO_ALIGN) 00157 size_t alignment = get_memory_alignment(); 00158 // Move the allocated pointer up to the next even alignment. 00159 size_t *root = (size_t *)((((size_t)alloc + alignment - 1) / alignment) * alignment); 00160 assert(alloc <= root && (size_t)((char *)root - (char *)alloc) < alignment); 00161 root[0] = size; 00162 root[1] = (size_t)alloc; // Save the pointer we originally allocated. 00163 return (void *)((char *)root + get_header_reserved_bytes()); 00164 #elif defined(DO_MEMORY_USAGE) 00165 size_t *root = (size_t *)alloc; 00166 root[0] = size; 00167 return (void *)((char *)root + get_header_reserved_bytes()); 00168 #else 00169 return alloc; 00170 #endif // DO_MEMORY_USAGE 00171 } 00172 00173 //////////////////////////////////////////////////////////////////// 00174 // Function: MemoryHook::ptr_to_alloc 00175 // Access: Private, Static 00176 // Description: Converts an application pointer back to the original 00177 // allocated pointer. Extracts size from the first n 00178 // bytes of the allocated space. 00179 //////////////////////////////////////////////////////////////////// 00180 INLINE void *MemoryHook:: 00181 ptr_to_alloc(void *ptr, size_t &size) { 00182 #if defined(MEMORY_HOOK_DO_ALIGN) 00183 size_t *root = (size_t *)((char *)ptr - get_header_reserved_bytes()); 00184 size = root[0]; 00185 void *alloc = (void *)root[1]; // Get the pointer we originally allocated. 00186 assert(alloc <= root && (size_t)((char *)root - (char *)alloc) < get_memory_alignment()); 00187 return alloc; 00188 #elif defined(DO_MEMORY_USAGE) 00189 size_t *root = (size_t *)((char *)ptr - get_header_reserved_bytes()); 00190 size = root[0]; 00191 return (void *)root; 00192 #else 00193 return ptr; 00194 #endif // DO_MEMORY_USAGE 00195 }