blob: 9f559b906b23a0fad333108af43e0c53d17123bf [file]
// Copyright 2017 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
//! Per-CPU execution helpers for the hypervisor.
use crate::arch_rs::curr_cpu_num;
use crate::kernel::mp::{MpIpiTarget, cpu_mask_t, cpu_num_t, cpu_num_to_mask, sync_exec};
use core::sync::atomic::{AtomicU32, Ordering};
use zx_status::Status;
struct PerCpuState<F> {
cpu_mask: AtomicU32,
task: F,
}
impl<F> PerCpuState<F> {
fn new(task: F) -> Self {
Self { cpu_mask: AtomicU32::new(0), task }
}
}
fn percpu_task<F>(state: &PerCpuState<F>)
where
F: Fn(cpu_num_t) -> Result<(), Status>,
{
let cpu_num = curr_cpu_num();
if (state.task)(cpu_num).is_ok() {
state.cpu_mask.fetch_or(cpu_num_to_mask(cpu_num), Ordering::SeqCst);
}
}
/// Executes a task on each online CPU, and returns a CPU mask containing each
/// CPU the task was successfully run on.
pub fn percpu_exec<F>(task: F) -> cpu_mask_t
where
F: Fn(cpu_num_t) -> Result<(), Status> + Sync,
{
let state = PerCpuState::new(task);
sync_exec(MpIpiTarget::All, 0, || percpu_task(&state));
state.cpu_mask.load(Ordering::SeqCst)
}