All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mike Galbraith <efault@gmx.de>
To: Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
	Thomas Gleixner <tglx@linutronix.de>
Cc: LKML <linux-kernel@vger.kernel.org>,
	linux-rt-users <linux-rt-users@vger.kernel.org>,
	Steven Rostedt <rostedt@goodmis.org>
Subject: [rfc patch-rt] posix_cpu_timers: Kill hotplug cpu notifier
Date: Mon, 26 Dec 2016 08:00:54 +0100	[thread overview]
Message-ID: <1482735654.4476.62.camel@gmx.de> (raw)
In-Reply-To: <20161223163213.szj43nv7rnelkbty@linutronix.de>

Shamelessly steal softirq.c thread initialization method.

Signed-off-by: Mike Galbraith <efault@gmx.de>
---
 include/linux/cpuhotplug.h     |    1 
 kernel/time/posix-cpu-timers.c |  158 ++++++++++++++---------------------------
 2 files changed, 56 insertions(+), 103 deletions(-)

--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -20,6 +20,7 @@ enum cpuhp_state {
 	CPUHP_SLUB_DEAD,
 	CPUHP_MM_WRITEBACK_DEAD,
 	CPUHP_SOFTIRQ_DEAD,
+	CPUHP_POSIXCPUTMR_DEAD,
 	CPUHP_NET_MVNETA_DEAD,
 	CPUHP_CPUIDLE_DEAD,
 	CPUHP_ARM64_FPSIMD_DEAD,
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -13,6 +13,8 @@
 #include <linux/random.h>
 #include <linux/tick.h>
 #include <linux/workqueue.h>
+#include <linux/smpboot.h>
+#include <linux/cpuhotplug.h>
 
 /*
  * Called after updating RLIMIT_CPU to run cpu timer and update
@@ -1220,62 +1222,36 @@ static void __run_posix_cpu_timers(struc
 DEFINE_PER_CPU(struct task_struct *, posix_timer_task);
 DEFINE_PER_CPU(struct task_struct *, posix_timer_tasklist);
 
-static int posix_cpu_timers_thread(void *data)
+static void posix_cpu_timers_thread(unsigned int cpu)
 {
-	int cpu = (long)data;
+	struct task_struct *tsk = NULL;
+	struct task_struct *next = NULL;
 
-	BUG_ON(per_cpu(posix_timer_task,cpu) != current);
+	/* grab task list */
+	raw_local_irq_disable();
+	tsk = per_cpu(posix_timer_tasklist, cpu);
+	per_cpu(posix_timer_tasklist, cpu) = NULL;
+	raw_local_irq_enable();
+
+	/* Process task list */
+	while (tsk) {
+		/* save next */
+		next = tsk->posix_timer_list;
 
-	while (!kthread_should_stop()) {
-		struct task_struct *tsk = NULL;
-		struct task_struct *next = NULL;
-
-		if (cpu_is_offline(cpu))
-			goto wait_to_die;
-
-		/* grab task list */
-		raw_local_irq_disable();
-		tsk = per_cpu(posix_timer_tasklist, cpu);
-		per_cpu(posix_timer_tasklist, cpu) = NULL;
-		raw_local_irq_enable();
-
-		/* its possible the list is empty, just return */
-		if (!tsk) {
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule();
-			__set_current_state(TASK_RUNNING);
-			continue;
-		}
-
-		/* Process task list */
-		while (1) {
-			/* save next */
-			next = tsk->posix_timer_list;
+		/* run the task timers, clear its ptr and
+		 * unreference it
+		 */
+		__run_posix_cpu_timers(tsk);
+		tsk->posix_timer_list = NULL;
+		put_task_struct(tsk);
 
-			/* run the task timers, clear its ptr and
-			 * unreference it
-			 */
-			__run_posix_cpu_timers(tsk);
-			tsk->posix_timer_list = NULL;
-			put_task_struct(tsk);
-
-			/* check if this is the last on the list */
-			if (next == tsk)
-				break;
-			tsk = next;
-		}
+		/* check if this is the last on the list */
+		if (next == tsk)
+			break;
+		tsk = next;
 	}
-	return 0;
 
-wait_to_die:
-	/* Wait for kthread_stop */
-	set_current_state(TASK_INTERRUPTIBLE);
-	while (!kthread_should_stop()) {
-		schedule();
-		set_current_state(TASK_INTERRUPTIBLE);
-	}
-	__set_current_state(TASK_RUNNING);
-	return 0;
+	return;
 }
 
 static inline int __fastpath_timer_check(struct task_struct *tsk)
@@ -1322,72 +1298,48 @@ void run_posix_cpu_timers(struct task_st
 	}
 }
 
