Skip to content

Commit e6d85dc

Browse files
authored
add hook for windows (#315)
2 parents 684b050 + 5fcab0c commit e6d85dc

File tree

13 files changed

+317
-39
lines changed

13 files changed

+317
-39
lines changed

.github/workflows/ci-preemptive.sh

100755100644
File mode changed.

.github/workflows/ci.sh

100755100644
File mode changed.

core/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,12 @@ io-uring = { workspace = true, optional = true }
4848

4949
[target.'cfg(windows)'.dependencies]
5050
windows-sys = { workspace = true, features = [
51+
"Win32_Security",
5152
"Win32_System_IO",
5253
"Win32_Foundation",
5354
"Win32_System_Kernel",
5455
"Win32_System_Threading",
56+
"Win32_Storage_FileSystem",
5557
"Win32_Networking_WinSock",
5658
"Win32_System_SystemInformation",
5759
"Win32_System_Diagnostics_Debug",

core/src/common/constants.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,12 @@ pub enum Syscall {
118118
pthread_mutex_trylock,
119119
pthread_mutex_lock,
120120
pthread_mutex_unlock,
121+
#[cfg(windows)]
122+
CreateFileW,
123+
#[cfg(windows)]
124+
SetFilePointerEx,
125+
#[cfg(windows)]
126+
WaitOnAddress,
121127
}
122128

123129
impl Syscall {

core/src/syscall/common.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@ pub extern "C" fn reset_errno() {
44
set_errno(0);
55
}
66

7+
#[macro_export]
8+
macro_rules! syscall_mod {
9+
($($mod_name: ident);*) => {
10+
$(
11+
pub use $mod_name::$mod_name;
12+
mod $mod_name;
13+
)*
14+
}
15+
}
16+
717
#[macro_export]
818
macro_rules! log_syscall {
919
( $socket:expr, $done:expr, $once_result:expr ) => {

core/src/syscall/unix/mod.rs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,6 @@
1+
use crate::syscall_mod;
12
use std::ffi::c_int;
23

3-
macro_rules! syscall_mod {
4-
($($mod_name: ident);*) => {
5-
$(
6-
pub use $mod_name::$mod_name;
7-
mod $mod_name;
8-
)*
9-
}
10-
}
11-
124
macro_rules! impl_facade {
135
( $struct_name:ident, $trait_name: ident, $syscall: ident($($arg: ident : $arg_type: ty),*) -> $result: ty ) => {
146
#[repr(C)]

core/src/syscall/unix/pthread_cond_timedwait.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ impl<I: PthreadCondTimedwaitSyscall> PthreadCondTimedwaitSyscall
7171
.unwrap_or(u64::MAX)
7272
};
7373
loop {
74+
let mut left_time = abstimeout.saturating_sub(now());
75+
if 0 == left_time {
76+
return libc::ETIMEDOUT;
77+
}
7478
let r = self.inner.pthread_cond_timedwait(
7579
fn_ptr,
7680
cond,
@@ -83,7 +87,7 @@ impl<I: PthreadCondTimedwaitSyscall> PthreadCondTimedwaitSyscall
8387
if libc::ETIMEDOUT != r {
8488
return r;
8589
}
86-
let left_time = abstimeout.saturating_sub(now());
90+
left_time = abstimeout.saturating_sub(now());
8791
if 0 == left_time {
8892
return libc::ETIMEDOUT;
8993
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
use std::ffi::c_uint;
2+
use once_cell::sync::Lazy;
3+
use windows_sys::core::PCWSTR;
4+
use windows_sys::Win32::Foundation::HANDLE;
5+
use windows_sys::Win32::Security::SECURITY_ATTRIBUTES;
6+
use windows_sys::Win32::Storage::FileSystem::{
7+
FILE_CREATION_DISPOSITION, FILE_FLAGS_AND_ATTRIBUTES, FILE_SHARE_MODE,
8+
};
9+
10+
#[must_use]
11+
pub extern "system" fn CreateFileW(
12+
fn_ptr: Option<
13+
&extern "system" fn(
14+
PCWSTR,
15+
c_uint,
16+
FILE_SHARE_MODE,
17+
*const SECURITY_ATTRIBUTES,
18+
FILE_CREATION_DISPOSITION,
19+
FILE_FLAGS_AND_ATTRIBUTES,
20+
HANDLE,
21+
) -> HANDLE,
22+
>,
23+
lpfilename: PCWSTR,
24+
dwdesiredaccess: c_uint,
25+
dwsharemode: FILE_SHARE_MODE,
26+
lpsecurityattributes: *const SECURITY_ATTRIBUTES,
27+
dwcreationdisposition: FILE_CREATION_DISPOSITION,
28+
dwflagsandattributes: FILE_FLAGS_AND_ATTRIBUTES,
29+
htemplatefile: HANDLE,
30+
) -> HANDLE {
31+
static CHAIN: Lazy<CreateFileWSyscallFacade<RawCreateFileWSyscall>> =
32+
Lazy::new(Default::default);
33+
CHAIN.CreateFileW(
34+
fn_ptr,
35+
lpfilename,
36+
dwdesiredaccess,
37+
dwsharemode,
38+
lpsecurityattributes,
39+
dwcreationdisposition,
40+
dwflagsandattributes,
41+
htemplatefile
42+
)
43+
}
44+
45+
trait CreateFileWSyscall {
46+
extern "system" fn CreateFileW(
47+
&self,
48+
fn_ptr: Option<
49+
&extern "system" fn(
50+
PCWSTR,
51+
c_uint,
52+
FILE_SHARE_MODE,
53+
*const SECURITY_ATTRIBUTES,
54+
FILE_CREATION_DISPOSITION,
55+
FILE_FLAGS_AND_ATTRIBUTES,
56+
HANDLE,
57+
) -> HANDLE,
58+
>,
59+
lpfilename: PCWSTR,
60+
dwdesiredaccess: c_uint,
61+
dwsharemode: FILE_SHARE_MODE,
62+
lpsecurityattributes: *const SECURITY_ATTRIBUTES,
63+
dwcreationdisposition: FILE_CREATION_DISPOSITION,
64+
dwflagsandattributes: FILE_FLAGS_AND_ATTRIBUTES,
65+
htemplatefile: HANDLE,
66+
) -> HANDLE;
67+
}
68+
69+
impl_facade!(CreateFileWSyscallFacade, CreateFileWSyscall,
70+
CreateFileW(
71+
lpfilename: PCWSTR,
72+
dwdesiredaccess: c_uint,
73+
dwsharemode: FILE_SHARE_MODE,
74+
lpsecurityattributes: *const SECURITY_ATTRIBUTES,
75+
dwcreationdisposition: FILE_CREATION_DISPOSITION,
76+
dwflagsandattributes: FILE_FLAGS_AND_ATTRIBUTES,
77+
htemplatefile: HANDLE
78+
) -> HANDLE
79+
);
80+
81+
impl_raw!(RawCreateFileWSyscall, CreateFileWSyscall, windows_sys::Win32::Storage::FileSystem,
82+
CreateFileW(
83+
lpfilename: PCWSTR,
84+
dwdesiredaccess: c_uint,
85+
dwsharemode: FILE_SHARE_MODE,
86+
lpsecurityattributes: *const SECURITY_ATTRIBUTES,
87+
dwcreationdisposition: FILE_CREATION_DISPOSITION,
88+
dwflagsandattributes: FILE_FLAGS_AND_ATTRIBUTES,
89+
htemplatefile: HANDLE
90+
) -> HANDLE
91+
);
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
use std::ffi::c_longlong;
2+
use once_cell::sync::Lazy;
3+
use windows_sys::Win32::Foundation::{BOOL, HANDLE};
4+
use windows_sys::Win32::Storage::FileSystem::SET_FILE_POINTER_MOVE_METHOD;
5+
6+
#[must_use]
7+
pub extern "system" fn SetFilePointerEx(
8+
fn_ptr: Option<&extern "system" fn(HANDLE, c_longlong, *mut c_longlong, SET_FILE_POINTER_MOVE_METHOD) -> BOOL>,
9+
hfile: HANDLE,
10+
lidistancetomove: c_longlong,
11+
lpnewfilepointer : *mut c_longlong,
12+
dwmovemethod : SET_FILE_POINTER_MOVE_METHOD
13+
) -> BOOL {
14+
static CHAIN: Lazy<SetFilePointerExSyscallFacade<RawSetFilePointerExSyscall>> =
15+
Lazy::new(Default::default);
16+
CHAIN.SetFilePointerEx(fn_ptr, hfile, lidistancetomove, lpnewfilepointer, dwmovemethod)
17+
}
18+
19+
trait SetFilePointerExSyscall {
20+
extern "system" fn SetFilePointerEx(
21+
&self,
22+
fn_ptr: Option<&extern "system" fn(HANDLE, c_longlong, *mut c_longlong, SET_FILE_POINTER_MOVE_METHOD) -> BOOL>,
23+
hfile: HANDLE,
24+
lidistancetomove: c_longlong,
25+
lpnewfilepointer : *mut c_longlong,
26+
dwmovemethod : SET_FILE_POINTER_MOVE_METHOD
27+
) -> BOOL;
28+
}
29+
30+
impl_facade!(SetFilePointerExSyscallFacade, SetFilePointerExSyscall,
31+
SetFilePointerEx(
32+
hfile: HANDLE,
33+
lidistancetomove: c_longlong,
34+
lpnewfilepointer : *mut c_longlong,
35+
dwmovemethod : SET_FILE_POINTER_MOVE_METHOD
36+
) -> BOOL
37+
);
38+
39+
impl_raw!(RawSetFilePointerExSyscall, SetFilePointerExSyscall, windows_sys::Win32::Storage::FileSystem,
40+
SetFilePointerEx(
41+
hfile: HANDLE,
42+
lidistancetomove: c_longlong,
43+
lpnewfilepointer : *mut c_longlong,
44+
dwmovemethod : SET_FILE_POINTER_MOVE_METHOD
45+
) -> BOOL
46+
);
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
use std::ffi::{c_uint, c_void};
2+
use std::time::Duration;
3+
use once_cell::sync::Lazy;
4+
use windows_sys::Win32::Foundation::{BOOL, ERROR_TIMEOUT, FALSE, TRUE};
5+
use crate::common::{get_timeout_time, now};
6+
use crate::net::EventLoops;
7+
use crate::syscall::common::reset_errno;
8+
use crate::syscall::set_errno;
9+
10+
#[must_use]
11+
pub extern "system" fn WaitOnAddress(
12+
fn_ptr: Option<&extern "system" fn(*const c_void, *const c_void, usize, c_uint) -> BOOL>,
13+
address: *const c_void,
14+
compareaddress: *const c_void,
15+
addresssize: usize,
16+
dwmilliseconds: c_uint
17+
) -> BOOL {
18+
static CHAIN: Lazy<WaitOnAddressSyscallFacade<NioWaitOnAddressSyscall<RawWaitOnAddressSyscall>>> =
19+
Lazy::new(Default::default);
20+
CHAIN.WaitOnAddress(fn_ptr, address, compareaddress, addresssize, dwmilliseconds)
21+
}
22+
23+
trait WaitOnAddressSyscall {
24+
extern "system" fn WaitOnAddress(
25+
&self,
26+
fn_ptr: Option<&extern "system" fn(*const c_void, *const c_void, usize, c_uint) -> BOOL>,
27+
address: *const c_void,
28+
compareaddress: *const c_void,
29+
addresssize: usize,
30+
dwmilliseconds: c_uint
31+
) -> BOOL;
32+
}
33+
34+
impl_facade!(WaitOnAddressSyscallFacade, WaitOnAddressSyscall,
35+
WaitOnAddress(
36+
address: *const c_void,
37+
compareaddress: *const c_void,
38+
addresssize: usize,
39+
dwmilliseconds: c_uint
40+
) -> BOOL
41+
);
42+
43+
#[repr(C)]
44+
#[derive(Debug, Default)]
45+
struct NioWaitOnAddressSyscall<I: WaitOnAddressSyscall> {
46+
inner: I,
47+
}
48+
49+
impl<I: WaitOnAddressSyscall> WaitOnAddressSyscall for NioWaitOnAddressSyscall<I> {
50+
extern "system" fn WaitOnAddress(
51+
&self,
52+
fn_ptr: Option<&extern "system" fn(*const c_void, *const c_void, usize, c_uint) -> BOOL>,
53+
address: *const c_void,
54+
compareaddress: *const c_void,
55+
addresssize: usize,
56+
dwmilliseconds: c_uint
57+
) -> BOOL {
58+
let timeout = get_timeout_time(Duration::from_millis(dwmilliseconds.into()));
59+
loop {
60+
let mut left_time = timeout.saturating_sub(now());
61+
if 0 == left_time {
62+
set_errno(ERROR_TIMEOUT);
63+
return FALSE;
64+
}
65+
let r = self.inner.WaitOnAddress(
66+
fn_ptr,
67+
address,
68+
compareaddress,
69+
addresssize,
70+
(left_time / 1_000_000).min(1).try_into().expect("overflow"),
71+
);
72+
if TRUE == r {
73+
reset_errno();
74+
return r;
75+
}
76+
left_time = timeout.saturating_sub(now());
77+
if 0 == left_time {
78+
set_errno(ERROR_TIMEOUT);
79+
return FALSE;
80+
}
81+
let wait_time = if left_time > 10_000_000 {
82+
10_000_000
83+
} else {
84+
left_time
85+
};
86+
if EventLoops::wait_event(Some(Duration::new(
87+
wait_time / 1_000_000_000,
88+
(wait_time % 1_000_000_000) as _,
89+
)))
90+
.is_err()
91+
{
92+
return r;
93+
}
94+
}
95+
}
96+
}
97+
98+
impl_raw!(RawWaitOnAddressSyscall, WaitOnAddressSyscall, windows_sys::Win32::System::Threading,
99+
WaitOnAddress(
100+
address: *const c_void,
101+
compareaddress: *const c_void,
102+
addresssize: usize,
103+
dwmilliseconds: c_uint
104+
) -> BOOL
105+
);

0 commit comments

Comments
 (0)