blob: e1c672f9b07a11029e88fe45bd0f2c74298fa76b [file] [log] [blame]
// Copyright 2019 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_SCANNER_H_
#define ZIRCON_KERNEL_VM_INCLUDE_VM_SCANNER_H_
#include <fbl/macros.h>
// TODO: Convert the scanner to be a proper singleton object and use that to namespace these enums
// instead.
namespace scanner {
enum class EvictionLevel : uint8_t {
OnlyOldest = 0,
IncludeNewest = 1,
};
enum class Output : bool {
Print = true,
NoPrint = false,
};
} // namespace scanner
// Increase the disable count of the scanner. This may need to block until the scanner finishes any
// current work and so should not be called with other locks held that may conflict with the
// scanner. Generally this is expected to be used by unittests.
void scanner_push_disable_count();
// Decrease the disable count of the scanner, potentially re-enabling the scanner if it reaches
// zero.
void scanner_pop_disable_count();
// Attempts to scan for, and dedupe, zero pages. Page candidates are pulled from the
// unswappable_zero_fork page queue. It will consider up to `limit` candidates, and return the
// number of pages actually deduped.
// This is expected to be used internally by the scanner thread, but is exposed for testing,
// debugging and other code to use.
uint64_t scanner_do_zero_scan(uint64_t limit);
// Instructs the scanner to reclaim memory until free memory equals the |free_mem_target| and at
// least |min_free_target| has been reclaimed. Reclamation will happen asynchronously and this
// function returns immediately. Once the target is reached, or there is no more memory that can be
// reclaimed, this process will stop and the free memory target will be cleared. The eviction_level
// is a rough control on how hard to try and evict. Multiple calls to
// scanner_trigger_asynchronous_evict will cause all the targets to get merged by adding together
// |min_free_target|, taking the max of |free_mem_target| and the highest or most aggressive of any
// eviction_level.
void scanner_trigger_asynchronous_evict(
uint64_t min_free_target, uint64_t free_mem_target,
scanner::EvictionLevel eviction_level = scanner::EvictionLevel::OnlyOldest,
scanner::Output output = scanner::Output::NoPrint);
// Performs a synchronous request to evict the requested number of pages. The return value is the
// number of pages evicted. The |eviction_level| is a rough control that maps to how old a page
// needs to be for being considered for eviction. This may acquire arbitrary vmo and aspace locks.
uint64_t scanner_synchronous_evict(uint64_t min_pages_to_evict,
scanner::EvictionLevel eviction_level, scanner::Output output);
// Sets the scanner to reclaim page tables when harvesting accessed bits in the future, unless
// page table reclamation was explicitly disabled on the command line. Repeatedly enabling does not
// stack.
void scanner_enable_page_table_reclaim();
// Inverse of |scanner_enable_page_table_reclaim|, also does not stack.
void scanner_disable_page_table_reclaim();
// AutoVmScannerDisable is an RAII helper for disabling scanning using the
// scanner_push_disable_count()/scanner_pop_disable_count(). Disabling the scanner is useful in test
// code where it is not possible or practical to hold locks to prevent the scanner from taking
// actions.
class AutoVmScannerDisable {
public:
AutoVmScannerDisable() { scanner_push_disable_count(); }
~AutoVmScannerDisable() { scanner_pop_disable_count(); }
DISALLOW_COPY_ASSIGN_AND_MOVE(AutoVmScannerDisable);
};
#endif // ZIRCON_KERNEL_VM_INCLUDE_VM_SCANNER_H_