Skip to content

Commit

Permalink
fix(driver,iocp): use WaitForMultipleObjectsEx on non-pc
Browse files Browse the repository at this point in the history
  • Loading branch information
Berrysoft committed Mar 8, 2024
1 parent 22c06b2 commit 56846f7
Showing 1 changed file with 26 additions and 12 deletions.
38 changes: 26 additions & 12 deletions compio-driver/src/iocp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -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<RawFd, 63>,
keys: ArrayVec<usize, 63>,
events: ArrayVec<RawFd, MAX_EVENT_COUNT>,
keys: ArrayVec<usize, MAX_EVENT_COUNT>,
}

impl EventPoller {
Expand Down Expand Up @@ -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)))
Expand Down

0 comments on commit 56846f7

Please sign in to comment.