Skip to content

Commit ccdd29f

Browse files
committed
rcu: Create reasonable API for do_exit() TASKS_RCU processing
Currently, the exit-time support for TASKS_RCU is open-coded in do_exit(). This commit creates exit_tasks_rcu_start() and exit_tasks_rcu_finish() APIs for do_exit() use. This has the benefit of confining the use of the tasks_rcu_exit_srcu variable to one file, allowing it to become static. Signed-off-by: Paul E. McKenney <[email protected]>
1 parent 7e42776 commit ccdd29f

File tree

4 files changed

+26
-11
lines changed

4 files changed

+26
-11
lines changed

include/linux/rcupdate.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,6 @@ static inline void rcu_init_nohz(void) { }
162162
* macro rather than an inline function to avoid #include hell.
163163
*/
164164
#ifdef CONFIG_TASKS_RCU
165-
#define TASKS_RCU(x) x
166-
extern struct srcu_struct tasks_rcu_exit_srcu;
167165
#define rcu_note_voluntary_context_switch_lite(t) \
168166
do { \
169167
if (READ_ONCE((t)->rcu_tasks_holdout)) \
@@ -176,12 +174,15 @@ extern struct srcu_struct tasks_rcu_exit_srcu;
176174
} while (0)
177175
void call_rcu_tasks(struct rcu_head *head, rcu_callback_t func);
178176
void synchronize_rcu_tasks(void);
177+
void exit_tasks_rcu_start(void);
178+
void exit_tasks_rcu_finish(void);
179179
#else /* #ifdef CONFIG_TASKS_RCU */
180-
#define TASKS_RCU(x) do { } while (0)
181180
#define rcu_note_voluntary_context_switch_lite(t) do { } while (0)
182181
#define rcu_note_voluntary_context_switch(t) rcu_all_qs()
183182
#define call_rcu_tasks call_rcu_sched
184183
#define synchronize_rcu_tasks synchronize_sched
184+
static inline void exit_tasks_rcu_start(void) { }
185+
static inline void exit_tasks_rcu_finish(void) { }
185186
#endif /* #else #ifdef CONFIG_TASKS_RCU */
186187

187188
/**

include/linux/sched.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -589,9 +589,10 @@ struct task_struct {
589589

590590
#ifdef CONFIG_TASKS_RCU
591591
unsigned long rcu_tasks_nvcsw;
592-
bool rcu_tasks_holdout;
593-
struct list_head rcu_tasks_holdout_list;
592+
u8 rcu_tasks_holdout;
593+
u8 rcu_tasks_idx;
594594
int rcu_tasks_idle_cpu;
595+
struct list_head rcu_tasks_holdout_list;
595596
#endif /* #ifdef CONFIG_TASKS_RCU */
596597

597598
struct sched_info sched_info;

kernel/exit.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,6 @@ void __noreturn do_exit(long code)
764764
{
765765
struct task_struct *tsk = current;
766766
int group_dead;
767-
TASKS_RCU(int tasks_rcu_i);
768767

769768
profile_task_exit(tsk);
770769
kcov_task_exit(tsk);
@@ -881,9 +880,7 @@ void __noreturn do_exit(long code)
881880
*/
882881
flush_ptrace_hw_breakpoint(tsk);
883882

884-
TASKS_RCU(preempt_disable());
885-
TASKS_RCU(tasks_rcu_i = __srcu_read_lock(&tasks_rcu_exit_srcu));
886-
TASKS_RCU(preempt_enable());
883+
exit_tasks_rcu_start();
887884
exit_notify(tsk, group_dead);
888885
proc_exit_connector(tsk);
889886
mpol_put_task_policy(tsk);
@@ -918,7 +915,7 @@ void __noreturn do_exit(long code)
918915
if (tsk->nr_dirtied)
919916
__this_cpu_add(dirty_throttle_leaks, tsk->nr_dirtied);
920917
exit_rcu();
921-
TASKS_RCU(__srcu_read_unlock(&tasks_rcu_exit_srcu, tasks_rcu_i));
918+
exit_tasks_rcu_finish();
922919

923920
do_task_dead();
924921
}

kernel/rcu/update.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,7 @@ static DECLARE_WAIT_QUEUE_HEAD(rcu_tasks_cbs_wq);
568568
static DEFINE_RAW_SPINLOCK(rcu_tasks_cbs_lock);
569569

570570
/* Track exiting tasks in order to allow them to be waited for. */
571-
DEFINE_SRCU(tasks_rcu_exit_srcu);
571+
DEFINE_STATIC_SRCU(tasks_rcu_exit_srcu);
572572

573573
/* Control stall timeouts. Disable with <= 0, otherwise jiffies till stall. */
574574
#define RCU_TASK_STALL_TIMEOUT (HZ * 60 * 10)
@@ -875,6 +875,22 @@ static void rcu_spawn_tasks_kthread(void)
875875
mutex_unlock(&rcu_tasks_kthread_mutex);
876876
}
877877

878+
/* Do the srcu_read_lock() for the above synchronize_srcu(). */
879+
void exit_tasks_rcu_start(void)
880+
{
881+
preempt_disable();
882+
current->rcu_tasks_idx = __srcu_read_lock(&tasks_rcu_exit_srcu);
883+
preempt_enable();
884+
}
885+
886+
/* Do the srcu_read_unlock() for the above synchronize_srcu(). */
887+
void exit_tasks_rcu_finish(void)
888+
{
889+
preempt_disable();
890+
__srcu_read_unlock(&tasks_rcu_exit_srcu, current->rcu_tasks_idx);
891+
preempt_enable();
892+
}
893+
878894
#endif /* #ifdef CONFIG_TASKS_RCU */
879895

880896
#ifndef CONFIG_TINY_RCU

0 commit comments

Comments
 (0)