-/*
- * posix_cpu_thread_call - callback that gets triggered when a CPU is added.
- * Here we can start up the necessary migration thread for the new CPU.
- */
-static int posix_cpu_thread_call(struct notifier_block *nfb,
-				 unsigned long action, void *hcpu)
+static void posix_cpu_thread_setup(unsigned int cpu)
 {
-	int cpu = (long)hcpu;
-	struct task_struct *p;
-	struct sched_param param;
+	struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
 
-	switch (action) {
-	case CPU_UP_PREPARE:
-		p = kthread_create(posix_cpu_timers_thread, hcpu,
-					"posixcputmr/%d",cpu);
-		if (IS_ERR(p))
-			return NOTIFY_BAD;
-		p->flags |= PF_NOFREEZE;
-		kthread_bind(p, cpu);
-		/* Must be high prio to avoid getting starved */
-		param.sched_priority = MAX_RT_PRIO-1;
-		sched_setscheduler(p, SCHED_FIFO, &param);
-		per_cpu(posix_timer_task,cpu) = p;
-		break;
-	case CPU_ONLINE:
-		/* Strictly unneccessary, as first user will wake it. */
-		wake_up_process(per_cpu(posix_timer_task,cpu));
-		break;
-#ifdef CONFIG_HOTPLUG_CPU
-	case CPU_UP_CANCELED:
-		/* Unbind it from offline cpu so it can run.  Fall thru. */
-		kthread_bind(per_cpu(posix_timer_task, cpu),
-			     cpumask_any(cpu_online_mask));
-		kthread_stop(per_cpu(posix_timer_task,cpu));
-		per_cpu(posix_timer_task,cpu) = NULL;
-		break;
-	case CPU_DEAD:
-		kthread_stop(per_cpu(posix_timer_task,cpu));
-		per_cpu(posix_timer_task,cpu) = NULL;
-		break;
-#endif
-	}
-	return NOTIFY_OK;
+	current->flags |= PF_NOFREEZE;
+	sched_setscheduler(current, SCHED_FIFO, &param);
 }
 
-/* Register at highest priority so that task migration (migrate_all_tasks)
- * happens before everything else.
- */
-static struct notifier_block posix_cpu_thread_notifier = {
-	.notifier_call = posix_cpu_thread_call,
-	.priority = 10
+static void posix_cpu_thread_cleanup(unsigned int cpu, bool online)
+{
+	struct sched_param param = { .sched_priority = 0 };
+
+	current->flags &= ~PF_NOFREEZE;
+	sched_setscheduler(current, SCHED_NORMAL, &param);
+}
+
+static int posix_cpu_thread_should_run(unsigned int cpu)
+{
+	return !!per_cpu(posix_timer_tasklist, cpu);
+}
+
+static struct smp_hotplug_thread posix_timer_threads = {
+	.store			= &posix_timer_task,
+	.setup			= posix_cpu_thread_setup,
+	.cleanup		= posix_cpu_thread_cleanup,
+	.thread_should_run	= posix_cpu_thread_should_run,
+	.thread_fn		= posix_cpu_timers_thread,
+	.thread_comm		= "posixcputmr/%u",
 };
 
 static int __init posix_cpu_thread_init(void)
 {
-	void *hcpu = (void *)(long)smp_processor_id();
-	/* Start one for boot CPU. */
+	struct smp_hotplug_thread *t = &posix_timer_threads;
 	unsigned long cpu;
 
-	/* init the per-cpu posix_timer_tasklets */
+	/* init the per-cpu posix_timer_tasklist */
 	for_each_possible_cpu(cpu)
 		per_cpu(posix_timer_tasklist, cpu) = NULL;
 
-	posix_cpu_thread_call(&posix_cpu_thread_notifier, CPU_UP_PREPARE, hcpu);
-	posix_cpu_thread_call(&posix_cpu_thread_notifier, CPU_ONLINE, hcpu);
-	register_cpu_notifier(&posix_cpu_thread_notifier);
+	cpuhp_setup_state_nocalls(CPUHP_POSIXCPUTMR_DEAD, "posixcputmr:dead", NULL, NULL);
+	BUG_ON(smpboot_register_percpu_thread(t));
+
 	return 0;
 }
 early_initcall(posix_cpu_thread_init);

  parent reply	other threads:[~2016-12-26  7:01 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-12-23 16:32 [ANNOUNCE] v4.9-rt1 Sebastian Andrzej Siewior
2016-12-26  6:54 ` [patch-rt] kvm: Convert pvclock_gtod_sync_lock to raw_spinlock_t Mike Galbraith
2017-01-20 16:44   ` Sebastian Andrzej Siewior
2017-01-20 17:32     ` Mike Galbraith
2016-12-26  7:00 ` Mike Galbraith [this message]
2017-01-20 16:46   ` [rfc patch-rt] posix_cpu_timers: Kill hotplug cpu notifier Sebastian Andrzej Siewior
2017-01-20 17:29     ` Mike Galbraith
2017-01-20 17:34       ` Sebastian Andrzej Siewior
2017-01-20 17:56         ` Mike Galbraith
2016-12-31  8:20 ` [patch-rt] softirq: Move ksoftirqd_running() under !CONFIG_PREEMPT_RT_FULL Mike Galbraith
2017-01-20 17:21   ` Sebastian Andrzej Siewior
2017-01-06  8:13 ` [rfc patch-rt] radix-tree: Partially disable memcg accounting in radix_tree_node_alloc() Mike Galbraith
2017-01-06  8:28   ` Mike Galbraith
2017-01-06  8:55   ` Michal Hocko
2017-01-06 10:52     ` Mike Galbraith
2017-01-06 12:20       ` Mike Galbraith
2017-01-06 12:44         ` Mike Galbraith
2017-01-25 15:06   ` Sebastian Andrzej Siewior
2017-01-26  3:42     ` Mike Galbraith
2017-01-08  8:32 ` {patch-rt] cpuset: Convert callback_lock to raw_spinlock_t Mike Galbraith
2017-01-25 15:45   ` Sebastian Andrzej Siewior

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1482735654.4476.62.camel@gmx.de \
    --to=efault@gmx.de \
    --cc=bigeasy@linutronix.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-rt-users@vger.kernel.org \
    --cc=rostedt@goodmis.org \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.