diff --git a/vmkit/src/sync.rs b/vmkit/src/sync.rs index 340733f..68cc126 100644 --- a/vmkit/src/sync.rs +++ b/vmkit/src/sync.rs @@ -58,7 +58,7 @@ pub struct Monitor { } impl Monitor { - pub fn new(value: T) -> Self { + pub const fn new(value: T) -> Self { Self { mutex: Mutex::new(value), cvar: Condvar::new(), @@ -86,6 +86,43 @@ impl Monitor { guard } + pub fn lock_with_handshake(&self) -> MonitorGuard { + let my_slot = get_thread_id().get(); + let guard = if my_slot != self.holder.load(Ordering::Relaxed) { + let guard = self.lock_with_handshake_no_rec::(); + self.holder.store(my_slot, Ordering::Release); + guard + } else { + MonitorGuard { + monitor: self, + guard: unsafe { ManuallyDrop::new(self.mutex.make_guard_unchecked()) }, + } + }; + self.rec_count.fetch_add(1, Ordering::Relaxed); + guard + } + + fn lock_with_handshake_no_rec(&self) -> MonitorGuard<'_, T> { + let tls = Thread::::current(); + tls.context.save_thread_state(); + + let mutex_guard = loop { + Thread::::enter_native(); + let guard = self.mutex.lock(); + if Thread::::attempt_leave_native_no_block() { + break guard; + } else { + drop(guard); + Thread::::leave_native(); + } + }; + + MonitorGuard { + monitor: self, + guard: ManuallyDrop::new(mutex_guard), + } + } + pub fn notify(&self) { self.cvar.notify_one(); }