Skip to content

Commit 4e50cec

Browse files
committed
avoid resetting the global purge counter if arena purge expire was not yet reached, possible fix for issue #1246
1 parent 661fe25 commit 4e50cec

1 file changed

Lines changed: 24 additions & 13 deletions

File tree

src/arena.c

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -550,16 +550,22 @@ static bool mi_arena_purge_range(mi_arena_t* arena, size_t idx, size_t startidx,
550550
return all_purged;
551551
}
552552

553-
// returns true if anything was purged
554-
static bool mi_arena_try_purge(mi_arena_t* arena, mi_msecs_t now, bool force)
553+
// returns
554+
// -1 = nothing was purged
555+
// 0 = nothing was purged yet because have not yet reached the expire time
556+
// 1 = some pages in the arena were purged
557+
static int mi_arena_try_purge(mi_arena_t* arena, mi_msecs_t now, bool force)
555558
{
556559
// check pre-conditions
557-
if (arena->memid.is_pinned) return false;
560+
if (arena->memid.is_pinned) return -1;
558561

559562
// expired yet?
560563
mi_msecs_t expire = mi_atomic_loadi64_relaxed(&arena->purge_expire);
561-
if (!force && (expire == 0 || expire > now)) return false;
562-
564+
if (!force) {
565+
if (expire == 0) return -1;
566+
if (expire > now) return 0;
567+
}
568+
563569
// reset expire (if not already set concurrently)
564570
mi_atomic_casi64_strong_acq_rel(&arena->purge_expire, &expire, (mi_msecs_t)0);
565571
_mi_stat_counter_increase(&_mi_stats_main.arena_purges, 1);
@@ -607,7 +613,7 @@ static bool mi_arena_try_purge(mi_arena_t* arena, mi_msecs_t now, bool force)
607613
mi_msecs_t expected = 0;
608614
mi_atomic_casi64_strong_acq_rel(&arena->purge_expire,&expected,_mi_clock_now() + delay);
609615
}
610-
return any_purged;
616+
return (any_purged ? 1 : -1);
611617
}
612618

613619
static void mi_arenas_try_purge( bool force, bool visit_all )
@@ -630,20 +636,25 @@ static void mi_arenas_try_purge( bool force, bool visit_all )
630636
mi_atomic_storei64_release(&mi_arenas_purge_expire, now + mi_arena_purge_delay());
631637
size_t max_purge_count = (visit_all ? max_arena : 2);
632638
bool all_visited = true;
639+
bool any_purged = false;
633640
for (size_t i = 0; i < max_arena; i++) {
634641
mi_arena_t* arena = mi_atomic_load_ptr_acquire(mi_arena_t, &mi_arenas[i]);
635642
if (arena != NULL) {
636-
if (mi_arena_try_purge(arena, now, force)) {
637-
if (max_purge_count <= 1) {
638-
all_visited = false;
639-
break;
643+
int purged = mi_arena_try_purge(arena, now, force);
644+
if (purged >= 0) { // purged, or not yet the expire-time reached
645+
any_purged = true;
646+
if (purged >= 1) { // purged at least one page
647+
if (max_purge_count <= 1) {
648+
all_visited = false;
649+
break;
650+
}
651+
max_purge_count--;
640652
}
641-
max_purge_count--;
642653
}
643654
}
644655
}
645-
if (all_visited) {
646-
// all arena's were visited and purged: reset global expire
656+
if (all_visited && !any_purged) {
657+
// all arena's were visited and nothing needed to be purged: reset global expire
647658
mi_atomic_storei64_release(&mi_arenas_purge_expire, 0);
648659
}
649660
}

0 commit comments

Comments
 (0)