@@ -67,7 +67,6 @@ static bool background_thread_enabled_at_fork;
6767static void
6868background_thread_info_init (tsdn_t * tsdn , background_thread_info_t * info ) {
6969 background_thread_wakeup_time_set (tsdn , info , 0 );
70- info -> pause = false;
7170 info -> npages_to_purge_new = 0 ;
7271 if (config_stats ) {
7372 info -> tot_n_runs = 0 ;
@@ -263,13 +262,20 @@ background_thread_sleep(tsdn_t *tsdn, background_thread_info_t *info,
263262 nstime_add (& info -> tot_sleep_time , & after_sleep );
264263 }
265264 }
266- while (info -> pause ) {
265+ }
266+
267+ static bool
268+ background_thread_pause_check (tsdn_t * tsdn , background_thread_info_t * info ) {
269+ if (unlikely (info -> state == background_thread_paused )) {
267270 malloc_mutex_unlock (tsdn , & info -> mtx );
268271 /* Wait on global lock to update status. */
269272 malloc_mutex_lock (tsdn , & background_thread_lock );
270273 malloc_mutex_unlock (tsdn , & background_thread_lock );
271274 malloc_mutex_lock (tsdn , & info -> mtx );
275+ return true;
272276 }
277+
278+ return false;
273279}
274280
275281static inline void
@@ -310,9 +316,10 @@ background_threads_disable_single(tsd_t *tsd, background_thread_info_t *info) {
310316 pre_reentrancy (tsd );
311317 malloc_mutex_lock (tsd_tsdn (tsd ), & info -> mtx );
312318 bool has_thread ;
313- if (info -> started ) {
319+ assert (info -> state != background_thread_paused );
320+ if (info -> state == background_thread_started ) {
314321 has_thread = true;
315- info -> started = false ;
322+ info -> state = background_thread_stopped ;
316323 pthread_cond_signal (& info -> cond );
317324 } else {
318325 has_thread = false;
@@ -344,14 +351,17 @@ check_background_thread_creation(tsd_t *tsd, unsigned *n_created,
344351 return ;
345352 }
346353
354+ malloc_mutex_unlock (tsd_tsdn (tsd ), & background_thread_info [0 ].mtx );
355+ label_restart :
356+ malloc_mutex_lock (tsd_tsdn (tsd ), & background_thread_lock );
347357 for (unsigned i = 1 ; i < ncpus ; i ++ ) {
348358 if (created_threads [i ]) {
349359 continue ;
350360 }
351361 background_thread_info_t * info = & background_thread_info [i ];
352362 malloc_mutex_lock (tsd_tsdn (tsd ), & info -> mtx );
353-
354- bool create = info -> started ;
363+ assert ( info -> state != background_thread_paused );
364+ bool create = ( info -> state == background_thread_started ) ;
355365 malloc_mutex_unlock (tsd_tsdn (tsd ), & info -> mtx );
356366 if (!create ) {
357367 continue ;
@@ -361,14 +371,12 @@ check_background_thread_creation(tsd_t *tsd, unsigned *n_created,
361371 * To avoid deadlock with prefork handlers (which waits for the
362372 * mutex held here), unlock before calling pthread_create().
363373 */
364- malloc_mutex_unlock (tsd_tsdn (tsd ),
365- & background_thread_info [ 0 ]. mtx );
374+ malloc_mutex_unlock (tsd_tsdn (tsd ), & background_thread_lock );
375+
366376 pre_reentrancy (tsd );
367377 int err = pthread_create_wrapper (& info -> thread , NULL ,
368378 background_thread_entry , (void * )(uintptr_t )i );
369379 post_reentrancy (tsd );
370- malloc_mutex_lock (tsd_tsdn (tsd ),
371- & background_thread_info [0 ].mtx );
372380
373381 if (err == 0 ) {
374382 (* n_created )++ ;
@@ -380,9 +388,11 @@ check_background_thread_creation(tsd_t *tsd, unsigned *n_created,
380388 abort ();
381389 }
382390 }
383- /* Since we unlocked and may miss signals, restart . */
384- i = 1 ;
391+ /* Restart since we unlocked. */
392+ goto label_restart ;
385393 }
394+ malloc_mutex_lock (tsd_tsdn (tsd ), & background_thread_info [0 ].mtx );
395+ malloc_mutex_unlock (tsd_tsdn (tsd ), & background_thread_lock );
386396}
387397
388398static void
@@ -395,7 +405,11 @@ background_thread0_work(tsd_t *tsd) {
395405 }
396406 /* Start working, and create more threads when asked. */
397407 unsigned n_created = 1 ;
398- while (background_thread_info [0 ].started ) {
408+ while (background_thread_info [0 ].state != background_thread_stopped ) {
409+ if (background_thread_pause_check (tsd_tsdn (tsd ),
410+ & background_thread_info [0 ])) {
411+ continue ;
412+ }
399413 check_background_thread_creation (tsd , & n_created ,
400414 (bool * )& created_threads );
401415 background_work_sleep_once (tsd_tsdn (tsd ),
@@ -409,16 +423,17 @@ background_thread0_work(tsd_t *tsd) {
409423 assert (!background_thread_enabled ());
410424 for (i = 1 ; i < ncpus ; i ++ ) {
411425 background_thread_info_t * info = & background_thread_info [i ];
426+ assert (info -> state != background_thread_paused );
412427 if (created_threads [i ]) {
413428 background_threads_disable_single (tsd , info );
414429 } else {
415430 malloc_mutex_lock (tsd_tsdn (tsd ), & info -> mtx );
416431 /* Clear in case the thread wasn't created. */
417- info -> started = false ;
432+ info -> state = background_thread_stopped ;
418433 malloc_mutex_unlock (tsd_tsdn (tsd ), & info -> mtx );
419434 }
420435 }
421- background_thread_info [0 ].started = false ;
436+ background_thread_info [0 ].state = background_thread_stopped ;
422437 assert (n_background_threads == 1 );
423438}
424439
@@ -432,10 +447,15 @@ background_work(tsd_t *tsd, unsigned ind) {
432447 if (ind == 0 ) {
433448 background_thread0_work (tsd );
434449 } else {
435- while (info -> started ) {
450+ while (info -> state != background_thread_stopped ) {
451+ if (background_thread_pause_check (tsd_tsdn (tsd ),
452+ info )) {
453+ continue ;
454+ }
436455 background_work_sleep_once (tsd_tsdn (tsd ), info , ind );
437456 }
438457 }
458+ assert (info -> state == background_thread_stopped );
439459 background_thread_wakeup_time_set (tsd_tsdn (tsd ), info , 0 );
440460 malloc_mutex_unlock (tsd_tsdn (tsd ), & info -> mtx );
441461}
@@ -463,7 +483,7 @@ background_thread_entry(void *ind_arg) {
463483static void
464484background_thread_init (tsd_t * tsd , background_thread_info_t * info ) {
465485 malloc_mutex_assert_owner (tsd_tsdn (tsd ), & background_thread_lock );
466- info -> started = true ;
486+ info -> state = background_thread_started ;
467487 background_thread_info_init (tsd_tsdn (tsd ), info );
468488 n_background_threads ++ ;
469489}
@@ -480,7 +500,8 @@ background_thread_create(tsd_t *tsd, unsigned arena_ind) {
480500
481501 bool need_new_thread ;
482502 malloc_mutex_lock (tsd_tsdn (tsd ), & info -> mtx );
483- need_new_thread = background_thread_enabled () && !info -> started ;
503+ need_new_thread = background_thread_enabled () &&
504+ (info -> state == background_thread_stopped );
484505 if (need_new_thread ) {
485506 background_thread_init (tsd , info );
486507 }
@@ -492,7 +513,7 @@ background_thread_create(tsd_t *tsd, unsigned arena_ind) {
492513 /* Threads are created asynchronously by Thread 0. */
493514 background_thread_info_t * t0 = & background_thread_info [0 ];
494515 malloc_mutex_lock (tsd_tsdn (tsd ), & t0 -> mtx );
495- assert (t0 -> started );
516+ assert (t0 -> state == background_thread_started );
496517 pthread_cond_signal (& t0 -> cond );
497518 malloc_mutex_unlock (tsd_tsdn (tsd ), & t0 -> mtx );
498519
@@ -512,7 +533,7 @@ background_thread_create(tsd_t *tsd, unsigned arena_ind) {
512533 malloc_printf ("<jemalloc>: arena 0 background thread creation "
513534 "failed (%d)\n" , err );
514535 malloc_mutex_lock (tsd_tsdn (tsd ), & info -> mtx );
515- info -> started = false ;
536+ info -> state = background_thread_stopped ;
516537 n_background_threads -- ;
517538 malloc_mutex_unlock (tsd_tsdn (tsd ), & info -> mtx );
518539
@@ -543,7 +564,7 @@ background_threads_enable(tsd_t *tsd) {
543564 }
544565 background_thread_info_t * info = & background_thread_info [i ];
545566 malloc_mutex_lock (tsd_tsdn (tsd ), & info -> mtx );
546- assert (! info -> started );
567+ assert (info -> state == background_thread_stopped );
547568 background_thread_init (tsd , info );
548569 malloc_mutex_unlock (tsd_tsdn (tsd ), & info -> mtx );
549570 marked [i % ncpus ] = true;
@@ -586,7 +607,7 @@ background_thread_interval_check(tsdn_t *tsdn, arena_t *arena,
586607 return ;
587608 }
588609
589- if (! info -> started ) {
610+ if (info -> state != background_thread_started ) {
590611 goto label_done ;
591612 }
592613 if (malloc_mutex_trylock (tsdn , & decay -> mtx )) {
@@ -694,7 +715,7 @@ background_thread_postfork_child(tsdn_t *tsdn) {
694715 for (unsigned i = 0 ; i < ncpus ; i ++ ) {
695716 background_thread_info_t * info = & background_thread_info [i ];
696717 malloc_mutex_lock (tsdn , & info -> mtx );
697- info -> started = false ;
718+ info -> state = background_thread_stopped ;
698719 int ret = pthread_cond_init (& info -> cond , NULL );
699720 assert (ret == 0 );
700721 background_thread_info_init (tsdn , info );
@@ -718,7 +739,7 @@ background_thread_stats_read(tsdn_t *tsdn, background_thread_stats_t *stats) {
718739 for (unsigned i = 0 ; i < ncpus ; i ++ ) {
719740 background_thread_info_t * info = & background_thread_info [i ];
720741 malloc_mutex_lock (tsdn , & info -> mtx );
721- if (info -> started ) {
742+ if (info -> state != background_thread_stopped ) {
722743 num_runs += info -> tot_n_runs ;
723744 nstime_add (& stats -> run_interval , & info -> tot_sleep_time );
724745 }
@@ -807,7 +828,7 @@ background_thread_boot1(tsdn_t *tsdn) {
807828 return true;
808829 }
809830 malloc_mutex_lock (tsdn , & info -> mtx );
810- info -> started = false ;
831+ info -> state = background_thread_stopped ;
811832 background_thread_info_init (tsdn , info );
812833 malloc_mutex_unlock (tsdn , & info -> mtx );
813834 }
0 commit comments