Rollup merge of #93843 - solid-rs:fix-kmc-solid-condvar, r=m-ou-se
kmc-solid: Fix wait queue manipulation errors in the `Condvar` implementation This PR fixes a number of bugs in the `Condvar` wait queue implementation used by the [`*-kmc-solid_*`](https://doc.rust-lang.org/nightly/rustc/platform-support/kmc-solid.html) Tier 3 targets. These bugs can occur when there are multiple threads waiting on the same `Condvar` and sometimes manifest as an `unwrap` failure.
This commit is contained in:
commit
8c60f44877
@ -15,10 +15,12 @@ unsafe impl Sync for Condvar {}
|
|||||||
pub type MovableCondvar = Condvar;
|
pub type MovableCondvar = Condvar;
|
||||||
|
|
||||||
impl Condvar {
|
impl Condvar {
|
||||||
|
#[inline]
|
||||||
pub const fn new() -> Condvar {
|
pub const fn new() -> Condvar {
|
||||||
Condvar { waiters: SpinMutex::new(waiter_queue::WaiterQueue::new()) }
|
Condvar { waiters: SpinMutex::new(waiter_queue::WaiterQueue::new()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub unsafe fn init(&mut self) {}
|
pub unsafe fn init(&mut self) {}
|
||||||
|
|
||||||
pub unsafe fn notify_one(&self) {
|
pub unsafe fn notify_one(&self) {
|
||||||
@ -190,7 +192,7 @@ pub unsafe fn insert(&mut self, mut waiter_ptr: NonNull<Waiter>) {
|
|||||||
let insert_after = {
|
let insert_after = {
|
||||||
let mut cursor = head.last;
|
let mut cursor = head.last;
|
||||||
loop {
|
loop {
|
||||||
if waiter.priority <= cursor.as_ref().priority {
|
if waiter.priority >= cursor.as_ref().priority {
|
||||||
// `cursor` and all previous waiters have the same or higher
|
// `cursor` and all previous waiters have the same or higher
|
||||||
// priority than `current_task_priority`. Insert the new
|
// priority than `current_task_priority`. Insert the new
|
||||||
// waiter right after `cursor`.
|
// waiter right after `cursor`.
|
||||||
@ -206,7 +208,7 @@ pub unsafe fn insert(&mut self, mut waiter_ptr: NonNull<Waiter>) {
|
|||||||
|
|
||||||
if let Some(mut insert_after) = insert_after {
|
if let Some(mut insert_after) = insert_after {
|
||||||
// Insert `waiter` after `insert_after`
|
// Insert `waiter` after `insert_after`
|
||||||
let insert_before = insert_after.as_ref().prev;
|
let insert_before = insert_after.as_ref().next;
|
||||||
|
|
||||||
waiter.prev = Some(insert_after);
|
waiter.prev = Some(insert_after);
|
||||||
insert_after.as_mut().next = Some(waiter_ptr);
|
insert_after.as_mut().next = Some(waiter_ptr);
|
||||||
@ -214,6 +216,8 @@ pub unsafe fn insert(&mut self, mut waiter_ptr: NonNull<Waiter>) {
|
|||||||
waiter.next = insert_before;
|
waiter.next = insert_before;
|
||||||
if let Some(mut insert_before) = insert_before {
|
if let Some(mut insert_before) = insert_before {
|
||||||
insert_before.as_mut().prev = Some(waiter_ptr);
|
insert_before.as_mut().prev = Some(waiter_ptr);
|
||||||
|
} else {
|
||||||
|
head.last = waiter_ptr;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Insert `waiter` to the front
|
// Insert `waiter` to the front
|
||||||
@ -240,11 +244,11 @@ pub unsafe fn remove(&mut self, mut waiter_ptr: NonNull<Waiter>) -> bool {
|
|||||||
match (waiter.prev, waiter.next) {
|
match (waiter.prev, waiter.next) {
|
||||||
(Some(mut prev), Some(mut next)) => {
|
(Some(mut prev), Some(mut next)) => {
|
||||||
prev.as_mut().next = Some(next);
|
prev.as_mut().next = Some(next);
|
||||||
next.as_mut().next = Some(prev);
|
next.as_mut().prev = Some(prev);
|
||||||
}
|
}
|
||||||
(None, Some(mut next)) => {
|
(None, Some(mut next)) => {
|
||||||
head.first = next;
|
head.first = next;
|
||||||
next.as_mut().next = None;
|
next.as_mut().prev = None;
|
||||||
}
|
}
|
||||||
(Some(mut prev), None) => {
|
(Some(mut prev), None) => {
|
||||||
prev.as_mut().next = None;
|
prev.as_mut().next = None;
|
||||||
@ -271,6 +275,7 @@ pub unsafe fn is_queued(&self, waiter: NonNull<Waiter>) -> bool {
|
|||||||
unsafe { waiter.as_ref().task != 0 }
|
unsafe { waiter.as_ref().task != 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn pop_front(&mut self) -> Option<abi::ID> {
|
pub fn pop_front(&mut self) -> Option<abi::ID> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let head = self.head.as_mut()?;
|
let head = self.head.as_mut()?;
|
||||||
|
Loading…
Reference in New Issue
Block a user