void TUNABLE_CALLBACK (set_mallopt_check) (tunable_val_t *valp) { int32_t value = (int32_t) valp->numval; if (value != 0) __malloc_check_init (); }
static void ptmalloc_init (void) { #if __STD_C const char* s; #else char* s; #endif int secure = 0; if(__malloc_initialized >= 0) return; __malloc_initialized = 0; #ifdef _LIBC # if defined SHARED && defined USE_TLS && !USE___THREAD /* ptmalloc_init_minimal may already have been called via __libc_malloc_pthread_startup, above. */ if (mp_.pagesize == 0) # endif #endif ptmalloc_init_minimal(); #ifndef NO_THREADS # if defined _LIBC && defined USE_TLS /* We know __pthread_initialize_minimal has already been called, and that is enough. */ # define NO_STARTER # endif # ifndef NO_STARTER /* 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_memalign_hook = __memalign_hook; save_free_hook = __free_hook; __malloc_hook = malloc_starter; __memalign_hook = memalign_starter; __free_hook = free_starter; # ifdef _LIBC /* Initialize the pthreads interface. */ if (__pthread_initialize != NULL) __pthread_initialize(); # endif /* !defined _LIBC */ # endif /* !defined NO_STARTER */ #endif /* !defined NO_THREADS */ mutex_init(&main_arena.mutex); main_arena.next = &main_arena; #if defined _LIBC && defined SHARED /* In case this libc copy is in a non-default namespace, never use brk. Likewise if dlopened from statically linked program. */ Dl_info di; struct link_map *l; if (_dl_open_hook != NULL || (_dl_addr (ptmalloc_init, &di, &l, NULL) != 0 && l->l_ns != LM_ID_BASE)) __morecore = __failing_morecore; #endif 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_unlock_all2); #ifndef NO_THREADS # ifndef NO_STARTER __malloc_hook = save_malloc_hook; __memalign_hook = save_memalign_hook; __free_hook = save_free_hook; # else # undef NO_STARTER # endif #endif #ifdef _LIBC secure = __libc_enable_secure; s = NULL; if (__builtin_expect (_environ != NULL, 1)) { 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) { if (memcmp (envline, "TOP_PAD_", 8) == 0) mALLOPt(M_TOP_PAD, atoi(&envline[9])); else if (memcmp (envline, "PERTURB_", 8) == 0) mALLOPt(M_PERTURB, 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_PERTURB_"))) mALLOPt(M_PERTURB, 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')); if (check_action != 0) __malloc_check_init(); } if(__malloc_initialize_hook != NULL) (*__malloc_initialize_hook)(); __malloc_initialized = 1; }
static void ptmalloc_init (void) { if(__malloc_initialized >= 0) return; __malloc_initialized = 0; #ifdef SHARED /* In case this libc copy is in a non-default namespace, never use brk. Likewise if dlopened from statically linked program. */ Dl_info di; struct link_map *l; if (_dl_open_hook != NULL || (_dl_addr (ptmalloc_init, &di, &l, NULL) != 0 && l->l_ns != LM_ID_BASE)) __morecore = __failing_morecore; #endif tsd_key_create(&arena_key, NULL); tsd_setspecific(arena_key, (void *)&main_arena); thread_atfork(ptmalloc_lock_all, ptmalloc_unlock_all, ptmalloc_unlock_all2); const char *s = NULL; if (__builtin_expect (_environ != NULL, 1)) { 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 (! __builtin_expect (__libc_enable_secure, 0)) { if (memcmp (envline, "TOP_PAD_", 8) == 0) __libc_mallopt(M_TOP_PAD, atoi(&envline[9])); else if (memcmp (envline, "PERTURB_", 8) == 0) __libc_mallopt(M_PERTURB, atoi(&envline[9])); } break; case 9: if (! __builtin_expect (__libc_enable_secure, 0)) { if (memcmp (envline, "MMAP_MAX_", 9) == 0) __libc_mallopt(M_MMAP_MAX, atoi(&envline[10])); #ifdef PER_THREAD else if (memcmp (envline, "ARENA_MAX", 9) == 0) __libc_mallopt(M_ARENA_MAX, atoi(&envline[10])); #endif } break; #ifdef PER_THREAD case 10: if (! __builtin_expect (__libc_enable_secure, 0)) { if (memcmp (envline, "ARENA_TEST", 10) == 0) __libc_mallopt(M_ARENA_TEST, atoi(&envline[11])); } break; #endif case 15: if (! __builtin_expect (__libc_enable_secure, 0)) { if (memcmp (envline, "TRIM_THRESHOLD_", 15) == 0) __libc_mallopt(M_TRIM_THRESHOLD, atoi(&envline[16])); else if (memcmp (envline, "MMAP_THRESHOLD_", 15) == 0) __libc_mallopt(M_MMAP_THRESHOLD, atoi(&envline[16])); } break; default: break; } } } if(s && s[0]) { __libc_mallopt(M_CHECK_ACTION, (int)(s[0] - '0')); if (check_action != 0) __malloc_check_init(); } void (*hook) (void) = force_reg (__malloc_initialize_hook); if (hook != NULL) (*hook)(); __malloc_initialized = 1; }
int __malloc_set_state(void* msptr) { struct malloc_save_state* ms = (struct malloc_save_state*)msptr; size_t i; mbinptr b; disallow_malloc_check = 1; ptmalloc_init(); if(ms->magic != MALLOC_STATE_MAGIC) return -1; /* Must fail if the major version is too high. */ if((ms->version & ~0xffl) > (MALLOC_STATE_VERSION & ~0xffl)) return -2; (void)mutex_lock(&main_arena.mutex); /* There are no fastchunks. */ clear_fastchunks(&main_arena); if (ms->version >= 4) set_max_fast(ms->max_fast); else set_max_fast(64); /* 64 used to be the value we always used. */ for (i=0; i<NFASTBINS; ++i) fastbin (&main_arena, i) = 0; for (i=0; i<BINMAPSIZE; ++i) main_arena.binmap[i] = 0; top(&main_arena) = ms->av[2]; main_arena.last_remainder = 0; for(i=1; i<NBINS; i++) { b = bin_at(&main_arena, i); if(ms->av[2*i+2] == 0) { assert(ms->av[2*i+3] == 0); first(b) = last(b) = b; } else { if(ms->version >= 3 && (i<NSMALLBINS || (largebin_index(chunksize(ms->av[2*i+2]))==i && largebin_index(chunksize(ms->av[2*i+3]))==i))) { first(b) = ms->av[2*i+2]; last(b) = ms->av[2*i+3]; /* Make sure the links to the bins within the heap are correct. */ first(b)->bk = b; last(b)->fd = b; /* Set bit in binblocks. */ mark_bin(&main_arena, i); } else { /* Oops, index computation from chunksize must have changed. Link the whole list into unsorted_chunks. */ first(b) = last(b) = b; b = unsorted_chunks(&main_arena); ms->av[2*i+2]->bk = b; ms->av[2*i+3]->fd = b->fd; b->fd->bk = ms->av[2*i+3]; b->fd = ms->av[2*i+2]; } } } if (ms->version < 3) { /* Clear fd_nextsize and bk_nextsize fields. */ b = unsorted_chunks(&main_arena)->fd; while (b != unsorted_chunks(&main_arena)) { if (!in_smallbin_range(chunksize(b))) { b->fd_nextsize = NULL; b->bk_nextsize = NULL; } b = b->fd; } } mp_.sbrk_base = ms->sbrk_base; main_arena.system_mem = ms->sbrked_mem_bytes; mp_.trim_threshold = ms->trim_threshold; mp_.top_pad = ms->top_pad; mp_.n_mmaps_max = ms->n_mmaps_max; mp_.mmap_threshold = ms->mmap_threshold; check_action = ms->check_action; main_arena.max_system_mem = ms->max_sbrked_mem; mp_.n_mmaps = ms->n_mmaps; mp_.max_n_mmaps = ms->max_n_mmaps; mp_.mmapped_mem = ms->mmapped_mem; mp_.max_mmapped_mem = ms->max_mmapped_mem; /* add version-dependent code here */ if (ms->version >= 1) { /* Check whether it is safe to enable malloc checking, or whether it is necessary to disable it. */ if (ms->using_malloc_checking && !using_malloc_checking && !disallow_malloc_check) __malloc_check_init (); else if (!ms->using_malloc_checking && using_malloc_checking) { __malloc_hook = NULL; __free_hook = NULL; __realloc_hook = NULL; __memalign_hook = NULL; using_malloc_checking = 0; } } if (ms->version >= 4) { #ifdef PER_THREAD mp_.arena_test = ms->arena_test; mp_.arena_max = ms->arena_max; narenas = ms->narenas; #endif } check_malloc_state(&main_arena); (void)mutex_unlock(&main_arena.mutex); return 0; }
static void ptmalloc_init (void) { if (__malloc_initialized >= 0) return; __malloc_initialized = 0; #ifdef SHARED /* In case this libc copy is in a non-default namespace, never use brk. Likewise if dlopened from statically linked program. */ Dl_info di; struct link_map *l; if (_dl_open_hook != NULL || (_dl_addr (ptmalloc_init, &di, &l, NULL) != 0 && l->l_ns != LM_ID_BASE)) __morecore = __failing_morecore; #endif thread_arena = &main_arena; malloc_init_state (&main_arena); #if HAVE_TUNABLES TUNABLE_GET (check, int32_t, TUNABLE_CALLBACK (set_mallopt_check)); TUNABLE_GET (top_pad, size_t, TUNABLE_CALLBACK (set_top_pad)); TUNABLE_GET (perturb, int32_t, TUNABLE_CALLBACK (set_perturb_byte)); TUNABLE_GET (mmap_threshold, size_t, TUNABLE_CALLBACK (set_mmap_threshold)); TUNABLE_GET (trim_threshold, size_t, TUNABLE_CALLBACK (set_trim_threshold)); TUNABLE_GET (mmap_max, int32_t, TUNABLE_CALLBACK (set_mmaps_max)); TUNABLE_GET (arena_max, size_t, TUNABLE_CALLBACK (set_arena_max)); TUNABLE_GET (arena_test, size_t, TUNABLE_CALLBACK (set_arena_test)); # if USE_TCACHE TUNABLE_GET (tcache_max, size_t, TUNABLE_CALLBACK (set_tcache_max)); TUNABLE_GET (tcache_count, size_t, TUNABLE_CALLBACK (set_tcache_count)); TUNABLE_GET (tcache_unsorted_limit, size_t, TUNABLE_CALLBACK (set_tcache_unsorted_limit)); # endif #else const char *s = NULL; if (__glibc_likely (_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 (!__builtin_expect (__libc_enable_secure, 0)) { if (memcmp (envline, "TOP_PAD_", 8) == 0) __libc_mallopt (M_TOP_PAD, atoi (&envline[9])); else if (memcmp (envline, "PERTURB_", 8) == 0) __libc_mallopt (M_PERTURB, atoi (&envline[9])); } break; case 9: if (!__builtin_expect (__libc_enable_secure, 0)) { if (memcmp (envline, "MMAP_MAX_", 9) == 0) __libc_mallopt (M_MMAP_MAX, atoi (&envline[10])); else if (memcmp (envline, "ARENA_MAX", 9) == 0) __libc_mallopt (M_ARENA_MAX, atoi (&envline[10])); } break; case 10: if (!__builtin_expect (__libc_enable_secure, 0)) { if (memcmp (envline, "ARENA_TEST", 10) == 0) __libc_mallopt (M_ARENA_TEST, atoi (&envline[11])); } break; case 15: if (!__builtin_expect (__libc_enable_secure, 0)) { if (memcmp (envline, "TRIM_THRESHOLD_", 15) == 0) __libc_mallopt (M_TRIM_THRESHOLD, atoi (&envline[16])); else if (memcmp (envline, "MMAP_THRESHOLD_", 15) == 0) __libc_mallopt (M_MMAP_THRESHOLD, atoi (&envline[16])); } break; default: break; } } } if (s && s[0] != '\0' && s[0] != '0') __malloc_check_init (); #endif #if HAVE_MALLOC_INIT_HOOK void (*hook) (void) = atomic_forced_read (__malloc_initialize_hook); if (hook != NULL) (*hook)(); #endif __malloc_initialized = 1; }