[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] Xen core parking 2: core parking implementation



# HG changeset patch
# User Liu, Jinsong <jinsong.liu@xxxxxxxxx>
# Date 1332515297 0
# Node ID 5863a55b807ef9111e3159e61e0ca52a55b5c215
# Parent  f6a2fb739ad053202dc037c963e55b9c3895c26a
Xen core parking 2: core parking implementation

This patch implement Xen core parking.
Different core parking sequence has different power/performance
result, due to cpu socket/core/thread topology.
This patch provide power-first and performance-first policies, users
can choose core parking policy by their own demand.

Signed-off-by: Liu, Jinsong <jinsong.liu@xxxxxxxxx>
Committed-by: Keir Fraser <keir@xxxxxxx>
---


diff -r f6a2fb739ad0 -r 5863a55b807e xen/common/core_parking.c
--- a/xen/common/core_parking.c Fri Mar 23 15:07:53 2012 +0000
+++ b/xen/common/core_parking.c Fri Mar 23 15:08:17 2012 +0000
@@ -1,13 +1,240 @@
+/*
+ *  core_parking.c - implement core parking according to dom0 requirement
+ *
+ *  Copyright (C) 2012, Intel Corporation.
+ *     Author: Liu, Jinsong <jinsong.liu@xxxxxxxxx>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or (at
+ *  your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ */
+
 #include <xen/types.h>
+#include <xen/cpu.h>
+#include <xen/init.h>
+#include <xen/cpumask.h>
+#include <asm/percpu.h>
+#include <asm/smp.h>
+
+#define CORE_PARKING_INCREMENT 1
+#define CORE_PARKING_DECREMENT 2
+
+static unsigned int core_parking_power(unsigned int event);
+static unsigned int core_parking_performance(unsigned int event);
 
 static uint32_t cur_idle_nums;
