Check if we need to signal the background thread early. */
| 654 | |
| 655 | /* Check if we need to signal the background thread early. */ |
| 656 | void |
| 657 | background_thread_interval_check(tsdn_t *tsdn, arena_t *arena, |
| 658 | arena_decay_t *decay, size_t npages_new) { |
| 659 | background_thread_info_t *info = arena_background_thread_info_get( |
| 660 | arena); |
| 661 | if (malloc_mutex_trylock(tsdn, &info->mtx)) { |
| 662 | /* |
| 663 | * Background thread may hold the mutex for a long period of |
| 664 | * time. We'd like to avoid the variance on application |
| 665 | * threads. So keep this non-blocking, and leave the work to a |
| 666 | * future epoch. |
| 667 | */ |
| 668 | return; |
| 669 | } |
| 670 | |
| 671 | if (info->state != background_thread_started) { |
| 672 | goto label_done; |
| 673 | } |
| 674 | if (malloc_mutex_trylock(tsdn, &decay->mtx)) { |
| 675 | goto label_done; |
| 676 | } |
| 677 | |
| 678 | ssize_t decay_time = atomic_load_zd(&decay->time_ms, ATOMIC_RELAXED); |
| 679 | if (decay_time <= 0) { |
| 680 | /* Purging is eagerly done or disabled currently. */ |
| 681 | goto label_done_unlock2; |
| 682 | } |
| 683 | uint64_t decay_interval_ns = nstime_ns(&decay->interval); |
| 684 | assert(decay_interval_ns > 0); |
| 685 | |
| 686 | nstime_t diff; |
| 687 | nstime_init(&diff, background_thread_wakeup_time_get(info)); |
| 688 | if (nstime_compare(&diff, &decay->epoch) <= 0) { |
| 689 | goto label_done_unlock2; |
| 690 | } |
| 691 | nstime_subtract(&diff, &decay->epoch); |
| 692 | if (nstime_ns(&diff) < BACKGROUND_THREAD_MIN_INTERVAL_NS) { |
| 693 | goto label_done_unlock2; |
| 694 | } |
| 695 | |
| 696 | if (npages_new > 0) { |
| 697 | size_t n_epoch = (size_t)(nstime_ns(&diff) / decay_interval_ns); |
| 698 | /* |
| 699 | * Compute how many new pages we would need to purge by the next |
| 700 | * wakeup, which is used to determine if we should signal the |
| 701 | * background thread. |
| 702 | */ |
| 703 | uint64_t npurge_new; |
| 704 | if (n_epoch >= SMOOTHSTEP_NSTEPS) { |
| 705 | npurge_new = npages_new; |
| 706 | } else { |
| 707 | uint64_t h_steps_max = h_steps[SMOOTHSTEP_NSTEPS - 1]; |
| 708 | assert(h_steps_max >= |
| 709 | h_steps[SMOOTHSTEP_NSTEPS - 1 - n_epoch]); |
| 710 | npurge_new = npages_new * (h_steps_max - |
| 711 | h_steps[SMOOTHSTEP_NSTEPS - 1 - n_epoch]); |
| 712 | npurge_new >>= SMOOTHSTEP_BFP; |
| 713 | } |
no test coverage detected