📄 malloc.c
字号:
/* bin<->block macros */#define idx2binblock(ix) ((unsigned)1 << ((ix) / BINBLOCKWIDTH))#define mark_binblock(a, ii) (binblocks(a) |= idx2binblock(ii))#define clear_binblock(a, ii) (binblocks(a) &= ~(idx2binblock(ii)))/* Static bookkeeping data *//* Helper macro to initialize bins */#define IAV(i) _bin_at(&main_arena, i), _bin_at(&main_arena, i)static arena main_arena = { { 0, 0, IAV(0), IAV(1), IAV(2), IAV(3), IAV(4), IAV(5), IAV(6), IAV(7), IAV(8), IAV(9), IAV(10), IAV(11), IAV(12), IAV(13), IAV(14), IAV(15), IAV(16), IAV(17), IAV(18), IAV(19), IAV(20), IAV(21), IAV(22), IAV(23), IAV(24), IAV(25), IAV(26), IAV(27), IAV(28), IAV(29), IAV(30), IAV(31), IAV(32), IAV(33), IAV(34), IAV(35), IAV(36), IAV(37), IAV(38), IAV(39), IAV(40), IAV(41), IAV(42), IAV(43), IAV(44), IAV(45), IAV(46), IAV(47), IAV(48), IAV(49), IAV(50), IAV(51), IAV(52), IAV(53), IAV(54), IAV(55), IAV(56), IAV(57), IAV(58), IAV(59), IAV(60), IAV(61), IAV(62), IAV(63), IAV(64), IAV(65), IAV(66), IAV(67), IAV(68), IAV(69), IAV(70), IAV(71), IAV(72), IAV(73), IAV(74), IAV(75), IAV(76), IAV(77), IAV(78), IAV(79), IAV(80), IAV(81), IAV(82), IAV(83), IAV(84), IAV(85), IAV(86), IAV(87), IAV(88), IAV(89), IAV(90), IAV(91), IAV(92), IAV(93), IAV(94), IAV(95), IAV(96), IAV(97), IAV(98), IAV(99), IAV(100), IAV(101), IAV(102), IAV(103), IAV(104), IAV(105), IAV(106), IAV(107), IAV(108), IAV(109), IAV(110), IAV(111), IAV(112), IAV(113), IAV(114), IAV(115), IAV(116), IAV(117), IAV(118), IAV(119), IAV(120), IAV(121), IAV(122), IAV(123), IAV(124), IAV(125), IAV(126), IAV(127) }, &main_arena, /* next */ 0, /* size */#if THREAD_STATS 0, 0, 0, /* stat_lock_direct, stat_lock_loop, stat_lock_wait */#endif MUTEX_INITIALIZER /* mutex */};#undef IAV/* Thread specific data */static tsd_key_t arena_key;static mutex_t list_lock = MUTEX_INITIALIZER;#if THREAD_STATSstatic int stat_n_heaps;#define THREAD_STAT(x) x#else#define THREAD_STAT(x) do ; while(0)#endif/* variables holding tunable values */static unsigned long trim_threshold = DEFAULT_TRIM_THRESHOLD;static unsigned long top_pad = DEFAULT_TOP_PAD;static unsigned int n_mmaps_max = DEFAULT_MMAP_MAX;static unsigned long mmap_threshold = DEFAULT_MMAP_THRESHOLD;static int check_action = DEFAULT_CHECK_ACTION;/* The first value returned from sbrk */static char* sbrk_base = (char*)(-1);/* The maximum memory obtained from system via sbrk */static unsigned long max_sbrked_mem;/* The maximum via either sbrk or mmap (too difficult to track with threads) */#ifdef NO_THREADSstatic unsigned long max_total_mem;#endif/* The total memory obtained from system via sbrk */#define sbrked_mem (main_arena.size)/* Tracking mmaps */static unsigned int n_mmaps;static unsigned int max_n_mmaps;static unsigned long mmapped_mem;static unsigned long max_mmapped_mem;/* Mapped memory in non-main arenas (reliable only for NO_THREADS). */static unsigned long arena_mem;#ifndef _LIBC#define weak_variable#else/* In GNU libc we want the hook variables to be weak definitions to avoid a problem with Emacs. */#define weak_variable weak_function#endif/* Already initialized? */int __malloc_initialized = -1;#ifndef NO_THREADS/* Magic value for the thread-specific arena pointer when malloc_atfork() is in use. */#define ATFORK_ARENA_PTR ((Void_t*)-1)/* The following two functions are registered via thread_atfork() to make sure that the mutexes remain in a consistent state in the fork()ed version of a thread. Also adapt the malloc and free hooks temporarily, because the `atfork' handler mechanism may use malloc/free internally (e.g. in LinuxThreads). */#if defined _LIBC || defined MALLOC_HOOKSstatic __malloc_ptr_t (*save_malloc_hook) __MALLOC_P ((size_t __size, const __malloc_ptr_t));static void (*save_free_hook) __MALLOC_P ((__malloc_ptr_t __ptr, const __malloc_ptr_t));static Void_t* save_arena;#endifstatic voidptmalloc_lock_all __MALLOC_P((void)){ arena *ar_ptr; (void)mutex_lock(&list_lock); for(ar_ptr = &main_arena;;) { (void)mutex_lock(&ar_ptr->mutex); ar_ptr = ar_ptr->next; if(ar_ptr == &main_arena) break; }#if defined _LIBC || defined MALLOC_HOOKS save_malloc_hook = __malloc_hook; save_free_hook = __free_hook; __malloc_hook = malloc_atfork; __free_hook = free_atfork; /* Only the current thread may perform malloc/free calls now. */ tsd_getspecific(arena_key, save_arena); tsd_setspecific(arena_key, ATFORK_ARENA_PTR);#endif}static voidptmalloc_unlock_all __MALLOC_P((void)){ arena *ar_ptr;#if defined _LIBC || defined MALLOC_HOOKS tsd_setspecific(arena_key, save_arena); __malloc_hook = save_malloc_hook; __free_hook = save_free_hook;#endif for(ar_ptr = &main_arena;;) { (void)mutex_unlock(&ar_ptr->mutex); ar_ptr = ar_ptr->next; if(ar_ptr == &main_arena) break; } (void)mutex_unlock(&list_lock);}static voidptmalloc_init_all __MALLOC_P((void)){ arena *ar_ptr;#if defined _LIBC || defined MALLOC_HOOKS tsd_setspecific(arena_key, save_arena); __malloc_hook = save_malloc_hook; __free_hook = save_free_hook;#endif for(ar_ptr = &main_arena;;) { (void)mutex_init(&ar_ptr->mutex); ar_ptr = ar_ptr->next; if(ar_ptr == &main_arena) break; } (void)mutex_init(&list_lock);}#endif /* !defined NO_THREADS *//* Initialization routine. */#if defined(_LIBC)#if 0static void ptmalloc_init __MALLOC_P ((void)) __attribute__ ((constructor));#endif#ifdef _LIBC#include <string.h>extern char **environ;static char *internal_functionnext_env_entry (char ***position){ char **current = *position; char *result = NULL; while (*current != NULL) { if (__builtin_expect ((*current)[0] == 'M', 0) && (*current)[1] == 'A' && (*current)[2] == 'L' && (*current)[3] == 'L' && (*current)[4] == 'O' && (*current)[5] == 'C' && (*current)[6] == '_') { result = &(*current)[7]; /* Save current position for next visit. */ *position = ++current; break; } ++current; } return result;}#endifstatic voidptmalloc_init __MALLOC_P((void))#elsevoidptmalloc_init __MALLOC_P((void))#endif{#if defined _LIBC || defined MALLOC_HOOKS# if __STD_C const char* s;# else char* s;# endif#endif int secure; if(__malloc_initialized >= 0) return; __malloc_initialized = 0;#ifdef _LIBC __libc_pagesize = __getpagesize();#endif#ifndef NO_THREADS#if defined _LIBC || defined MALLOC_HOOKS /* With some threads implementations, creating thread-specific data or initializing a mutex may call malloc() itself. Provide a simple starter version (realloc() won't work). */ save_malloc_hook = __malloc_hook; save_free_hook = __free_hook; __malloc_hook = malloc_starter; __free_hook = free_starter;#endif#ifdef _LIBC /* Initialize the pthreads interface. */ if (__pthread_initialize != NULL) __pthread_initialize();#endif#endif /* !defined NO_THREADS */ mutex_init(&main_arena.mutex); mutex_init(&list_lock); tsd_key_create(&arena_key, NULL); tsd_setspecific(arena_key, (Void_t *)&main_arena); thread_atfork(ptmalloc_lock_all, ptmalloc_unlock_all, ptmalloc_init_all);#if defined _LIBC || defined MALLOC_HOOKS#ifndef NO_THREADS __malloc_hook = save_malloc_hook; __free_hook = save_free_hook;#endif secure = __libc_enable_secure;#ifdef _LIBC s = NULL; if (environ != NULL) { char **runp = environ; char *envline; while (__builtin_expect ((envline = next_env_entry (&runp)) != NULL, 0)) { size_t len = strcspn (envline, "="); if (envline[len] != '=') /* This is a "MALLOC_" variable at the end of the string without a '=' character. Ignore it since otherwise we will access invalid memory below. */ continue; switch (len) { case 6: if (memcmp (envline, "CHECK_", 6) == 0) s = &envline[7]; break; case 8: if (! secure && memcmp (envline, "TOP_PAD_", 8) == 0) mALLOPt(M_TOP_PAD, atoi(&envline[9])); break; case 9: if (! secure && memcmp (envline, "MMAP_MAX_", 9) == 0) mALLOPt(M_MMAP_MAX, atoi(&envline[10])); break; case 15: if (! secure) { if (memcmp (envline, "TRIM_THRESHOLD_", 15) == 0) mALLOPt(M_TRIM_THRESHOLD, atoi(&envline[16])); else if (memcmp (envline, "MMAP_THRESHOLD_", 15) == 0) mALLOPt(M_MMAP_THRESHOLD, atoi(&envline[16])); } break; default: break; } } }#else if (! secure) { if((s = getenv("MALLOC_TRIM_THRESHOLD_"))) mALLOPt(M_TRIM_THRESHOLD, atoi(s)); if((s = getenv("MALLOC_TOP_PAD_"))) mALLOPt(M_TOP_PAD, atoi(s)); if((s = getenv("MALLOC_MMAP_THRESHOLD_"))) mALLOPt(M_MMAP_THRESHOLD, atoi(s)); if((s = getenv("MALLOC_MMAP_MAX_"))) mALLOPt(M_MMAP_MAX, atoi(s)); } s = getenv("MALLOC_CHECK_");#endif if(s) { if(s[0]) mALLOPt(M_CHECK_ACTION, (int)(s[0] - '0')); __malloc_check_init(); } if(__malloc_initialize_hook != NULL) (*__malloc_initialize_hook)();#endif __malloc_initialized = 1;}/* There are platforms (e.g. Hurd) with a link-time hook mechanism. */#ifdef thread_atfork_staticthread_atfork_static(ptmalloc_lock_all, ptmalloc_unlock_all, \ ptmalloc_init_all)#endif#if defined _LIBC || defined MALLOC_HOOKS/* Hooks for debugging versions. The initial hooks just call the initialization routine, then do the normal work. */static Void_t*#if __STD_Cmalloc_hook_ini(size_t sz, const __malloc_ptr_t caller)#elsemalloc_hook_ini(sz, caller) size_t sz; const __malloc_ptr_t caller;#endif{ __malloc_hook = NULL; ptmalloc_init(); return mALLOc(sz);}static Void_t*#if __STD_Crealloc_hook_ini(Void_t* ptr, size_t sz, const __malloc_ptr_t caller)#elserealloc_hook_ini(ptr, sz, caller) Void_t* ptr; size_t sz; const __malloc_ptr_t caller;#endif{ __malloc_hook
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -