@@ -723,10 +723,17 @@ DEFINE_RCU_TASKS(rcu_tasks_trace, rcu_tasks_wait_gp, call_rcu_tasks_trace,
723
723
"RCU Tasks Trace" );
724
724
725
725
/* If we are the last reader, wake up the grace-period kthread. */
726
- void rcu_read_unlock_trace_special (struct task_struct * t )
726
+ void rcu_read_unlock_trace_special (struct task_struct * t , int nesting )
727
727
{
728
- WRITE_ONCE (t -> trc_reader_need_end , false);
729
- if (atomic_dec_and_test (& trc_n_readers_need_end ))
728
+ int nq = t -> trc_reader_special .b .need_qs ;
729
+
730
+ if (t -> trc_reader_special .b .need_mb )
731
+ smp_mb (); // Pairs with update-side barriers.
732
+ // Update .need_qs before ->trc_reader_nesting for irq/NMI handlers.
733
+ if (nq )
734
+ WRITE_ONCE (t -> trc_reader_special .b .need_qs , false);
735
+ WRITE_ONCE (t -> trc_reader_nesting , nesting );
736
+ if (nq && atomic_dec_and_test (& trc_n_readers_need_end ))
730
737
wake_up (& trc_wait );
731
738
}
732
739
EXPORT_SYMBOL_GPL (rcu_read_unlock_trace_special );
@@ -777,8 +784,8 @@ static void trc_read_check_handler(void *t_in)
777
784
// Get here if the task is in a read-side critical section. Set
778
785
// its state so that it will awaken the grace-period kthread upon
779
786
// exit from that critical section.
780
- WARN_ON_ONCE (t -> trc_reader_need_end );
781
- WRITE_ONCE (t -> trc_reader_need_end , true);
787
+ WARN_ON_ONCE (t -> trc_reader_special . b . need_qs );
788
+ WRITE_ONCE (t -> trc_reader_special . b . need_qs , true);
782
789
783
790
reset_ipi :
784
791
// Allow future IPIs to be sent on CPU and for task.
@@ -804,8 +811,8 @@ static bool trc_inspect_reader(struct task_struct *t, void *arg)
804
811
// exit from that critical section.
805
812
if (unlikely (t -> trc_reader_nesting )) {
806
813
atomic_inc (& trc_n_readers_need_end ); // One more to wait on.
807
- WARN_ON_ONCE (t -> trc_reader_need_end );
808
- WRITE_ONCE (t -> trc_reader_need_end , true);
814
+ WARN_ON_ONCE (t -> trc_reader_special . b . need_qs );
815
+ WRITE_ONCE (t -> trc_reader_special . b . need_qs , true);
809
816
}
810
817
return true;
811
818
}
@@ -884,7 +891,7 @@ static void rcu_tasks_trace_pregp_step(void)
884
891
static void rcu_tasks_trace_pertask (struct task_struct * t ,
885
892
struct list_head * hop )
886
893
{
887
- WRITE_ONCE (t -> trc_reader_need_end , false);
894
+ WRITE_ONCE (t -> trc_reader_special . b . need_qs , false);
888
895
WRITE_ONCE (t -> trc_reader_checked , false);
889
896
t -> trc_ipi_to_cpu = -1 ;
890
897
trc_wait_for_one_reader (t , hop );
@@ -916,7 +923,7 @@ static void show_stalled_task_trace(struct task_struct *t, bool *firstreport)
916
923
".i" [is_idle_task (t )],
917
924
".N" [cpu > 0 && tick_nohz_full_cpu (cpu )],
918
925
t -> trc_reader_nesting ,
919
- " N" [!!t -> trc_reader_need_end ],
926
+ " N" [!!t -> trc_reader_special . b . need_qs ],
920
927
cpu );
921
928
sched_show_task (t );
922
929
}
@@ -980,11 +987,11 @@ static void rcu_tasks_trace_postgp(struct rcu_tasks *rtp)
980
987
break ; // Count reached zero.
981
988
// Stall warning time, so make a list of the offenders.
982
989
for_each_process_thread (g , t )
983
- if (READ_ONCE (t -> trc_reader_need_end ))
990
+ if (READ_ONCE (t -> trc_reader_special . b . need_qs ))
984
991
trc_add_holdout (t , & holdouts );
985
992
firstreport = true;
986
993
list_for_each_entry_safe (t , g , & holdouts , trc_holdout_list )
987
- if (READ_ONCE (t -> trc_reader_need_end )) {
994
+ if (READ_ONCE (t -> trc_reader_special . b . need_qs )) {
988
995
show_stalled_task_trace (t , & firstreport );
989
996
trc_del_holdout (t );
990
997
}
@@ -1003,8 +1010,8 @@ void exit_tasks_rcu_finish_trace(struct task_struct *t)
1003
1010
WRITE_ONCE (t -> trc_reader_checked , true);
1004
1011
WARN_ON_ONCE (t -> trc_reader_nesting );
1005
1012
WRITE_ONCE (t -> trc_reader_nesting , 0 );
1006
- if (WARN_ON_ONCE (READ_ONCE (t -> trc_reader_need_end )))
1007
- rcu_read_unlock_trace_special (t );
1013
+ if (WARN_ON_ONCE (READ_ONCE (t -> trc_reader_special . b . need_qs )))
1014
+ rcu_read_unlock_trace_special (t , 0 );
1008
1015
}
1009
1016
1010
1017
/**
0 commit comments