about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2022-11-20 09:14:24 +0000
committerEric Wong <e@80x24.org>2022-12-02 09:40:01 +0000
commite20367559b8bd677b7386818cb8a672b003f2e25 (patch)
treee0828951efa30bf5d058e98b68cdcd824519f908
parent45c7129666ba9e1f82f23f5d6211e0805b04c999 (diff)
downloadmwrap-e20367559b8bd677b7386818cb8a672b003f2e25.tar.gz
There's no need to worry about race conditions if operating on
idle arenas, so clean them up immediately rather than cleaning
them up after a pthread_create (which may never come).

We'll also inform active threads about the trim earlier so they
have more cycles to react to the lazy trim request.
-rw-r--r--mymalloc.h29
1 files changed, 18 insertions, 11 deletions
diff --git a/mymalloc.h b/mymalloc.h
index e789cf3..4904b74 100644
--- a/mymalloc.h
+++ b/mymalloc.h
@@ -150,23 +150,30 @@ static void remote_free_finish(mstate ms)
 
 int malloc_trim(size_t pad)
 {
-        mstate ms = ms_tsd;
+        mstate m;
+        int ret = 0;
 
         CHECK(int, 0, pthread_mutex_lock(&global_mtx));
-        { /* be lazy for sibling threads, readers are not synchronized */
-                mstate m;
-                cds_list_for_each_entry(m, &arenas_unused, arena_node)
-                        uatomic_set(&m->trim_check, 0);
-                cds_list_for_each_entry(m, &arenas_active, arena_node)
-                        uatomic_set(&m->trim_check, 0);
+
+        /* be lazy for active sibling threads, readers are not synchronized */
+        cds_list_for_each_entry(m, &arenas_active, arena_node)
+                uatomic_set(&m->trim_check, 0);
+
+        /* nobody is using idle arenas, clean immediately */
+        cds_list_for_each_entry(m, &arenas_unused, arena_node) {
+                m->trim_check = 0;
+                remote_free_finish(m);
+                ret |= sys_trim(m, pad);
         }
+
         CHECK(int, 0, pthread_mutex_unlock(&global_mtx));
 
-        if (ms) { /* trim our own arena immediately */
-                remote_free_finish(ms);
-                return sys_trim(ms, pad);
+        m = ms_tsd;
+        if (m) { /* trim our own arena immediately */
+                remote_free_finish(m);
+                ret |= sys_trim(m, pad);
         }
-        return 0;
+        return ret;
 }
 
 static void remote_free_enqueue(mstate fm, void *mem)