Skip to contentSkip to conversation

cpusets: Isolate CPUs via sysfs using cpusets

PATCH In review Viresh Kumar 2 participants 13 messages Apr 4, 2014 – Apr 7, 2014

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

v2 cover cpusets: Isolate CPUs via sysfs using cpusets

We need to migrate away all the background kernel activities (Unbound) for systems requiring isolation of cores (HPC, Real time, networking, etc). After creating cpusets, you can write 1 or 0 to cpuset.quiesce file.

In our case, we are working on a networking machine which wants to run time critical data plane threads on some CPUs, i.e. a single thread per CPU. And these CPUs shouldn't be interrupted at all by background kernel activities, like timers/hrtimers/workqueues/etc..

Writing '1': on this file would migrate unbound/unpinned timers and hrtimers away from the CPUs of the cpuset in question. Also it would disallow addition of any new unpinned timers & hrtimers to isolated CPUs.

Writing '0': will disable isolation of CPUs in current cpuset and unpinned timers/hrtimers would be allowed in future on these CPUs.

This patchset allow us to do this. In the first few patches it builds basic infrastructure in timers and hrtimers and then finally use that in cpusets. Also it updates get_nohz_timer_target() to stop adding new timers/hrtimers to these isolated CPUs.

V1: https://lkml.org/lkml/2014/3/20/319

Not many comments received.

Based on some other timers/hrtimers cleanup I did:
http://comments.gmane.org/gmane.linux.kernel/1677797

Available here: git://git.linaro.org/people/viresh.kumar/linux.git isolate-cpusets

V1->V2:
- Add support to migrate hrtimers as well (V1 only had timers)
- cpuset.quiesce now supports writing 0 and reading as well
- update get_nohz_timer_target() to stop adding new timers/hrtimers to these isolated CPUs.
- Minor fixups that I noticed

