Skip to content

Commit d942d77

Browse files
committed
progress towards potential queue solution
1 parent fb33533 commit d942d77

File tree

1 file changed

+20
-19
lines changed

1 file changed

+20
-19
lines changed

library/std/src/sys/sync/rwlock/queue.rs

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ impl RwLock {
468468
pub unsafe fn downgrade(&self) {
469469
// Atomically attempt to go from a single writer without any waiting threads to a single
470470
// reader without any waiting threads.
471-
if let Err(state) = self.state.compare_exchange(
471+
if let Err(mut state) = self.state.compare_exchange(
472472
without_provenance_mut(LOCKED),
473473
without_provenance_mut(LOCKED | SINGLE),
474474
Release,
@@ -478,7 +478,6 @@ impl RwLock {
478478
state.mask(LOCKED).addr() != 0 && state.mask(QUEUED).addr() != 0,
479479
"RwLock should be LOCKED and QUEUED"
480480
);
481-
482481
// 1. Attempt to grab the queue lock
483482
// 2. Find the tail of the queue
484483
// 3. While the current tail is not a writer:
@@ -493,29 +492,31 @@ impl RwLock {
493492
// number of readers into the current node state or the head state.
494493

495494
// Attempt to grab the queue lock.
496-
loop {
497-
// Atomically release the lock and try to acquire the queue lock.
498-
let next = state.map_addr(|addr| addr | QUEUE_LOCKED);
499-
match self.state.compare_exchange_weak(state & !QUEUE_LOCKED, next, AcqRel, Relaxed)
500-
{
501-
// The queue lock was acquired. Release it, waking up the next
502-
// waiter in the process.
503-
Ok(_) if state.addr() & QUEUE_LOCKED == 0 => unsafe {
504-
return self.unlock_queue(next);
505-
},
506-
// Another thread already holds the queue lock, leave waking up
507-
// waiters to it.
508-
Ok(_) => return,
509-
Err(new) => state = new,
495+
state = loop {
496+
match self.state.fetch_update(Release, Acquire, |ptr: State| {
497+
// Go from not queue locked to being queue locked.
498+
if ptr.mask(QUEUE_LOCKED).addr() != 0 {
499+
Some(without_provenance_mut(ptr.addr() | QUEUE_LOCKED))
500+
} else {
501+
None
502+
}
503+
}) {
504+
Ok(state) => break state,
505+
Err(_) => {}
510506
}
511-
}
507+
};
508+
509+
// SAFETY: FIXME
510+
let _head = unsafe { to_node(state).as_ref() };
512511

513512
// FIXME Is this correct?
514513
// SAFETY: Since we have the write lock, nobody else can be modifying state, and since
515514
// we got `state` from the `compare_exchange`, we know it is a valid head of the queue.
516-
let tail = unsafe { add_backlinks_and_find_tail(to_node(state)) };
515+
let tail = unsafe { add_backlinks_and_find_tail(to_node(state)).as_ref() };
517516

518-
todo!()
517+
while !tail.write {
518+
todo!()
519+
}
519520
}
520521
}
521522

0 commit comments

Comments
 (0)