Skip to content

Commit 1f46842

Browse files
committed
Discuss: Blocked resched
Signed-off-by: guoweikang <[email protected]>
1 parent d75aaa3 commit 1f46842

File tree

2 files changed

+41
-64
lines changed

2 files changed

+41
-64
lines changed

modules/axtask/src/run_queue.rs

Lines changed: 14 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use scheduler::BaseScheduler;
1010
use axhal::cpu::this_cpu_id;
1111

1212
use crate::task::{CurrentTask, TaskState};
13-
use crate::wait_queue::{WaitQueueGuard, WaitTaskNode};
1413
use crate::{AxCpuMask, AxTaskRef, Scheduler, TaskInner, WaitQueue};
1514

1615
macro_rules! percpu_static {
@@ -260,18 +259,27 @@ impl<'a, G: BaseGuard> CurrentRunQueueRef<'a, G> {
260259
}
261260
}
262261

262+
/// Reschedule current task.
263+
///
264+
/// Once current is running, need to put RQ again.
265+
pub fn reschedule(&mut self) {
266+
let curr = &self.current_task;
267+
if curr.is_running() {
268+
self.inner
269+
.put_task_with_state(curr.clone(), TaskState::Running, false);
270+
}
271+
272+
self.inner.resched();
273+
}
274+
263275
/// Yield the current task and reschedule.
264276
/// This function will put the current task into this run queue with `Ready` state,
265277
/// and reschedule to the next task on this run queue.
266278
pub fn yield_current(&mut self) {
267279
let curr = &self.current_task;
268280
trace!("task yield: {}", curr.id_name());
269281
assert!(curr.is_running());
270-
271-
self.inner
272-
.put_task_with_state(curr.clone(), TaskState::Running, false);
273-
274-
self.inner.resched();
282+
self.reschedule();
275283
}
276284

277285
/// Migrate the current task to a new run queue matching its CPU affinity and reschedule.
@@ -360,42 +368,6 @@ impl<'a, G: BaseGuard> CurrentRunQueueRef<'a, G> {
360368
unreachable!("task exited!");
361369
}
362370

363-
/// Block the current task, put current task into the wait queue and reschedule.
364-
/// Mark the state of current task as `Blocked`, set the `in_wait_queue` flag as true.
365-
/// Note:
366-
/// 1. The caller must hold the lock of the wait queue.
367-
/// 2. The caller must ensure that the current task is in the running state.
368-
/// 3. The caller must ensure that the current task is not the idle task.
369-
/// 4. The lock of the wait queue will be released explicitly after current task is pushed into it.
370-
pub fn blocked_resched(
371-
&mut self,
372-
mut wq_guard: WaitQueueGuard,
373-
curr_waiter: Arc<WaitTaskNode>,
374-
) {
375-
let curr = &self.current_task;
376-
assert!(curr.is_running());
377-
assert!(!curr.is_idle());
378-
// we must not block current task with preemption disabled.
379-
// Current expected preempt count is 2.
380-
// 1 for `NoPreemptIrqSave`, 1 for wait queue's `SpinNoIrq`.
381-
#[cfg(feature = "preempt")]
382-
assert!(curr.can_preempt(2));
383-
384-
// Mark the task as blocked, this has to be done before adding it to the wait queue
385-
// while holding the lock of the wait queue.
386-
curr.set_state(TaskState::Blocked);
387-
wq_guard.push_back(curr_waiter);
388-
// Drop the lock of wait queue explictly.
389-
drop(wq_guard);
390-
391-
// Current task's state has been changed to `Blocked` and added to the wait queue.
392-
// Note that the state may have been set as `Ready` in `unblock_task()`,
393-
// see `unblock_task()` for details.
394-
395-
debug!("task block: {}", curr.id_name());
396-
self.inner.resched();
397-
}
398-
399371
#[cfg(feature = "irq")]
400372
pub fn sleep_until(&mut self, deadline: axhal::time::TimeValue) {
401373
let curr = &self.current_task;

modules/axtask/src/wait_queue.rs

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ use kspin::{SpinNoIrq, SpinNoIrqGuard};
55
use linked_list::{def_node, List};
66

77
use crate::{current_run_queue, select_run_queue, AxTaskRef};
8-
9-
#[cfg(feature = "irq")]
10-
use crate::CurrentTask;
8+
use crate::task::TaskState;
119

1210
def_node!(WaitTaskNode, AxTaskRef);
1311

@@ -55,6 +53,18 @@ impl WaitQueue {
5553
}
5654
}
5755

