#![forbid(unsafe_code)] //! Process-owned trusted runtime services.//!//! Production sidecars construct exactly one [`SidecarRuntime`] at their//! process entrypoint. Subsystems receive a clone of [`RuntimeContext`]; they//! never construct Tokio runtimes of their own. use std::cell::Cell;use std::fmt;use std::future::Future;use std::pin::Pin;use std::sync::atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering};use std::sync::{mpsc, Arc, Mutex, OnceLock};use std::task::{Context, Poll};use std::thread;use std::time::{Duration, Instant}; use accounting::{LimitError, Reservation, ResourceClass, ResourceLedger, ResourceLimit};use fairness::{FairBudget, FairWorkBroker, FairnessConfig};use metrics::{ ExecutorMetricClass, RuntimeMetrics, TelemetryFallback, TelemetryFallbackCode, TelemetrySeverity, TelemetrySubsystem, WatchdogMetric,}; pub mod accounting;pub mod capability;pub mod fairness;pub mod metrics;pub mod readiness;pub mod supervision; pub use supervision::{ TaskClass, TaskClassSnapshot, TaskOwner, TaskSpawnError, TaskSupervisor, TaskTerminalReason, TaskTerminalReport,}; const DEFAULT_MAX_BLOCKING_JOB_BYTES: usize = 64 * 1024 * 1024;const DEFAULT_BLOCKING_JOB_TIMEOUT_MS: u64 = 30_000;const DEFAULT_MAX_BLOCKING_JOBS: usize = 1_028;const DEFAULT_MAX_QUEUED_BLOCKING_JOBS: usize = 1024;const DEFAULT_MAX_PROCESS_CAPABILITIES: usize = 16_384;const DEFAULT_MAX_PROCESS_SOCKETS: usize = 8_192;const DEFAULT_MAX_PROCESS_CONNECTIONS: usize = 8_192;const DEFAULT_MAX_PROCESS_SOCKET_BUFFERED_BYTES: usize = 1024 * 1024 * 1024;const DEFAULT_MAX_PROCESS_DATAGRAMS: usize = 65_536;const DEFAULT_MAX_PROCESS_TIMERS: usize = 65_536;const DEFAULT_MAX_PROCESS_TASKS: usize = 65_536;const DEFAULT_MAX_PROCESS_READY_HANDLES: usize = 16_384;const DEFAULT_MAX_PROCESS_HANDLE_COMMANDS: usize = 65_536;const DEFAULT_MAX_PROCESS_HANDLE_COMMAND_BYTES: usize = 256 * 1024 * 1024;const DEFAULT_MAX_PROCESS_BRIDGE_CALLS: usize = 65_536;const DEFAULT_MAX_PROCESS_BRIDGE_REQUEST_BYTES: usize = 256 * 1024 * 1024;const DEFAULT_MAX_PROCESS_BRIDGE_RESPONSE_BYTES: usize = 256 * 1024 * 1024;const DEFAULT_MAX_PROCESS_ASYNC_COMPLETIONS: usize = 65_536;const DEFAULT_MAX_PROCESS_ASYNC_COMPLETION_BYTES: usize = 256 * 1024 * 1024;const DEFAULT_MAX_PROCESS_UDP_DATAGRAMS: usize = 65_536;const DEFAULT_MAX_PROCESS_UDP_BYTES: usize = 256 * 1024 * 1024;const DEFAULT_MAX_PROCESS_TLS_BYTES: usize = 256 * 1024 * 1024;const DEFAULT_MAX_PROCESS_HTTP2_CONNECTIONS: usize = 4_096;const DEFAULT_MAX_PROCESS_HTTP2_STREAMS: usize = 65_536;const DEFAULT_MAX_PROCESS_HTTP2_BYTES: usize = 512 * 1024 * 1024;const DEFAULT_MAX_PROCESS_HTTP2_HEADER_BYTES: usize = 128 * 1024 * 1024;const DEFAULT_MAX_PROCESS_HTTP2_DATA_BYTES: usize = 512 * 1024 * 1024;const DEFAULT_MAX_PROCESS_HTTP2_COMMANDS: usize = 65_536;const DEFAULT_MAX_PROCESS_HTTP2_COMMAND_BYTES: usize = 256 * 1024 * 1024;const DEFAULT_MAX_PROCESS_HTTP2_EVENTS: usize = 65_536;const DEFAULT_MAX_PROCESS_HTTP2_EVENT_BYTES: usize = 512 * 1024 * 1024;const DEFAULT_TASK_POLL_WATCHDOG_MS: u64 = 100;const DEFAULT_MAX_TERMINAL_TASK_REPORTS: usize = 4_096;const DEFAULT_VM_EXECUTOR_TEARDOWN_TIMEOUT_MS: u64 = 5_000;pub const DEFAULT_PROTOCOL_MAX_INGRESS_FRAMES: usize = 128;pub const DEFAULT_PROTOCOL_MAX_INGRESS_BYTES: usize = 64 * 1024 * 1024;pub const DEFAULT_PROTOCOL_MAX_CONTROL_FRAMES: usize = 1_024;pub const DEFAULT_PROTOCOL_MAX_CONTROL_BYTES: usize = 64 * 1024 * 1024;pub const DEFAULT_PROTOCOL_MAX_EGRESS_FRAMES: usize = 4_096;pub const DEFAULT_PROTOCOL_MAX_EGRESS_BYTES: usize = 256 * 1024 * 1024;pub const DEFAULT_PROTOCOL_MAX_PENDING_RESPONSES: usize = 10_000;pub const DEFAULT_PROTOCOL_MAX_PENDING_RESPONSE_BYTES: usize = 256 * 1024 * 1024;pub const DEFAULT_PROTOCOL_MAX_PROCESS_EVENTS: usize = 10_000;pub const DEFAULT_PROTOCOL_MAX_OUTBOUND_REQUESTS: usize = 10_000;pub const DEFAULT_PROTOCOL_MAX_COMPLETED_RESPONSES: usize = 10_000;const DEFAULT_FAIRNESS_VM_OPERATIONS: usize = 64;const DEFAULT_FAIRNESS_VM_BYTES: usize = 1024 * 1024;const DEFAULT_FAIRNESS_CAPABILITY_OPERATIONS: usize = 16;const DEFAULT_FAIRNESS_CAPABILITY_BYTES: usize = 256 * 1024;const DEFAULT_FAIRNESS_MAX_VMS: usize = 4_096;const DEFAULT_FAIRNESS_MAX_CAPABILITIES_PER_VM: usize = 16_384; thread_local! { static IS_AGENTOS_RUNTIME_WORKER: Cell<bool> = const { Cell::new(false) };} /// Whether the current OS thread is one of the process runtime's fixed workers.////// Synchronous compatibility adapters use this to reject waits that would/// consume a trusted runtime worker and could deadlock the work they submitted.pub fn is_runtime_worker_thread() -> bool { IS_AGENTOS_RUNTIME_WORKER.with(Cell::get)} /// Process-owned bounds for the multiplexed sidecar transport.////// Ordinary frames and response/control frames have independent admission so/// an event or request backlog cannot consume the capacity needed to settle an/// already-registered bridge call. Byte ceilings cover retained decoded or/// encoded frames; the one active decoder is separately bounded by the wire/// codec's `max_frame_bytes` setting.#[derive(Clone, Debug, PartialEq, Eq)]pub struct RuntimeProtocolConfig { pub max_ingress_frames: usize, pub max_ingress_bytes: usize, pub max_control_frames: usize, pub max_control_bytes: usize, pub max_egress_frames: usize, pub max_egress_bytes: usize, pub max_pending_responses: usize, pub max_pending_response_bytes: usize, pub max_process_events: usize, pub max_outbound_requests: usize, pub max_completed_responses: usize,} impl Default for RuntimeProtocolConfig { fn default() -> Self { Self { max_ingress_frames: DEFAULT_PROTOCOL_MAX_INGRESS_FRAMES, max_ingress_bytes: DEFAULT_PROTOCOL_MAX_INGRESS_BYTES, max_control_frames: DEFAULT_PROTOCOL_MAX_CONTROL_FRAMES, max_control_bytes: DEFAULT_PROTOCOL_MAX_CONTROL_BYTES, max_egress_frames: DEFAULT_PROTOCOL_MAX_EGRESS_FRAMES, max_egress_bytes: DEFAULT_PROTOCOL_MAX_EGRESS_BYTES, max_pending_responses: DEFAULT_PROTOCOL_MAX_PENDING_RESPONSES, max_pending_response_bytes: DEFAULT_PROTOCOL_MAX_PENDING_RESPONSE_BYTES, max_process_events: DEFAULT_PROTOCOL_MAX_PROCESS_EVENTS, max_outbound_requests: DEFAULT_PROTOCOL_MAX_OUTBOUND_REQUESTS, max_completed_responses: DEFAULT_PROTOCOL_MAX_COMPLETED_RESPONSES, } }} #[derive(Clone, Debug, PartialEq, Eq)]pub struct RuntimeFairnessConfig { pub vm_quantum_operations: usize, pub vm_quantum_bytes: usize, pub capability_quantum_operations: usize, pub capability_quantum_bytes: usize, pub max_vm_deficit_operations: usize, pub max_vm_deficit_bytes: usize, pub max_capability_deficit_operations: usize, pub max_capability_deficit_bytes: usize, pub max_vms: usize, pub max_capabilities_per_vm: usize,} impl Default for RuntimeFairnessConfig { fn default() -> Self { Self { vm_quantum_operations: DEFAULT_FAIRNESS_VM_OPERATIONS, vm_quantum_bytes: DEFAULT_FAIRNESS_VM_BYTES, capability_quantum_operations: DEFAULT_FAIRNESS_CAPABILITY_OPERATIONS, capability_quantum_bytes: DEFAULT_FAIRNESS_CAPABILITY_BYTES, max_vm_deficit_operations: DEFAULT_FAIRNESS_VM_OPERATIONS * 4, max_vm_deficit_bytes: DEFAULT_FAIRNESS_VM_BYTES * 4, max_capability_deficit_operations: DEFAULT_FAIRNESS_CAPABILITY_OPERATIONS * 4, max_capability_deficit_bytes: DEFAULT_FAIRNESS_CAPABILITY_BYTES * 4, max_vms: DEFAULT_FAIRNESS_MAX_VMS, max_capabilities_per_vm: DEFAULT_FAIRNESS_MAX_CAPABILITIES_PER_VM, } }} impl RuntimeFairnessConfig { fn scheduler_config(&self) -> FairnessConfig { FairnessConfig { vm_quantum: FairBudget::new(self.vm_quantum_operations, self.vm_quantum_bytes), capability_quantum: FairBudget::new( self.capability_quantum_operations, self.capability_quantum_bytes, ), max_vm_deficit: FairBudget::new( self.max_vm_deficit_operations, self.max_vm_deficit_bytes, ), max_capability_deficit: FairBudget::new( self.max_capability_deficit_operations, self.max_capability_deficit_bytes, ), max_vms: self.max_vms, max_capabilities_per_vm: self.max_capabilities_per_vm, } }} #[derive(Clone, Debug, PartialEq, Eq)]pub struct RuntimeResourceConfig { pub max_capabilities: usize, pub max_ready_handles: usize, pub max_sockets: usize, pub max_connections: usize, pub max_socket_buffered_bytes: usize, pub max_datagrams: usize, pub max_timers: usize, pub max_tasks: usize, pub max_handle_commands: usize, pub max_handle_command_bytes: usize, pub max_bridge_calls: usize, pub max_bridge_request_bytes: usize, pub max_bridge_response_bytes: usize, pub max_async_completions: usize, pub max_async_completion_bytes: usize, pub max_udp_datagrams: usize, pub max_udp_bytes: usize, pub max_tls_bytes: usize, pub max_http2_connections: usize, pub max_http2_streams: usize, pub max_http2_buffered_bytes: usize, pub max_http2_header_bytes: usize, pub max_http2_data_bytes: usize, pub max_http2_commands: usize, pub max_http2_command_bytes: usize, pub max_http2_events: usize, pub max_http2_event_bytes: usize,} impl Default for RuntimeResourceConfig { fn default() -> Self { Self { max_capabilities: DEFAULT_MAX_PROCESS_CAPABILITIES, max_ready_handles: DEFAULT_MAX_PROCESS_READY_HANDLES, max_sockets: DEFAULT_MAX_PROCESS_SOCKETS, max_connections: DEFAULT_MAX_PROCESS_CONNECTIONS, max_socket_buffered_bytes: DEFAULT_MAX_PROCESS_SOCKET_BUFFERED_BYTES, max_datagrams: DEFAULT_MAX_PROCESS_DATAGRAMS, max_timers: DEFAULT_MAX_PROCESS_TIMERS, max_tasks: DEFAULT_MAX_PROCESS_TASKS, max_handle_commands: DEFAULT_MAX_PROCESS_HANDLE_COMMANDS, max_handle_command_bytes: DEFAULT_MAX_PROCESS_HANDLE_COMMAND_BYTES, max_bridge_calls: DEFAULT_MAX_PROCESS_BRIDGE_CALLS, max_bridge_request_bytes: DEFAULT_MAX_PROCESS_BRIDGE_REQUEST_BYTES, max_bridge_response_bytes: DEFAULT_MAX_PROCESS_BRIDGE_RESPONSE_BYTES, max_async_completions: DEFAULT_MAX_PROCESS_ASYNC_COMPLETIONS, max_async_completion_bytes: DEFAULT_MAX_PROCESS_ASYNC_COMPLETION_BYTES, max_udp_datagrams: DEFAULT_MAX_PROCESS_UDP_DATAGRAMS, max_udp_bytes: DEFAULT_MAX_PROCESS_UDP_BYTES, max_tls_bytes: DEFAULT_MAX_PROCESS_TLS_BYTES, max_http2_connections: DEFAULT_MAX_PROCESS_HTTP2_CONNECTIONS, max_http2_streams: DEFAULT_MAX_PROCESS_HTTP2_STREAMS, max_http2_buffered_bytes: DEFAULT_MAX_PROCESS_HTTP2_BYTES, max_http2_header_bytes: DEFAULT_MAX_PROCESS_HTTP2_HEADER_BYTES, max_http2_data_bytes: DEFAULT_MAX_PROCESS_HTTP2_DATA_BYTES, max_http2_commands: DEFAULT_MAX_PROCESS_HTTP2_COMMANDS, max_http2_command_bytes: DEFAULT_MAX_PROCESS_HTTP2_COMMAND_BYTES, max_http2_events: DEFAULT_MAX_PROCESS_HTTP2_EVENTS, max_http2_event_bytes: DEFAULT_MAX_PROCESS_HTTP2_EVENT_BYTES, } }} impl RuntimeResourceConfig { fn limits(&self) -> Vec<(ResourceClass, ResourceLimit)> { vec![ ( ResourceClass::Capabilities, ResourceLimit::new(self.max_capabilities, "runtime.resources.maxCapabilities"), ), ( ResourceClass::ReadyHandles, ResourceLimit::new(self.max_ready_handles, "runtime.resources.maxReadyHandles"), ), ( ResourceClass::Sockets, ResourceLimit::new(self.max_sockets, "runtime.resources.maxSockets"), ), ( ResourceClass::Connections, ResourceLimit::new(self.max_connections, "runtime.resources.maxConnections"), ), ( ResourceClass::BufferedBytes, ResourceLimit::new( self.max_socket_buffered_bytes, "runtime.resources.maxSocketBufferedBytes", ), ), ( ResourceClass::Datagrams, ResourceLimit::new(self.max_datagrams, "runtime.resources.maxDatagrams"), ), ( ResourceClass::Timers, ResourceLimit::new(self.max_timers, "runtime.resources.maxTimers"), ), ( ResourceClass::Tasks, ResourceLimit::new(self.max_tasks, "runtime.resources.maxTasks"), ), ( ResourceClass::HandleCommands, ResourceLimit::new( self.max_handle_commands, "runtime.resources.maxHandleCommands", ), ), ( ResourceClass::HandleCommandBytes, ResourceLimit::new( self.max_handle_command_bytes, "runtime.resources.maxHandleCommandBytes", ), ), ( ResourceClass::BridgeCalls, ResourceLimit::new(self.max_bridge_calls, "runtime.resources.maxBridgeCalls"), ), ( ResourceClass::BridgeRequestBytes, ResourceLimit::new( self.max_bridge_request_bytes, "runtime.resources.maxBridgeRequestBytes", ), ), ( ResourceClass::BridgeResponseBytes, ResourceLimit::new( self.max_bridge_response_bytes, "runtime.resources.maxBridgeResponseBytes", ), ), ( ResourceClass::AsyncCompletions, ResourceLimit::new( self.max_async_completions, "runtime.resources.maxAsyncCompletions", ), ), ( ResourceClass::AsyncCompletionBytes, ResourceLimit::new( self.max_async_completion_bytes, "runtime.resources.maxAsyncCompletionBytes", ), ), ( ResourceClass::UdpDatagrams, ResourceLimit::new(self.max_udp_datagrams, "runtime.resources.maxUdpDatagrams"), ), ( ResourceClass::UdpBytes, ResourceLimit::new(self.max_udp_bytes, "runtime.resources.maxUdpBytes"), ), ( ResourceClass::TlsBytes, ResourceLimit::new(self.max_tls_bytes, "runtime.resources.maxTlsBytes"), ), ( ResourceClass::Http2Connections, ResourceLimit::new( self.max_http2_connections, "runtime.resources.maxHttp2Connections", ), ), ( ResourceClass::Http2Streams, ResourceLimit::new(self.max_http2_streams, "runtime.resources.maxHttp2Streams"), ), ( ResourceClass::Http2BufferedBytes, ResourceLimit::new( self.max_http2_buffered_bytes, "runtime.resources.maxHttp2BufferedBytes", ), ), ( ResourceClass::Http2HeaderBytes, ResourceLimit::new( self.max_http2_header_bytes, "runtime.resources.maxHttp2HeaderBytes", ), ), ( ResourceClass::Http2DataBytes, ResourceLimit::new( self.max_http2_data_bytes, "runtime.resources.maxHttp2DataBytes", ), ), ( ResourceClass::Http2Commands, ResourceLimit::new( self.max_http2_commands, "runtime.resources.maxHttp2Commands", ), ), ( ResourceClass::Http2CommandBytes, ResourceLimit::new( self.max_http2_command_bytes, "runtime.resources.maxHttp2CommandBytes", ), ), ( ResourceClass::Http2Events, ResourceLimit::new(self.max_http2_events, "runtime.resources.maxHttp2Events"), ), ( ResourceClass::Http2EventBytes, ResourceLimit::new( self.max_http2_event_bytes, "runtime.resources.maxHttp2EventBytes", ), ), ] }} #[derive(Clone, Debug, PartialEq, Eq)]pub struct RuntimeConfig { pub worker_threads: usize, pub max_active_vm_executors: usize, pub vm_executor_teardown_timeout_ms: u64, pub blocking_worker_threads: usize, pub max_blocking_jobs: usize, pub max_queued_blocking_jobs: usize, pub max_blocking_job_bytes: usize, pub blocking_job_timeout_ms: u64, pub task_poll_watchdog_ms: u64, pub max_terminal_task_reports: usize, pub protocol: RuntimeProtocolConfig, pub resources: RuntimeResourceConfig, pub fairness: RuntimeFairnessConfig,} impl Default for RuntimeConfig { fn default() -> Self { let available = thread::available_parallelism() .map(usize::from) .unwrap_or(1); Self { worker_threads: available.clamp(1, 4), max_active_vm_executors: available.max(1), vm_executor_teardown_timeout_ms: DEFAULT_VM_EXECUTOR_TEARDOWN_TIMEOUT_MS, blocking_worker_threads: available.clamp(1, 4), max_blocking_jobs: DEFAULT_MAX_BLOCKING_JOBS, max_queued_blocking_jobs: DEFAULT_MAX_QUEUED_BLOCKING_JOBS, max_blocking_job_bytes: DEFAULT_MAX_BLOCKING_JOB_BYTES, blocking_job_timeout_ms: DEFAULT_BLOCKING_JOB_TIMEOUT_MS, task_poll_watchdog_ms: DEFAULT_TASK_POLL_WATCHDOG_MS, max_terminal_task_reports: DEFAULT_MAX_TERMINAL_TASK_REPORTS, protocol: RuntimeProtocolConfig::default(), resources: RuntimeResourceConfig::default(), fairness: RuntimeFairnessConfig::default(), } }} impl RuntimeConfig { pub fn validate(&self) -> Result<(), RuntimeBuildError> { for (field, value) in [ ("runtime.workerThreads", self.worker_threads), ( "runtime.executor.maxActiveVms", self.max_active_vm_executors, ), ( "runtime.blocking.workerThreads", self.blocking_worker_threads, ), ("runtime.blocking.maxJobs", self.max_blocking_jobs), ( "runtime.blocking.maxQueuedJobs", self.max_queued_blocking_jobs, ), ( "runtime.blocking.maxQueuedBytes", self.max_blocking_job_bytes, ), ( "runtime.tasks.maxTerminalReports", self.max_terminal_task_reports, ), ( "runtime.protocol.maxIngressFrames", self.protocol.max_ingress_frames, ), ( "runtime.protocol.maxIngressBytes", self.protocol.max_ingress_bytes, ), ( "runtime.protocol.maxControlFrames", self.protocol.max_control_frames, ), ( "runtime.protocol.maxControlBytes", self.protocol.max_control_bytes, ), ( "runtime.protocol.maxEgressFrames", self.protocol.max_egress_frames,Lines 1–500 of 2181. Load more
#![forbid(unsafe_code)] //! Process-owned trusted runtime services. //! //! Production sidecars construct exactly one [`SidecarRuntime`] at their //! process entrypoint. Subsystems receive a clone of [`RuntimeContext`]; they //! never construct Tokio runtimes of their own. use std::cell::Cell; use std::fmt; use std::future::Future; use std::pin::Pin; use std::sync::atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering}; use std::sync::{mpsc, Arc, Mutex, OnceLock}; use std::task::{Context, Poll}; use std::thread; use std::time::{Duration, Instant}; use accounting::{LimitError, Reservation, ResourceClass, ResourceLedger, ResourceLimit}; use fairness::{FairBudget, FairWorkBroker, FairnessConfig}; use metrics::{ ExecutorMetricClass, RuntimeMetrics, TelemetryFallback, TelemetryFallbackCode, TelemetrySeverity, TelemetrySubsystem, WatchdogMetric, }; pub mod accounting; pub mod capability; pub mod fairness; pub mod metrics; pub mod readiness; pub mod supervision; pub use supervision::{ TaskClass, TaskClassSnapshot, TaskOwner, TaskSpawnError, TaskSupervisor, TaskTerminalReason, TaskTerminalReport, }; const DEFAULT_MAX_BLOCKING_JOB_BYTES: usize = 64 * 1024 * 1024; const DEFAULT_BLOCKING_JOB_TIMEOUT_MS: u64 = 30_000; const DEFAULT_MAX_BLOCKING_JOBS: usize = 1_028; const DEFAULT_MAX_QUEUED_BLOCKING_JOBS: usize = 1024; const DEFAULT_MAX_PROCESS_CAPABILITIES: usize = 16_384; const DEFAULT_MAX_PROCESS_SOCKETS: usize = 8_192; const DEFAULT_MAX_PROCESS_CONNECTIONS: usize = 8_192; const DEFAULT_MAX_PROCESS_SOCKET_BUFFERED_BYTES: usize = 1024 * 1024 * 1024; const DEFAULT_MAX_PROCESS_DATAGRAMS: usize = 65_536; const DEFAULT_MAX_PROCESS_TIMERS: usize = 65_536; const DEFAULT_MAX_PROCESS_TASKS: usize = 65_536; const DEFAULT_MAX_PROCESS_READY_HANDLES: usize = 16_384; const DEFAULT_MAX_PROCESS_HANDLE_COMMANDS: usize = 65_536; const DEFAULT_MAX_PROCESS_HANDLE_COMMAND_BYTES: usize = 256 * 1024 * 1024; const DEFAULT_MAX_PROCESS_BRIDGE_CALLS: usize = 65_536; const DEFAULT_MAX_PROCESS_BRIDGE_REQUEST_BYTES: usize = 256 * 1024 * 1024; const DEFAULT_MAX_PROCESS_BRIDGE_RESPONSE_BYTES: usize = 256 * 1024 * 1024; const DEFAULT_MAX_PROCESS_ASYNC_COMPLETIONS: usize = 65_536; const DEFAULT_MAX_PROCESS_ASYNC_COMPLETION_BYTES: usize = 256 * 1024 * 1024; const DEFAULT_MAX_PROCESS_UDP_DATAGRAMS: usize = 65_536; const DEFAULT_MAX_PROCESS_UDP_BYTES: usize = 256 * 1024 * 1024; const DEFAULT_MAX_PROCESS_TLS_BYTES: usize = 256 * 1024 * 1024; const DEFAULT_MAX_PROCESS_HTTP2_CONNECTIONS: usize = 4_096; const DEFAULT_MAX_PROCESS_HTTP2_STREAMS: usize = 65_536; const DEFAULT_MAX_PROCESS_HTTP2_BYTES: usize = 512 * 1024 * 1024; const DEFAULT_MAX_PROCESS_HTTP2_HEADER_BYTES: usize = 128 * 1024 * 1024; const DEFAULT_MAX_PROCESS_HTTP2_DATA_BYTES: usize = 512 * 1024 * 1024; const DEFAULT_MAX_PROCESS_HTTP2_COMMANDS: usize = 65_536; const DEFAULT_MAX_PROCESS_HTTP2_COMMAND_BYTES: usize = 256 * 1024 * 1024; const DEFAULT_MAX_PROCESS_HTTP2_EVENTS: usize = 65_536; const DEFAULT_MAX_PROCESS_HTTP2_EVENT_BYTES: usize = 512 * 1024 * 1024; const DEFAULT_TASK_POLL_WATCHDOG_MS: u64 = 100; const DEFAULT_MAX_TERMINAL_TASK_REPORTS: usize = 4_096; const DEFAULT_VM_EXECUTOR_TEARDOWN_TIMEOUT_MS: u64 = 5_000; pub const DEFAULT_PROTOCOL_MAX_INGRESS_FRAMES: usize = 128; pub const DEFAULT_PROTOCOL_MAX_INGRESS_BYTES: usize = 64 * 1024 * 1024; pub const DEFAULT_PROTOCOL_MAX_CONTROL_FRAMES: usize = 1_024; pub const DEFAULT_PROTOCOL_MAX_CONTROL_BYTES: usize = 64 * 1024 * 1024; pub const DEFAULT_PROTOCOL_MAX_EGRESS_FRAMES: usize = 4_096; pub const DEFAULT_PROTOCOL_MAX_EGRESS_BYTES: usize = 256 * 1024 * 1024; pub const DEFAULT_PROTOCOL_MAX_PENDING_RESPONSES: usize = 10_000; pub const DEFAULT_PROTOCOL_MAX_PENDING_RESPONSE_BYTES: usize = 256 * 1024 * 1024; pub const DEFAULT_PROTOCOL_MAX_PROCESS_EVENTS: usize = 10_000; pub const DEFAULT_PROTOCOL_MAX_OUTBOUND_REQUESTS: usize = 10_000; pub const DEFAULT_PROTOCOL_MAX_COMPLETED_RESPONSES: usize = 10_000; const DEFAULT_FAIRNESS_VM_OPERATIONS: usize = 64; const DEFAULT_FAIRNESS_VM_BYTES: usize = 1024 * 1024; const DEFAULT_FAIRNESS_CAPABILITY_OPERATIONS: usize = 16; const DEFAULT_FAIRNESS_CAPABILITY_BYTES: usize = 256 * 1024; const DEFAULT_FAIRNESS_MAX_VMS: usize = 4_096; const DEFAULT_FAIRNESS_MAX_CAPABILITIES_PER_VM: usize = 16_384; thread_local! { static IS_AGENTOS_RUNTIME_WORKER: Cell<bool> = const { Cell::new(false) }; } /// Whether the current OS thread is one of the process runtime's fixed workers. /// /// Synchronous compatibility adapters use this to reject waits that would /// consume a trusted runtime worker and could deadlock the work they submitted. pub fn is_runtime_worker_thread() -> bool { IS_AGENTOS_RUNTIME_WORKER.with(Cell::get) } /// Process-owned bounds for the multiplexed sidecar transport. /// /// Ordinary frames and response/control frames have independent admission so /// an event or request backlog cannot consume the capacity needed to settle an /// already-registered bridge call. Byte ceilings cover retained decoded or /// encoded frames; the one active decoder is separately bounded by the wire /// codec's `max_frame_bytes` setting. #[derive(Clone, Debug, PartialEq, Eq)] pub struct RuntimeProtocolConfig { pub max_ingress_frames: usize, pub max_ingress_bytes: usize, pub max_control_frames: usize, pub max_control_bytes: usize, pub max_egress_frames: usize, pub max_egress_bytes: usize, pub max_pending_responses: usize, pub max_pending_response_bytes: usize, pub max_process_events: usize, pub max_outbound_requests: usize, pub max_completed_responses: usize, } impl Default for RuntimeProtocolConfig { fn default() -> Self { Self { max_ingress_frames: DEFAULT_PROTOCOL_MAX_INGRESS_FRAMES, max_ingress_bytes: DEFAULT_PROTOCOL_MAX_INGRESS_BYTES, max_control_frames: DEFAULT_PROTOCOL_MAX_CONTROL_FRAMES, max_control_bytes: DEFAULT_PROTOCOL_MAX_CONTROL_BYTES, max_egress_frames: DEFAULT_PROTOCOL_MAX_EGRESS_FRAMES, max_egress_bytes: DEFAULT_PROTOCOL_MAX_EGRESS_BYTES, max_pending_responses: DEFAULT_PROTOCOL_MAX_PENDING_RESPONSES, max_pending_response_bytes: DEFAULT_PROTOCOL_MAX_PENDING_RESPONSE_BYTES, max_process_events: DEFAULT_PROTOCOL_MAX_PROCESS_EVENTS, max_outbound_requests: DEFAULT_PROTOCOL_MAX_OUTBOUND_REQUESTS, max_completed_responses: DEFAULT_PROTOCOL_MAX_COMPLETED_RESPONSES, } } } #[derive(Clone, Debug, PartialEq, Eq)] pub struct RuntimeFairnessConfig { pub vm_quantum_operations: usize, pub vm_quantum_bytes: usize, pub capability_quantum_operations: usize, pub capability_quantum_bytes: usize, pub max_vm_deficit_operations: usize, pub max_vm_deficit_bytes: usize, pub max_capability_deficit_operations: usize, pub max_capability_deficit_bytes: usize, pub max_vms: usize, pub max_capabilities_per_vm: usize, } impl Default for RuntimeFairnessConfig { fn default() -> Self { Self { vm_quantum_operations: DEFAULT_FAIRNESS_VM_OPERATIONS, vm_quantum_bytes: DEFAULT_FAIRNESS_VM_BYTES, capability_quantum_operations: DEFAULT_FAIRNESS_CAPABILITY_OPERATIONS, capability_quantum_bytes: DEFAULT_FAIRNESS_CAPABILITY_BYTES, max_vm_deficit_operations: DEFAULT_FAIRNESS_VM_OPERATIONS * 4, max_vm_deficit_bytes: DEFAULT_FAIRNESS_VM_BYTES * 4, max_capability_deficit_operations: DEFAULT_FAIRNESS_CAPABILITY_OPERATIONS * 4, max_capability_deficit_bytes: DEFAULT_FAIRNESS_CAPABILITY_BYTES * 4, max_vms: DEFAULT_FAIRNESS_MAX_VMS, max_capabilities_per_vm: DEFAULT_FAIRNESS_MAX_CAPABILITIES_PER_VM, } } } impl RuntimeFairnessConfig { fn scheduler_config(&self) -> FairnessConfig { FairnessConfig { vm_quantum: FairBudget::new(self.vm_quantum_operations, self.vm_quantum_bytes), capability_quantum: FairBudget::new( self.capability_quantum_operations, self.capability_quantum_bytes, ), max_vm_deficit: FairBudget::new( self.max_vm_deficit_operations, self.max_vm_deficit_bytes, ), max_capability_deficit: FairBudget::new( self.max_capability_deficit_operations, self.max_capability_deficit_bytes, ), max_vms: self.max_vms, max_capabilities_per_vm: self.max_capabilities_per_vm, } } } #[derive(Clone, Debug, PartialEq, Eq)] pub struct RuntimeResourceConfig { pub max_capabilities: usize, pub max_ready_handles: usize, pub max_sockets: usize, pub max_connections: usize, pub max_socket_buffered_bytes: usize, pub max_datagrams: usize, pub max_timers: usize, pub max_tasks: usize, pub max_handle_commands: usize, pub max_handle_command_bytes: usize, pub max_bridge_calls: usize, pub max_bridge_request_bytes: usize, pub max_bridge_response_bytes: usize, pub max_async_completions: usize, pub max_async_completion_bytes: usize, pub max_udp_datagrams: usize, pub max_udp_bytes: usize, pub max_tls_bytes: usize, pub max_http2_connections: usize, pub max_http2_streams: usize, pub max_http2_buffered_bytes: usize, pub max_http2_header_bytes: usize, pub max_http2_data_bytes: usize, pub max_http2_commands: usize, pub max_http2_command_bytes: usize, pub max_http2_events: usize, pub max_http2_event_bytes: usize, } impl Default for RuntimeResourceConfig { fn default() -> Self { Self { max_capabilities: DEFAULT_MAX_PROCESS_CAPABILITIES, max_ready_handles: DEFAULT_MAX_PROCESS_READY_HANDLES, max_sockets: DEFAULT_MAX_PROCESS_SOCKETS, max_connections: DEFAULT_MAX_PROCESS_CONNECTIONS, max_socket_buffered_bytes: DEFAULT_MAX_PROCESS_SOCKET_BUFFERED_BYTES, max_datagrams: DEFAULT_MAX_PROCESS_DATAGRAMS, max_timers: DEFAULT_MAX_PROCESS_TIMERS, max_tasks: DEFAULT_MAX_PROCESS_TASKS, max_handle_commands: DEFAULT_MAX_PROCESS_HANDLE_COMMANDS, max_handle_command_bytes: DEFAULT_MAX_PROCESS_HANDLE_COMMAND_BYTES, max_bridge_calls: DEFAULT_MAX_PROCESS_BRIDGE_CALLS, max_bridge_request_bytes: DEFAULT_MAX_PROCESS_BRIDGE_REQUEST_BYTES, max_bridge_response_bytes: DEFAULT_MAX_PROCESS_BRIDGE_RESPONSE_BYTES, max_async_completions: DEFAULT_MAX_PROCESS_ASYNC_COMPLETIONS, max_async_completion_bytes: DEFAULT_MAX_PROCESS_ASYNC_COMPLETION_BYTES, max_udp_datagrams: DEFAULT_MAX_PROCESS_UDP_DATAGRAMS, max_udp_bytes: DEFAULT_MAX_PROCESS_UDP_BYTES, max_tls_bytes: DEFAULT_MAX_PROCESS_TLS_BYTES, max_http2_connections: DEFAULT_MAX_PROCESS_HTTP2_CONNECTIONS, max_http2_streams: DEFAULT_MAX_PROCESS_HTTP2_STREAMS, max_http2_buffered_bytes: DEFAULT_MAX_PROCESS_HTTP2_BYTES, max_http2_header_bytes: DEFAULT_MAX_PROCESS_HTTP2_HEADER_BYTES, max_http2_data_bytes: DEFAULT_MAX_PROCESS_HTTP2_DATA_BYTES, max_http2_commands: DEFAULT_MAX_PROCESS_HTTP2_COMMANDS, max_http2_command_bytes: DEFAULT_MAX_PROCESS_HTTP2_COMMAND_BYTES, max_http2_events: DEFAULT_MAX_PROCESS_HTTP2_EVENTS, max_http2_event_bytes: DEFAULT_MAX_PROCESS_HTTP2_EVENT_BYTES, } } } impl RuntimeResourceConfig { fn limits(&self) -> Vec<(ResourceClass, ResourceLimit)> { vec![ ( ResourceClass::Capabilities, ResourceLimit::new(self.max_capabilities, "runtime.resources.maxCapabilities"), ), ( ResourceClass::ReadyHandles, ResourceLimit::new(self.max_ready_handles, "runtime.resources.maxReadyHandles"), ), ( ResourceClass::Sockets, ResourceLimit::new(self.max_sockets, "runtime.resources.maxSockets"), ), ( ResourceClass::Connections, ResourceLimit::new(self.max_connections, "runtime.resources.maxConnections"), ), ( ResourceClass::BufferedBytes, ResourceLimit::new( self.max_socket_buffered_bytes, "runtime.resources.maxSocketBufferedBytes", ), ), ( ResourceClass::Datagrams, ResourceLimit::new(self.max_datagrams, "runtime.resources.maxDatagrams"), ), ( ResourceClass::Timers, ResourceLimit::new(self.max_timers, "runtime.resources.maxTimers"), ), ( ResourceClass::Tasks, ResourceLimit::new(self.max_tasks, "runtime.resources.maxTasks"), ), ( ResourceClass::HandleCommands, ResourceLimit::new( self.max_handle_commands, "runtime.resources.maxHandleCommands", ), ), ( ResourceClass::HandleCommandBytes, ResourceLimit::new( self.max_handle_command_bytes, "runtime.resources.maxHandleCommandBytes", ), ), ( ResourceClass::BridgeCalls, ResourceLimit::new(self.max_bridge_calls, "runtime.resources.maxBridgeCalls"), ), ( ResourceClass::BridgeRequestBytes, ResourceLimit::new( self.max_bridge_request_bytes, "runtime.resources.maxBridgeRequestBytes", ), ), ( ResourceClass::BridgeResponseBytes, ResourceLimit::new( self.max_bridge_response_bytes, "runtime.resources.maxBridgeResponseBytes", ), ), ( ResourceClass::AsyncCompletions, ResourceLimit::new( self.max_async_completions, "runtime.resources.maxAsyncCompletions", ), ), ( ResourceClass::AsyncCompletionBytes, ResourceLimit::new( self.max_async_completion_bytes, "runtime.resources.maxAsyncCompletionBytes", ), ), ( ResourceClass::UdpDatagrams, ResourceLimit::new(self.max_udp_datagrams, "runtime.resources.maxUdpDatagrams"), ), ( ResourceClass::UdpBytes, ResourceLimit::new(self.max_udp_bytes, "runtime.resources.maxUdpBytes"), ), ( ResourceClass::TlsBytes, ResourceLimit::new(self.max_tls_bytes, "runtime.resources.maxTlsBytes"), ), ( ResourceClass::Http2Connections, ResourceLimit::new( self.max_http2_connections, "runtime.resources.maxHttp2Connections", ), ), ( ResourceClass::Http2Streams, ResourceLimit::new(self.max_http2_streams, "runtime.resources.maxHttp2Streams"), ), ( ResourceClass::Http2BufferedBytes, ResourceLimit::new( self.max_http2_buffered_bytes, "runtime.resources.maxHttp2BufferedBytes", ), ), ( ResourceClass::Http2HeaderBytes, ResourceLimit::new( self.max_http2_header_bytes, "runtime.resources.maxHttp2HeaderBytes", ), ), ( ResourceClass::Http2DataBytes, ResourceLimit::new( self.max_http2_data_bytes, "runtime.resources.maxHttp2DataBytes", ), ), ( ResourceClass::Http2Commands, ResourceLimit::new( self.max_http2_commands, "runtime.resources.maxHttp2Commands", ), ), ( ResourceClass::Http2CommandBytes, ResourceLimit::new( self.max_http2_command_bytes, "runtime.resources.maxHttp2CommandBytes", ), ), ( ResourceClass::Http2Events, ResourceLimit::new(self.max_http2_events, "runtime.resources.maxHttp2Events"), ), ( ResourceClass::Http2EventBytes, ResourceLimit::new( self.max_http2_event_bytes, "runtime.resources.maxHttp2EventBytes", ), ), ] } } #[derive(Clone, Debug, PartialEq, Eq)] pub struct RuntimeConfig { pub worker_threads: usize, pub max_active_vm_executors: usize, pub vm_executor_teardown_timeout_ms: u64, pub blocking_worker_threads: usize, pub max_blocking_jobs: usize, pub max_queued_blocking_jobs: usize, pub max_blocking_job_bytes: usize, pub blocking_job_timeout_ms: u64, pub task_poll_watchdog_ms: u64, pub max_terminal_task_reports: usize, pub protocol: RuntimeProtocolConfig, pub resources: RuntimeResourceConfig, pub fairness: RuntimeFairnessConfig, } impl Default for RuntimeConfig { fn default() -> Self { let available = thread::available_parallelism() .map(usize::from) .unwrap_or(1); Self { worker_threads: available.clamp(1, 4), max_active_vm_executors: available.max(1), vm_executor_teardown_timeout_ms: DEFAULT_VM_EXECUTOR_TEARDOWN_TIMEOUT_MS, blocking_worker_threads: available.clamp(1, 4), max_blocking_jobs: DEFAULT_MAX_BLOCKING_JOBS, max_queued_blocking_jobs: DEFAULT_MAX_QUEUED_BLOCKING_JOBS, max_blocking_job_bytes: DEFAULT_MAX_BLOCKING_JOB_BYTES, blocking_job_timeout_ms: DEFAULT_BLOCKING_JOB_TIMEOUT_MS, task_poll_watchdog_ms: DEFAULT_TASK_POLL_WATCHDOG_MS, max_terminal_task_reports: DEFAULT_MAX_TERMINAL_TASK_REPORTS, protocol: RuntimeProtocolConfig::default(), resources: RuntimeResourceConfig::default(), fairness: RuntimeFairnessConfig::default(), } } } impl RuntimeConfig { pub fn validate(&self) -> Result<(), RuntimeBuildError> { for (field, value) in [ ("runtime.workerThreads", self.worker_threads), ( "runtime.executor.maxActiveVms", self.max_active_vm_executors, ), ( "runtime.blocking.workerThreads", self.blocking_worker_threads, ), ("runtime.blocking.maxJobs", self.max_blocking_jobs), ( "runtime.blocking.maxQueuedJobs", self.max_queued_blocking_jobs, ), ( "runtime.blocking.maxQueuedBytes", self.max_blocking_job_bytes, ), ( "runtime.tasks.maxTerminalReports", self.max_terminal_task_reports, ), ( "runtime.protocol.maxIngressFrames", self.protocol.max_ingress_frames, ), ( "runtime.protocol.maxIngressBytes", self.protocol.max_ingress_bytes, ), ( "runtime.protocol.maxControlFrames", self.protocol.max_control_frames, ), ( "runtime.protocol.maxControlBytes", self.protocol.max_control_bytes, ), ( "runtime.protocol.maxEgressFrames", self.protocol.max_egress_frames,