2 * Copyright 2013, Paweł Dziepak, pdziepak@quarnos.org.
3 * Distributed under the terms of the MIT License.
7 #include <util/AutoLock.h>
9 #include "scheduler_common.h"
10 #include "scheduler_cpu.h"
11 #include "scheduler_modes.h"
12 #include "scheduler_profiler.h"
13 #include "scheduler_thread.h"
16 using namespace Scheduler
;
19 const bigtime_t kCacheExpire
= 100000;
29 set_cpu_enabled(int32
/* cpu */, bool /* enabled */)
35 has_cache_expired(const ThreadData
* threadData
)
37 SCHEDULER_ENTER_FUNCTION();
38 if (threadData
->WentSleepActive() == 0)
40 CoreEntry
* core
= threadData
->Core();
41 bigtime_t activeTime
= core
->GetActiveTime();
42 return activeTime
- threadData
->WentSleepActive() > kCacheExpire
;
47 choose_core(const ThreadData
* /* threadData */)
49 SCHEDULER_ENTER_FUNCTION();
52 PackageEntry
* package
= gIdlePackageList
.Last();
53 if (package
== NULL
) {
55 package
= PackageEntry::GetMostIdlePackage();
58 CoreEntry
* core
= NULL
;
60 core
= package
->GetIdleCore();
63 ReadSpinLocker
coreLocker(gCoreHeapsLock
);
64 // no idle cores, use least occupied core
65 core
= gCoreLoadHeap
.PeekMinimum();
67 core
= gCoreHighLoadHeap
.PeekMinimum();
76 rebalance(const ThreadData
* threadData
)
78 SCHEDULER_ENTER_FUNCTION();
80 CoreEntry
* core
= threadData
->Core();
83 // Get the least loaded core.
84 ReadSpinLocker
coreLocker(gCoreHeapsLock
);
85 CoreEntry
* other
= gCoreLoadHeap
.PeekMinimum();
87 other
= gCoreHighLoadHeap
.PeekMinimum();
89 ASSERT(other
!= NULL
);
91 // Check if the least loaded core is significantly less loaded than
93 int32 coreLoad
= core
->GetLoad();
94 int32 otherLoad
= other
->GetLoad();
95 if (other
== core
|| otherLoad
+ kLoadDifference
>= coreLoad
)
98 // Check whether migrating the current thread would result in both core
99 // loads become closer to the average.
100 int32 difference
= coreLoad
- otherLoad
- kLoadDifference
;
101 ASSERT(difference
> 0);
103 int32 threadLoad
= threadData
->GetLoad() / core
->CPUCount();
104 return difference
>= threadLoad
? other
: core
;
109 rebalance_irqs(bool idle
)
111 SCHEDULER_ENTER_FUNCTION();
116 cpu_ent
* cpu
= get_cpu_struct();
117 SpinLocker
locker(cpu
->irqs_lock
);
119 irq_assignment
* chosen
= NULL
;
120 irq_assignment
* irq
= (irq_assignment
*)list_get_first_item(&cpu
->irqs
);
123 while (irq
!= NULL
) {
124 if (chosen
== NULL
|| chosen
->load
< irq
->load
)
126 totalLoad
+= irq
->load
;
127 irq
= (irq_assignment
*)list_get_next_item(&cpu
->irqs
, irq
);
132 if (chosen
== NULL
|| totalLoad
< kLowLoad
)
135 ReadSpinLocker
coreLocker(gCoreHeapsLock
);
136 CoreEntry
* other
= gCoreLoadHeap
.PeekMinimum();
138 other
= gCoreHighLoadHeap
.PeekMinimum();
141 int32 newCPU
= other
->CPUHeap()->PeekRoot()->ID();
143 ASSERT(other
!= NULL
);
145 CoreEntry
* core
= CoreEntry::GetCore(cpu
->cpu_num
);
148 if (other
->GetLoad() + kLoadDifference
>= core
->GetLoad())
151 assign_io_interrupt_to_cpu(chosen
->irq
, newCPU
);
155 scheduler_mode_operations gSchedulerLowLatencyMode
= {