From 56846f78a833b1f9ce28ab44ee7e71e22a037810 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=AE=87=E9=80=B8?= Date: Fri, 8 Mar 2024 14:54:33 +0800 Subject: [PATCH] fix(driver,iocp): use WaitForMultipleObjectsEx on non-pc --- compio-driver/src/iocp/mod.rs | 38 ++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/compio-driver/src/iocp/mod.rs b/compio-driver/src/iocp/mod.rs index f12e7f87..524f9f89 100644 --- a/compio-driver/src/iocp/mod.rs +++ b/compio-driver/src/iocp/mod.rs @@ -23,7 +23,7 @@ use windows_sys::Win32::{ }, Networking::WinSock::{WSACleanup, WSAStartup, WSADATA}, System::{ - Threading::{WaitForSingleObject, INFINITE}, + Threading::{WaitForMultipleObjectsEx, WaitForSingleObject, INFINITE}, IO::OVERLAPPED, }, UI::WindowsAndMessaging::{ @@ -360,10 +360,15 @@ impl NotifyHandle { } } +// `MsgWaitForMultipleObjectsEx` can handle only 63 events. +#[cfg(target_vendor = "pc")] +const MAX_EVENT_COUNT: usize = 63; +#[cfg(not(target_vendor = "pc"))] +const MAX_EVENT_COUNT: usize = 64; + struct EventPoller { - // `MsgWaitForMultipleObjectsEx` can handle only 63 events. - events: ArrayVec, - keys: ArrayVec, + events: ArrayVec, + keys: ArrayVec, } impl EventPoller { @@ -392,28 +397,37 @@ impl EventPoller { let events_len = self.events.len() as u32; let res = unsafe { - MsgWaitForMultipleObjectsEx( - events_len, - self.events.as_mut_ptr().cast(), - timeout, - QS_ALLINPUT, - MWMO_ALERTABLE | MWMO_INPUTAVAILABLE, - ) + if cfg!(target_vendor = "pc") { + MsgWaitForMultipleObjectsEx( + events_len, + self.events.as_mut_ptr().cast(), + timeout, + QS_ALLINPUT, + MWMO_ALERTABLE | MWMO_INPUTAVAILABLE, + ) + } else { + WaitForMultipleObjectsEx(events_len, self.events.as_mut_ptr().cast(), 0, timeout, 1) + } }; match res { WAIT_FAILED => Err(io::Error::last_os_error()), WAIT_TIMEOUT => Err(io::Error::from_raw_os_error(ERROR_TIMEOUT as _)), + // APC WAIT_IO_COMPLETION => Err(io::ErrorKind::Interrupted.into()), _ => { if res == WAIT_OBJECT_0 { + // IOCP Ok(None) } else if res > WAIT_OBJECT_0 && res < WAIT_OBJECT_0 + events_len { + // Event objects let index = (res - WAIT_OBJECT_0) as usize; self.events.remove(index); Ok(Some((self.keys.remove(index), true))) - } else if res == WAIT_OBJECT_0 + events_len { + } else if cfg!(target_vendor = "pc") && res == WAIT_OBJECT_0 + events_len { + // Message queue Err(io::ErrorKind::Interrupted.into()) } else if res > WAIT_ABANDONED_0 && res < WAIT_ABANDONED_0 + events_len { + // Abandoned event objects let index = (res - WAIT_ABANDONED_0) as usize; self.events.remove(index); Ok(Some((self.keys.remove(index), false)))