diff --git a/kernel/src/net/socket/ip/datagram/mod.rs b/kernel/src/net/socket/ip/datagram/mod.rs index 301c3cd6..7bad0b5e 100644 --- a/kernel/src/net/socket/ip/datagram/mod.rs +++ b/kernel/src/net/socket/ip/datagram/mod.rs @@ -47,8 +47,10 @@ impl OptionSet { } pub struct DatagramSocket { - options: RwLock, + // Lock order: `inner` first, `options` second inner: RwLock, PreemptDisabled>, + options: RwLock, + is_nonblocking: AtomicBool, pollee: Pollee, } @@ -101,9 +103,9 @@ impl DatagramSocket { let unbound_datagram = UnboundDatagram::new(); Arc::new(Self { inner: RwLock::new(Takeable::new(Inner::Unbound(unbound_datagram))), + options: RwLock::new(OptionSet::new()), is_nonblocking: AtomicBool::new(is_nonblocking), pollee: Pollee::new(), - options: RwLock::new(OptionSet::new()), }) } @@ -257,8 +259,8 @@ impl Socket for DatagramSocket { fn bind(&self, socket_addr: SocketAddr) -> Result<()> { let endpoint = socket_addr.try_into()?; - let can_reuse = self.options.read().socket.reuse_addr(); let mut inner = self.inner.write(); + let can_reuse = self.options.read().socket.reuse_addr(); inner.borrow_result(|owned_inner| { let bound_datagram = match owned_inner.bind( &endpoint, @@ -373,10 +375,10 @@ impl Socket for DatagramSocket { } fn set_option(&self, option: &dyn SocketOption) -> Result<()> { + let inner = self.inner.read(); let mut options = self.options.write(); - let mut inner = self.inner.write(); - match options.socket.set_option(option, inner.as_mut()) { + match options.socket.set_option(option, inner.as_ref()) { Err(e) => Err(e), Ok(need_iface_poll) => { let iface_to_poll = need_iface_poll diff --git a/kernel/src/net/socket/ip/options.rs b/kernel/src/net/socket/ip/options.rs index a14004ca..0162bd5c 100644 --- a/kernel/src/net/socket/ip/options.rs +++ b/kernel/src/net/socket/ip/options.rs @@ -54,7 +54,7 @@ impl IpOptionSet { pub(super) fn set_option( &mut self, option: &dyn SocketOption, - socket: &mut dyn SetIpLevelOption, + socket: &dyn SetIpLevelOption, ) -> Result { match_sock_option_ref!(option, { ip_tos: Tos => { diff --git a/kernel/src/net/socket/ip/stream/mod.rs b/kernel/src/net/socket/ip/stream/mod.rs index 8a4c9842..33db1b99 100644 --- a/kernel/src/net/socket/ip/stream/mod.rs +++ b/kernel/src/net/socket/ip/stream/mod.rs @@ -58,8 +58,10 @@ pub(in crate::net) use self::observer::StreamObserver; pub use self::util::CongestionControl; pub struct StreamSocket { - options: RwLock, + // Lock order: `state` first, `options` second state: RwLock, PreemptDisabled>, + options: RwLock, + is_nonblocking: AtomicBool, pollee: Pollee, } @@ -102,8 +104,8 @@ impl StreamSocket { pub fn new(is_nonblocking: bool) -> Arc { let init_stream = InitStream::new(); Arc::new(Self { - options: RwLock::new(OptionSet::new()), state: RwLock::new(Takeable::new(State::Init(init_stream))), + options: RwLock::new(OptionSet::new()), is_nonblocking: AtomicBool::new(is_nonblocking), pollee: Pollee::new(), }) @@ -190,11 +192,11 @@ impl StreamSocket { fn start_connect(&self, remote_endpoint: &IpEndpoint) -> Option> { let is_nonblocking = self.is_nonblocking(); + let mut state = self.write_updated_state(); + let options = self.options.read(); let raw_option = options.raw(); - let mut state = self.write_updated_state(); - let (result_or_block, iface_to_poll) = state.borrow_result(|mut owned_state| { let mut init_stream = match owned_state { State::Init(init_stream) => init_stream, @@ -426,12 +428,12 @@ impl Socket for StreamSocket { fn bind(&self, socket_addr: SocketAddr) -> Result<()> { let endpoint = socket_addr.try_into()?; - let can_reuse = self.options.read().socket.reuse_addr(); let mut state = self.write_updated_state(); - let State::Init(init_stream) = state.as_mut() else { return_errno_with_message!(Errno::EINVAL, "the socket is already bound to an address"); }; + + let can_reuse = self.options.read().socket.reuse_addr(); init_stream.bind(&endpoint, can_reuse) } @@ -446,11 +448,11 @@ impl Socket for StreamSocket { } fn listen(&self, backlog: usize) -> Result<()> { + let mut state = self.write_updated_state(); + let options = self.options.read(); let raw_option = options.raw(); - let mut state = self.write_updated_state(); - state.borrow_result(|owned_state| { let init_stream = match owned_state { State::Init(init_stream) => init_stream, @@ -665,8 +667,8 @@ impl Socket for StreamSocket { } fn set_option(&self, option: &dyn SocketOption) -> Result<()> { - let mut options = self.options.write(); let mut state = self.write_updated_state(); + let mut options = self.options.write(); // Deal with socket-level options let need_iface_poll = match options.socket.set_option(option, state.as_mut()) { diff --git a/kernel/src/net/socket/util/options.rs b/kernel/src/net/socket/util/options.rs index 6bd71a92..41248aae 100644 --- a/kernel/src/net/socket/util/options.rs +++ b/kernel/src/net/socket/util/options.rs @@ -91,7 +91,7 @@ impl SocketOptionSet { pub fn set_option( &mut self, option: &dyn SocketOption, - socket: &mut dyn SetSocketLevelOption, + socket: &dyn SetSocketLevelOption, ) -> Result { match_sock_option_ref!(option, { socket_recv_buf: RecvBuf => {