[haiku-commits] BRANCH pdziepak-github.scheduler [e2ff9a2] in src/system/kernel/scheduler: . src/system/kernel

  • From: pdziepak-github.scheduler <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 18 Nov 2013 07:15:38 +0100 (CET)

added 2 changesets to branch 'refs/remotes/pdziepak-github/scheduler'
old head: d897a478d7c01054aad29b23f7f545073c797530
new head: e2ff9a2865beeabed2dbe7cc2b975b377cd12087
overview: https://github.com/pdziepak/Haiku/compare/d897a47...e2ff9a2

----------------------------------------------------------------------------

f14e456: kernel: Use CPU topology to distribute IRQs

e2ff9a2: scheduler: Rebalance IRQs on overloaded cores

                                    [ Pawel Dziepak <pdziepak@xxxxxxxxxxx> ]

----------------------------------------------------------------------------

2 files changed, 71 insertions(+), 3 deletions(-)
src/system/kernel/int.cpp                 | 21 ++++++++++-
src/system/kernel/scheduler/scheduler.cpp | 53 ++++++++++++++++++++++++++-

############################################################################

Commit:      f14e4567e81270bf6ddf1a3abfef662885763e3d
Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Mon Nov 18 04:32:51 2013 UTC

kernel: Use CPU topology to distribute IRQs

----------------------------------------------------------------------------

diff --git a/src/system/kernel/int.cpp b/src/system/kernel/int.cpp
index cfea6fe..baed8fd 100644
--- a/src/system/kernel/int.cpp
+++ b/src/system/kernel/int.cpp
@@ -67,7 +67,8 @@ struct io_vector {
 #endif
 };
 
-static uint32 sLastCPU;
+static int32 sLastCPU;
+
 static struct io_vector sVectors[NUM_IO_VECTORS];
 static bool sAllocatedIOInterruptVectors[NUM_IO_VECTORS];
 static mutex sIOInterruptVectorAllocationLock
@@ -387,6 +388,22 @@ restore_interrupts(cpu_status status)
 }
 
 
+static
+uint32 assign_cpu(void)
+{
+       int32 nextID = atomic_add(&sLastCPU, 1);
+       cpu_topology_node* node = get_cpu_topology();
+
+       while (node->level != CPU_TOPOLOGY_SMT) {
+               int levelSize = node->children_count;
+               node = node->children[nextID % levelSize];
+               nextID /= levelSize;
+       }
+
+       return node->id;
+}
+
+
 /*!    Install a handler to be called when an interrupt is triggered
        for the given interrupt number with \a data as the argument.
 */
@@ -426,7 +443,7 @@ install_io_interrupt_handler(long vector, interrupt_handler 
handler, void *data,
        if (sVectors[vector].type == INTERRUPT_TYPE_IRQ
                && sVectors[vector].handler_list == NULL) {
 
-               int32 cpuID = atomic_add(&sLastCPU, 1) % smp_get_num_cpus();
+               int32 cpuID = assign_cpu();
                arch_int_assign_to_cpu(vector, cpuID);
 
                ASSERT(sVectors[vector].assigned_cpu.cpu == -1);

############################################################################

Commit:      e2ff9a2865beeabed2dbe7cc2b975b377cd12087
Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Mon Nov 18 06:05:35 2013 UTC

scheduler: Rebalance IRQs on overloaded cores

----------------------------------------------------------------------------

diff --git a/src/system/kernel/scheduler/scheduler.cpp 
b/src/system/kernel/scheduler/scheduler.cpp
index 86760d5..e8cbffb 100644
--- a/src/system/kernel/scheduler/scheduler.cpp
+++ b/src/system/kernel/scheduler/scheduler.cpp
@@ -64,7 +64,9 @@ const bigtime_t kCacheExpire = 100000;
 
 const int kTargetLoad = kMaxLoad * 55 / 100;
 const int kHighLoad = kMaxLoad * 70 / 100;
+const int kVeryHighLoad = (kMaxLoad + kHighLoad) / 2;
 const int kLoadDifference = kMaxLoad * 20 / 100;
+const int kLowLoad = kLoadDifference / 2;
 
 static bigtime_t sDisableSmallTaskPacking;
 static int32 sSmallTaskCore;
@@ -76,6 +78,7 @@ static rw_spinlock sSchedulerModeLock = 
B_RW_SPINLOCK_INITIALIZER;
 
 static int32 (*sChooseCore)(Thread* thread);
 static bool (*sShouldRebalance)(Thread* thread);
+static void (*sRebalanceIRQs)(void);
 
 
 // Heaps in sCPUPriorityHeaps are used for load balancing on a core the logical
@@ -893,7 +896,7 @@ should_rebalance_power_saving(Thread* thread)
                if (coreEntry->fLoad > kHighLoad) {
                        if (!is_task_small(thread))
                                return true;
-               } else if (coreEntry->fLoad > (kHighLoad + kMaxLoad) / 2)
+               } else if (coreEntry->fLoad > kVeryHighLoad)
                        disable_small_task_packing();
        }
 
