mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
feat!: add cooperative execution-time limits across engine, VM, and binding (#539)
- Introduce ExecutionTimer/ExecutionTimerConfig to allow limiting evaluating time. - To amortize time checking costs, checking interval can be configured via the notion of work units - A global fallback time limit can be set to universally limit all evaluation in addition to engine level limit setting. - Implement limnits in interpreter and RVM. In RVM, also handle suspend/resume so that time during pause is not counted. - Add engine-level APIs to set/clear per-engine timer configuration and apply global fallback defaults. - Surface execution-time limits through FFI and C# bindings - Add C# tests and example usage to validate engine overrides, global fallback behavior, and compiled policy enforcement. - Expand docs for execution-time limit - Add interpreter YAML cases and VM unit tests for time-limit behavior and deterministic time sources. Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
committed by
GitHub
parent
e68e852ee3
commit
394625d4bc
@@ -1,8 +1,12 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
use crate::common::{RegorusResult, RegorusStatus};
|
||||
use crate::common::{to_regorus_result, RegorusResult, RegorusStatus};
|
||||
use alloc::format;
|
||||
use anyhow::{anyhow, Result};
|
||||
use core::num::NonZeroU32;
|
||||
use core::time::Duration;
|
||||
use regorus::utils::limits::{self, ExecutionTimerConfig};
|
||||
|
||||
#[cfg(feature = "allocator-memory-limits")]
|
||||
fn some_or_none(flag: bool, value: u64) -> Option<u64> {
|
||||
@@ -131,6 +135,45 @@ fn feature_disabled(function: &str) -> RegorusResult {
|
||||
)
|
||||
}
|
||||
|
||||
/// FFI representation of [`ExecutionTimerConfig`].
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct RegorusExecutionTimerConfig {
|
||||
/// Wall-clock limit expressed in nanoseconds.
|
||||
pub limit_ns: u64,
|
||||
/// Number of work units between timer checks (must be non-zero).
|
||||
pub check_interval: u32,
|
||||
}
|
||||
|
||||
impl RegorusExecutionTimerConfig {
|
||||
pub fn to_execution_timer_config(self) -> Result<ExecutionTimerConfig> {
|
||||
let check_interval = NonZeroU32::new(self.check_interval)
|
||||
.ok_or_else(|| anyhow!("execution_timer.check_interval must be non-zero"))?;
|
||||
let limit = Duration::from_nanos(self.limit_ns);
|
||||
|
||||
Ok(ExecutionTimerConfig {
|
||||
limit,
|
||||
check_interval,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn regorus_set_fallback_execution_timer_config(
|
||||
config: RegorusExecutionTimerConfig,
|
||||
) -> RegorusResult {
|
||||
to_regorus_result(|| -> Result<()> {
|
||||
limits::set_fallback_execution_timer_config(Some(config.to_execution_timer_config()?));
|
||||
Ok(())
|
||||
}())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn regorus_clear_fallback_execution_timer_config() -> RegorusResult {
|
||||
limits::set_fallback_execution_timer_config(None);
|
||||
RegorusResult::ok_void()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{
|
||||
|
||||
Reference in New Issue
Block a user