use super::*;
impl ThreadCore {
pub(crate) fn try_claim_reap(&self) -> bool {
self.reap_gate
.compare_exchange(0, REAP_CLAIMED, Ordering::AcqRel, Ordering::Acquire)
.is_ok()
}
pub(crate) fn external_lease_count(&self) -> usize {
self.reap_signal.external_lease_count()
}
pub(crate) fn reserve_scheduler_inbox_delivery(&self) -> bool {
let Some(_activity) = self.try_scheduler_activity() else {
return false;
};
if self.state() == ThreadState::Exited {
return false;
}
self.scheduler_inbox_deliveries
.try_update(Ordering::AcqRel, Ordering::Acquire, |deliveries| {
deliveries.checked_add(1)
})
.expect("scheduler inbox delivery count overflow");
true
}
pub(crate) fn cancel_scheduler_inbox_delivery(&self) {
self.finish_scheduler_inbox_delivery();
}
pub(crate) fn accept_scheduler_inbox_delivery(&self) -> ThreadSchedulerInboxDelivery<'_> {
assert!(
self.scheduler_inbox_deliveries.load(Ordering::Acquire) != 0,
"owner consumed an unreserved scheduler inbox delivery"
);
ThreadSchedulerInboxDelivery { core: self }
}
pub(crate) fn scheduler_inbox_delivery_count(&self) -> usize {
self.scheduler_inbox_deliveries.load(Ordering::Acquire)
}
pub(crate) fn affinity_completion(&self) -> &crate::sched::affinity::ThreadAffinityCompletion {
&self.affinity_completion
}
pub(crate) fn publish_affinity_completion(&self, generation: u64) -> bool {
self.affinity_completion.publish(generation)
}
pub(crate) fn notify_affinity_waiters(&self) {
self.affinity_completion.notify_waiters();
}
pub(crate) fn try_scheduler_activity(&self) -> Option<ThreadSchedulerActivity<'_>> {
let preempt = crate::runtime::enter_preempt_guard(
crate::runtime::PreemptGuardSource::SchedulerActivity,
);
let mut observed = self.scheduler_activity_gate.load(Ordering::Acquire);
loop {
if observed & SCHEDULER_ACTIVITY_CLOSED != 0 {
release_scheduler_preempt(preempt);
return None;
}
assert!(
observed < SCHEDULER_ACTIVITY_MAX_READERS,
"scheduler activity reader count overflow"
);
match self.scheduler_activity_gate.compare_exchange_weak(
observed,
observed + 1,
Ordering::Acquire,
Ordering::Relaxed,
) {
Ok(_) => {
return Some(ThreadSchedulerActivity {
core: self,
preempt,
_not_send: PhantomData,
});
}
Err(updated) => observed = updated,
}
}
}
pub(crate) fn close_owned_scheduler_activity(
self: &Arc<Self>,
) -> Option<OwnedThreadSchedulerExit> {
let preempt = crate::runtime::enter_preempt_guard(
crate::runtime::PreemptGuardSource::SchedulerActivity,
);
if !self.close_scheduler_activity_gate() {
release_scheduler_preempt(preempt);
return None;
}
Some(OwnedThreadSchedulerExit {
core: Arc::clone(self),
preempt,
sealed: false,
_not_send: PhantomData,
})
}
pub(crate) fn cancel_reap_claim(&self) {
self.reap_gate.store(0, Ordering::Release);
}
pub(super) fn finish_scheduler_activity(&self) {
let previous = self.scheduler_activity_gate.fetch_sub(1, Ordering::Release);
assert!(
previous & SCHEDULER_ACTIVITY_MAX_READERS != 0,
"unbalanced scheduler activity guard"
);
}
fn close_scheduler_activity_gate(&self) -> bool {
let previous = self
.scheduler_activity_gate
.fetch_or(SCHEDULER_ACTIVITY_CLOSED, Ordering::AcqRel);
if previous & SCHEDULER_ACTIVITY_CLOSED != 0 {
return false;
}
while self.scheduler_activity_gate.load(Ordering::Acquire) != SCHEDULER_ACTIVITY_CLOSED {
core::hint::spin_loop();
}
true
}
pub(super) fn reopen_scheduler_activity(&self) {
assert_eq!(
self.scheduler_activity_gate.compare_exchange(
SCHEDULER_ACTIVITY_CLOSED,
0,
Ordering::Release,
Ordering::Acquire,
),
Ok(SCHEDULER_ACTIVITY_CLOSED),
"only a quiescent uncommitted exit may reopen scheduler activity"
);
}
pub(super) fn finish_scheduler_inbox_delivery(&self) {
let previous = self
.scheduler_inbox_deliveries
.fetch_sub(1, Ordering::AcqRel);
assert!(previous != 0, "unbalanced scheduler inbox delivery");
if previous == 1 && self.reap_signal.exited.load(Ordering::Acquire) {
self.reap_signal.publish();
}
}
pub(super) fn try_enter_weak_upgrade(&self) -> bool {
let mut observed = self.reap_gate.load(Ordering::Acquire);
loop {
if observed & REAP_CLAIMED != 0 {
return false;
}
assert!(
observed < REAP_MAX_UPGRADE_READERS,
"thread weak-upgrade reader count overflow"
);
match self.reap_gate.compare_exchange_weak(
observed,
observed + 1,
Ordering::Acquire,
Ordering::Relaxed,
) {
Ok(_) => return true,
Err(updated) => observed = updated,
}
}
}
pub(super) fn exit_weak_upgrade(&self) {
let previous = self.reap_gate.fetch_sub(1, Ordering::Release);
assert!(
previous != 0 && previous & REAP_CLAIMED == 0,
"unbalanced thread weak-upgrade gate"
);
}
}