From: Max Krasnyansky <[EMAIL PROTECTED]>

Here we're just exporting CPU isolation bitmap so that it can
be used outside the scheduler code.
Helper functions like cpu_isolated() are provided for easy access.
This is very similar to cpu_online() and friends.

The patch also exports 'isolated' bit via sysfs in very much the
same way 'online' bit is exposed today.

CPUs can be isolated either via command line isolcpu= option or
by doing something like this:
   echo 0 > /sys/devices/system/cpu/cpu1/online
   echo 1 > /sys/devices/system/cpu/cpu1/isolated
   echo 1 > /sys/devices/system/cpu/cpu1/online

Signed-off-by: Max Krasnyansky <[EMAIL PROTECTED]>
---
 drivers/base/cpu.c      |   47 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/cpumask.h |    3 +++
 kernel/sched.c          |   12 ++++++++----
 3 files changed, 58 insertions(+), 4 deletions(-)

diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index c5885f5..f59c719 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -55,10 +55,57 @@ static ssize_t store_online(struct sys_device *dev, const 
char *buf,
 }
 static SYSDEV_ATTR(online, 0644, show_online, store_online);
 
+#ifdef CONFIG_CPUISOL
+/*
+ * This is under config hotplug is because in order to 
+ * dynamically isolate a CPU it needs to be brought down.
+ * In other words the sequence should be
+ *   echo 0 > /sys/device/system/cpuN/online
+ *   echo 1 > /sys/device/system/cpuN/isolated
+ */
+static ssize_t show_isol(struct sys_device *dev, char *buf)
+{
+       struct cpu *cpu = container_of(dev, struct cpu, sysdev);
+
+       return sprintf(buf, "%u\n", !!cpu_isolated(cpu->sysdev.id));
+}
+
+static ssize_t store_isol(struct sys_device *dev, const char *buf,
+                           size_t count)
+{
+       struct cpu *cpu = container_of(dev, struct cpu, sysdev);
+       ssize_t ret = 0;
+
+       if (cpu_online(cpu->sysdev.id))
+               return -EBUSY;
+
+       switch (buf[0]) {
+       case '0':
+               cpu_clear(cpu->sysdev.id, cpu_isolated_map);
+               break;
+       case '1':
+               cpu_set(cpu->sysdev.id, cpu_isolated_map);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       if (ret >= 0)
+               ret = count;
+       return ret;
+}
+static SYSDEV_ATTR(isolated, 0600, show_isol, store_isol);
+#endif /* CONFIG_CPUISOL */
+
 static void __devinit register_cpu_control(struct cpu *cpu)
 {
        sysdev_create_file(&cpu->sysdev, &attr_online);
+
+#ifdef CONFIG_CPUISOL
+       sysdev_create_file(&cpu->sysdev, &attr_isolated);
+#endif
 }
+
 void unregister_cpu(struct cpu *cpu)
 {
        int logical_cpu = cpu->sysdev.id;
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index 85bd790..84d1561 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -380,6 +380,7 @@ static inline void __cpus_remap(cpumask_t *dstp, const 
cpumask_t *srcp,
 extern cpumask_t cpu_possible_map;
 extern cpumask_t cpu_online_map;
 extern cpumask_t cpu_present_map;
+extern cpumask_t cpu_isolated_map;
 
 #if NR_CPUS > 1
 #define num_online_cpus()      cpus_weight(cpu_online_map)
@@ -388,6 +389,7 @@ extern cpumask_t cpu_present_map;
 #define cpu_online(cpu)                cpu_isset((cpu), cpu_online_map)
 #define cpu_possible(cpu)      cpu_isset((cpu), cpu_possible_map)
 #define cpu_present(cpu)       cpu_isset((cpu), cpu_present_map)
+#define cpu_isolated(cpu)      cpu_isset((cpu), cpu_isolated_map)
 #else
 #define num_online_cpus()      1
 #define num_possible_cpus()    1
@@ -395,6 +397,7 @@ extern cpumask_t cpu_present_map;
 #define cpu_online(cpu)                ((cpu) == 0)
 #define cpu_possible(cpu)      ((cpu) == 0)
 #define cpu_present(cpu)       ((cpu) == 0)
+#define cpu_isolated(cpu)      (0)
 #endif
 
 #define cpu_is_offline(cpu)    unlikely(!cpu_online(cpu))
diff --git a/kernel/sched.c b/kernel/sched.c
index 524285e..2fc942e 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -4815,10 +4815,17 @@ asmlinkage long sys_sched_setaffinity(pid_t pid, 
unsigned int len,
  * as new cpu's are detected in the system via any platform specific
  * method, such as ACPI for e.g.
  */
-
 cpumask_t cpu_present_map __read_mostly;
 EXPORT_SYMBOL(cpu_present_map);
 
+/*
+ * Represents isolated cpu's.
+ * These cpu's have isolated scheduling domains. In general any 
+ * kernel activity should be avoided as much as possible on them.
+ */
+cpumask_t cpu_isolated_map __read_mostly = CPU_MASK_NONE;
+EXPORT_SYMBOL(cpu_isolated_map);
+
 #ifndef CONFIG_SMP
 cpumask_t cpu_online_map __read_mostly = CPU_MASK_ALL;
 EXPORT_SYMBOL(cpu_online_map);
@@ -6186,9 +6193,6 @@ cpu_attach_domain(struct sched_domain *sd, struct 
root_domain *rd, int cpu)
        rcu_assign_pointer(rq->sd, sd);
 }
 
-/* cpus with isolated domains */
-static cpumask_t cpu_isolated_map = CPU_MASK_NONE;
-
 /* Setup the mask of cpus configured for isolated domains */
 static int __init isolated_cpu_setup(char *str)
 {
-- 
1.5.3.7

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to