56+
fn waiter_blocked(&self, waiter: &Node) {
57+
let curr = waiter.inner();
58+
assert!(curr.is_running());
59+
assert!(!curr.is_idle());
60+
let mut wq_locked = self.list.lock();
61+
debug!("task block: {}", curr.id_name());
62+
// Mark the task as blocked, this has to be done before adding it to the wait queue
63+
// while holding the lock of the wait queue.
64+
curr.set_state(TaskState::Blocked);
65+
wq_locked.push_back(waiter.clone());
66+
}
67+
5868
/// Cancel events by removing the task from the wait list.
5969
/// If `from_timer_list` is true, try to remove the task from the timer list.
6070
fn cancel_events(&self, waiter: &Node, _from_timer_list: bool) {
@@ -82,7 +92,8 @@ impl WaitQueue {
8292
/// notifies it.
8393
pub fn wait(&self) {
8494
declare_current_waiter!(waiter);
85-
current_run_queue::<NoPreemptIrqSave>().blocked_resched(self.list.lock(), waiter.clone());
95+
self.waiter_blocked(&waiter);
96+
current_run_queue::<NoPreemptIrqSave>().reschedule();
8697
self.cancel_events(&waiter, false);
8798
}
8899

@@ -97,13 +108,12 @@ impl WaitQueue {
97108
{
98109
declare_current_waiter!(waiter);
99110
loop {
100-
let mut rq = current_run_queue::<NoPreemptIrqSave>();
101-
let wq = self.list.lock();
102111
if condition() {
103112
break;
104113
}
105-
rq.blocked_resched(wq, waiter.clone());
114+
self.waiter_blocked(&waiter);
106115
// Preemption may occur here.
116+
current_run_queue::<NoPreemptIrqSave>().reschedule();
107117
}
108118

109119
self.cancel_events(&waiter, false);
@@ -114,20 +124,16 @@ impl WaitQueue {
114124
#[cfg(feature = "irq")]
115125
pub fn wait_timeout(&self, dur: core::time::Duration) -> bool {
116126
declare_current_waiter!(waiter);
117-
let mut rq = current_run_queue::<NoPreemptIrqSave>();
118-
let curr = crate::current();
119127
let deadline = axhal::time::wall_time() + dur;
120128
debug!(
121129
"task wait_timeout: {} deadline={:?}",
122-
curr.id_name(),
130+
waiter.inner().id_name(),
123131
deadline
124132
);
125-
crate::timers::set_alarm_wakeup(deadline, curr.clone());
126-
127-
rq.blocked_resched(self.list.lock(), waiter.clone());
128-
133+
self.waiter_blocked(&waiter);
134+
crate::timers::set_alarm_wakeup(deadline, waiter.inner().clone());
135+
current_run_queue::<NoPreemptIrqSave>().reschedule();
129136
let timeout = axhal::time::wall_time() >= deadline;
130-
131137
// Always try to remove the task from the timer list.
132138
self.cancel_events(&waiter, true);
133139
timeout
@@ -144,28 +150,27 @@ impl WaitQueue {
144150
F: Fn() -> bool,
145151
{
146152
declare_current_waiter!(waiter);
147-
let curr = crate::current();
148153
let deadline = axhal::time::wall_time() + dur;
149154
debug!(
150155
"task wait_timeout: {}, deadline={:?}",
151-
curr.id_name(),
156+
waiter.inner().id_name(),
152157
deadline
153158
);
154-
crate::timers::set_alarm_wakeup(deadline, curr.clone());
159+
crate::timers::set_alarm_wakeup(deadline, waiter.inner().clone());
155160

156161
let mut timeout = true;
157162
loop {
158-
let mut rq = current_run_queue::<NoPreemptIrqSave>();
159163
if axhal::time::wall_time() >= deadline {
160164
break;
161165
}
162-
let mut wq = self.list.lock();
163166
if condition() {
164167
timeout = false;
165168
break;
166169
}
167-
rq.blocked_resched(wq, waiter.clone());
170+
171+
self.waiter_blocked(&waiter);
168172
// Preemption may occur here.
173+
current_run_queue::<NoPreemptIrqSave>().reschedule();
169174
}
170175

171176
// Always try to remove the task from the timer list.
@@ -217,7 +222,7 @@ impl WaitQueue {
217222
}
218223
cursor.move_next();
219224
}
220-
}
225+
}
221226
}
222227

223228
fn unblock_one_task(task: AxTaskRef, resched: bool) {

0 commit comments

Comments
 (0)