Skip to repository content176 lines · 6.1 KB · rust
tenant.openagents/omega
No repository description is available.
OpenAgents Git authority 2026-07-28T05:55:25.241Z Public web read
NIP-34 coordinate
30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omegaMaintainersHidden in public view
References2 branches · 1 tag
Read-only clone
git clone https://openagents.com/git/tenant.openagents/omega.gitBrowse files
dispatcher.rs
1use dispatch2::{DispatchQueue, DispatchQueueGlobalPriority, DispatchTime, GlobalQueueIdentifier};
2use gpui::{PlatformDispatcher, Priority, RunnableMeta, RunnableVariant};
3use gpui_util::ResultExt;
4use mach2::{
5 kern_return::KERN_SUCCESS,
6 mach_time::mach_timebase_info_data_t,
7 thread_policy::{
8 THREAD_EXTENDED_POLICY, THREAD_EXTENDED_POLICY_COUNT, THREAD_PRECEDENCE_POLICY,
9 THREAD_PRECEDENCE_POLICY_COUNT, THREAD_TIME_CONSTRAINT_POLICY,
10 THREAD_TIME_CONSTRAINT_POLICY_COUNT, thread_extended_policy_data_t,
11 thread_precedence_policy_data_t, thread_time_constraint_policy_data_t,
12 },
13};
14
15use async_task::Runnable;
16use objc::{
17 class, msg_send,
18 runtime::{BOOL, YES},
19 sel, sel_impl,
20};
21use std::{ffi::c_void, ptr::NonNull, time::Duration};
22
23pub(crate) struct MacDispatcher;
24
25impl MacDispatcher {
26 pub fn new() -> Self {
27 Self
28 }
29}
30
31impl PlatformDispatcher for MacDispatcher {
32 fn is_main_thread(&self) -> bool {
33 let is_main_thread: BOOL = unsafe { msg_send![class!(NSThread), isMainThread] };
34 is_main_thread == YES
35 }
36
37 fn dispatch(&self, runnable: RunnableVariant, priority: Priority) {
38 let context = runnable.into_raw().as_ptr() as *mut c_void;
39
40 let queue_priority = match priority {
41 Priority::RealtimeAudio => {
42 panic!("RealtimeAudio priority should use spawn_realtime, not dispatch")
43 }
44 Priority::High => DispatchQueueGlobalPriority::High,
45 Priority::Medium => DispatchQueueGlobalPriority::Default,
46 Priority::Low => DispatchQueueGlobalPriority::Low,
47 };
48
49 unsafe {
50 DispatchQueue::global_queue(GlobalQueueIdentifier::Priority(queue_priority))
51 .exec_async_f(context, trampoline);
52 }
53 }
54
55 fn dispatch_on_main_thread(&self, runnable: RunnableVariant, _priority: Priority) {
56 let context = runnable.into_raw().as_ptr() as *mut c_void;
57 unsafe {
58 DispatchQueue::main().exec_async_f(context, trampoline);
59 }
60 }
61
62 fn dispatch_after(&self, duration: Duration, runnable: RunnableVariant) {
63 let context = runnable.into_raw().as_ptr() as *mut c_void;
64 let queue = DispatchQueue::global_queue(GlobalQueueIdentifier::Priority(
65 DispatchQueueGlobalPriority::High,
66 ));
67 let when = DispatchTime::NOW.time(duration.as_nanos() as i64);
68 unsafe {
69 DispatchQueue::exec_after_f(when, &queue, context, trampoline);
70 }
71 }
72
73 fn spawn_realtime(&self, f: Box<dyn FnOnce() + Send>) {
74 std::thread::spawn(move || {
75 set_audio_thread_priority().log_err();
76 f();
77 });
78 }
79}
80
81fn set_audio_thread_priority() -> anyhow::Result<()> {
82 // https://chromium.googlesource.com/chromium/chromium/+/master/base/threading/platform_thread_mac.mm#93
83
84 // SAFETY: always safe to call
85 let thread_id = unsafe { libc::pthread_self() };
86
87 // SAFETY: thread_id is a valid thread id
88 let thread_id = unsafe { libc::pthread_mach_thread_np(thread_id) };
89
90 // Fixed priority thread
91 let mut policy = thread_extended_policy_data_t { timeshare: 0 };
92
93 // SAFETY: thread_id is a valid thread id
94 // SAFETY: thread_extended_policy_data_t is passed as THREAD_EXTENDED_POLICY
95 let result = unsafe {
96 mach2::thread_policy::thread_policy_set(
97 thread_id,
98 THREAD_EXTENDED_POLICY,
99 &mut policy as *mut _ as *mut _,
100 THREAD_EXTENDED_POLICY_COUNT,
101 )
102 };
103
104 if result != KERN_SUCCESS {
105 anyhow::bail!("failed to set thread extended policy");
106 }
107
108 // relatively high priority
109 let mut precedence = thread_precedence_policy_data_t { importance: 63 };
110
111 // SAFETY: thread_id is a valid thread id
112 // SAFETY: thread_precedence_policy_data_t is passed as THREAD_PRECEDENCE_POLICY
113 let result = unsafe {
114 mach2::thread_policy::thread_policy_set(
115 thread_id,
116 THREAD_PRECEDENCE_POLICY,
117 &mut precedence as *mut _ as *mut _,
118 THREAD_PRECEDENCE_POLICY_COUNT,
119 )
120 };
121
122 if result != KERN_SUCCESS {
123 anyhow::bail!("failed to set thread precedence policy");
124 }
125
126 const GUARANTEED_AUDIO_DUTY_CYCLE: f32 = 0.75;
127 const MAX_AUDIO_DUTY_CYCLE: f32 = 0.85;
128
129 // ~128 frames @ 44.1KHz
130 const TIME_QUANTUM: f32 = 2.9;
131
132 const AUDIO_TIME_NEEDED: f32 = GUARANTEED_AUDIO_DUTY_CYCLE * TIME_QUANTUM;
133 const MAX_TIME_ALLOWED: f32 = MAX_AUDIO_DUTY_CYCLE * TIME_QUANTUM;
134
135 let mut timebase_info = mach_timebase_info_data_t { numer: 0, denom: 0 };
136 // SAFETY: timebase_info is a valid pointer to a mach_timebase_info_data_t struct
137 unsafe { mach2::mach_time::mach_timebase_info(&mut timebase_info) };
138
139 let ms_to_abs_time = ((timebase_info.denom as f32) / (timebase_info.numer as f32)) * 1000000f32;
140
141 let mut time_constraints = thread_time_constraint_policy_data_t {
142 period: (TIME_QUANTUM * ms_to_abs_time) as u32,
143 computation: (AUDIO_TIME_NEEDED * ms_to_abs_time) as u32,
144 constraint: (MAX_TIME_ALLOWED * ms_to_abs_time) as u32,
145 preemptible: 0,
146 };
147
148 // SAFETY: thread_id is a valid thread id
149 // SAFETY: thread_precedence_pthread_time_constraint_policy_data_t is passed as THREAD_TIME_CONSTRAINT_POLICY
150 let result = unsafe {
151 mach2::thread_policy::thread_policy_set(
152 thread_id,
153 THREAD_TIME_CONSTRAINT_POLICY,
154 &mut time_constraints as *mut _ as *mut _,
155 THREAD_TIME_CONSTRAINT_POLICY_COUNT,
156 )
157 };
158
159 if result != KERN_SUCCESS {
160 anyhow::bail!("failed to set thread time constraint policy");
161 }
162
163 Ok(())
164}
165
166extern "C" fn trampoline(context: *mut c_void) {
167 let runnable =
168 unsafe { Runnable::<RunnableMeta>::from_raw(NonNull::new_unchecked(context as *mut ())) };
169
170 let location = runnable.metadata().location;
171 let spawned = runnable.metadata().spawned;
172 gpui::profiler::update_running_task(spawned, location);
173 runnable.run();
174 gpui::profiler::save_task_timing();
175}
176