blob: 9d57144926fee6b86e41094480b0808be9c2208c [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
#include <kernel/event.h>
#include <kernel/thread.h>
#include <lk/init.h>
#include <vm/scanner.h>
#include <vm/vm.h>
#include <vm/vm_aspace.h>
namespace {
// Atomic used to track whether a scanner thread has been created yet or not.
ktl::atomic<bool> scanner_initialized = false;
// Tracks whether the scanner should perform reclamation the next time it does a scan pass
ktl::atomic<bool> scanner_perform_reclamation = false;
// Event to signal the scanner thread to perform a scan.
event_t scanner_request_event =
EVENT_INITIAL_VALUE(scanner_request_event, false, EVENT_FLAG_AUTOUNSIGNAL);
void scanner_do_single_scan(bool reclaim) {
uint32_t zero_pages = VmObject::ScanAllForZeroPages(reclaim);
printf("[SCAN]: Found %u zero pages that %s de-duped\n", zero_pages,
reclaim ? "were" : "could be");
}
int scanner_request_thread(void *) {
while (1) {
event_wait(&scanner_request_event);
bool reclaim = scanner_perform_reclamation.exchange(false);
scanner_do_single_scan(reclaim);
}
return 0;
}
} // namespace
void scanner_trigger_scan(bool reclaim) {
// Lazily create the scanner thread the first time a scan is triggered.
bool was_initialized = scanner_initialized.exchange(true);
if (!was_initialized) {
thread_t *thread =
thread_create("scanner-request-thread", scanner_request_thread, nullptr, LOW_PRIORITY);
DEBUG_ASSERT(thread);
thread_resume(thread);
}
// For multiple triggers we want to ensure any reclaim request is sticky until a scan runs.
if (reclaim) {
scanner_perform_reclamation = true;
}
event_signal(&scanner_request_event, true);
}