aboutsummaryrefslogtreecommitdiff
path: root/malloc/arena.c
AgeCommit message (Collapse)Author
2016-10-28malloc: Use accessors for chunk metadata accessFlorian Weimer
This change allows us to change the encoding of these struct members in a centralized fashion.
2016-09-21malloc: Manual part of conversion to __libc_lockFlorian Weimer
This removes the old mutex_t-related definitions from malloc-machine.h, too.
2016-09-06malloc: Automated part of conversion to __libc_lockFlorian Weimer
2016-08-02malloc: Preserve arena free list/thread count invariant [BZ #20370]Florian Weimer
It is necessary to preserve the invariant that if an arena is on the free list, it has thread attach count zero. Otherwise, when arena_thread_freeres sees the zero attach count, it will add it, and without the invariant, an arena could get pushed to the list twice, resulting in a cycle. One possible execution trace looks like this: Thread 1 examines free list and observes it as empty. Thread 2 exits and adds its arena to the free list, with attached_threads == 0). Thread 1 selects this arena in reused_arena (not from the free list). Thread 1 increments attached_threads and attaches itself. (The arena remains on the free list.) Thread 1 exits, decrements attached_threads, and adds the arena to the free list. The final step creates a cycle in the usual way (by overwriting the next_free member with the former list head, while there is another list item pointing to the arena structure). tst-malloc-thread-exit exhibits this issue, but it was only visible with a debugger because the incorrect fix in bug 19243 removed the assert from get_free_list.
2016-06-21malloc: Avoid premature fallback to mmap [BZ #20284]Florian Weimer
Before this change, the while loop in reused_arena which avoids returning a corrupt arena would never execute its body if the selected arena were not corrupt. As a result, result == begin after the loop, and the function returns NULL, triggering fallback to mmap.
2016-06-20Revert __malloc_initialize_hook symbol poisoningFlorian Weimer
It turns out the Emacs-internal malloc implementation uses __malloc_* symbols. If glibc poisons them in <stdc-pre.h>, Emacs will no longer compile.
2016-06-10malloc: Remove __malloc_initialize_hook from the API [BZ #19564]Florian Weimer
__malloc_initialize_hook is interposed by application code, so the usual approach to define a compatibility symbol does not work. This commit adds a new mechanism based on #pragma GCC poison in <stdc-predef.h>.
2016-04-14malloc: Add missing internal_function attributes on function definitionsFlorian Weimer
Fixes build on i386 after commit 29d794863cd6e03115d3670707cc873a9965ba92.
2016-04-14malloc: Remove malloc hooks from fork handlerFlorian Weimer
The fork handler now runs so late that there is no risk anymore that other fork handlers in the same thread use malloc, so it is no longer necessary to install malloc hooks which made a subset of malloc functionality available to the thread that called fork.
2016-04-14malloc: Run fork handler as late as possible [BZ #19431]Florian Weimer
Previously, a thread M invoking fork would acquire locks in this order: (M1) malloc arena locks (in the registered fork handler) (M2) libio list lock A thread F invoking flush (NULL) would acquire locks in this order: (F1) libio list lock (F2) individual _IO_FILE locks A thread G running getdelim would use this order: (G1) _IO_FILE lock (G2) malloc arena lock After executing (M1), (F1), (G1), none of the threads can make progress. This commit changes the fork lock order to: (M'1) libio list lock (M'2) malloc arena locks It explicitly encodes the lock order in the implementations of fork, and does not rely on the registration order, thus avoiding the deadlock.
2016-02-19malloc: Remove NO_THREADSFlorian Weimer
No functional change. It was not possible to build without threading support before.
2016-02-19malloc: Remove arena_mem variableFlorian Weimer
The computed value is never used. The accesses were data races.
2016-01-04Update copyright dates with scripts/update-copyrights.Joseph Myers
2015-12-23malloc: Update comment for list_lockFlorian Weimer
2015-12-21malloc: Fix list_lock/arena lock deadlock [BZ #19182]Florian Weimer
* malloc/arena.c (list_lock): Document lock ordering requirements. (free_list_lock): New lock. (ptmalloc_lock_all): Comment on free_list_lock. (ptmalloc_unlock_all2): Reinitialize free_list_lock. (detach_arena): Update comment. free_list_lock is now needed. (_int_new_arena): Use free_list_lock around detach_arena call. Acquire arena lock after list_lock. Add comment, including FIXME about incorrect synchronization. (get_free_list): Switch to free_list_lock. (reused_arena): Acquire free_list_lock around detach_arena call and attached threads counter update. Add two FIXMEs about incorrect synchronization. (arena_thread_freeres): Switch to free_list_lock. * malloc/malloc.c (struct malloc_state): Update comments to mention free_list_lock.
2015-12-16malloc: Fix attached thread reference count handling [BZ #19243]Florian Weimer
reused_arena can increase the attached thread count of arenas on the free list. This means that the assertion that the reference count is zero is incorrect. In this case, the reference count initialization is incorrect as well and could cause arenas to be put on the free list too early (while they still have attached threads). * malloc/arena.c (get_free_list): Remove assert and adjust reference count handling. Add comment about reused_arena interaction. (reused_arena): Add comments abount get_free_list interaction. * malloc/tst-malloc-thread-exit.c: New file. * malloc/Makefile (tests): Add tst-malloc-thread-exit. (tst-malloc-thread-exit): Link against libpthread.
2015-11-24Replace MUTEX_INITIALIZER with _LIBC_LOCK_INITIALIZER in generic codeFlorian Weimer
* sysdeps/mach/hurd/libc-lock.h (_LIBC_LOCK_INITIALIZER): Define. (__libc_lock_define_initialized): Use it. * sysdeps/nptl/libc-lockP.h (_LIBC_LOCK_INITIALIZER): Define. * malloc/arena.c (list_lock): Use _LIBC_LOCK_INITIALIZER. * malloc/malloc.c (main_arena): Likewise. * sysdeps/generic/malloc-machine.h (MUTEX_INITIALIZER): Remove. * sysdeps/nptl/malloc-machine.h (MUTEX_INITIALIZER): Remove.
2015-10-28malloc: Prevent arena free_list from turning cyclic [BZ #19048]Florian Weimer
[BZ# 19048] * malloc/malloc.c (struct malloc_state): Update comment. Add attached_threads member. (main_arena): Initialize attached_threads. * malloc/arena.c (list_lock): Update comment. (ptmalloc_lock_all, ptmalloc_unlock_all): Likewise. (ptmalloc_unlock_all2): Reinitialize arena reference counts. (deattach_arena): New function. (_int_new_arena): Initialize arena reference count and deattach replaced arena. (get_free_list, reused_arena): Update reference count and deattach replaced arena. (arena_thread_freeres): Update arena reference count and only put unreferenced arenas on the free list.
2015-10-17malloc: Rewrite with explicit TLS access using __threadFlorian Weimer
2015-10-07malloc: Consistently apply trim_threshold to all heaps (Bug 17195)Carlos O'Donell
In the per-thread arenas we apply trim_threshold-based checks to the extra space between the pad and the top_area. This isn't quite accurate and instead we should be harmonizing with the way in which trim_treshold is applied everywhere else like sysrtim and _int_free. The trimming check should be based on the size of the top chunk and only the size of the top chunk. The following patch harmonizes the trimming and make it consistent for the main arena and thread arenas. In the old code a large padding request might have meant that trimming was not triggered. Now trimming is considered first based on the chunk, then the pad is subtracted, and the remainder trimmed. This is how all the other trimmings operate. I didn't measure the performance difference of this change because it corrects what I consider to be a behavioural anomaly. We'll need some profile driven optimization to make this code better, and even there Ondrej and others have better ideas on how to speedup malloc. Tested on x86_64 with no regressions. Already reviewed by Siddhesh Poyarekar and Mel Gorman here and discussed here: https://sourceware.org/ml/libc-alpha/2015-05/msg00002.html
2015-08-24Don't use the main arena in retry path if it is corruptSiddhesh Poyarekar
If allocation on a non-main arena fails, the main arena is used without checking to see if it is corrupt. Add a check that avoids the main arena if it is corrupt. * malloc/arena.c (arena_get_retry): Don't use main_arena if it is corrupt.
2015-08-24Drop unused first argument from arena_get2Siddhesh Poyarekar
The arena pointer in the first argument to arena_get2 was used in the old days before per-thread arenas. They're unused now and hence can be dropped. ChangeLog: * malloc/arena.c (arena_get2): Drop unused argument. (arena_lock): Adjust. (arena_get_retry): Likewise.
2015-06-26malloc: Do not corrupt the top of a threaded heap if top chunk is MINSIZE ↵Mel Gorman
[BZ #18502] mksquashfs was reported in openSUSE to be causing segmentation faults when creating installation images. Testing showed that mksquashfs sometimes failed and could be reproduced within 10 attempts. The core dump looked like the heap top was corrupted and was pointing to an unmapped area. In other cases, this has been due to an application corrupting glibc structures but mksquashfs appears to be fine in this regard. The problem is that heap_trim is "growing" the top into unmapped space. If the top chunk == MINSIZE then top_area is -1 and this check does not behave as expected due to a signed/unsigned comparison if (top_area <= pad) return 0; The next calculation extra = ALIGN_DOWN(top_area - pad, pagesz) calculates extra as a negative number which also is unnoticed due to a signed/unsigned comparison. We then call shrink_heap(heap, negative_number) which crashes later. This patch adds a simple check against MINSIZE to make sure extra does not become negative. It adds a cast to hint to the reader that this is a signed vs unsigned issue. Without the patch, mksquash fails within 10 attempts. With it applied, it completed 1000 times without error. The standard test suite "make check" showed no changes in the summary of test results.
2015-05-19Avoid deadlock in malloc on backtrace (BZ #16159)Siddhesh Poyarekar
When the malloc subsystem detects some kind of memory corruption, depending on the configuration it prints the error, a backtrace, a memory map and then aborts the process. In this process, the backtrace() call may result in a call to malloc, resulting in various kinds of problematic behavior. In one case, the malloc it calls may detect a corruption and call backtrace again, and a stack overflow may result due to the infinite recursion. In another case, the malloc it calls may deadlock on an arena lock with the malloc (or free, realloc, etc.) that detected the corruption. In yet another case, if the program is linked with pthreads, backtrace may do a pthread_once initialization, which deadlocks on itself. In all these cases, the program exit is not as intended. This is avoidable by marking the arena that malloc detected a corruption on, as unusable. The following patch does that. Features of this patch are as follows: - A flag is added to the mstate struct of the arena to indicate if the arena is corrupt. - The flag is checked whenever malloc functions try to get a lock on an arena. If the arena is unusable, a NULL is returned, causing the malloc to use mmap or try the next arena. - malloc_printerr sets the corrupt flag on the arena when it detects a corruption - free does not concern itself with the flag at all. It is not important since the backtrace workflow does not need free. A free in a parallel thread may cause another corruption, but that's not new - The flag check and set are not atomic and may race. This is fine since we don't care about contention during the flag check. We want to make sure that the malloc call in the backtrace does not trip on itself and all that action happens in the same thread and not across threads. I verified that the test case does not show any regressions due to this patch. I also ran the malloc benchmarks and found an insignificant difference in timings (< 2%). * malloc/Makefile (tests): New test case tst-malloc-backtrace. * malloc/arena.c (arena_lock): Check if arena is corrupt. (reused_arena): Find a non-corrupt arena. (heap_trim): Pass arena to unlink. * malloc/hooks.c (malloc_check_get_size): Pass arena to malloc_printerr. (top_check): Likewise. (free_check): Likewise. (realloc_check): Likewise. * malloc/malloc.c (malloc_printerr): Add arena argument. (unlink): Likewise. (munmap_chunk): Adjust. (ARENA_CORRUPTION_BIT): New macro. (arena_is_corrupt): Likewise. (set_arena_corrupt): Likewise. (sysmalloc): Use mmap if there are no usable arenas. (_int_malloc): Likewise. (__libc_malloc): Don't fail if arena_get returns NULL. (_mid_memalign): Likewise. (__libc_calloc): Likewise. (__libc_realloc): Adjust for additional argument to malloc_printerr. (_int_free): Likewise. (malloc_consolidate): Likewise. (_int_realloc): Likewise. (_int_memalign): Don't touch corrupt arenas. * malloc/tst-malloc-backtrace.c: New test case.
2015-04-02malloc: Consistently apply trim_threshold to all heaps [BZ #17195]Mel Gorman
Trimming heaps is a balance between saving memory and the system overhead required to update page tables and discard allocated pages. The malloc option M_TRIM_THRESHOLD is a tunable that users are meant to use to decide where this balance point is but it is only applied to the main arena. For scalability reasons, glibc malloc has per-thread heaps but these are shrunk with madvise() if there is one page free at the top of the heap. In some circumstances this can lead to high system overhead if a thread has a control flow like while (data_to_process) { buf = malloc(large_size); do_stuff(); free(buf); } For a large size, the free() will call madvise (pagetable teardown, page free and TLB flush) every time followed immediately by a malloc (fault, kernel page alloc, zeroing and charge accounting). The kernel overhead can dominate such a workload. This patch allows the user to tune when madvise gets called by applying the trim threshold to the per-thread heaps and using similar logic to the main arena when deciding whether to shrink. Alternatively if the dynamic brk/mmap threshold gets adjusted then the new values will be obeyed by the per-thread heaps. Bug 17195 was a test case motivated by a problem encountered in scientific applications written in python that performance badly due to high page fault overhead. The basic operation of such a program was posted by Julian Taylor https://sourceware.org/ml/libc-alpha/2015-02/msg00373.html With this patch applied, the overhead is eliminated. All numbers in this report are in seconds and were recorded by running Julian's program 30 times. pyarray glibc madvise 2.21 v2 System min 1.81 ( 0.00%) 0.00 (100.00%) System mean 1.93 ( 0.00%) 0.02 ( 99.20%) System stddev 0.06 ( 0.00%) 0.01 ( 88.99%) System max 2.06 ( 0.00%) 0.03 ( 98.54%) Elapsed min 3.26 ( 0.00%) 2.37 ( 27.30%) Elapsed mean 3.39 ( 0.00%) 2.41 ( 28.84%) Elapsed stddev 0.14 ( 0.00%) 0.02 ( 82.73%) Elapsed max 4.05 ( 0.00%) 2.47 ( 39.01%) glibc madvise 2.21 v2 User 141.86 142.28 System 57.94 0.60 Elapsed 102.02 72.66 Note that almost a minutes worth of system time is eliminted and the program completes 28% faster on average. To illustrate the problem without python this is a basic test-case for the worst case scenario where every free is a madvise followed by a an alloc /* gcc bench-free.c -lpthread -o bench-free */ static int num = 1024; void __attribute__((noinline,noclone)) dostuff (void *p) { } void *worker (void *data) { int i; for (i = num; i--;) { void *m = malloc (48*4096); dostuff (m); free (m); } return NULL; } int main() { int i; pthread_t t; void *ret; if (pthread_create (&t, NULL, worker, NULL)) exit (2); if (pthread_join (t, &ret)) exit (3); return 0; } Before the patch, this resulted in 1024 calls to madvise. With the patch applied, madvise is called twice because the default trim threshold is high enough to avoid this. This a more complex case where there is a mix of frees. It's simply a different worker function for the test case above void *worker (void *data) { int i; int j = 0; void *free_index[num]; for (i = num; i--;) { void *m = malloc ((i % 58) *4096); dostuff (m); if (i % 2 == 0) { free (m); } else { free_index[j++] = m; } } for (; j >= 0; j--) { free(free_index[j]); } return NULL; } glibc 2.21 calls malloc 90305 times but with the patch applied, it's called 13438. Increasing the trim threshold will decrease the number of times it's called with the option of eliminating the overhead. ebizzy is meant to generate a workload resembling common web application server workloads. It is threaded with a large working set that at its core has an allocation, do_stuff, free loop that also hits this case. The primary metric of the benchmark is records processed per second. This is running on my desktop which is a single socket machine with an I7-4770 and 8 cores. Each thread count was run for 30 seconds. It was only run once as the performance difference is so high that the variation is insignificant. glibc 2.21 patch threads 1 10230 44114 threads 2 19153 84925 threads 4 34295 134569 threads 8 51007 183387 Note that the saving happens to be a concidence as the size allocated by ebizzy was less than the default threshold. If a different number of chunks were specified then it may also be necessary to tune the threshold to compensate This is roughly quadrupling the performance of this benchmark. The difference in system CPU usage illustrates why. ebizzy running 1 thread with glibc 2.21 10230 records/s 306904 real 30.00 s user 7.47 s sys 22.49 s 22.49 seconds was spent in the kernel for a workload runinng 30 seconds. With the patch applied ebizzy running 1 thread with patch applied 44126 records/s 1323792 real 30.00 s user 29.97 s sys 0.00 s system CPU usage was zero with the patch applied. strace shows that glibc running this workload calls madvise approximately 9000 times a second. With the patch applied madvise was called twice during the workload (or 0.06 times per second). 2015-02-10 Mel Gorman <mgorman@suse.de> [BZ #17195] * malloc/arena.c (free): Apply trim threshold to per-thread heaps as well as the main arena.
2015-02-17Use alignment macros, pagesize and powerof2.Carlos O'Donell
We are replacing all of the bespoke alignment code with ALIGN_UP, ALIGN_DOWN, PTR_ALIGN_UP, and PTR_ALIGN_DOWN. This cleans up malloc/malloc.c, malloc/arena.c, and elf/dl-reloc.c. It also makes all the code consistently use pagesize, and powerof2 as required. Code size is reduced with the removal of precomputed pagemask, and use of pagesize instead. No measurable difference in performance. No regressions on x86_64.
2015-01-02Update copyright dates with scripts/update-copyrights.Joseph Myers
2014-02-10Use glibc_likely instead __builtin_expect.Ondřej Bílka
2014-02-10Remove THREAD_STATS.Ondřej Bílka
A THREAD_STATS macro duplicates gathering information that could be obtained by systemtap probes instead.
2014-01-02Reformat malloc to gnu style.Ondřej Bílka
2014-01-01Update copyright notices with scripts/update-copyrightsAllan McRae
2013-12-10Drop PER_THREAD conditionals from malloc.Ondřej Bílka
2013-12-09Replace malloc force_reg by atomic_forced_read.Ondřej Bílka
2013-09-20Add malloc probes for sbrk and heap resizing.Alexandre Oliva
for ChangeLog * malloc/arena.c (new_heap): New memory_heap_new probe. (grow_heap): New memory_heap_more probe. (shrink_heap): New memory_heap_less probe. (heap_trim): New memory_heap_free probe. * malloc/malloc.c (sysmalloc): New memory_sbrk_more probe. (systrim): New memory_sbrk_less probe. * manual/probes.texi: Document them.
2013-09-20Add catch-all alloc retry probe.Alexandre Oliva
for ChangeLog * malloc/arena.c (arena_get_retry): Add memory_arena_retry probe. * manual/probes.texi: Document it.
2013-09-20Add probes for malloc arena changes.Alexandre Oliva
for ChangeLog * malloc/arena.c (get_free_list): Add probe memory_arena_reuse_free_list. (reused_arena) [PER_THREAD]: Add probes memory_arena_reuse_wait and memory_arena_reuse. (arena_get2) [!PER_THREAD]: Likewise. * malloc/malloc.c (__libc_realloc) [!PER_THREAD]: Add probe memory_arena_reuse_realloc. * manual/probes.texi: Document them.
2013-09-20Add first set of memory probes.Alexandre Oliva
for ChangeLog * malloc/malloc.c: Include stap-probe.h. (__libc_mallopt): Add memory_mallopt probe. * malloc/arena.c (_int_new_arena): Add memory_arena_new probe. * manual/probes.texi: New. * manual/Makefile (chapters): Add probes. * manual/threads.texi: Set next node.
2013-03-08Remove __malloc_ptr_t.Joseph Myers
2013-01-17Add HAVE_MREMAP for mremap usagePino Toscano
Introduce (only on Linux) and use a HAVE_MREMAP symbol to advertize mremap availability. Move the malloc-sysdep.h include from arena.c to malloc.c, since what is provided by malloc-sysdep.h is needed earlier in malloc.c, before the inclusion of arena.c.
2013-01-02Update copyright notices with scripts/update-copyrights.Joseph Myers
2012-10-04Name space hygeine for madvise.Roland McGrath
2012-09-25Shrink heap on linux when overcommit_memory == 2Siddhesh Poyarekar
Using madvise with MADV_DONTNEED to release memory back to the kernel is not sufficient to change the commit charge accounted against the process on Linux. It is OK however, when overcommit is enabled or is heuristic. However, when overcommit is restricted to a percentage of memory setting the contents of /proc/sys/vm/overcommit_memory as 2, it makes a difference since memory requests will fail. Hence, we do what we do with secure exec binaries, which is to call mmap on the region to be dropped with MAP_FIXED. This internally unmaps the pages in question and reduces the amount of memory accounted against the process.
2012-09-24Properly handle fencepost with MALLOC_ALIGN_MASKH.J. Lu
2012-09-07Cleanup code duplication in malloc on fallback to use another arenaSiddhesh Poyarekar
Break the fallback code to try another arena into a separate function for readability.
2012-09-05* malloc/arena.c: Fold copyright years.Alexandre Oliva
* malloc/mcheck.c, malloc/memusage.c: Likewise.
2012-08-17Make malloc build for no-threads configurations.Roland McGrath
2012-08-10Fix whitespace problems detected by commit hooks.Jeff Law
2012-08-10 [BZ #13939]Jeff Law
* malloc.c/arena.c (reused_arena): New parameter, avoid_arena. When avoid_arena is set, don't retry in the that arena. Pick the next one, whatever it might be. (arena_get2): New parameter avoid_arena, pass through to reused_arena. (arena_lock): Pass in new parameter to arena_get2. * malloc/malloc.c (__libc_memalign): Pass in new parameter to arena_get2. (__libc_malloc): Unify retrying after main arena failure with __libc_memalign version. (__libc_valloc, __libc_pvalloc, __libc_calloc): Likewise.
2012-02-09Replace FSF snail mail address with URLs.Paul Eggert
2012-01-31Cleanups of mallocUlrich Drepper
Remove ugly names and unnecessary wrappers.