|
1250 | 1250 | <a href="#1250" id="1250">1250</a>
|
1251 | 1251 | <a href="#1251" id="1251">1251</a>
|
1252 | 1252 | <a href="#1252" id="1252">1252</a>
|
| 1253 | +<a href="#1253" id="1253">1253</a> |
| 1254 | +<a href="#1254" id="1254">1254</a> |
| 1255 | +<a href="#1255" id="1255">1255</a> |
| 1256 | +<a href="#1256" id="1256">1256</a> |
| 1257 | +<a href="#1257" id="1257">1257</a> |
| 1258 | +<a href="#1258" id="1258">1258</a> |
| 1259 | +<a href="#1259" id="1259">1259</a> |
1253 | 1260 | </pre><pre class="rust"><code><span class="doccomment">//! Key types and functions for multitasking that build on the basic [`Task`].
|
1254 | 1261 | //!
|
1255 | 1262 | //! The main types of interest are:
|
|
1289 | 1296 | };
|
1290 | 1297 | <span class="kw">use </span>core::{
|
1291 | 1298 | any::Any,
|
| 1299 | + cell::RefMut, |
1292 | 1300 | fmt,
|
1293 | 1301 | hash::{Hash, Hasher},
|
1294 | 1302 | ops::Deref,
|
|
2062 | 2070 | /// Hence, the the main [`task_switch()`] routine proceeds with the context switch
|
2063 | 2071 | /// after we return to it from this function.
|
2064 | 2072 | </span><span class="kw">fn </span>task_switch_inner(
|
2065 |
| - curr_task_tls_slot: <span class="kw-2">&mut </span><span class="prelude-ty">Option</span><TaskRef>, |
| 2073 | + <span class="kw-2">mut </span>curr_task_tls_slot: RefMut<<span class="lifetime">'_</span>, <span class="prelude-ty">Option</span><TaskRef>>, |
2066 | 2074 | next: TaskRef,
|
2067 | 2075 | cpu_id: CpuId,
|
2068 | 2076 | preemption_guard: PreemptionGuard,
|
2069 | 2077 | ) -> <span class="prelude-ty">Result</span><TaskSwitchInnerRet, (bool, PreemptionGuard)> {
|
2070 |
| - <span class="kw">let </span><span class="prelude-val">Some</span>(<span class="kw-2">ref </span>curr) = curr_task_tls_slot <span class="kw">else </span>{ |
| 2078 | + <span class="kw">let </span><span class="prelude-val">Some</span>(curr) = curr_task_tls_slot.as_ref() <span class="kw">else </span>{ |
2071 | 2079 | <span class="macro">error!</span>(<span class="string">"BUG: task_switch_inner(): couldn't get current task"</span>);
|
2072 | 2080 | <span class="kw">return </span><span class="prelude-val">Err</span>((<span class="bool-val">false</span>, preemption_guard));
|
2073 | 2081 | };
|
|
2077 | 2085 | <span class="kw">return </span><span class="prelude-val">Err</span>((<span class="bool-val">false</span>, preemption_guard));
|
2078 | 2086 | }
|
2079 | 2087 |
|
2080 |
| - <span class="comment">// trace!("task_switch [0]: (CPU {}) prev {:?}, next {:?}, interrupts?: {}", cpu_id, curr, next, irq_safety::interrupts_enabled()); |
| 2088 | + <span class="comment">// log::trace!("task_switch [0]: (CPU {}) prev {:?}, next {:?}, interrupts?: {}", cpu_id, curr, next, irq_safety::interrupts_enabled()); |
2081 | 2089 |
|
2082 | 2090 | // These conditions are checked elsewhere, but can be re-enabled if we want to be extra strict.
|
2083 | 2091 | // if !next.is_runnable() {
|
|
2160 | 2168 | // We store the removed `TaskRef` in CPU-local storage so that it remains accessible
|
2161 | 2169 | // until *after* the context switch.
|
2162 | 2170 | </span><span class="kw">if </span>curr_task_has_exited {
|
2163 |
| - <span class="comment">// trace!("task_switch(): deiniting current task TLS for: {:?}, next: {}", curr_task_tls_slot.as_deref(), next.deref()); |
| 2171 | + <span class="comment">// log::trace!("[CPU {}] task_switch(): deiniting current task TLS for: {:?}, next: {}", cpu_id, curr_task_tls_slot.as_deref(), next.deref()); |
2164 | 2172 | </span><span class="kw">let </span>prev_taskref = curr_task_tls_slot.take();
|
2165 | 2173 | DROP_AFTER_TASK_SWITCH.with_mut(|d| d.<span class="number">0 </span>= prev_taskref);
|
2166 | 2174 | }
|
2167 | 2175 |
|
| 2176 | + <span class="comment">// Now we are done touching the current task's TLS slot, so proactively drop it now |
| 2177 | + // to ensure that it isn't accidentally dropped later after we've switched the active TLS area. |
| 2178 | + </span>drop(curr_task_tls_slot); |
| 2179 | + |
2168 | 2180 | <span class="comment">// Now, set the next task as the current task running on this CPU.
|
2169 | 2181 | //
|
2170 | 2182 | // Note that we cannot do this until we've done the above part that cleans up
|
|
2381 | 2393 | <span class="prelude-val">Ok</span>(ExitableTaskRef { task: taskref })
|
2382 | 2394 | }
|
2383 | 2395 | <span class="prelude-val">Err</span>(_e) => {
|
2384 |
| - <span class="macro">log::error!</span>(<span class="string">"BUG: init_current_task() failed to mutably borrow CURRENT_TASK"</span>); |
| 2396 | + <span class="macro">log::error!</span>(<span class="string">"[CPU {}] BUG: init_current_task(): failed to mutably borrow CURRENT_TASK. \ |
| 2397 | + Task ID: {}, {:?}"</span>, cpu::current_cpu(), current_task_id, taskref, |
| 2398 | + ); |
2385 | 2399 | <span class="prelude-val">Err</span>(InitCurrentTaskError::AlreadyBorrowed(current_task_id))
|
2386 | 2400 | }
|
2387 | 2401 | }
|
|
2397 | 2411 | /// Returns an `Err` containing the `value` if the current task cannot be obtained.
|
2398 | 2412 | </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>with_current_task_tls_slot_mut<F, R, T>(function: F, value: T) -> <span class="prelude-ty">Result</span><R, T>
|
2399 | 2413 | <span class="kw">where
|
2400 |
| - </span>F: FnOnce(<span class="kw-2">&mut </span><span class="prelude-ty">Option</span><TaskRef>, T) -> R |
| 2414 | + </span>F: FnOnce(core::cell::RefMut<<span class="lifetime">'_</span>, <span class="prelude-ty">Option</span><TaskRef>>, T) -> R |
2401 | 2415 | {
|
2402 |
| - <span class="kw">if let </span><span class="prelude-val">Ok</span>(tls_slot) = CURRENT_TASK.try_borrow_mut().as_deref_mut() { |
| 2416 | + <span class="kw">if let </span><span class="prelude-val">Ok</span>(tls_slot) = CURRENT_TASK.try_borrow_mut() { |
2403 | 2417 | <span class="prelude-val">Ok</span>(function(tls_slot, value))
|
2404 | 2418 | } <span class="kw">else </span>{
|
2405 | 2419 | <span class="prelude-val">Err</span>(value)
|
|
0 commit comments