@@ -37,6 +37,7 @@ use alloc::{
37
37
} ;
38
38
use core:: {
39
39
any:: Any ,
40
+ cell:: RefMut ,
40
41
fmt,
41
42
hash:: { Hash , Hasher } ,
42
43
ops:: Deref ,
@@ -810,12 +811,12 @@ type TaskSwitchInnerRet = (*mut usize, usize, SimdExt, SimdExt);
810
811
/// Hence, the the main [`task_switch()`] routine proceeds with the context switch
811
812
/// after we return to it from this function.
812
813
fn task_switch_inner (
813
- curr_task_tls_slot : & mut Option < TaskRef > ,
814
+ mut curr_task_tls_slot : RefMut < ' _ , Option < TaskRef > > ,
814
815
next : TaskRef ,
815
816
cpu_id : CpuId ,
816
817
preemption_guard : PreemptionGuard ,
817
818
) -> Result < TaskSwitchInnerRet , ( bool , PreemptionGuard ) > {
818
- let Some ( ref curr) = curr_task_tls_slot else {
819
+ let Some ( curr) = curr_task_tls_slot. as_ref ( ) else {
819
820
error ! ( "BUG: task_switch_inner(): couldn't get current task" ) ;
820
821
return Err ( ( false , preemption_guard) ) ;
821
822
} ;
@@ -825,7 +826,7 @@ fn task_switch_inner(
825
826
return Err ( ( false , preemption_guard) ) ;
826
827
}
827
828
828
- // trace!("task_switch [0]: (CPU {}) prev {:?}, next {:?}, interrupts?: {}", cpu_id, curr, next, irq_safety::interrupts_enabled());
829
+ // log:: trace!("task_switch [0]: (CPU {}) prev {:?}, next {:?}, interrupts?: {}", cpu_id, curr, next, irq_safety::interrupts_enabled());
829
830
830
831
// These conditions are checked elsewhere, but can be re-enabled if we want to be extra strict.
831
832
// if !next.is_runnable() {
@@ -908,11 +909,15 @@ fn task_switch_inner(
908
909
// We store the removed `TaskRef` in CPU-local storage so that it remains accessible
909
910
// until *after* the context switch.
910
911
if curr_task_has_exited {
911
- // trace!("task_switch(): deiniting current task TLS for: {:?}, next: {}", curr_task_tls_slot.as_deref(), next.deref());
912
+ // log:: trace!("[CPU {}] task_switch(): deiniting current task TLS for: {:?}, next: {}", cpu_id , curr_task_tls_slot.as_deref(), next.deref());
912
913
let prev_taskref = curr_task_tls_slot. take ( ) ;
913
914
DROP_AFTER_TASK_SWITCH . with_mut ( |d| d. 0 = prev_taskref) ;
914
915
}
915
916
917
+ // Now we are done touching the current task's TLS slot, so proactively drop it now
918
+ // to ensure that it isn't accidentally dropped later after we've switched the active TLS area.
919
+ drop ( curr_task_tls_slot) ;
920
+
916
921
// Now, set the next task as the current task running on this CPU.
917
922
//
918
923
// Note that we cannot do this until we've done the above part that cleans up
@@ -1129,7 +1134,9 @@ mod tls_current_task {
1129
1134
Ok ( ExitableTaskRef { task : taskref } )
1130
1135
}
1131
1136
Err ( _e) => {
1132
- log:: error!( "BUG: init_current_task() failed to mutably borrow CURRENT_TASK" ) ;
1137
+ log:: error!( "[CPU {}] BUG: init_current_task(): failed to mutably borrow CURRENT_TASK. \
1138
+ Task ID: {}, {:?}", cpu:: current_cpu( ) , current_task_id, taskref,
1139
+ ) ;
1133
1140
Err ( InitCurrentTaskError :: AlreadyBorrowed ( current_task_id) )
1134
1141
}
1135
1142
}
@@ -1145,9 +1152,9 @@ mod tls_current_task {
1145
1152
/// Returns an `Err` containing the `value` if the current task cannot be obtained.
1146
1153
pub ( crate ) fn with_current_task_tls_slot_mut < F , R , T > ( function : F , value : T ) -> Result < R , T >
1147
1154
where
1148
- F : FnOnce ( & mut Option < TaskRef > , T ) -> R
1155
+ F : FnOnce ( core :: cell :: RefMut < ' _ , Option < TaskRef > > , T ) -> R
1149
1156
{
1150
- if let Ok ( tls_slot) = CURRENT_TASK . try_borrow_mut ( ) . as_deref_mut ( ) {
1157
+ if let Ok ( tls_slot) = CURRENT_TASK . try_borrow_mut ( ) {
1151
1158
Ok ( function ( tls_slot, value) )
1152
1159
} else {
1153
1160
Err ( value)
0 commit comments