Known issues:
1. Patch: "timer: track pinned timers with TIMER_PINNED flag", following reporting by kbuild system (Don't know how to fix this):

config: make ARCH=blackfin allyesconfig

Note: the vireshk/timer-cleanup-for-tglx HEAD ea63467ac9150cd86f4d960887116f99a2803b56 builds fine. It only hurts bisectibility.

All error/warnings:

kernel/timer.c: In function 'init_timers':
>> kernel/timer.c:1683:2: error: call to '__compiletime_assert_1683' >> declared with attribute error: BUILD_BUG_ON failed:
>> __alignof__(struct tvec_base) & TIMER_FLAG_MASK

2. Patch: "timer: don't migrate pinned timers", following reporting by kbuild system (Not really a problem created due to this patch, but just highlighted an existing bug. As pinned timers must be removed by owners before CPU goes down):

smpboot: CPU 1 is now offline
------------[ cut here ]------------
WARNING: CPU: 0 PID: 1935 at kernel/timer.c:1621 migrate_timer_list+0xd6/0xf0()
migrate_timer_list: can't migrate pinned timer: ffffffff81f06a60, deactivating it Modules linked in:

Viresh Kumar (8):
timer: track pinned timers with TIMER_PINNED flag
timer: don't migrate pinned timers
timer: create timer_quiesce_cpu() to isolate CPU from timers
hrtimer: update timer->state with 'pinned' information
hrtimer: don't migrate pinned timers
hrtimer: create hrtimer_quiesce_cpu() to isolate CPU from hrtimers
cpuset: Create sysfs file: cpusets.quiesce to isolate CPUs
sched: don't queue timers on quiesced CPUs

 Documentation/cgroups/cpusets.txt | 19 +++++++-
 include/linux/cpuset.h            |  8 ++++
 include/linux/hrtimer.h           |  6 +++
 include/linux/timer.h             | 13 ++++--
 kernel/cpuset.c                   | 76 ++++++++++++++++++++++++++++++++
 kernel/hrtimer.c                  | 69 ++++++++++++++++++++++++-----
 kernel/sched/core.c               |  9 ++--
 kernel/timer.c                    | 91 +++++++++++++++++++++++++++++++--------
 8 files changed, 253 insertions(+), 38 deletions(-)
Signature · 1 line
1.7.12.rc2.18.g61b472e
#1 lore raw

PATCH v2 1/8 timer: track pinned timers with TIMER_PINNED flag

In order to quiesce a CPU on which Isolation might be required, we need to move away all the timers queued on that CPU. There are two types of timers queued on any CPU: ones that are pinned to that CPU and others can run on any CPU but are queued on CPU in question. And we need to migrate only the second type of timers away from the CPU entering quiesce state.

For this we need some basic infrastructure in timer core to identify which timers are pinned and which are not.

Hence, this patch adds another flag bit TIMER_PINNED which will be set only for the timers which are pinned to a CPU.

It also removes 'pinned' parameter of __mod_timer() as it is no more required.

NOTE: One functional change worth mentioning

Existing Behavior: add_timer_on() followed by multiple mod_timer() wouldn't pin the timer on CPU mentioned in add_timer_on()..

New Behavior: add_timer_on() followed by multiple mod_timer() would pin the timer on CPU running mod_timer().

I didn't gave much attention to this as we should call mod_timer_on() for the timers queued with add_timer_on(). Though if required we can simply clear the TIMER_PINNED flag in mod_timer().

---
 include/linux/timer.h | 10 ++++++----
 kernel/timer.c        | 27 ++++++++++++++++++++-------
 2 files changed, 26 insertions(+), 11 deletions(-)
include/linux/timer.h +6 -4
index 8c5a197..2962403 100644
@@ -49,7 +49,7 @@ extern struct tvec_base boot_tvec_bases;
 #endif
 
 /*
- * Note that all tvec_bases are at least 4 byte aligned and lower two bits
+ * Note that all tvec_bases are at least 8 byte aligned and lower three bits
  * of base in timer_list is guaranteed to be zero. Use them for flags.
  *
  * A deferrable timer will work normally when the system is busy, but
@@ -61,14 +61,18 @@ extern struct tvec_base boot_tvec_bases;
  * the completion of the running instance from IRQ handlers, for example,
  * by calling del_timer_sync().
  *
+ * A pinned timer is allowed to run only on the cpu mentioned and shouldn't be
+ * migrated to any other CPU.
+ *
  * Note: The irq disabled callback execution is a special case for
  * workqueue locking issues. It's not meant for executing random crap
  * with interrupts disabled. Abuse is monitored!
  */
 #define TIMER_DEFERRABLE		0x1LU
 #define TIMER_IRQSAFE			0x2LU
+#define TIMER_PINNED			0x4LU
 
-#define TIMER_FLAG_MASK			0x3LU
+#define TIMER_FLAG_MASK			0x7LU
 
 #define __TIMER_INITIALIZER(_function, _expires, _data, _flags) { \
 		.entry = { .prev = TIMER_ENTRY_STATIC },	\
@@ -179,8 +183,6 @@ extern int mod_timer_pinned(struct timer_list *timer, unsigned long expires);
 
 extern void set_timer_slack(struct timer_list *time, int slack_hz);
 
-#define TIMER_NOT_PINNED	0
-#define TIMER_PINNED		1
 /*
  * The jiffies value which is added to now, when there is no timer
  * in the timer wheel:
kernel/timer.c +20 -7
index d13eb56..e8bcaff 100644
@@ -104,6 +104,11 @@ static inline unsigned int tbase_get_irqsafe(struct tvec_base *base)
 	return ((unsigned int)(unsigned long)base & TIMER_IRQSAFE);
 }
 
+static inline unsigned int tbase_get_pinned(struct tvec_base *base)
+{
+	return ((unsigned int)(unsigned long)base & TIMER_PINNED);
+}
+
 static inline struct tvec_base *tbase_get_base(struct tvec_base *base)
 {
 	return ((struct tvec_base *)((unsigned long)base & ~TIMER_FLAG_MASK));
@@ -117,6 +122,13 @@ timer_set_base(struct timer_list *timer, struct tvec_base *new_base)
 	timer->base = (struct tvec_base *)((unsigned long)(new_base) | flags);
 }
 
+static inline void
+timer_set_flags(struct timer_list *timer, unsigned int flags)
+{
+	timer->base = (struct tvec_base *)((unsigned long)(timer->base) |
+					   flags);
+}
+
 static unsigned long round_jiffies_common(unsigned long j, int cpu,
 		bool force_up)
 {
@@ -742,8 +754,7 @@ static struct tvec_base *lock_timer_base(struct timer_list *timer,
 }
 
 static inline int
-__mod_timer(struct timer_list *timer, unsigned long expires,
-						bool pending_only, int pinned)
+__mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only)
 {
 	struct tvec_base *base, *new_base;
 	unsigned long flags;
@@ -760,7 +771,7 @@ __mod_timer(struct timer_list *timer, unsigned long expires,
 
 	debug_activate(timer, expires);
 
-	cpu = get_nohz_timer_target(pinned);
+	cpu = get_nohz_timer_target(tbase_get_pinned(timer->base));
 	new_base = per_cpu(tvec_bases, cpu);
 
 	if (base != new_base) {
@@ -802,7 +813,7 @@ out_unlock:
  */
 int mod_timer_pending(struct timer_list *timer, unsigned long expires)
 {
-	return __mod_timer(timer, expires, true, TIMER_NOT_PINNED);
+	return __mod_timer(timer, expires, true);
 }
 EXPORT_SYMBOL(mod_timer_pending);
 
@@ -877,7 +888,7 @@ int mod_timer(struct timer_list *timer, unsigned long expires)
 	if (timer_pending(timer) && timer->expires == expires)
 		return 1;
 
-	return __mod_timer(timer, expires, false, TIMER_NOT_PINNED);
+	return __mod_timer(timer, expires, false);
 }
 EXPORT_SYMBOL(mod_timer);
 
