[PATCH 3/7] fork: Explicity test for idle tasks in copy_thread

From: Eric W. Biederman
Date: Fri May 06 2022 - 10:15:55 EST


The architectures ia64 and parisc have special handling for the idle
thread in copy_process. Add a flag named idle to kernel_clone_args
and use it to explicity test if an idle process is being created.

Fullfill the expectations of the rest of the copy_thread
implemetations and pass a function pointer in .stack from fork_idle().
This makes what is happening in copy_thread better defined, and is
useful to make idle threads less special.

Signed-off-by: "Eric W. Biederman" <ebiederm@xxxxxxxxxxxx>
---
arch/ia64/kernel/process.c | 2 +-
arch/parisc/kernel/process.c | 2 +-
include/linux/sched/task.h | 1 +
kernel/fork.c | 9 +++++++++
4 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index 10d41ded05a5..8f010ae818bc 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -342,7 +342,7 @@ copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
ia64_drop_fpu(p); /* don't pick up stale state from a CPU's fph */

if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
- if (unlikely(!user_stack_base)) {
+ if (unlikely(args->idle)) {
/* fork_idle() called us */
return 0;
}
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index 129c17de45ba..30a5874ca845 100644
--- a/arch/parisc/kernel/process.c
+++ b/arch/parisc/kernel/process.c
@@ -224,7 +224,7 @@ copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
/* kernel thread */
memset(cregs, 0, sizeof(struct pt_regs));
- if (!usp) /* idle thread */
+ if (args->idle) /* idle thread */
return 0;
/* Must exit via ret_from_kernel_thread in order
* to call schedule_tail()
diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h
index fcdcba231aac..3d6b99ce5408 100644
--- a/include/linux/sched/task.h
+++ b/include/linux/sched/task.h
@@ -33,6 +33,7 @@ struct kernel_clone_args {
int cgroup;
int io_thread;
int kthread;
+ int idle;
struct cgroup *cgrp;
struct css_set *cset;
};
diff --git a/kernel/fork.c b/kernel/fork.c
index d39a248a8d8d..93d77ee921ff 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -2544,12 +2544,21 @@ static inline void init_idle_pids(struct task_struct *idle)
}
}

+static int idle_dummy(void *dummy)
+{
+ /* This function is never called */
+ return 0;
+}
+
struct task_struct * __init fork_idle(int cpu)
{
struct task_struct *task;
struct kernel_clone_args args = {
.flags = CLONE_VM,
+ .stack = (unsigned long)&idle_dummy,
+ .stack_size = (unsigned long)NULL,
.kthread = 1,
+ .idle = 1,
};

task = copy_process(&init_struct_pid, 0, cpu_to_node(cpu), &args);
--
2.35.3