@@ -5,9 +5,7 @@ use kspin::{SpinNoIrq, SpinNoIrqGuard};
55use linked_list:: { def_node, List } ;
66
77use crate :: { current_run_queue, select_run_queue, AxTaskRef } ;
8-
9- #[ cfg( feature = "irq" ) ]
10- use crate :: CurrentTask ;
8+ use crate :: task:: TaskState ;
119
1210def_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
223228fn unblock_one_task ( task : AxTaskRef , resched : bool ) {
0 commit comments