[5/5] Add single-threaded path to _int_malloc
Commit Message
This patch adds a single-threaded fast path to _int_malloc.
Since the goal is to use a single test to skip multiple atomic
operations, some of the fastbin allocation code has to be
duplicated.
Passes GLIBC tests, OK for commit?
ChangeLog:
2017-10-11 Wilco Dijkstra <wdijkstr@arm.com>
* malloc/malloc.c (_int_malloc): Add SINGLE_THREAD_P path.
--
@@ -3565,37 +3565,77 @@ _int_malloc (mstate av, size_t bytes)
{
idx = fastbin_index (nb);
mfastbinptr *fb = &fastbin (av, idx);
- mchunkptr pp = *fb;
- REMOVE_FB (fb, victim, pp);
- if (victim != 0)
- {
- if (__builtin_expect (fastbin_index (chunksize (victim)) != idx, 0))
- malloc_printerr ("malloc(): memory corruption (fast)");
- check_remalloced_chunk (av, victim, nb);
-#if USE_TCACHE
- /* While we're here, if we see other chunks of the same size,
- stash them in the tcache. */
- size_t tc_idx = csize2tidx (nb);
- if (tcache && tc_idx < mp_.tcache_bins)
- {
- mchunkptr tc_victim;
+ mchunkptr next;
- /* While bin not empty and tcache not full, copy chunks over. */
- while (tcache->counts[tc_idx] < mp_.tcache_count
- && (pp = *fb) != NULL)
+ if (SINGLE_THREAD_P)
+ {
+ victim = *fb;
+ if (victim != NULL)
+ {
+ size_t victim_idx = fastbin_index (chunksize (victim));
+ next = victim->fd;
+ if (__builtin_expect (victim_idx != idx, 0))
+ malloc_printerr ("malloc(): memory corruption (fast)");
+ check_remalloced_chunk (av, victim, nb);
+#if USE_TCACHE
+ /* While we're here, if we see other chunks of the same size,
+ stash them in the tcache. */
+ size_t tc_idx = csize2tidx (nb);
+ if (next != NULL && tcache && tc_idx < mp_.tcache_bins)
{
- REMOVE_FB (fb, tc_victim, pp);
- if (tc_victim != 0)
+ mchunkptr tc_victim;
+
+ /* While bin not empty and tcache not full, copy chunks. */
+ while (tcache->counts[tc_idx] < mp_.tcache_count)
{
+ tc_victim = next;
+ next = tc_victim->fd;
tcache_put (tc_victim, tc_idx);
- }
+ if (next == NULL)
+ break;
+ }
}
- }
#endif
- void *p = chunk2mem (victim);
- alloc_perturb (p, bytes);
- return p;
+ *fb = next;
+ void *p = chunk2mem (victim);
+ alloc_perturb (p, bytes);
+ return p;
+ }
}
+ else
+ {
+ next = *fb;
+ REMOVE_FB (fb, victim, next);
+ if (victim != 0)
+ {
+ size_t victim_idx = fastbin_index (chunksize (victim));
+ if (__builtin_expect (victim_idx != idx, 0))
+ malloc_printerr ("malloc(): memory corruption (fast)");
+ check_remalloced_chunk (av, victim, nb);
+#if USE_TCACHE
+ /* While we're here, if we see other chunks of the same size,
+ stash them in the tcache. */
+ size_t tc_idx = csize2tidx (nb);
+ if (tcache && tc_idx < mp_.tcache_bins)
+ {
+ mchunkptr tc_victim;
+
+ /* While bin not empty and tcache not full, copy chunks. */
+ while (tcache->counts[tc_idx] < mp_.tcache_count
+ && (next = *fb) != NULL)
+ {
+ REMOVE_FB (fb, tc_victim, next);
+ if (tc_victim == NULL)
+ break;
+ tcache_put (tc_victim, tc_idx);
+ }
+ }
+#endif
+ void *p = chunk2mem (victim);
+ alloc_perturb (p, bytes);
+ return p;
+ }
+ }
}
/*