@@ -905,7 +916,8 @@ int mod_timer_pinned(struct timer_list *timer, unsigned long expires)
 	if (timer->expires == expires && timer_pending(timer))
 		return 1;
 
-	return __mod_timer(timer, expires, false, TIMER_PINNED);
+	timer_set_flags(timer, TIMER_PINNED);
+	return __mod_timer(timer, expires, false);
 }
 EXPORT_SYMBOL(mod_timer_pinned);
 
@@ -944,6 +956,7 @@ void add_timer_on(struct timer_list *timer, int cpu)
 
 	timer_stats_timer_set_start_info(timer);
 	BUG_ON(timer_pending(timer) || !timer->function);
+	timer_set_flags(timer, TIMER_PINNED);
 	spin_lock_irqsave(&base->lock, flags);
 	timer_set_base(timer, base);
 	debug_activate(timer, timer->expires);
@@ -1493,7 +1506,7 @@ signed long __sched schedule_timeout(signed long timeout)
 	expire = timeout + jiffies;
 
 	setup_timer_on_stack(&timer, process_timeout, (unsigned long)current);
-	__mod_timer(&timer, expire, false, TIMER_NOT_PINNED);
+	__mod_timer(&timer, expire, false);
 	schedule();
 	del_singleshot_timer_sync(&timer);
 
Signature · 1 line
1.7.12.rc2.18.g61b472e
#2 lore raw

PATCH v2 2/8 timer: don't migrate pinned timers

In reply to Viresh Kumar

migrate_timer() is called when a CPU goes down and its timers are required to be migrated to some other CPU. Its the responsibility of the users of the timer to remove it before control reaches to migrate_timers().

As these were the pinned timers, the best we can do is: don't migrate these and report to the user as well.

That's all this patch does.

---
 kernel/timer.c | 10 ++++++++++
 1 file changed, 10 insertions(+)
