proc: Add an interface to get all the tasks that share a core

Core-scheduling allows tasks to share a core. The per-process interface
is the prctl(2) PR_SET_CORE_SCHED added in earlier patches which allows
a process to set or change the set of processes it is allowed to share a
core with.

This proc file is intended to help with introspection and testing to
determine which other processes does it share a core with.

Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org>
diff --git a/fs/proc/base.c b/fs/proc/base.c
index a8a3879..9a55e90 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -3206,6 +3206,9 @@
 #ifdef CONFIG_PROC_PID_ARCH_STATUS
 	ONE("arch_status", S_IRUGO, proc_pid_arch_status),
 #endif
+#ifdef CONFIG_SCHED_CORE
+	ONE("coresched_tasks", S_IRUGO, sched_core_proc_tasks),
+#endif
 };
 
 static int proc_tgid_base_readdir(struct file *file, struct dir_context *ctx)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 58d01eb..11bc110 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1988,8 +1988,12 @@
 
 #ifdef CONFIG_SCHED_CORE
 int sched_core_join_pid(pid_t pid);
+int sched_core_proc_tasks(struct seq_file *m, struct pid_namespace *ns,
+			  struct pid *pid, struct task_struct *p);
 #else
 static int sched_core_join_pid(pid_t pid) { return -ENOTSUPP; }
+static int sched_core_proc_tasks(struct seq_file *m, struct pid_namespace *ns,
+				 struct pid *pid, struct task_struct *p) { return -ENOTSUPP; }
 #endif
 
 void __exit_umh(struct task_struct *tsk);
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 2f98e46..e0c793e 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -3408,6 +3408,25 @@
 	}
 }
 
+/* Go through all TGIDs and print ones with @p's tag. */
+int sched_core_proc_tasks(struct seq_file *m, struct pid_namespace *ns,
+				struct pid *pid, struct task_struct *tsk)
+{
+	struct task_struct *p;
+
+	rcu_read_lock();
+	mutex_lock(&sched_core_mutex);
+	for_each_process(p) {
+		if (p == tsk)
+			continue;
+		if (tsk->core_cookie == p->core_cookie)
+			seq_printf(m, "%d\n", p->pid);
+	}
+	mutex_unlock(&sched_core_mutex);
+	rcu_read_unlock();
+
+	return 0;
+}
 #endif /* CONFIG_SCHED_CORE */
 
 /*