blob: bc5ac7c0d414ef3963e1f93d8e763429a3208f0d [file] [edit]
// Copyright 2021 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#ifndef ZIRCON_KERNEL_VM_INCLUDE_VM_PHYSICAL_PAGE_BORROWING_CONFIG_H_
#define ZIRCON_KERNEL_VM_INCLUDE_VM_PHYSICAL_PAGE_BORROWING_CONFIG_H_
#include <assert.h>
#include <ktl/atomic.h>
// Allow the ppb kernel command to dynamically control whether physical page borrowing is enabled
// or disabled (for pager-backed VMOs only for now).
class PhysicalPageBorrowingConfig {
public:
PhysicalPageBorrowingConfig() = default;
PhysicalPageBorrowingConfig(const PhysicalPageBorrowingConfig& to_copy) = delete;
PhysicalPageBorrowingConfig(PhysicalPageBorrowingConfig&& to_move) = delete;
PhysicalPageBorrowingConfig& operator=(const PhysicalPageBorrowingConfig& to_copy) = delete;
PhysicalPageBorrowingConfig& operator=(PhysicalPageBorrowingConfig&& to_move) = delete;
static PhysicalPageBorrowingConfig& Get() { return instance_; }
// true - allow page borrowing when a page is logically moved to MRU queue
// false - disallow page borrowing when a page is logically moved to MRU queue
void set_borrowing_on_mru_enabled(bool enabled) {
borrowing_on_mru_enabled_.store(enabled, ktl::memory_order_relaxed);
}
bool is_borrowing_on_mru_enabled() {
return borrowing_on_mru_enabled_.load(ktl::memory_order_relaxed);
}
// true - decommitted contiguous VMO pages will decommit+loan the pages.
// false - decommit of a contiguous VMO page zeroes instead of decommitting+loaning.
void set_loaning_enabled(bool enabled) {
loaning_enabled_.store(enabled, ktl::memory_order_relaxed);
}
bool is_loaning_enabled() { return loaning_enabled_.load(ktl::memory_order_relaxed); }
// true - loaned pages will be replaced with new page with copied contents.
// false - loaned pages will be evicted.
void set_replace_on_unloan_enabled(bool enabled) {
replace_on_unloan_.store(enabled, ktl::memory_order_relaxed);
}
bool is_replace_on_unloan_enabled() { return replace_on_unloan_.load(ktl::memory_order_relaxed); }
// Increment the active unloans counter when a contiguous VMO starts unloaning.
void NotifyUnloanStarted() { active_unloans_.fetch_add(1, ktl::memory_order_relaxed); }
// Decrement the active unloans counter when a contiguous VMO completes unloaning.
void NotifyUnloanFinished() {
uint32_t prev = active_unloans_.fetch_sub(1, ktl::memory_order_relaxed);
DEBUG_ASSERT(prev > 0);
}
// Returns true if borrowing is permitted at this time. To avoid lock contention on the borrowing
// VMOs' paged_vmo_lock_ between the LRU thread (sweeping) and the unloaning thread, borrowing is
// temporarily disabled if any unloans are currently in progress.
bool is_borrowing_active() {
return is_borrowing_on_mru_enabled() && (active_unloans_.load(ktl::memory_order_relaxed) == 0);
}
private:
// Singleton.
static PhysicalPageBorrowingConfig instance_;
// Enable page borrowing when a page is logically moved to the MRU queue. If true, replace an
// accessed non-loaned page with loaned on access. If false, this is disabled.
ktl::atomic<bool> borrowing_on_mru_enabled_ = false;
// Enable page loaning. If false, no page loaning will occur. If true, decommitting pages of a
// contiguous VMO will loan the pages. This can be dynamically changed, but changes will only
// apply to subsequent decommit of contiguous VMO pages.
ktl::atomic<bool> loaning_enabled_ = false;
// Enables copy of page contents, instead of eviction, when a loaned page is committed back to its
// contiguous owner.
ktl::atomic<bool> replace_on_unloan_ = false;
// Tracks the number of active unloaning operations in progress. See comment near
// is_borrowing_active() for how this is used.
ktl::atomic<uint32_t> active_unloans_ = 0;
};
#endif // ZIRCON_KERNEL_VM_INCLUDE_VM_PHYSICAL_PAGE_BORROWING_CONFIG_H_