kernel/timer.c +10 -0
index e8bcaff..6c3a371 100644
@@ -1606,11 +1606,21 @@ static int init_timers_cpu(int cpu)
 static void migrate_timer_list(struct tvec_base *new_base, struct list_head *head)
 {
 	struct timer_list *timer;
+	int is_pinned;
 
 	while (!list_empty(head)) {
 		timer = list_first_entry(head, struct timer_list, entry);
 		/* We ignore the accounting on the dying cpu */
 		detach_timer(timer, false);
+
+		is_pinned = tbase_get_pinned(timer->base);
+
+		/* Check if CPU still has pinned timers */
+		if (unlikely(WARN(is_pinned,
+				  "%s: can't migrate pinned timer: %p, deactivating it\n",
+				  __func__, timer)))
+			continue;
+
 		timer_set_base(timer, new_base);
 		internal_add_timer(new_base, timer);
 	}
Signature · 1 line
1.7.12.rc2.18.g61b472e
#3 lore raw

PATCH v2 3/8 timer: create timer_quiesce_cpu() to isolate CPU from timers

In reply to Viresh Kumar

To isolate CPUs (isolate from timers) from sysfs using cpusets, we need some support from the timer core. i.e. A routine timer_quiesce_cpu() which would migrate away all the unpinned timers, but shouldn't touch the pinned ones.

This patch creates this routine.

---
 include/linux/timer.h |  3 +++
 kernel/timer.c        | 54 ++++++++++++++++++++++++++++++++++++++++-----------
 2 files changed, 46 insertions(+), 11 deletions(-)
include/linux/timer.h +3 -0
index 2962403..1588a4f 100644
@@ -196,6 +196,9 @@ extern void set_timer_slack(struct timer_list *time, int slack_hz);
  */
 extern unsigned long get_next_timer_interrupt(unsigned long now);
 
+/* To be used from cpusets, only */
+extern void timer_quiesce_cpu(void *cpup);
+
 /*
  * Timer-statistics info:
  */
kernel/timer.c +43 -11

96 lines not on this page · raw message

Signature · 1 line
1.7.12.rc2.18.g61b472e
#4 lore raw

PATCH v2 4/8 hrtimer: update timer->state with 'pinned' information

In reply to Viresh Kumar

'Pinned' information would be required in migrate_hrtimers() now, as we can migrate non-pinned timers away without a hotplug (i.e. with cpuset.quiesce). And so we may need to identify pinned timers now, as we can't migrate them.

This patch reuses the timer->state variable for setting this flag as there were enough number of free bits available in this variable. And there is no point increasing size of this struct by adding another field.

---
 include/linux/hrtimer.h |  3 +++
 kernel/hrtimer.c        | 12 ++++++++++--
 2 files changed, 13 insertions(+), 2 deletions(-)
include/linux/hrtimer.h +3 -0
index 435ac4c..9fdb67b 100644
@@ -55,6 +55,7 @@ enum hrtimer_restart {
  * 0x01		enqueued into rbtree
  * 0x02		callback function running
  * 0x04		timer is migrated to another cpu
+ * 0x08		timer is pinned to a cpu
  *
  * Special cases:
  * 0x03		callback function running and enqueued
@@ -81,6 +82,8 @@ enum hrtimer_restart {
 #define HRTIMER_STATE_ENQUEUED	0x01
 #define HRTIMER_STATE_CALLBACK	0x02
 #define HRTIMER_STATE_MIGRATE	0x04
+#define HRTIMER_PINNED_SHIFT	3
+#define HRTIMER_STATE_PINNED	(1 << HRTIMER_PINNED_SHIFT)
 
 /**
  * struct hrtimer - the basic hrtimer structure
kernel/hrtimer.c +10 -2
index d62fe32..c5a4bf4 100644
@@ -905,7 +905,11 @@ static void __remove_hrtimer(struct hrtimer *timer, unsigned long newstate,
 			hrtimer_force_reprogram(base->cpu_base, 1);
 	}
 #endif
-	timer->state = newstate;
+	/*
+	 * We need to preserve PINNED state here, otherwise we may end up
+	 * migrating pinned hrtimers as well.
+	 */
+	timer->state = newstate | (timer->state & HRTIMER_STATE_PINNED);
 }
 
 /* remove hrtimer, called with base lock held */
@@ -970,6 +974,10 @@ int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
 
 	timer_stats_hrtimer_set_start_info(timer);
 
+	/* Update pinned state */
+	timer->state &= ~HRTIMER_STATE_PINNED;
+	timer->state |= !!(mode & HRTIMER_MODE_PINNED) << HRTIMER_PINNED_SHIFT;
+
 	enqueue_hrtimer(timer);
 
 	/*
@@ -1227,7 +1235,7 @@ static void __run_hrtimer(struct hrtimer *timer, ktime_t *now)
 	 * hrtimer_start_range_ns() or in hrtimer_interrupt()
 	 */
 	if (restart != HRTIMER_NORESTART) {
-		BUG_ON(timer->state != HRTIMER_STATE_CALLBACK);
+		BUG_ON(!(timer->state & HRTIMER_STATE_CALLBACK));
 		enqueue_hrtimer(timer);
 	}
 
Signature · 1 line
1.7.12.rc2.18.g61b472e
#5 lore raw

PATCH v2 5/8 hrtimer: don't migrate pinned timers

In reply to Viresh Kumar

migrate_hrtimer() is called when a CPU goes down and its timers are required to be migrated to some other CPU. Its the responsibility of the users of the hrtimer to remove it before control reaches to migrate_hrtimer().

As these were the pinned hrtimers, the best we can do is: don't migrate these and report to the user as well.

That's all this patch does.

---
 kernel/hrtimer.c | 10 ++++++++++
 1 file changed, 10 insertions(+)
kernel/hrtimer.c +10 -0
index c5a4bf4..853dd8c 100644
@@ -1640,6 +1640,7 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
 {
 	struct hrtimer *timer;
 	struct timerqueue_node *node;
+	int is_pinned;
 
 	while ((node = timerqueue_getnext(&old_base->active))) {
 		timer = container_of(node, struct hrtimer, node);
@@ -1652,6 +1653,15 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
 		 * under us on another CPU
 		 */
 		__remove_hrtimer(timer, HRTIMER_STATE_MIGRATE, 0);
+
+		is_pinned = timer->state & HRTIMER_STATE_PINNED;
+
+		/* Check if CPU still has pinned timers */
+		if (unlikely(WARN(is_pinned,
+				  "%s: can't migrate pinned timer: %p, deactivating it\n",
+				  __func__, timer)))
+			continue;
+
 		timer->base = new_base;
 		/*
 		 * Enqueue the timers on the new cpu. This does not
Signature · 1 line
1.7.12.rc2.18.g61b472e
#6 lore raw

PATCH v2 6/8 hrtimer: create hrtimer_quiesce_cpu() to isolate CPU from hrtimers

In reply to Viresh Kumar

To isolate CPUs (isolate from hrtimers) from sysfs using cpusets, we need some support from the hrtimer core. i.e. A routine hrtimer_quiesce_cpu() which would migrate away all the unpinned hrtimers, but shouldn't touch the pinned ones.

This patch creates this routine.

---
 include/linux/hrtimer.h |  3 +++
 kernel/hrtimer.c        | 47 +++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 42 insertions(+), 8 deletions(-)
include/linux/hrtimer.h +3 -0
index 9fdb67b..0718753 100644
@@ -350,6 +350,9 @@ DECLARE_PER_CPU(struct tick_device, tick_cpu_device);
 
 /* Exported timer functions: */
 
+/* To be used from cpusets, only */
+extern void hrtimer_quiesce_cpu(void *cpup);
+
 /* Initialize timers: */
 extern void hrtimer_init(struct hrtimer *timer, clockid_t which_clock,
 			 enum hrtimer_mode mode);
kernel/hrtimer.c +39 -8

96 lines not on this page · raw message

Signature · 1 line
1.7.12.rc2.18.g61b472e
#7 lore raw

PATCH v2 7/8 cpuset: Create sysfs file: cpusets.quiesce to isolate CPUs

In reply to Viresh Kumar

For networking applications, platforms need to provide one CPU per each user space data plane thread. These CPUs shouldn't be interrupted by kernel at all unless userspace has requested for some functionality. Currently, there are background kernel activities that are running on almost every CPU, like:
timers/hrtimers/watchdogs/etc, and these are required to be migrated to other CPUs.

To achieve that, this patch adds another option to cpusets, i.e. 'quiesce'. Writing '1' on this file would migrate these unbound/unpinned timers/hrtimers away from the CPUs of the cpuset in question. Also it would disallow addition of any new unpinned timers/hrtimers to isolated CPUs (This would be handled in next patch). Writing '0' will disable isolation of CPUs in current cpuset and unpinned timers/hrtimers would be allowed in future on these CPUs.

Currently, only timers and hrtimers are migrated. This would be followed by other kernel infrastructure later if required.

---
 Documentation/cgroups/cpusets.txt | 19 ++++++++--
 include/linux/cpuset.h            |  8 +++++
 kernel/cpuset.c                   | 76 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 101 insertions(+), 2 deletions(-)
Documentation/cgroups/cpusets.txt +17 -2
index 7740038..8c1078b 100644
@@ -22,7 +22,8 @@ CONTENTS:
   1.6 What is memory spread ?
   1.7 What is sched_load_balance ?
   1.8 What is sched_relax_domain_level ?
-  1.9 How do I use cpusets ?
+  1.9 What is quiesce?
+  1.10 How do I use cpusets ?
 2. Usage Examples and Syntax
   2.1 Basic Usage
   2.2 Adding/removing cpus
@@ -581,7 +582,21 @@ If your situation is:
 then increasing 'sched_relax_domain_level' would benefit you.
 
 
-1.9 How do I use cpusets ?
+1.9 What is quiesce ?
+--------------------------------------
+We need to migrate away all the background kernel activities (Unbound) for
+systems requiring isolation of cores (HPC, Real time, networking, etc). After
+creating cpusets, you can write 1 or 0 to cpuset.quiesce file.
+
+Writing '1': on this file would migrate unbound/unpinned timers and hrtimers
+away from the CPUs of the cpuset in question. Also it would disallow addition of
+any new unpinned timers & hrtimers to isolated CPUs.
+
+Writing '0': will disable isolation of CPUs in current cpuset and unpinned
+timers/hrtimers would be allowed in future on these CPUs.
+
+
+1.10 How do I use cpusets ?
 --------------------------
 
 In order to minimize the impact of cpusets on critical kernel
include/linux/cpuset.h +8 -0
index 3fe661f..1ce0775 100644
@@ -15,6 +15,13 @@
 
 #ifdef CONFIG_CPUSETS
 
+extern cpumask_var_t cpuset_quiesced_cpus_mask;
+
+static inline bool cpu_quiesced(int cpu)
+{
+	return cpumask_test_cpu(cpu, cpuset_quiesced_cpus_mask);
+}
+
 extern int number_of_cpusets;	/* How many cpusets are defined in system? */
 
 extern int cpuset_init(void);
@@ -123,6 +130,7 @@ static inline void set_mems_allowed(nodemask_t nodemask)
 
 #else /* !CONFIG_CPUSETS */
 
+static inline bool cpu_quiesced(int cpu) { return 0; }
 static inline int cpuset_init(void) { return 0; }
 static inline void cpuset_init_smp(void) {}
 
kernel/cpuset.c +76 -0

140 lines not on this page · raw message

Signature · 1 line
1.7.12.rc2.18.g61b472e
#8 lore raw

PATCH v2 8/8 sched: don't queue timers on quiesced CPUs

In reply to Viresh Kumar

CPUSets have cpusets.quiesce sysfs file now, with which some CPUs can opt for isolating themselves from background kernel activities, like: timers & hrtimers.

get_nohz_timer_target() is used for finding suitable CPU for firing a timer. To guarantee that new timers wouldn't be queued on quiesced CPUs, we need to modify this routine.

---
 kernel/sched/core.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)
kernel/sched/core.c +5 -4
index c0339e2..b235af2 100644
@@ -557,17 +557,18 @@ void resched_cpu(int cpu)
  */
 int get_nohz_timer_target(int pinned)
 {
-	int cpu = smp_processor_id();
-	int i;
+	int cpu = smp_processor_id(), i;
 	struct sched_domain *sd;
 
-	if (pinned || !get_sysctl_timer_migration() || !idle_cpu(cpu))
+	if (pinned || !get_sysctl_timer_migration() ||
+	    !(idle_cpu(cpu) || cpu_quiesced(cpu)))
 		return cpu;
 
 	rcu_read_lock();
 	for_each_domain(cpu, sd) {
 		for_each_cpu(i, sched_domain_span(sd)) {
-			if (!idle_cpu(i)) {
+			/* Don't push timers to quiesced CPUs */
+			if (!(cpu_quiesced(i) || idle_cpu(i))) {
 				cpu = i;
 				goto unlock;
 			}
Signature · 1 line
1.7.12.rc2.18.g61b472e
#9 lore raw
In reply to Viresh Kumar
Quoted 3 lines · Viresh Kumar

We need to migrate away all the background kernel activities (Unbound) for systems requiring isolation of cores (HPC, Real time, networking, etc). After creating cpusets, you can write 1 or 0 to cpuset.quiesce file.

I wonder if adding a quiesce switch is really necessary.

Seems to me that if you don't have load balancing turned off, you can't be very concerned about perturbation, so this should be tied into the load balancing on/off switch as an extension to isolating cores from the #1 perturbation source, the scheduler.

I also didn't notice a check for is_cpu_exclusive() at a glance, which would be a bug, but one that would go away if this additional isolation were coupled to the existing isolation switch.

-Mike

#10 lore raw

Hi Mike,

Quoted 6 lines · Mike Galbraith

I wonder if adding a quiesce switch is really necessary.

Seems to me that if you don't have load balancing turned off, you can't be very concerned about perturbation, so this should be tied into the load balancing on/off switch as an extension to isolating cores from the #1 perturbation source, the scheduler.

Its more about not doing any background activities on these CPU which can be avoided. So, even if a add_timer() is issued from these isolated CPUs, it should goto the set chosen for doing background activity, unless add_timer_on() has been issued, in which case user wants that code to execute on the isolated core.

Probably, yes, people would be disabling load_balancing between these cpusets to avoid migration of tasks to isolated core as well.. Atleast we are using it :)

Quoted 3 lines

I also didn't notice a check for is_cpu_exclusive() at a glance, which would be a bug, but one that would go away if this additional isolation were coupled to the existing isolation switch.

Yeah, there is no check for that. But I didn't got your point completely. Why do I need to check for exclusivity on the isolated CPUs? So, that same CPU isn't isolated as well as non-isolated on two separate sets?

Thanks for your feedback.

--
viresh

#11 lore raw
Quoted 16 lines · Viresh Kumar

Hi Mike,

Quoted 6 lines · Mike Galbraith

I wonder if adding a quiesce switch is really necessary.

Seems to me that if you don't have load balancing turned off, you can't be very concerned about perturbation, so this should be tied into the load balancing on/off switch as an extension to isolating cores from the #1 perturbation source, the scheduler.

Its more about not doing any background activities on these CPU which can be avoided. So, even if a add_timer() is issued from these isolated CPUs, it should goto the set chosen for doing background activity, unless add_timer_on() has been issued, in which case user wants that code to execute on the isolated core.

Quoted 3 lines

Probably, yes, people would be disabling load_balancing between these cpusets to avoid migration of tasks to isolated core as well.. Atleast we are using it :)

Yes, that's the whole point I'm trying to make. If you do not have cores isolated, there's no point to quiesce, as timers and whatnot are the least of your worries. Conversely, why would you bother isolating cores if you didn't want a nice quiet environment. Seems to me full isolation ala killing sched domains implies that your goal is bare metal.. or as close as you can get to that anyway.

Quoted 7 lines
Quoted 3 lines

I also didn't notice a check for is_cpu_exclusive() at a glance, which would be a bug, but one that would go away if this additional isolation were coupled to the existing isolation switch.

Yeah, there is no check for that. But I didn't got your point completely. Why do I need to check for exclusivity on the isolated CPUs? So, that same CPU isn't isolated as well as non-isolated on two separate sets?

Yes, both on and off is kinda hard to do per cpu :)

-Mike

#12 lore raw
Quoted 1 line · Mike Galbraith

Yes, both on and off is kinda hard to do per cpu :)

Correct.. would get it fixed in V3..