+static unsigned int core_parking_cpunum[NR_CPUS] = {[0 ... NR_CPUS-1] = -1};
+
+static struct core_parking_policy {
+    char name[30];
+    unsigned int (*next)(unsigned int event);
+} *core_parking_policy;
+
+static enum core_parking_controller {
+    POWER_FIRST,
+    PERFORMANCE_FIRST
+} core_parking_controller = POWER_FIRST;
+
+static void __init setup_core_parking_option(char *str)
+{
+    if ( !strcmp(str, "power") )
+        core_parking_controller = POWER_FIRST;
+    else if ( !strcmp(str, "performance") )
+        core_parking_controller = PERFORMANCE_FIRST;
+    else
+        return;
+}
+custom_param("core_parking", setup_core_parking_option);
+
+static unsigned int core_parking_performance(unsigned int event)
+{
+    unsigned int cpu = -1;
+
+    switch ( event )
+    {
+    case CORE_PARKING_INCREMENT:
+    {
+        int core_tmp, core_weight = -1;
+        int sibling_tmp, sibling_weight = -1;
+        cpumask_t core_candidate_map, sibling_candidate_map;
+        cpumask_clear(&core_candidate_map);
+        cpumask_clear(&sibling_candidate_map);
+
+        for_each_cpu(cpu, &cpu_online_map)
+        {
+            if ( cpu == 0 )
+                continue;
+
+            core_tmp = cpumask_weight(per_cpu(cpu_core_mask, cpu));
+            if ( core_weight < core_tmp )
+            {
+                core_weight = core_tmp;
+                cpumask_clear(&core_candidate_map);
+                cpumask_set_cpu(cpu, &core_candidate_map);
+            }
+            else if ( core_weight == core_tmp )
+                cpumask_set_cpu(cpu, &core_candidate_map);
+        }
+
+        for_each_cpu(cpu, &core_candidate_map)
+        {
+            sibling_tmp = cpumask_weight(per_cpu(cpu_sibling_mask, cpu));
+            if ( sibling_weight < sibling_tmp )
+            {
+                sibling_weight = sibling_tmp;
+                cpumask_clear(&sibling_candidate_map);
+                cpumask_set_cpu(cpu, &sibling_candidate_map);
+            }
+            else if ( sibling_weight == sibling_tmp )
+                cpumask_set_cpu(cpu, &sibling_candidate_map);
+        }
+
+        cpu = cpumask_first(&sibling_candidate_map);
+    }
+    break;
+
+    case CORE_PARKING_DECREMENT:
+    {
+        cpu = core_parking_cpunum[cur_idle_nums -1];
+    }
+    break;
+
+    default:
+        break;
+    }
+
+    return cpu;
+}
+
+static unsigned int core_parking_power(unsigned int event)
+{
+    unsigned int cpu = -1;
+
+    switch ( event )
+    {
+    case CORE_PARKING_INCREMENT:
+    {
+        int core_tmp, core_weight = NR_CPUS + 1;
+        int sibling_tmp, sibling_weight = NR_CPUS + 1;
+        cpumask_t core_candidate_map, sibling_candidate_map;
+        cpumask_clear(&core_candidate_map);
+        cpumask_clear(&sibling_candidate_map);
+
+        for_each_cpu(cpu, &cpu_online_map)
+        {
+            if ( cpu == 0 )
+                continue;
+
+            core_tmp = cpumask_weight(per_cpu(cpu_core_mask, cpu));
+            if ( core_weight > core_tmp )
+            {
+                core_weight = core_tmp;
+                cpumask_clear(&core_candidate_map);
+                cpumask_set_cpu(cpu, &core_candidate_map);
+            }
+            else if ( core_weight == core_tmp )
+                cpumask_set_cpu(cpu, &core_candidate_map);
+        }
+
+        for_each_cpu(cpu, &core_candidate_map)
+        {
+            sibling_tmp = cpumask_weight(per_cpu(cpu_sibling_mask, cpu));
+            if ( sibling_weight > sibling_tmp )
+            {
+                sibling_weight = sibling_tmp;
+                cpumask_clear(&sibling_candidate_map);
+                cpumask_set_cpu(cpu, &sibling_candidate_map);
+            }
+            else if ( sibling_weight == sibling_tmp )
+                cpumask_set_cpu(cpu, &sibling_candidate_map);
+        }
+
+        cpu = cpumask_first(&sibling_candidate_map);
+    }
+    break;
+
+    case CORE_PARKING_DECREMENT:
+    {
+        cpu = core_parking_cpunum[cur_idle_nums -1];
+    }
+    break;
+
+    default:
+        break;
+    }
+
+    return cpu;
+}
 
 long core_parking_helper(void *data)
 {
-    return 0;
+    uint32_t idle_nums = (unsigned long)data;
+    unsigned int cpu;
+    int ret = 0;
+
+    if ( !core_parking_policy )
+        return -EINVAL;
+
+    while ( cur_idle_nums < idle_nums )
+    {
+        cpu = core_parking_policy->next(CORE_PARKING_INCREMENT);
+        ret = cpu_down(cpu);
+        if ( ret )
+            return ret;
+        core_parking_cpunum[cur_idle_nums++] = cpu;
+    }
+
+    while ( cur_idle_nums > idle_nums )
+    {
+        cpu = core_parking_policy->next(CORE_PARKING_DECREMENT);
+        ret = cpu_up(cpu);
+        if ( ret )
+            return ret;
+        core_parking_cpunum[--cur_idle_nums] = -1;
+    }
+
+    return ret;
 }
 
 uint32_t get_cur_idle_nums(void)
 {
     return cur_idle_nums;
 }
+
+static struct core_parking_policy power_first = {
+    .name = "power",
+    .next = core_parking_power,
+};
+
+static struct core_parking_policy performance_first = {
+    .name = "performance",
+    .next = core_parking_performance,
+};
+
+static int register_core_parking_policy(struct core_parking_policy *policy)
+{
+    if ( !policy || !policy->next )
+        return -EINVAL;
+
+    core_parking_policy = policy;
+    return 0;
+}
+
+static int __init core_parking_init(void)
+{
+    int ret = 0;
+
+    if ( core_parking_controller == PERFORMANCE_FIRST )
+        ret = register_core_parking_policy(&performance_first);
+    else
+        ret = register_core_parking_policy(&power_first);
+
+    return ret;
+}
+__initcall(core_parking_init);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.