Skip to content

Commit 4e3857a

Browse files
authored
add IOCP accept (#384)
2 parents f26ecd9 + fe85826 commit 4e3857a

File tree

4 files changed

+251
-21
lines changed

4 files changed

+251
-21
lines changed

core/src/net/operator/windows/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ impl<'o> Operator<'o> {
238238
let mut sock_info: WSAPROTOCOL_INFOW = std::mem::zeroed();
239239
let mut sock_info_len = size_of::<WSAPROTOCOL_INFOW>()
240240
.try_into()
241-
.expect("protocol_len overflow");
241+
.expect("sock_info_len overflow");
242242
if getsockopt(
243243
fd,
244244
SOL_SOCKET,

core/src/syscall/unix/mod.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,10 @@ macro_rules! impl_io_uring {
6161
fn_ptr: Option<&extern "C" fn($($arg_type),*) -> $result>,
6262
$($arg: $arg_type),*
6363
) -> $result {
64-
if let Ok(arc) = $crate::net::EventLoops::$syscall($($arg, )*) {
65-
use $crate::common::constants::{CoroutineState, SyscallState};
66-
use $crate::scheduler::{SchedulableCoroutine, SchedulableSuspender};
64+
use $crate::common::constants::{CoroutineState, SyscallState};
65+
use $crate::scheduler::{SchedulableCoroutine, SchedulableSuspender};
6766

67+
if let Ok(arc) = $crate::net::EventLoops::$syscall($($arg, )*) {
6868
if let Some(co) = SchedulableCoroutine::current() {
6969
if let CoroutineState::Syscall((), syscall, SyscallState::Executing) = co.state()
7070
{
@@ -136,10 +136,10 @@ macro_rules! impl_io_uring_read {
136136
$fd: $fd_type,
137137
$($arg: $arg_type),*
138138
) -> $result {
139-
if let Ok(arc) = $crate::net::EventLoops::$syscall($fd, $($arg, )*) {
140-
use $crate::common::constants::{CoroutineState, SyscallState};
141-
use $crate::scheduler::{SchedulableCoroutine, SchedulableSuspender};
139+
use $crate::common::constants::{CoroutineState, SyscallState};
140+
use $crate::scheduler::{SchedulableCoroutine, SchedulableSuspender};
142141

142+
if let Ok(arc) = $crate::net::EventLoops::$syscall($fd, $($arg, )*) {
143143
if let Some(co) = SchedulableCoroutine::current() {
144144
if let CoroutineState::Syscall((), syscall, SyscallState::Executing) = co.state()
145145
{
@@ -222,10 +222,10 @@ macro_rules! impl_io_uring_write {
222222
$fd: $fd_type,
223223
$($arg: $arg_type),*
224224
) -> $result {
225-
if let Ok(arc) = $crate::net::EventLoops::$syscall($fd, $($arg, )*) {
226-
use $crate::common::constants::{CoroutineState, SyscallState};
227-
use $crate::scheduler::{SchedulableCoroutine, SchedulableSuspender};
225+
use $crate::common::constants::{CoroutineState, SyscallState};
226+
use $crate::scheduler::{SchedulableCoroutine, SchedulableSuspender};
228227

228+
if let Ok(arc) = $crate::net::EventLoops::$syscall($fd, $($arg, )*) {
229229
if let Some(co) = SchedulableCoroutine::current() {
230230
if let CoroutineState::Syscall((), syscall, SyscallState::Executing) = co.state()
231231
{

core/src/syscall/windows/accept.rs

Lines changed: 94 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::convert::TryInto;
12
use once_cell::sync::Lazy;
23
use std::ffi::c_int;
34
use windows_sys::Win32::Networking::WinSock::{SOCKADDR, SOCKET};
@@ -9,8 +10,16 @@ pub extern "system" fn accept(
910
address: *mut SOCKADDR,
1011
address_len: *mut c_int,
1112
) -> SOCKET {
12-
static CHAIN: Lazy<AcceptSyscallFacade<NioAcceptSyscall<RawAcceptSyscall>>> =
13-
Lazy::new(Default::default);
13+
cfg_if::cfg_if! {
14+
if #[cfg(feature = "iocp")] {
15+
static CHAIN: Lazy<
16+
AcceptSyscallFacade<IocpAcceptSyscall<NioAcceptSyscall<RawAcceptSyscall>>>
17+
> = Lazy::new(Default::default);
18+
} else {
19+
static CHAIN: Lazy<AcceptSyscallFacade<NioAcceptSyscall<RawAcceptSyscall>>> =
20+
Lazy::new(Default::default);
21+
}
22+
}
1423
CHAIN.accept(fn_ptr, fd, address, address_len)
1524
}
1625

@@ -28,6 +37,89 @@ impl_facade!(AcceptSyscallFacade, AcceptSyscall,
2837
accept(fd: SOCKET, address: *mut SOCKADDR, address_len: *mut c_int) -> SOCKET
2938
);
3039

40+
#[repr(C)]
41+
#[derive(Debug, Default)]
42+
#[cfg(all(windows, feature = "iocp"))]
43+
struct IocpAcceptSyscall<I: AcceptSyscall> {
44+
inner: I,
45+
}
46+
47+
#[cfg(all(windows, feature = "iocp"))]
48+
impl<I: AcceptSyscall> AcceptSyscall for IocpAcceptSyscall<I> {
49+
extern "system" fn accept(
50+
&self,
51+
fn_ptr: Option<&extern "system" fn(SOCKET, *mut SOCKADDR, *mut c_int) -> SOCKET>,
52+
fd: SOCKET,
53+
address: *mut SOCKADDR,
54+
address_len: *mut c_int
55+
) -> SOCKET {
56+
use crate::common::constants::{CoroutineState, SyscallState};
57+
use crate::scheduler::{SchedulableCoroutine, SchedulableSuspender};
58+
use windows_sys::Win32::Networking::WinSock::{INVALID_SOCKET, getsockopt, SOL_SOCKET, SO_PROTOCOL_INFO, WSAPROTOCOL_INFOW};
59+
60+
if let Ok(arc) = crate::net::EventLoops::accept(fd, address, address_len) {
61+
if let Some(co) = SchedulableCoroutine::current() {
62+
if let CoroutineState::Syscall((), syscall, SyscallState::Executing) = co.state()
63+
{
64+
let new_state = SyscallState::Suspend(crate::syscall::recv_time_limit(fd));
65+
if co.syscall((), syscall, new_state).is_err() {
66+
crate::error!(
67+
"{} change to syscall {} {} failed !",
68+
co.name(), syscall, new_state
69+
);
70+
}
71+
}
72+
}
73+
if let Some(suspender) = SchedulableSuspender::current() {
74+
suspender.suspend();
75+
//回来的时候,系统调用已经执行完了
76+
}
77+
if let Some(co) = SchedulableCoroutine::current() {
78+
if let CoroutineState::Syscall((), syscall, SyscallState::Callback) = co.state()
79+
{
80+
let new_state = SyscallState::Executing;
81+
if co.syscall((), syscall, new_state).is_err() {
82+
crate::error!(
83+
"{} change to syscall {} {} failed !",
84+
co.name(), syscall, new_state
85+
);
86+
}
87+
}
88+
}
89+
let (lock, cvar) = &*arc;
90+
let syscall_result = cvar
91+
.wait_while(lock.lock().expect("lock failed"),
92+
|&mut result| result.is_none()
93+
)
94+
.expect("lock failed")
95+
.expect("no syscall result");
96+
if syscall_result < 0 {
97+
crate::syscall::set_errno((-syscall_result).try_into().expect("errno overflow"));
98+
return INVALID_SOCKET;
99+
}
100+
unsafe {
101+
let mut sock_info: WSAPROTOCOL_INFOW = std::mem::zeroed();
102+
let mut sock_info_len = size_of::<WSAPROTOCOL_INFOW>()
103+
.try_into()
104+
.expect("sock_info_len overflow");
105+
if getsockopt(
106+
fd,
107+
SOL_SOCKET,
108+
SO_PROTOCOL_INFO,
109+
std::ptr::from_mut(&mut sock_info).cast(),
110+
&mut sock_info_len,
111+
) != 0
112+
{
113+
return INVALID_SOCKET;
114+
}
115+
(*address).sa_family = sock_info.iAddressFamily.try_into().expect("iAddressFamily overflow");
116+
}
117+
return SOCKET::try_from(syscall_result).expect("overflow");
118+
}
119+
self.inner.accept(fn_ptr, fd, address, address_len)
120+
}
121+
}
122+
31123
impl_nio_read!(NioAcceptSyscall, AcceptSyscall,
32124
accept(fd: SOCKET, address: *mut SOCKADDR, address_len: *mut c_int) -> SOCKET
33125
);

core/src/syscall/windows/mod.rs

Lines changed: 147 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ macro_rules! impl_iocp {
6666
fn_ptr: Option<&extern "system" fn($($arg_type),*) -> $result>,
6767
$($arg: $arg_type),*
6868
) -> $result {
69-
use $crate::common::constants::{CoroutineState, SyscallName, SyscallState};
69+
use $crate::common::constants::{CoroutineState, SyscallState};
7070
use $crate::scheduler::{SchedulableCoroutine, SchedulableSuspender};
7171

7272
if let Ok(arc) = $crate::net::EventLoops::$syscall($($arg, )*) {
@@ -77,9 +77,7 @@ macro_rules! impl_iocp {
7777
if co.syscall((), syscall, new_state).is_err() {
7878
$crate::error!(
7979
"{} change to syscall {} {} failed !",
80-
co.name(),
81-
syscall,
82-
new_state
80+
co.name(), syscall, new_state
8381
);
8482
}
8583
}
@@ -109,11 +107,7 @@ macro_rules! impl_iocp {
109107
.expect("no syscall result");
110108
if syscall_result < 0 {
111109
$crate::syscall::set_errno((-syscall_result).try_into().expect("errno overflow"));
112-
if SyscallName::accept == SyscallName::$syscall {
113-
syscall_result = 0;
114-
} else {
115-
syscall_result = -1;
116-
}
110+
syscall_result = -1;
117111
}
118112
return <$result>::try_from(syscall_result).expect("overflow");
119113
}
@@ -123,6 +117,150 @@ macro_rules! impl_iocp {
123117
}
124118
}
125119

120+
#[allow(unused_macros)]
121+
macro_rules! impl_iocp_read {
122+
(
123+
$struct_name:ident, $trait_name: ident,
124+
$syscall: ident($fd: ident : $fd_type: ty, $($arg: ident : $arg_type: ty),*) -> $result: ty
125+
) => {
126+
#[repr(C)]
127+
#[derive(Debug, Default)]
128+
#[cfg(all(windows, feature = "iocp"))]
129+
struct $struct_name<I: $trait_name> {
130+
inner: I,
131+
}
132+
133+
#[cfg(all(windows, feature = "iocp"))]
134+
impl<I: $trait_name> $trait_name for $struct_name<I> {
135+
extern "system" fn $syscall(
136+
&self,
137+
fn_ptr: Option<&extern "system" fn($fd_type, $($arg_type),*) -> $result>,
138+
$fd: $fd_type,
139+
$($arg: $arg_type),*
140+
) -> $result {
141+
use $crate::common::constants::{CoroutineState, SyscallState};
142+
use $crate::scheduler::{SchedulableCoroutine, SchedulableSuspender};
143+
144+
if let Ok(arc) = $crate::net::EventLoops::$syscall($fd, $($arg, )*) {
145+
if let Some(co) = SchedulableCoroutine::current() {
146+
if let CoroutineState::Syscall((), syscall, SyscallState::Executing) = co.state()
147+
{
148+
let new_state = SyscallState::Suspend($crate::syscall::recv_time_limit($fd));
149+
if co.syscall((), syscall, new_state).is_err() {
150+
$crate::error!(
151+
"{} change to syscall {} {} failed !",
152+
co.name(), syscall, new_state
153+
);
154+
}
155+
}
156+
}
157+
if let Some(suspender) = SchedulableSuspender::current() {
158+
suspender.suspend();
159+
//回来的时候,系统调用已经执行完了
160+
}
161+
if let Some(co) = SchedulableCoroutine::current() {
162+
if let CoroutineState::Syscall((), syscall, SyscallState::Callback) = co.state()
163+
{
164+
let new_state = SyscallState::Executing;
165+
if co.syscall((), syscall, new_state).is_err() {
166+
$crate::error!(
167+
"{} change to syscall {} {} failed !",
168+
co.name(), syscall, new_state
169+
);
170+
}
171+
}
172+
}
173+
let (lock, cvar) = &*arc;
174+
let mut syscall_result = cvar
175+
.wait_while(lock.lock().expect("lock failed"),
176+
|&mut result| result.is_none()
177+
)
178+
.expect("lock failed")
179+
.expect("no syscall result");
180+
if syscall_result < 0 {
181+
$crate::syscall::set_errno((-syscall_result).try_into().expect("errno overflow"));
182+
syscall_result = -1;
183+
}
184+
return <$result>::try_from(syscall_result).expect("overflow");
185+
}
186+
self.inner.$syscall(fn_ptr, $fd, $($arg, )*)
187+
}
188+
}
189+
}
190+
}
191+
192+
#[allow(unused_macros)]
193+
macro_rules! impl_iocp_write {
194+
(
195+
$struct_name:ident, $trait_name: ident,
196+
$syscall: ident($fd: ident : $fd_type: ty, $($arg: ident : $arg_type: ty),*) -> $result: ty
197+
) => {
198+
#[repr(C)]
199+
#[derive(Debug, Default)]
200+
#[cfg(all(windows, feature = "iocp"))]
201+
struct $struct_name<I: $trait_name> {
202+
inner: I,
203+
}
204+
205+
#[cfg(all(windows, feature = "iocp"))]
206+
impl<I: $trait_name> $trait_name for $struct_name<I> {
207+
extern "system" fn $syscall(
208+
&self,
209+
fn_ptr: Option<&extern "system" fn($fd_type, $($arg_type),*) -> $result>,
210+
$fd: $fd_type,
211+
$($arg: $arg_type),*
212+
) -> $result {
213+
use $crate::common::constants::{CoroutineState, SyscallState};
214+
use $crate::scheduler::{SchedulableCoroutine, SchedulableSuspender};
215+
216+
if let Ok(arc) = $crate::net::EventLoops::$syscall($fd, $($arg, )*) {
217+
if let Some(co) = SchedulableCoroutine::current() {
218+
if let CoroutineState::Syscall((), syscall, SyscallState::Executing) = co.state()
219+
{
220+
let new_state = SyscallState::Suspend($crate::syscall::send_time_limit($fd));
221+
if co.syscall((), syscall, new_state).is_err() {
222+
$crate::error!(
223+
"{} change to syscall {} {} failed !",
224+
co.name(), syscall, new_state
225+
);
226+
}
227+
}
228+
}
229+
if let Some(suspender) = SchedulableSuspender::current() {
230+
suspender.suspend();
231+
//回来的时候,系统调用已经执行完了
232+
}
233+
if let Some(co) = SchedulableCoroutine::current() {
234+
if let CoroutineState::Syscall((), syscall, SyscallState::Callback) = co.state()
235+
{
236+
let new_state = SyscallState::Executing;
237+
if co.syscall((), syscall, new_state).is_err() {
238+
$crate::error!(
239+
"{} change to syscall {} {} failed !",
240+
co.name(), syscall, new_state
241+
);
242+
}
243+
}
244+
}
245+
let (lock, cvar) = &*arc;
246+
let mut syscall_result = cvar
247+
.wait_while(lock.lock().expect("lock failed"),
248+
|&mut result| result.is_none()
249+
)
250+
.expect("lock failed")
251+
.expect("no syscall result");
252+
if syscall_result < 0 {
253+
$crate::syscall::set_errno((-syscall_result).try_into().expect("errno overflow"));
254+
syscall_result = -1;
255+
}
256+
return <$result>::try_from(syscall_result).expect("overflow");
257+
}
258+
self.inner.$syscall(fn_ptr, $fd, $($arg, )*)
259+
}
260+
}
261+
}
262+
}
263+
126264
macro_rules! impl_nio_read {
127265
(
128266
$struct_name:ident, $trait_name: ident,

0 commit comments

Comments
 (0)