Fix UB in the locking code of context switching
The spin crate considers it UB to call force_write_unlock while there is a threads trying to obtain a read lock on the same rwlock. This also switches to the spinning_lot crate for the context rwlock as it has support for a write guard keeping a reference to the rwlock using an Arc instead of a reference.
This commit is contained in:
+2
-1
@@ -34,6 +34,7 @@ use core::{
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
};
|
||||
use spin::RwLock;
|
||||
use spinning_top::RwSpinlock;
|
||||
|
||||
use super::{CallerCtx, GlobalSchemes, KernelSchemes, OpenResult};
|
||||
|
||||
@@ -265,7 +266,7 @@ fn new_handle(handle: Handle) -> Result<usize> {
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
fn get_context(id: ContextId) -> Result<Arc<RwLock<Context>>> {
|
||||
fn get_context(id: ContextId) -> Result<Arc<RwSpinlock<Context>>> {
|
||||
context::contexts()
|
||||
.get(id)
|
||||
.ok_or(Error::new(ENOENT))
|
||||
|
||||
+6
-5
@@ -12,6 +12,7 @@ use core::{
|
||||
};
|
||||
use hashbrown::hash_map::{Entry, HashMap};
|
||||
use spin::{Mutex, RwLock};
|
||||
use spinning_top::RwSpinlock;
|
||||
use syscall::{
|
||||
FobtainFdFlags, MunmapFlags, SendFdFlags, MAP_FIXED_NOREPLACE, SKMSG_FOBTAINFD,
|
||||
SKMSG_FRETURNFD, SKMSG_PROVIDE_MMAP,
|
||||
@@ -50,7 +51,7 @@ pub struct UserInner {
|
||||
pub flags: usize,
|
||||
pub scheme_id: SchemeId,
|
||||
next_id: Mutex<u64>,
|
||||
context: Weak<RwLock<Context>>,
|
||||
context: Weak<RwSpinlock<Context>>,
|
||||
todo: WaitQueue<Packet>,
|
||||
states: Mutex<HashMap<u64, State>>,
|
||||
unmounting: AtomicBool,
|
||||
@@ -58,11 +59,11 @@ pub struct UserInner {
|
||||
|
||||
enum State {
|
||||
Waiting {
|
||||
context: Weak<RwLock<Context>>,
|
||||
context: Weak<RwSpinlock<Context>>,
|
||||
fd: Option<Arc<RwLock<FileDescription>>>,
|
||||
},
|
||||
Responded(Response),
|
||||
Fmap(Weak<RwLock<Context>>),
|
||||
Fmap(Weak<RwSpinlock<Context>>),
|
||||
Placeholder,
|
||||
}
|
||||
|
||||
@@ -84,7 +85,7 @@ impl UserInner {
|
||||
handle_id: usize,
|
||||
name: Box<str>,
|
||||
flags: usize,
|
||||
context: Weak<RwLock<Context>>,
|
||||
context: Weak<RwSpinlock<Context>>,
|
||||
) -> UserInner {
|
||||
UserInner {
|
||||
root_id,
|
||||
@@ -274,7 +275,7 @@ impl UserInner {
|
||||
// TODO: Hypothetical accept_head_leak, accept_tail_leak options might be useful for
|
||||
// libc-controlled buffer pools.
|
||||
fn capture_inner<const READ: bool, const WRITE: bool>(
|
||||
context_weak: &Weak<RwLock<Context>>,
|
||||
context_weak: &Weak<RwSpinlock<Context>>,
|
||||
user_buf: UserSlice<READ, WRITE>,
|
||||
) -> Result<CaptureGuard<READ, WRITE>> {
|
||||
let (mode, map_flags) = match (READ, WRITE) {
|
||||
|
||||
Reference in New Issue
Block a user