basix_doc 0.1
|
00001 00002 /****************************************************************************** 00003 * MODULE : Fast memory allocation 00004 * DESCRIPTION: Fast allocations is realized by using a linked list 00005 * of allocations for each fixed size divisible by 00006 * a word length up to MMX_MAX_FAST. Otherwise, 00007 * usual memory allocation is used. 00008 * COPYRIGHT : (C) 1999-2008 Joris van der Hoeven 00009 ******************************************************************************* 00010 * This software falls under the GNU general public license and comes WITHOUT 00011 * ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details. 00012 * If you don't have this file, write to the Free Software Foundation, Inc., 00013 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00014 ******************************************************************************/ 00015 00016 #include <basix/port.hpp> 00017 #ifdef BASIX_HAVE_STDINT_H 00018 #include <stdint.h> 00019 using ::uintptr_t; 00020 #endif 00021 00022 namespace mmx { 00023 00024 #ifdef MMX_ENABLE_FAST_ALLOCATORS 00025 00026 char alloc_table[MMX_MAX_FAST]; // Static declaration initializes with NULL's 00027 char* alloc_mem= NULL; 00028 size_t alloc_remains= 0; 00029 nat allocated= 0; 00030 nat fast_chunks= 0; 00031 nat large_uses= 0; 00032 00033 void* 00034 safe_malloc (register size_t sz) { 00035 // Always guarantees 16 byte alignment 00036 register char* ret; 00037 register char* ptr= (char*) malloc (sz + 16); 00038 if (ptr == NULL) { 00039 fprintf (stderr, "Fatal error: out of memory\n"); 00040 assert (false); 00041 exit (1); 00042 } 00043 ret= ptr + (16 - (((nat) ((uintptr_t) ((void*) ptr))) & 15)); 00044 //printf ("Alloc: %lx, %lx\n", 00045 // (uintptr_t) (void*) ret, (uintptr_t) (void*) ptr); 00046 *((void**) ((void*) (ret - sizeof (void*))))= (void*) ptr; 00047 return (void*) ret; 00048 } 00049 00050 void* 00051 enlarge_malloc (register size_t sz) { 00052 if (alloc_remains<sz) { 00053 alloc_mem = (char *) safe_malloc (MMX_BLOCK_SIZE); 00054 alloc_remains= MMX_BLOCK_SIZE - 16; 00055 fast_chunks++; 00056 } 00057 register void* ptr= alloc_mem; 00058 if ((sz&15) == 0 && (((nat) ((uintptr_t) ptr)) & 15) != 0) { 00059 // NOTE: force 16 byte alignment for sizes which are multiples of 16 00060 nat sz2= 16 - (((nat) ((uintptr_t) ptr)) & 15); 00061 MMX_IND (ptr) = MMX_ALLOC_PTR (sz2); 00062 MMX_ALLOC_PTR (sz2) = ptr; 00063 alloc_mem += sz2; 00064 alloc_remains -= sz2; 00065 ptr = alloc_mem; 00066 } 00067 alloc_mem += sz; 00068 alloc_remains-= sz; 00069 return ptr; 00070 } 00071 00072 void* 00073 mmx_malloc_thread_unsafe (register size_t sz) { 00074 if (sz == 0) return NULL; 00075 sz= (sz+MMX_WORD_LENGTH_INC)&MMX_WORD_MASK; 00076 if (sz<MMX_MAX_FAST) { 00077 register void *ptr= MMX_ALLOC_PTR (sz); 00078 if (ptr==NULL) return enlarge_malloc (sz); 00079 //assert (((nat) ptr) != 2); 00080 //assert (((nat) (MMX_IND (ptr))) != 2); 00081 MMX_ALLOC_PTR (sz)= MMX_IND (ptr); 00082 return ptr; 00083 } 00084 else { 00085 //printf ("Big alloc of %d bytes", (int) sz); 00086 //printf ("Memory used: %d bytes", (int) mmx_used_bytes ()); 00087 large_uses += sz; 00088 return safe_malloc (sz); 00089 } 00090 } 00091 00092 void 00093 mmx_free_thread_unsafe (register void* ptr, register size_t sz) { 00094 if (sz == 0) return; 00095 sz=(sz+MMX_WORD_LENGTH_INC)&MMX_WORD_MASK; 00096 if (sz<MMX_MAX_FAST) { 00097 MMX_IND (ptr) = MMX_ALLOC_PTR (sz); 00098 MMX_ALLOC_PTR (sz)= ptr; 00099 } 00100 else { 00101 large_uses -= sz; 00102 safe_free (ptr); 00103 //printf ("Big free of %d bytes", (int) sz); 00104 //printf ("Memory used: %d bytes", (int) mmx_used_bytes ()); 00105 } 00106 } 00107 00108 void* 00109 mmx_realloc_thread_unsafe (register void* old_ptr, register size_t old_sz, 00110 register size_t new_sz) { 00111 void* new_ptr= mmx_malloc_thread_unsafe (new_sz); 00112 memcpy (new_ptr, old_ptr, new_sz < old_sz ? new_sz: old_sz); 00113 mmx_free_thread_unsafe (old_ptr, old_sz); 00114 return new_ptr; 00115 } 00116 00117 size_t 00118 mmx_compute_free (void* ptr) { 00119 nat i= (nat) -1; 00120 while (ptr!=NULL) { 00121 i++; 00122 ptr= MMX_IND (ptr); 00123 } 00124 return i; 00125 } 00126 00127 size_t 00128 mmx_used_bytes () { 00129 size_t free_bytes= alloc_remains; 00130 size_t chunks_use= MMX_BLOCK_SIZE*fast_chunks; 00131 for (nat i=MMX_WORD_LENGTH; i<MMX_MAX_FAST; i+=MMX_WORD_LENGTH) 00132 free_bytes += i*mmx_compute_free (alloc_table+i); 00133 size_t small_uses= chunks_use- free_bytes; 00134 return small_uses+ large_uses; 00135 } 00136 00137 void 00138 mmx_mem_info () { 00139 mmout << "\n---------------- memory statistics ----------------\n"; 00140 size_t free_bytes= alloc_remains; 00141 size_t chunks_use= MMX_BLOCK_SIZE*fast_chunks; 00142 for (nat i=MMX_WORD_LENGTH; i<MMX_MAX_FAST; i+=MMX_WORD_LENGTH) 00143 free_bytes += i*mmx_compute_free (alloc_table+i); 00144 size_t small_uses= chunks_use- free_bytes; 00145 size_t total_uses= small_uses+ large_uses; 00146 // mmout << "Fast chunks : " << chunks_use << " bytes\n"; 00147 // mmout << "Free on chunks: " << alloc_remains << " bytes\n"; 00148 mmout << "User : " << total_uses << " bytes\n"; 00149 mmout << "Allocator : " << chunks_use+ large_uses << " bytes\n"; 00150 mmout << "Small mallocs : " 00151 << ((100*((float) small_uses))/((float) total_uses)) << "%\n"; 00152 } 00153 00154 #else // not MMX_ENABLE_FAST_ALLOCATORS 00155 00156 extern size_t bytes_in_use= 0; 00157 00158 size_t 00159 mmx_used_bytes () { 00160 return bytes_in_use; 00161 } 00162 00163 #endif // MMX_ENABLE_FAST_ALLOCATORS 00164 00165 } // namespace mmx