@@ -924,6 +927,48 @@ should_rebalance(Thread* thread)
 }
 
 
+static void
+rebalance_irqs_low_latency(void)
+{
+       cpu_ent* cpu = get_cpu_struct();
+       SpinLocker locker(cpu->irqs_lock);
+
+       irq_assignment* chosen = NULL;
+       irq_assignment* irq = (irq_assignment*)list_get_first_item(&cpu->irqs);
+
+       int32 totalLoad = 0;
+       while (irq != NULL) {
+               if (chosen == NULL || chosen->load < irq->load)
+                       chosen = irq;
+               totalLoad += irq->load;
+               irq = (irq_assignment*)list_get_next_item(&cpu->irqs, irq);
+       }
+
+       locker.Unlock();
+
+       if (chosen == NULL || totalLoad < kLowLoad)
+               return;
+
+       SpinLocker coreLocker(sCoreHeapsLock);
+       CoreEntry* other = sCoreLoadHeap->PeekMinimum();
+       if (other == NULL)
+               other = sCoreHighLoadHeap->PeekMinimum();
+       coreLocker.Unlock();
+
+       ASSERT(other != NULL);
+
+       int32 thisCore = sCPUToCore[smp_get_current_cpu()];
+       if (other->fCoreID == thisCore)
+               return;
+
+       if (other->fLoad + kLoadDifference >= sCoreEntries[thisCore].fLoad)
+               return;
+
+       int32 newCPU = choose_cpu(other->fCoreID);
+       assign_io_interrupt_to_cpu(chosen->irq, newCPU);
+}
+
+
 static inline void
 compute_cpu_load(int32 cpu)
 {
@@ -934,6 +979,9 @@ compute_cpu_load(int32 cpu)
        if (oldLoad < 0)
                return;
 
+       if (sCPUEntries[cpu].fLoad > kVeryHighLoad)
+               sRebalanceIRQs();
+
        if (oldLoad != sCPUEntries[cpu].fLoad) {
                int32 core = sCPUToCore[cpu];
 
@@ -1625,13 +1673,16 @@ scheduler_set_operation_mode(scheduler_mode mode)
                case SCHEDULER_MODE_LOW_LATENCY:
                        sDisableSmallTaskPacking = -1;
                        sSmallTaskCore = -1;
+
                        sChooseCore = choose_core_low_latency;
                        sShouldRebalance = should_rebalance_low_latency;
+                       sRebalanceIRQs = rebalance_irqs_low_latency;
                        break;
 
                case SCHEDULER_MODE_POWER_SAVING:
                        sDisableSmallTaskPacking = 0;
                        sSmallTaskCore = -1;
+
                        sChooseCore = choose_core_power_saving;
                        sShouldRebalance = should_rebalance_power_saving;
                        break;


Other related posts:

  • » [haiku-commits] BRANCH pdziepak-github.scheduler [e2ff9a2] in src/system/kernel/scheduler: . src/system/kernel - pdziepak-github . scheduler