blob: 62c1426cc86e62707cf0dc202181ad70bf38b39a [file] [log] [blame] [edit]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
pub mod restorable;
pub mod simple;
use crate::ProcessId;
use crate::ProcessState;
use crate::ThreadId;
use crate::ThreadState;
pub trait ProcessContext {
type TM<'a>: ThreadMap
where
Self: 'a;
fn timestamp(&self) -> u64;
fn state(&self) -> ProcessState;
fn thread_map(&mut self) -> Self::TM<'_>;
}
pub trait ProcessMap {
type P<'a>: ProcessContext
where
Self: 'a;
/// Insert a new process or update a process if exists.
///
/// Returns [None] if inserting.
///
/// Returns [ProcessContext] if the process exists and is updated.
///
/// If an entry for `process_id` exists whose timestamp does not equal `timestamp`, that process
/// entry is removed from the map before the new process entry is inserted, and [None] is
/// returned.
fn insert_or_update(
&mut self,
process_id: ProcessId,
timestamp: u64,
state: ProcessState,
) -> Option<Self::P<'_>>;
fn get_process(&mut self, process_id: ProcessId) -> Option<Self::P<'_>>;
/// Remove a process.
///
/// `timestamp` is used to identify the process with `process_id` if it is `Option::Some`.
/// Otherwise this does not check the stored timestamp in the map.
fn remove_process(&mut self, process_id: ProcessId, timestamp: Option<u64>);
/// Reduce storage size by compacting holes left by deleted processes and threads.
///
/// NOTE: compact() should be called on every process/thread context update. It still works
/// without compact()ing, but next compact() will take longer time for accumulating removed
/// contexts which will cause inconsistent latency of the process/thread context update latency
/// and performance degradation. [The Tail at Scale](https://research.google/pubs/pub40801/).
fn compact(&mut self);
}
pub trait ThreadMap {
/// Insert a new thread or update a thread if exist.
///
/// Before inserting a new thread GC threads in the map. This is to avoid useless memory
/// consumption of from dead threads for the case a process spawns many short-term threads while
/// the process state keeps the same. The `fn_is_thread_alive` is used to check whether the
/// thread is alive or not.
fn insert_or_update<F>(
&mut self,
thread_id: ThreadId,
timestamp: u64,
state: ThreadState,
fn_is_thread_alive: F,
) where
F: FnMut(&ThreadId) -> bool;
fn retain_threads<F>(&mut self, f: F)
where
F: FnMut(&ThreadId, &ThreadEntry) -> bool;
fn remove_thread(&mut self, thread_id: ThreadId);
}
pub struct ThreadEntry {
pub timestamp: u64,
pub state: ThreadState,
}