blob: bd7f6f125cfb27b3727857f2963f5315bbb67e47 [file] [log] [blame]
// Copyright 2025 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use crate::power::EbpfSuspendGuard;
use crate::task::CurrentTask;
use ebpf_api::{CurrentTaskContext, Map, MapValueRef, MapsContext};
use starnix_sync::{EbpfStateLock, Locked};
use starnix_uapi::{gid_t, pid_t, uid_t};
enum SuspendLockState<'a> {
NotLocked(&'a mut Locked<EbpfStateLock>),
#[allow(dead_code)]
Locked(EbpfSuspendGuard<'a>),
}
pub struct EbpfRunContextImpl<'a> {
current_task: &'a CurrentTask,
// Must precede `map_refs` to ensure it's dropped after `base`.
suspend_lock_state: SuspendLockState<'a>,
map_refs: Vec<MapValueRef<'a>>,
}
impl<'a> EbpfRunContextImpl<'a> {
pub fn new(locked: &'a mut Locked<EbpfStateLock>, current_task: &'a CurrentTask) -> Self {
Self {
current_task,
suspend_lock_state: SuspendLockState::NotLocked(locked),
map_refs: vec![],
}
}
}
impl<'a> MapsContext<'a> for EbpfRunContextImpl<'a> {
fn on_map_access(&mut self, map: &Map) {
if map.uses_locks() && matches!(self.suspend_lock_state, SuspendLockState::NotLocked(_)) {
replace_with::replace_with(&mut self.suspend_lock_state, |state| {
let SuspendLockState::NotLocked(locked) = state else { unreachable!() };
SuspendLockState::Locked(
self.current_task
.kernel()
.suspend_resume_manager
.acquire_ebpf_suspend_lock(locked),
)
});
}
}
fn add_value_ref(&mut self, map_ref: MapValueRef<'a>) {
self.map_refs.push(map_ref)
}
}
impl<'a> CurrentTaskContext for EbpfRunContextImpl<'a> {
fn get_uid_gid(&self) -> (uid_t, gid_t) {
self.current_task.with_current_creds(|creds| (creds.uid, creds.gid))
}
fn get_tid_tgid(&self) -> (pid_t, pid_t) {
let task = &self.current_task.task;
(task.get_tid(), task.get_pid())
}
}