diff options
Diffstat (limited to 'rts/sm/NonMovingSweep.c')
-rw-r--r-- | rts/sm/NonMovingSweep.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/rts/sm/NonMovingSweep.c b/rts/sm/NonMovingSweep.c index 31a9041880..cf5fcd70d7 100644 --- a/rts/sm/NonMovingSweep.c +++ b/rts/sm/NonMovingSweep.c @@ -293,9 +293,33 @@ void nonmovingSweepMutLists() } } +/* A variant of freeChain_lock that will only hold the lock for at most max_dur + * freed blocks to ensure that we don't starve other lock users (e.g. the + * mutator). + */ +static void freeChain_lock_max(bdescr *bd, int max_dur) +{ + ACQUIRE_SM_LOCK; + bdescr *next_bd; + int i = 0; + while (bd != NULL) { + next_bd = bd->link; + freeGroup(bd); + bd = next_bd; + if (i == max_dur) { + RELEASE_SM_LOCK; + yieldThread(); + ACQUIRE_SM_LOCK; + i = 0; + } + i++; + } + RELEASE_SM_LOCK; +} + void nonmovingSweepLargeObjects() { - freeChain_lock(nonmoving_large_objects); + freeChain_lock_max(nonmoving_large_objects, 10000); nonmoving_large_objects = nonmoving_marked_large_objects; n_nonmoving_large_blocks = n_nonmoving_marked_large_blocks; nonmoving_marked_large_objects = NULL; |