Skip to content

Commit c9d16c8

Browse files
authored
threadpool: improve cooperative downsizing (#4293)
Turn the exit flag back into a proper count. Fixes a regression introduced in commit 27229aa.
1 parent a379089 commit c9d16c8

File tree

2 files changed

+15
-8
lines changed

2 files changed

+15
-8
lines changed

ChangeLog

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
- make `subsample-mode=on` and `lossless=true` mutually exclusive [kleisauke]
99
- fix SZI write with openslide4 [goran-hc]
1010
- heifsave: prevent use of AV1 intra block copy feature [lovell]
11+
- threadpool: improve cooperative downsizing [kleisauke]
1112

1213
10/10/24 8.16.0
1314

libvips/iofuncs/threadpool.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -270,18 +270,18 @@ typedef struct _VipsThreadpool {
270270
*/
271271
int n_waiting; // (atomic)
272272

273+
/* Increment this and the next worker will decrement and exit if needed
274+
* (used to downsize the threadpool).
275+
*/
276+
int exit; // (atomic)
277+
273278
/* Set this to abort evaluation early with an error.
274279
*/
275280
gboolean error;
276281

277282
/* Ask threads to exit, either set by allocate, or on free.
278283
*/
279284
gboolean stop;
280-
281-
/* Set this and the next worker to see it will clear the flag and exit
282-
* (used to downsize the threadpool).
283-
*/
284-
gboolean exit; // (atomic)
285285
} VipsThreadpool;
286286

287287
static int
@@ -325,14 +325,20 @@ vips_worker_work_unit(VipsWorker *worker)
325325

326326
/* Has a thread been asked to exit? Volunteer if yes.
327327
*/
328-
if (g_atomic_int_compare_and_exchange(&pool->exit, TRUE, FALSE)) {
328+
if (g_atomic_int_add(&pool->exit, -1) > 0) {
329329
/* A thread had been asked to exit, and we've grabbed the
330330
* flag.
331331
*/
332332
worker->stop = TRUE;
333333
g_mutex_unlock(pool->allocate_lock);
334334
return;
335335
}
336+
else {
337+
/* No one had been asked to exit and we've mistakenly taken
338+
* the exit count below zero. Put it back up again.
339+
*/
340+
g_atomic_int_inc(&pool->exit);
341+
}
336342

337343
if (vips_worker_allocate(worker)) {
338344
pool->error = TRUE;
@@ -513,7 +519,7 @@ vips_threadpool_new(VipsImage *im)
513519
vips_semaphore_init(&pool->tick, 0, "tick");
514520
pool->error = FALSE;
515521
pool->stop = FALSE;
516-
pool->exit = FALSE;
522+
pool->exit = 0;
517523

518524
/* If this is a tiny image, we won't need all max_workers threads.
519525
* Guess how
@@ -696,7 +702,7 @@ vips_threadpool_run(VipsImage *im,
696702
if (n_waiting > 3 &&
697703
n_working > 1) {
698704
VIPS_DEBUG_MSG("shrinking thread pool\n");
699-
g_atomic_int_set(&pool->exit, TRUE);
705+
g_atomic_int_inc(&pool->exit);
700706
n_working -= 1;
701707
}
702708
else if (n_waiting < 2 &&

0 commit comments

Comments
 (0)