mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-17 12:47:16 +00:00
Avoid holding lock when call accept and recvfrom
This commit is contained in:
parent
4f00e5a167
commit
ab4b1b47dc
@ -112,24 +112,25 @@ impl Socket for StreamSocket {
|
|||||||
|
|
||||||
fn connect(&self, sockaddr: SocketAddr) -> Result<()> {
|
fn connect(&self, sockaddr: SocketAddr) -> Result<()> {
|
||||||
let remote_endpoint = sockaddr.try_into()?;
|
let remote_endpoint = sockaddr.try_into()?;
|
||||||
let state = self.state.read();
|
|
||||||
match &*state {
|
let init_stream = match &*self.state.read() {
|
||||||
State::Init(init_stream) => {
|
State::Init(init_stream) => init_stream.clone(),
|
||||||
let init_stream = init_stream.clone();
|
|
||||||
drop(state);
|
|
||||||
init_stream.connect(&remote_endpoint)?;
|
|
||||||
let nonblocking = init_stream.is_nonblocking();
|
|
||||||
let bound_socket = init_stream.bound_socket().unwrap();
|
|
||||||
let connected_stream = Arc::new(ConnectedStream::new(
|
|
||||||
nonblocking,
|
|
||||||
bound_socket,
|
|
||||||
remote_endpoint,
|
|
||||||
));
|
|
||||||
*self.state.write() = State::Connected(connected_stream);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
_ => return_errno_with_message!(Errno::EINVAL, "cannot connect"),
|
_ => return_errno_with_message!(Errno::EINVAL, "cannot connect"),
|
||||||
}
|
};
|
||||||
|
|
||||||
|
init_stream.connect(&remote_endpoint)?;
|
||||||
|
|
||||||
|
let connected_stream = {
|
||||||
|
let nonblocking = init_stream.is_nonblocking();
|
||||||
|
let bound_socket = init_stream.bound_socket().unwrap();
|
||||||
|
Arc::new(ConnectedStream::new(
|
||||||
|
nonblocking,
|
||||||
|
bound_socket,
|
||||||
|
remote_endpoint,
|
||||||
|
))
|
||||||
|
};
|
||||||
|
*self.state.write() = State::Connected(connected_stream);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn listen(&self, backlog: usize) -> Result<()> {
|
fn listen(&self, backlog: usize) -> Result<()> {
|
||||||
@ -153,17 +154,23 @@ impl Socket for StreamSocket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn accept(&self) -> Result<(Arc<dyn FileLike>, SocketAddr)> {
|
fn accept(&self) -> Result<(Arc<dyn FileLike>, SocketAddr)> {
|
||||||
let state = self.state.read();
|
let listen_stream = match &*self.state.read() {
|
||||||
match &*state {
|
State::Listen(listen_stream) => listen_stream.clone(),
|
||||||
State::Listen(listen_stream) => {
|
|
||||||
let (connected_stream, remote_endpoint) = listen_stream.accept()?;
|
|
||||||
let state = RwLock::new(State::Connected(Arc::new(connected_stream)));
|
|
||||||
let accepted_socket = Arc::new(StreamSocket { state });
|
|
||||||
let socket_addr = remote_endpoint.try_into()?;
|
|
||||||
Ok((accepted_socket, socket_addr))
|
|
||||||
}
|
|
||||||
_ => return_errno_with_message!(Errno::EINVAL, "the socket is not listening"),
|
_ => return_errno_with_message!(Errno::EINVAL, "the socket is not listening"),
|
||||||
}
|
};
|
||||||
|
|
||||||
|
let (connected_stream, remote_endpoint) = {
|
||||||
|
let listen_stream = listen_stream.clone();
|
||||||
|
listen_stream.accept()?
|
||||||
|
};
|
||||||
|
|
||||||
|
let accepted_socket = {
|
||||||
|
let state = RwLock::new(State::Connected(Arc::new(connected_stream)));
|
||||||
|
Arc::new(StreamSocket { state })
|
||||||
|
};
|
||||||
|
|
||||||
|
let socket_addr = remote_endpoint.try_into()?;
|
||||||
|
Ok((accepted_socket, socket_addr))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shutdown(&self, cmd: SockShutdownCmd) -> Result<()> {
|
fn shutdown(&self, cmd: SockShutdownCmd) -> Result<()> {
|
||||||
@ -202,11 +209,12 @@ impl Socket for StreamSocket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn recvfrom(&self, buf: &mut [u8], flags: SendRecvFlags) -> Result<(usize, SocketAddr)> {
|
fn recvfrom(&self, buf: &mut [u8], flags: SendRecvFlags) -> Result<(usize, SocketAddr)> {
|
||||||
let state = self.state.read();
|
let connected_stream = match &*self.state.read() {
|
||||||
let (recv_size, remote_endpoint) = match &*state {
|
State::Connected(connected_stream) => connected_stream.clone(),
|
||||||
State::Connected(connected_stream) => connected_stream.recvfrom(buf, flags),
|
_ => return_errno_with_message!(Errno::EINVAL, "the socket is not connected"),
|
||||||
_ => return_errno_with_message!(Errno::EINVAL, "cannot recv"),
|
};
|
||||||
}?;
|
|
||||||
|
let (recv_size, remote_endpoint) = connected_stream.recvfrom(buf, flags)?;
|
||||||
let socket_addr = remote_endpoint.try_into()?;
|
let socket_addr = remote_endpoint.try_into()?;
|
||||||
Ok((recv_size, socket_addr))
|
Ok((recv_size, socket_addr))
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user