1d287274dSPawel Dziepak/*
2d287274dSPawel Dziepak * Copyright 2013, Pawe�� Dziepak, pdziepak@quarnos.org.
3d287274dSPawel Dziepak * Distributed under the terms of the MIT License.
4d287274dSPawel Dziepak */
5d287274dSPawel Dziepak
6d287274dSPawel Dziepak
7d287274dSPawel Dziepak#include "scheduler_cpu.h"
8d287274dSPawel Dziepak
9d287274dSPawel Dziepak#include <util/AutoLock.h>
10d287274dSPawel Dziepak
11d287274dSPawel Dziepak#include <algorithm>
12d287274dSPawel Dziepak
13d287274dSPawel Dziepak#include "scheduler_thread.h"
14d287274dSPawel Dziepak
15d287274dSPawel Dziepak
16d36098e0SPawel Dziepaknamespace Scheduler {
17d36098e0SPawel Dziepak
18d36098e0SPawel Dziepak
19d36098e0SPawel DziepakCPUEntry* gCPUEntries;
20d36098e0SPawel Dziepak
21d36098e0SPawel DziepakCoreEntry* gCoreEntries;
22d36098e0SPawel DziepakCoreLoadHeap gCoreLoadHeap;
23d36098e0SPawel DziepakCoreLoadHeap gCoreHighLoadHeap;
24d36098e0SPawel Dziepakrw_spinlock gCoreHeapsLock = B_RW_SPINLOCK_INITIALIZER;
25d36098e0SPawel Dziepakint32 gCoreCount;
26d36098e0SPawel Dziepak
27d36098e0SPawel DziepakPackageEntry* gPackageEntries;
28d36098e0SPawel DziepakIdlePackageList gIdlePackageList;
29d36098e0SPawel Dziepakrw_spinlock gIdlePackageLock = B_RW_SPINLOCK_INITIALIZER;
30d36098e0SPawel Dziepakint32 gPackageCount;
31d36098e0SPawel Dziepak
32d36098e0SPawel Dziepak
33d36098e0SPawel Dziepak}	// namespace Scheduler
34d36098e0SPawel Dziepak
35d287274dSPawel Dziepakusing namespace Scheduler;
36d287274dSPawel Dziepak
37d287274dSPawel Dziepak
3860e198f2SPawel Dziepakclass Scheduler::DebugDumper {
3960e198f2SPawel Dziepakpublic:
40a08b40d4SPawel Dziepak	static	void		DumpCPURunQueue(CPUEntry* cpu);
41e1e7235cSPawel Dziepak	static	void		DumpCoreRunQueue(CoreEntry* core);
426155ab7bSPawel Dziepak	static	void		DumpCoreLoadHeapEntry(CoreEntry* core);
4360e198f2SPawel Dziepak	static	void		DumpIdleCoresInPackage(PackageEntry* package);
446155ab7bSPawel Dziepak
456155ab7bSPawel Dziepakprivate:
466155ab7bSPawel Dziepak	struct CoreThreadsData {
476155ab7bSPawel Dziepak			CoreEntry*	fCore;
486155ab7bSPawel Dziepak			int32		fLoad;
496155ab7bSPawel Dziepak	};
506155ab7bSPawel Dziepak
516155ab7bSPawel Dziepak	static	void		_AnalyzeCoreThreads(Thread* thread, void* data);
5260e198f2SPawel Dziepak};
5360e198f2SPawel Dziepak
5460e198f2SPawel Dziepak
55d287274dSPawel Dziepakstatic CPUPriorityHeap sDebugCPUHeap;
56d287274dSPawel Dziepakstatic CoreLoadHeap sDebugCoreHeap;
57d287274dSPawel Dziepak
58d287274dSPawel Dziepak
59d287274dSPawel Dziepakvoid
60d287274dSPawel DziepakThreadRunQueue::Dump() const
61d287274dSPawel Dziepak{
62d287274dSPawel Dziepak	ThreadRunQueue::ConstIterator iterator = GetConstIterator();
63d287274dSPawel Dziepak	if (!iterator.HasNext())
64d287274dSPawel Dziepak		kprintf("Run queue is empty.\n");
65d287274dSPawel Dziepak	else {
66d287274dSPawel Dziepak		kprintf("thread      id      priority penalty  name\n");
67d287274dSPawel Dziepak		while (iterator.HasNext()) {
68d287274dSPawel Dziepak			ThreadData* threadData = iterator.Next();
69d287274dSPawel Dziepak			Thread* thread = threadData->GetThread();
70d287274dSPawel Dziepak
71d287274dSPawel Dziepak			kprintf("%p  %-7" B_PRId32 " %-8" B_PRId32 " %-8" B_PRId32 " %s\n",
72d287274dSPawel Dziepak				thread, thread->id, thread->priority,
739c465cc8SPawel Dziepak				thread->priority - threadData->GetEffectivePriority(),
749c465cc8SPawel Dziepak				thread->name);
75d287274dSPawel Dziepak		}
76d287274dSPawel Dziepak	}
77d287274dSPawel Dziepak}
78d287274dSPawel Dziepak
79d287274dSPawel Dziepak
80d287274dSPawel DziepakCPUEntry::CPUEntry()
81d287274dSPawel Dziepak	:
82d287274dSPawel Dziepak	fLoad(0),
83d287274dSPawel Dziepak	fMeasureActiveTime(0),
84230d1fcfSPawel Dziepak	fMeasureTime(0),
85230d1fcfSPawel Dziepak	fUpdateLoadEvent(false)
86d287274dSPawel Dziepak{
87d287274dSPawel Dziepak	B_INITIALIZE_RW_SPINLOCK(&fSchedulerModeLock);
8826592750SPawel Dziepak	B_INITIALIZE_SPINLOCK(&fQueueLock);
89d287274dSPawel Dziepak}
90d287274dSPawel Dziepak
91d287274dSPawel Dziepak
92a08b40d4SPawel Dziepakvoid
93a08b40d4SPawel DziepakCPUEntry::Init(int32 id, CoreEntry* core)
94a08b40d4SPawel Dziepak{
95a08b40d4SPawel Dziepak	fCPUNumber = id;
96a08b40d4SPawel Dziepak	fCore = core;
97a08b40d4SPawel Dziepak}
98a08b40d4SPawel Dziepak
99a08b40d4SPawel Dziepak
100a08b40d4SPawel Dziepakvoid
101a08b40d4SPawel DziepakCPUEntry::Start()
102a08b40d4SPawel Dziepak{
103a08b40d4SPawel Dziepak	fLoad = 0;
104a08b40d4SPawel Dziepak	fCore->AddCPU(this);
105a08b40d4SPawel Dziepak}
106a08b40d4SPawel Dziepak
107a08b40d4SPawel Dziepak
108a08b40d4SPawel Dziepakvoid
109a08b40d4SPawel DziepakCPUEntry::Stop()
110a08b40d4SPawel Dziepak{
111a08b40d4SPawel Dziepak	cpu_ent* entry = &gCPU[fCPUNumber];
112a08b40d4SPawel Dziepak
113a08b40d4SPawel Dziepak	// get rid of irqs
114a08b40d4SPawel Dziepak	SpinLocker locker(entry->irqs_lock);
115a08b40d4SPawel Dziepak	irq_assignment* irq
116a08b40d4SPawel Dziepak		= (irq_assignment*)list_get_first_item(&entry->irqs);
117a08b40d4SPawel Dziepak	while (irq != NULL) {
118a08b40d4SPawel Dziepak		locker.Unlock();
119a08b40d4SPawel Dziepak
120a08b40d4SPawel Dziepak		assign_io_interrupt_to_cpu(irq->irq, -1);
121a08b40d4SPawel Dziepak
122a08b40d4SPawel Dziepak		locker.Lock();
123a08b40d4SPawel Dziepak		irq = (irq_assignment*)list_get_first_item(&entry->irqs);
124a08b40d4SPawel Dziepak	}
125a08b40d4SPawel Dziepak	locker.Unlock();
126a08b40d4SPawel Dziepak}
127a08b40d4SPawel Dziepak
128a08b40d4SPawel Dziepak
129a08b40d4SPawel Dziepakvoid
130a08b40d4SPawel DziepakCPUEntry::PushFront(ThreadData* thread, int32 priority)
131a08b40d4SPawel Dziepak{
13296dcc73bSPawel Dziepak	SCHEDULER_ENTER_FUNCTION();
133a08b40d4SPawel Dziepak	fRunQueue.PushFront(thread, priority);
134a08b40d4SPawel Dziepak}
135a08b40d4SPawel Dziepak
136a08b40d4SPawel Dziepak
137a08b40d4SPawel Dziepakvoid
138a08b40d4SPawel DziepakCPUEntry::PushBack(ThreadData* thread, int32 priority)
139a08b40d4SPawel Dziepak{
14096dcc73bSPawel Dziepak	SCHEDULER_ENTER_FUNCTION();
141a08b40d4SPawel Dziepak	fRunQueue.PushBack(thread, priority);
142a08b40d4SPawel Dziepak}
143a08b40d4SPawel Dziepak
144a08b40d4SPawel Dziepak
145a08b40d4SPawel Dziepakvoid
146a08b40d4SPawel DziepakCPUEntry::Remove(ThreadData* thread)
147a08b40d4SPawel Dziepak{
14896dcc73bSPawel Dziepak	SCHEDULER_ENTER_FUNCTION();
149b24ea642SPawel Dziepak	ASSERT(thread->IsEnqueued());
150b24ea642SPawel Dziepak	thread->SetDequeued();
151a08b40d4SPawel Dziepak	fRunQueue.Remove(thread);
152a08b40d4SPawel Dziepak}
153a08b40d4SPawel Dziepak
154a08b40d4SPawel Dziepak
1558235bbc9SPawel Dziepakinline ThreadData*
1568235bbc9SPawel DziepakCoreEntry::PeekThread() const
1578235bbc9SPawel Dziepak{
1588235bbc9SPawel Dziepak	SCHEDULER_ENTER_FUNCTION();
1598235bbc9SPawel Dziepak	return fRunQueue.PeekMaximum();
1608235bbc9SPawel Dziepak}
1618235bbc9SPawel Dziepak
1628235bbc9SPawel Dziepak
163a08b40d4SPawel Dziepakinline ThreadData*
164a08b40d4SPawel DziepakCPUEntry::PeekThread() const
165a08b40d4SPawel Dziepak{
16696dcc73bSPawel Dziepak	SCHEDULER_ENTER_FUNCTION();
167a08b40d4SPawel Dziepak	return fRunQueue.PeekMaximum();
168a08b40d4SPawel Dziepak}
169a08b40d4SPawel Dziepak
170a08b40d4SPawel Dziepak
171a08b40d4SPawel DziepakThreadData*
172a08b40d4SPawel DziepakCPUEntry::PeekIdleThread() const
173a08b40d4SPawel Dziepak{
17496dcc73bSPawel Dziepak	SCHEDULER_ENTER_FUNCTION();
175a08b40d4SPawel Dziepak	return fRunQueue.GetHead(B_IDLE_PRIORITY);
176a08b40d4SPawel Dziepak}
177a08b40d4SPawel Dziepak
178a08b40d4SPawel Dziepak
179d287274dSPawel Dziepakvoid
180d287274dSPawel DziepakCPUEntry::UpdatePriority(int32 priority)
181d287274dSPawel Dziepak{
18296dcc73bSPawel Dziepak	SCHEDULER_ENTER_FUNCTION();
18396dcc73bSPawel Dziepak
184a5f45afaSPawel Dziepak	ASSERT(!gCPU[fCPUNumber].disabled);
1859116eec2SPawel Dziepak
186ef8e55a1SPawel Dziepak	int32 oldPriority = CPUPriorityHeap::GetKey(this);
187ef8e55a1SPawel Dziepak	if (oldPriority == priority)
188d287274dSPawel Dziepak		return;
189ef8e55a1SPawel Dziepak	fCore->CPUHeap()->ModifyKey(this, priority);
190d287274dSPawel Dziepak
191ef8e55a1SPawel Dziepak	if (oldPriority == B_IDLE_PRIORITY)
192ef8e55a1SPawel Dziepak		fCore->CPUWakesUp(this);
193ef8e55a1SPawel Dziepak	else if (priority == B_IDLE_PRIORITY)
194ef8e55a1SPawel Dziepak		fCore->CPUGoesIdle(this);
195d287274dSPawel Dziepak}
196d287274dSPawel Dziepak
197d287274dSPawel Dziepak
198d287274dSPawel Dziepakvoid
199d287274dSPawel DziepakCPUEntry::ComputeLoad()
200d287274dSPawel Dziepak{
20196dcc73bSPawel Dziepak	SCHEDULER_ENTER_FUNCTION();
20296dcc73bSPawel Dziepak
203a2634874SPawel Dziepak	ASSERT(gTrackCPULoad);
204a5f45afaSPawel Dziepak	ASSERT(!gCPU[fCPUNumber].disabled);
205d287274dSPawel Dziepak	ASSERT(fCPUNumber == smp_get_current_cpu());
206d287274dSPawel Dziepak
207a2634874SPawel Dziepak	int oldLoad = compute_load(fMeasureTime, fMeasureActiveTime, fLoad,
208a2634874SPawel Dziepak			system_time());
209d287274dSPawel Dziepak	if (oldLoad < 0)
210d287274dSPawel Dziepak		return;
211d287274dSPawel Dziepak
212d287274dSPawel Dziepak	if (fLoad > kVeryHighLoad)
213d287274dSPawel Dziepak		gCurrentMode->rebalance_irqs(false);
214d287274dSPawel Dziepak}
215d287274dSPawel Dziepak
216d287274dSPawel Dziepak
217d287274dSPawel DziepakThreadData*
218d287274dSPawel DziepakCPUEntry::ChooseNextThread(ThreadData* oldThread, bool putAtBack)
219d287274dSPawel Dziepak{
22096dcc73bSPawel Dziepak	SCHEDULER_ENTER_FUNCTION();
22196dcc73bSPawel Dziepak
22226592750SPawel Dziepak	int32 oldPriority = -1;
22326592750SPawel Dziepak	if (oldThread != NULL)
22426592750SPawel Dziepak		oldPriority = oldThread->GetEffectivePriority();
225d287274dSPawel Dziepak
22626592750SPawel Dziepak	CPURunQueueLocker cpuLocker(this);
227d287274dSPawel Dziepak
22826592750SPawel Dziepak	ThreadData* pinnedThread = fRunQueue.PeekMaximum();
229d287274dSPawel Dziepak	int32 pinnedPriority = -1;
230d287274dSPawel Dziepak	if (pinnedThread != NULL)
231d287274dSPawel Dziepak		pinnedPriority = pinnedThread->GetEffectivePriority();
232d287274dSPawel Dziepak
23326592750SPawel Dziepak	CoreRunQueueLocker coreLocker(fCore);
23426592750SPawel Dziepak
23526592750SPawel Dziepak	ThreadData* sharedThread = fCore->PeekThread();
23626592750SPawel Dziepak	ASSERT(sharedThread != NULL || pinnedThread != NULL || oldThread != NULL);
23726592750SPawel Dziepak
238d287274dSPawel Dziepak	int32 sharedPriority = -1;
239d287274dSPawel Dziepak	if (sharedThread != NULL)
240d287274dSPawel Dziepak		sharedPriority = sharedThread->GetEffectivePriority();
241d287274dSPawel Dziepak
242d287274dSPawel Dziepak	int32 rest = std::max(pinnedPriority, sharedPriority);
243d287274dSPawel Dziepak	if (oldPriority > rest || (!putAtBack && oldPriority == rest))
244d287274dSPawel Dziepak		return oldThread;
245d287274dSPawel Dziepak
246d287274dSPawel Dziepak	if (sharedPriority > pinnedPriority) {
247b24ea642SPawel Dziepak		fCore->Remove(sharedThread);
248d287274dSPawel Dziepak		return sharedThread;
249d287274dSPawel Dziepak	}
250d287274dSPawel Dziepak
25126592750SPawel Dziepak	coreLocker.Unlock();
25226592750SPawel Dziepak
253b24ea642SPawel Dziepak	Remove(pinnedThread);
254d287274dSPawel Dziepak	return pinnedThread;
255d287274dSPawel Dziepak}
256d287274dSPawel Dziepak
257d287274dSPawel Dziepak
258d287274dSPawel Dziepakvoid
259d287274dSPawel DziepakCPUEntry::TrackActivity(ThreadData* oldThreadData, ThreadData* nextThreadData)
260d287274dSPawel Dziepak{
26196dcc73bSPawel Dziepak	SCHEDULER_ENTER_FUNCTION();
26296dcc73bSPawel Dziepak
263d287274dSPawel Dziepak	cpu_ent* cpuEntry = &gCPU[fCPUNumber];
264d287274dSPawel Dziepak
265d287274dSPawel Dziepak	Thread* oldThread = oldThreadData->GetThread();
266d287274dSPawel Dziepak	if (!thread_is_idle_thread(oldThread)) {
267d287274dSPawel Dziepak		bigtime_t active
268d287274dSPawel Dziepak			= (oldThread->kernel_time - cpuEntry->last_kernel_time)
269d287274dSPawel Dziepak				+ (oldThread->user_time - cpuEntry->last_user_time);
270d287274dSPawel Dziepak
271b258298cSPawel Dziepak		WriteSequentialLocker locker(cpuEntry->active_time_lock);
272b258298cSPawel Dziepak		cpuEntry->active_time += active;
273b258298cSPawel Dziepak		locker.Unlock();
274b258298cSPawel Dziepak
275335c6055SPawel Dziepak		fMeasureActiveTime += active;
276335c6055SPawel Dziepak		fCore->IncreaseActiveTime(active);
277335c6055SPawel Dziepak
278d287274dSPawel Dziepak		oldThreadData->UpdateActivity(active);
279d287274dSPawel Dziepak	}
280d287274dSPawel Dziepak
281a2634874SPawel Dziepak	if (gTrackCPULoad) {
2828235bbc9SPawel Dziepak		if (!cpuEntry->disabled)
2838235bbc9SPawel Dziepak			ComputeLoad();
284a2634874SPawel Dziepak		_RequestPerformanceLevel(nextThreadData);
2858235bbc9SPawel Dziepak	}
286d287274dSPawel Dziepak
287d287274dSPawel Dziepak	Thread* nextThread = nextThreadData->GetThread();
288d287274dSPawel Dziepak	if (!thread_is_idle_thread(nextThread)) {
289d287274dSPawel Dziepak		cpuEntry->last_kernel_time = nextThread->kernel_time;
290d287274dSPawel Dziepak		cpuEntry->last_user_time = nextThread->user_time;
291d287274dSPawel Dziepak
292b24ea642SPawel Dziepak		nextThreadData->SetLastInterruptTime(cpuEntry->interrupt_time);
293d287274dSPawel Dziepak	}
294d287274dSPawel Dziepak}
295d287274dSPawel Dziepak
296d287274dSPawel Dziepak
297230d1fcfSPawel Dziepakvoid
298230d1fcfSPawel DziepakCPUEntry::StartQuantumTimer(ThreadData* thread, bool wasPreempted)
299230d1fcfSPawel Dziepak{
300230d1fcfSPawel Dziepak	cpu_ent* cpu = &gCPU[ID()];
301230d1fcfSPawel Dziepak
302230d1fcfSPawel Dziepak	if (!wasPreempted || fUpdateLoadEvent)
303230d1fcfSPawel Dziepak		cancel_timer(&cpu->quantum_timer);
304230d1fcfSPawel Dziepak	fUpdateLoadEvent = false;
305230d1fcfSPawel Dziepak
306230d1fcfSPawel Dziepak	if (!thread->IsIdle()) {
307230d1fcfSPawel Dziepak		bigtime_t quantum = thread->GetQuantumLeft();
308230d1fcfSPawel Dziepak		add_timer(&cpu->quantum_timer, &CPUEntry::_RescheduleEvent, quantum,
309230d1fcfSPawel Dziepak			B_ONE_SHOT_RELATIVE_TIMER);
310230d1fcfSPawel Dziepak	} else if (gTrackCoreLoad) {
311230d1fcfSPawel Dziepak		add_timer(&cpu->quantum_timer, &CPUEntry::_UpdateLoadEvent,
312a57a7a8cSPawel Dziepak			kLoadMeasureInterval * 2, B_ONE_SHOT_RELATIVE_TIMER);
313230d1fcfSPawel Dziepak		fUpdateLoadEvent = true;
314230d1fcfSPawel Dziepak	}
315230d1fcfSPawel Dziepak}
316230d1fcfSPawel Dziepak
317230d1fcfSPawel Dziepak
3188235bbc9SPawel Dziepakvoid
319d287274dSPawel DziepakCPUEntry::_RequestPerformanceLevel(ThreadData* threadData)
320d287274dSPawel Dziepak{
32196dcc73bSPawel Dziepak	SCHEDULER_ENTER_FUNCTION();
32296dcc73bSPawel Dziepak
3231524fbf7SPawel Dziepak	if (gCPU[fCPUNumber].disabled) {
3241524fbf7SPawel Dziepak		decrease_cpu_performance(kCPUPerformanceScaleMax);
3251524fbf7SPawel Dziepak		return;
3261524fbf7SPawel Dziepak	}
3271524fbf7SPawel Dziepak
328d287274dSPawel Dziepak	int32 load = std::max(threadData->GetLoad(), fCore->GetLoad());
329335c6055SPawel Dziepak	ASSERT(load >= 0 && load <= kMaxLoad);
330d287274dSPawel Dziepak
331d287274dSPawel Dziepak	if (load < kTargetLoad) {
332d287274dSPawel Dziepak		int32 delta = kTargetLoad - load;
333d287274dSPawel Dziepak
334d287274dSPawel Dziepak		delta *= kTargetLoad;
335d287274dSPawel Dziepak		delta /= kCPUPerformanceScaleMax;
336d287274dSPawel Dziepak
337d287274dSPawel Dziepak		decrease_cpu_performance(delta);
338d287274dSPawel Dziepak	} else {
339d287274dSPawel Dziepak		int32 delta = load - kTargetLoad;
340d287274dSPawel Dziepak		delta *= kMaxLoad - kTargetLoad;
341d287274dSPawel Dziepak		delta /= kCPUPerformanceScaleMax;
342d287274dSPawel Dziepak
3431b06228fSPawel Dziepak		increase_cpu_performance(delta);
344d287274dSPawel Dziepak	}
345d287274dSPawel Dziepak}
346d287274dSPawel Dziepak
347d287274dSPawel Dziepak
348230d1fcfSPawel Dziepak/* static */ int32
349230d1fcfSPawel DziepakCPUEntry::_RescheduleEvent(timer* /* unused */)
350230d1fcfSPawel Dziepak{
351230d1fcfSPawel Dziepak	get_cpu_struct()->invoke_scheduler = true;
352230d1fcfSPawel Dziepak	get_cpu_struct()->preempted = true;
353230d1fcfSPawel Dziepak	return B_HANDLED_INTERRUPT;
354230d1fcfSPawel Dziepak}
355230d1fcfSPawel Dziepak
356230d1fcfSPawel Dziepak
357230d1fcfSPawel Dziepak/* static */ int32
358230d1fcfSPawel DziepakCPUEntry::_UpdateLoadEvent(timer* /* unused */)
359230d1fcfSPawel Dziepak{
360230d1fcfSPawel Dziepak	CoreEntry::GetCore(smp_get_current_cpu())->ChangeLoad(0);
361230d1fcfSPawel Dziepak	CPUEntry::GetCPU(smp_get_current_cpu())->fUpdateLoadEvent = false;
362230d1fcfSPawel Dziepak	return B_HANDLED_INTERRUPT;
363230d1fcfSPawel Dziepak}
364230d1fcfSPawel Dziepak
365230d1fcfSPawel Dziepak
366d287274dSPawel DziepakCPUPriorityHeap::CPUPriorityHeap(int32 cpuCount)
367d287274dSPawel Dziepak	:
368ef8e55a1SPawel Dziepak	Heap<CPUEntry, int32>(cpuCount)
369d287274dSPawel Dziepak{
370d287274dSPawel Dziepak}
371d287274dSPawel Dziepak
372d287274dSPawel Dziepak
373d287274dSPawel Dziepakvoid
374d287274dSPawel DziepakCPUPriorityHeap::Dump()
375d287274dSPawel Dziepak{
376d287274dSPawel Dziepak	kprintf("cpu priority load\n");
377ef8e55a1SPawel Dziepak	CPUEntry* entry = PeekRoot();
378d287274dSPawel Dziepak	while (entry) {
379a08b40d4SPawel Dziepak		int32 cpu = entry->ID();
380d287274dSPawel Dziepak		int32 key = GetKey(entry);
381d287274dSPawel Dziepak		kprintf("%3" B_PRId32 " %8" B_PRId32 " %3" B_PRId32 "%%\n", cpu, key,
382a08b40d4SPawel Dziepak			entry->GetLoad() / 10);
383d287274dSPawel Dziepak
384ef8e55a1SPawel Dziepak		RemoveRoot();
385d287274dSPawel Dziepak		sDebugCPUHeap.Insert(entry, key);
386d287274dSPawel Dziepak
387ef8e55a1SPawel Dziepak		entry = PeekRoot();
388d287274dSPawel Dziepak	}
389d287274dSPawel Dziepak
390ef8e55a1SPawel Dziepak	entry = sDebugCPUHeap.PeekRoot();
391d287274dSPawel Dziepak	while (entry) {
392d287274dSPawel Dziepak		int32 key = GetKey(entry);
393ef8e55a1SPawel Dziepak		sDebugCPUHeap.RemoveRoot();
394d287274dSPawel Dziepak		Insert(entry, key);
395ef8e55a1SPawel Dziepak		entry = sDebugCPUHeap.PeekRoot();
396d287274dSPawel Dziepak	}
397d287274dSPawel Dziepak}
398d287274dSPawel Dziepak
399d287274dSPawel Dziepak
400d287274dSPawel DziepakCoreEntry::CoreEntry()
401d287274dSPawel Dziepak	:
402d287274dSPawel Dziepak	fCPUCount(0),
403d36098e0SPawel Dziepak	fIdleCPUCount(0),
404d287274dSPawel Dziepak	fThreadCount(0),
405d287274dSPawel Dziepak	fActiveTime(0),
406d287274dSPawel Dziepak	fLoad(0),
4076155ab7bSPawel Dziepak	fCurrentLoad(0),
4086155ab7bSPawel Dziepak	fLoadMeasurementEpoch(0),
409a2634874SPawel Dziepak	fHighLoad(false),
410a2634874SPawel Dziepak	fLastLoadUpdate(0)
411d287274dSPawel Dziepak{
412d287274dSPawel Dziepak	B_INITIALIZE_SPINLOCK(&fCPULock);
413d287274dSPawel Dziepak	B_INITIALIZE_SPINLOCK(&fQueueLock);
414ad6b9a1dSPawel Dziepak	B_INITIALIZE_SEQLOCK(&fActiveTimeLock);
4156155ab7bSPawel Dziepak	B_INITIALIZE_RW_SPINLOCK(&fLoadLock);
416d287274dSPawel Dziepak}
417d287274dSPawel Dziepak
418d287274dSPawel Dziepak
419d287274dSPawel Dziepakvoid
420e1e7235cSPawel DziepakCoreEntry::Init(int32 id, PackageEntry* package)
421d287274dSPawel Dziepak{
422e1e7235cSPawel Dziepak	fCoreID = id;
423e1e7235cSPawel Dziepak	fPackage = package;
424e1e7235cSPawel Dziepak}
425e1e7235cSPawel Dziepak
426d287274dSPawel Dziepak
427e1e7235cSPawel Dziepakvoid
428e1e7235cSPawel DziepakCoreEntry::PushFront(ThreadData* thread, int32 priority)
429e1e7235cSPawel Dziepak{
43096dcc73bSPawel Dziepak	SCHEDULER_ENTER_FUNCTION();
43196dcc73bSPawel Dziepak
432e1e7235cSPawel Dziepak	fRunQueue.PushFront(thread, priority);
433e1e7235cSPawel Dziepak	atomic_add(&fThreadCount, 1);
434e1e7235cSPawel Dziepak}
435e1e7235cSPawel Dziepak
436e1e7235cSPawel Dziepak
437e1e7235cSPawel Dziepakvoid
438e1e7235cSPawel DziepakCoreEntry::PushBack(ThreadData* thread, int32 priority)
439e1e7235cSPawel Dziepak{
44096dcc73bSPawel Dziepak	SCHEDULER_ENTER_FUNCTION();
44196dcc73bSPawel Dziepak
442e1e7235cSPawel Dziepak	fRunQueue.PushBack(thread, priority);
443e1e7235cSPawel Dziepak	atomic_add(&fThreadCount, 1);
444e1e7235cSPawel Dziepak}
445e1e7235cSPawel Dziepak
446e1e7235cSPawel Dziepak
447e1e7235cSPawel Dziepakvoid
448b24ea642SPawel DziepakCoreEntry::Remove(ThreadData* thread)
449e1e7235cSPawel Dziepak{
45096dcc73bSPawel Dziepak	SCHEDULER_ENTER_FUNCTION();
45196dcc73bSPawel Dziepak
452f116370eSPawel Dziepak	ASSERT(!thread->IsIdle());
453f116370eSPawel Dziepak
454b24ea642SPawel Dziepak	ASSERT(thread->IsEnqueued());
455b24ea642SPawel Dziepak	thread->SetDequeued();
4569c465cc8SPawel Dziepak
457e1e7235cSPawel Dziepak	fRunQueue.Remove(thread);
458e1e7235cSPawel Dziepak	atomic_add(&fThreadCount, -1);
459e1e7235cSPawel Dziepak}
460e1e7235cSPawel Dziepak
461e1e7235cSPawel Dziepak
462e1e7235cSPawel Dziepakvoid
463e1e7235cSPawel DziepakCoreEntry::AddCPU(CPUEntry* cpu)
464e1e7235cSPawel Dziepak{
465e1e7235cSPawel Dziepak	ASSERT(fCPUCount >= 0);
466d36098e0SPawel Dziepak	ASSERT(fIdleCPUCount >= 0);
467ef8e55a1SPawel Dziepak
468d36098e0SPawel Dziepak	fIdleCPUCount++;
469e1e7235cSPawel Dziepak	if (fCPUCount++ == 0) {
470e1e7235cSPawel Dziepak		// core has been reenabled
471e1e7235cSPawel Dziepak		fLoad = 0;
4726155ab7bSPawel Dziepak		fCurrentLoad = 0;
473e1e7235cSPawel Dziepak		fHighLoad = false;
474e1e7235cSPawel Dziepak		gCoreLoadHeap.Insert(this, 0);
475e1e7235cSPawel Dziepak
476e1e7235cSPawel Dziepak		fPackage->AddIdleCore(this);
477e1e7235cSPawel Dziepak	}
478e1e7235cSPawel Dziepak
479e1e7235cSPawel Dziepak	fCPUHeap.Insert(cpu, B_IDLE_PRIORITY);
480e1e7235cSPawel Dziepak}
481e1e7235cSPawel Dziepak
482e1e7235cSPawel Dziepak
483e1e7235cSPawel Dziepakvoid
484e1e7235cSPawel DziepakCoreEntry::RemoveCPU(CPUEntry* cpu, ThreadProcessing& threadPostProcessing)
485e1e7235cSPawel Dziepak{
486e1e7235cSPawel Dziepak	ASSERT(fCPUCount > 0);
487d36098e0SPawel Dziepak	ASSERT(fIdleCPUCount > 0);
488ef8e55a1SPawel Dziepak
489d36098e0SPawel Dziepak	fIdleCPUCount--;
490e1e7235cSPawel Dziepak	if (--fCPUCount == 0) {
491a2634874SPawel Dziepak		// unassign threads
492a2634874SPawel Dziepak		thread_map(CoreEntry::_UnassignThread, this);
493a2634874SPawel Dziepak
494e1e7235cSPawel Dziepak		// core has been disabled
495e1e7235cSPawel Dziepak		if (fHighLoad) {
496e1e7235cSPawel Dziepak			gCoreHighLoadHeap.ModifyKey(this, -1);
497e1e7235cSPawel Dziepak			ASSERT(gCoreHighLoadHeap.PeekMinimum() == this);
498e1e7235cSPawel Dziepak			gCoreHighLoadHeap.RemoveMinimum();
499e1e7235cSPawel Dziepak		} else {
500e1e7235cSPawel Dziepak			gCoreLoadHeap.ModifyKey(this, -1);
501e1e7235cSPawel Dziepak			ASSERT(gCoreLoadHeap.PeekMinimum() == this);
502e1e7235cSPawel Dziepak			gCoreLoadHeap.RemoveMinimum();
503e1e7235cSPawel Dziepak		}
504e1e7235cSPawel Dziepak
505e1e7235cSPawel Dziepak		fPackage->RemoveIdleCore(this);
506e1e7235cSPawel Dziepak
507e1e7235cSPawel Dziepak		// get rid of threads
508e1e7235cSPawel Dziepak		while (fRunQueue.PeekMaximum() != NULL) {
509e1e7235cSPawel Dziepak			ThreadData* threadData = fRunQueue.PeekMaximum();
510e1e7235cSPawel Dziepak
511b24ea642SPawel Dziepak			Remove(threadData);
512e1e7235cSPawel Dziepak
513e1e7235cSPawel Dziepak			ASSERT(threadData->Core() == NULL);
514e1e7235cSPawel Dziepak			threadPostProcessing(threadData);
515e1e7235cSPawel Dziepak		}
516b24ea642SPawel Dziepak
517b24ea642SPawel Dziepak		fThreadCount = 0;
518e1e7235cSPawel Dziepak	}
519e1e7235cSPawel Dziepak
520ef8e55a1SPawel Dziepak	fCPUHeap.ModifyKey(cpu, -1);
521ef8e55a1SPawel Dziepak	ASSERT(fCPUHeap.PeekRoot() == cpu);
522ef8e55a1SPawel Dziepak	fCPUHeap.RemoveRoot();
523e1e7235cSPawel Dziepak
524a08b40d4SPawel Dziepak	ASSERT(cpu->GetLoad() >= 0 && cpu->GetLoad() <= kMaxLoad);
525e1e7235cSPawel Dziepak	ASSERT(fLoad >= 0);
526e1e7235cSPawel Dziepak}
527e1e7235cSPawel Dziepak
528e1e7235cSPawel Dziepak
5296155ab7bSPawel Dziepakvoid
530667b23ddSPawel DziepakCoreEntry::_UpdateLoad(bool forceUpdate)
5316155ab7bSPawel Dziepak{
5326155ab7bSPawel Dziepak	SCHEDULER_ENTER_FUNCTION();
5336155ab7bSPawel Dziepak
5346155ab7bSPawel Dziepak	if (fCPUCount <= 0)
5356155ab7bSPawel Dziepak		return;
5366155ab7bSPawel Dziepak
5376155ab7bSPawel Dziepak	bigtime_t now = system_time();
538667b23ddSPawel Dziepak	bool intervalEnded = now >= kLoadMeasureInterval + fLastLoadUpdate;
539a57a7a8cSPawel Dziepak	bool intervalSkipped = now >= kLoadMeasureInterval * 2 + fLastLoadUpdate;
540667b23ddSPawel Dziepak
541667b23ddSPawel Dziepak	if (!intervalEnded && !forceUpdate)
5426155ab7bSPawel Dziepak		return;
543667b23ddSPawel Dziepak
544230d1fcfSPawel Dziepak	WriteSpinLocker coreLocker(gCoreHeapsLock);
5456155ab7bSPawel Dziepak
546a57a7a8cSPawel Dziepak	int32 newKey;
547667b23ddSPawel Dziepak	if (intervalEnded) {
548667b23ddSPawel Dziepak		WriteSpinLocker locker(fLoadLock);
5496155ab7bSPawel Dziepak
550a57a7a8cSPawel Dziepak		newKey = intervalSkipped ? fCurrentLoad : GetLoad();
551a57a7a8cSPawel Dziepak
552667b23ddSPawel Dziepak		ASSERT(fCurrentLoad >= 0);
553667b23ddSPawel Dziepak		ASSERT(fLoad >= fCurrentLoad);
554667b23ddSPawel Dziepak
555667b23ddSPawel Dziepak		fLoad = fCurrentLoad;
556667b23ddSPawel Dziepak		fLoadMeasurementEpoch++;
557667b23ddSPawel Dziepak		fLastLoadUpdate = now;
558a57a7a8cSPawel Dziepak	} else
559a57a7a8cSPawel Dziepak		newKey = GetLoad();
560a57a7a8cSPawel Dziepak
561a57a7a8cSPawel Dziepak	int32 oldKey = CoreLoadHeap::GetKey(this);
562a57a7a8cSPawel Dziepak
563a57a7a8cSPawel Dziepak	ASSERT(oldKey >= 0);
564a57a7a8cSPawel Dziepak	ASSERT(newKey >= 0);
5656155ab7bSPawel Dziepak
5666155ab7bSPawel Dziepak	if (oldKey == newKey)
5676155ab7bSPawel Dziepak		return;
5686155ab7bSPawel Dziepak
5696155ab7bSPawel Dziepak	if (newKey > kHighLoad) {
5706155ab7bSPawel Dziepak		if (!fHighLoad) {
5716155ab7bSPawel Dziepak			gCoreLoadHeap.ModifyKey(this, -1);
5726155ab7bSPawel Dziepak			ASSERT(gCoreLoadHeap.PeekMinimum() == this);
5736155ab7bSPawel Dziepak			gCoreLoadHeap.RemoveMinimum();
5746155ab7bSPawel Dziepak
5756155ab7bSPawel Dziepak			gCoreHighLoadHeap.Insert(this, newKey);
5766155ab7bSPawel Dziepak
5776155ab7bSPawel Dziepak			fHighLoad = true;
5786155ab7bSPawel Dziepak		} else
5796155ab7bSPawel Dziepak			gCoreHighLoadHeap.ModifyKey(this, newKey);
5806155ab7bSPawel Dziepak	} else if (newKey < kMediumLoad) {
5816155ab7bSPawel Dziepak		if (fHighLoad) {
5826155ab7bSPawel Dziepak			gCoreHighLoadHeap.ModifyKey(this, -1);
5836155ab7bSPawel Dziepak			ASSERT(gCoreHighLoadHeap.PeekMinimum() == this);
5846155ab7bSPawel Dziepak			gCoreHighLoadHeap.RemoveMinimum();
5856155ab7bSPawel Dziepak
5866155ab7bSPawel Dziepak			gCoreLoadHeap.Insert(this, newKey);
5876155ab7bSPawel Dziepak
5886155ab7bSPawel Dziepak			fHighLoad = false;
5896155ab7bSPawel Dziepak		} else
5906155ab7bSPawel Dziepak			gCoreLoadHeap.ModifyKey(this, newKey);
5916155ab7bSPawel Dziepak	} else {
5926155ab7bSPawel Dziepak		if (fHighLoad)
5936155ab7bSPawel Dziepak			gCoreHighLoadHeap.ModifyKey(this, newKey);
5946155ab7bSPawel Dziepak		else
5956155ab7bSPawel Dziepak			gCoreLoadHeap.ModifyKey(this, newKey);
5966155ab7bSPawel Dziepak	}
5976155ab7bSPawel Dziepak}
5986155ab7bSPawel Dziepak
5996155ab7bSPawel Dziepak
600e1e7235cSPawel Dziepak/* static */ void
601e1e7235cSPawel DziepakCoreEntry::_UnassignThread(Thread* thread, void* data)
602e1e7235cSPawel Dziepak{
603e1e7235cSPawel Dziepak	CoreEntry* core = static_cast<CoreEntry*>(data);
604e1e7235cSPawel Dziepak	ThreadData* threadData = thread->scheduler_data;
605e1e7235cSPawel Dziepak
606e1e7235cSPawel Dziepak	if (threadData->Core() == core && thread->pinned_to_cpu == 0)
607e1e7235cSPawel Dziepak		threadData->UnassignCore();
608e1e7235cSPawel Dziepak}
609e1e7235cSPawel Dziepak
610e1e7235cSPawel Dziepak
611d287274dSPawel DziepakCoreLoadHeap::CoreLoadHeap(int32 coreCount)
612d287274dSPawel Dziepak	:
613d287274dSPawel Dziepak	MinMaxHeap<CoreEntry, int32>(coreCount)
614d287274dSPawel Dziepak{
615d287274dSPawel Dziepak}
616d287274dSPawel Dziepak
617d287274dSPawel Dziepak
618d287274dSPawel Dziepakvoid
619d287274dSPawel DziepakCoreLoadHeap::Dump()
620d287274dSPawel Dziepak{
621d287274dSPawel Dziepak	CoreEntry* entry = PeekMinimum();
622d287274dSPawel Dziepak	while (entry) {
623d287274dSPawel Dziepak		int32 key = GetKey(entry);
624d36098e0SPawel Dziepak
6256155ab7bSPawel Dziepak		DebugDumper::DumpCoreLoadHeapEntry(entry);
626d287274dSPawel Dziepak
627d287274dSPawel Dziepak		RemoveMinimum();
628d287274dSPawel Dziepak		sDebugCoreHeap.Insert(entry, key);
629d287274dSPawel Dziepak
630d287274dSPawel Dziepak		entry = PeekMinimum();
631d287274dSPawel Dziepak	}
632d287274dSPawel Dziepak
633d287274dSPawel Dziepak	entry = sDebugCoreHeap.PeekMinimum();
634d287274dSPawel Dziepak	while (entry) {
635d287274dSPawel Dziepak		int32 key = GetKey(entry);
636d287274dSPawel Dziepak		sDebugCoreHeap.RemoveMinimum();
637d287274dSPawel Dziepak		Insert(entry, key);
638d287274dSPawel Dziepak		entry = sDebugCoreHeap.PeekMinimum();
639d287274dSPawel Dziepak	}
640d287274dSPawel Dziepak}
641d287274dSPawel Dziepak
642d287274dSPawel Dziepak
643d287274dSPawel DziepakPackageEntry::PackageEntry()
644d287274dSPawel Dziepak	:
645d287274dSPawel Dziepak	fIdleCoreCount(0),
646d287274dSPawel Dziepak	fCoreCount(0)
647d287274dSPawel Dziepak{
648d287274dSPawel Dziepak	B_INITIALIZE_RW_SPINLOCK(&fCoreLock);
649d287274dSPawel Dziepak}
650d287274dSPawel Dziepak
651d287274dSPawel Dziepak
65260e198f2SPawel Dziepakvoid
65360e198f2SPawel DziepakPackageEntry::Init(int32 id)
65460e198f2SPawel Dziepak{
65560e198f2SPawel Dziepak	fPackageID = id;
65660e198f2SPawel Dziepak}
65760e198f2SPawel Dziepak
65860e198f2SPawel Dziepak
65960e198f2SPawel Dziepakvoid
66060e198f2SPawel DziepakPackageEntry::AddIdleCore(CoreEntry* core)
66160e198f2SPawel Dziepak{
66260e198f2SPawel Dziepak	fCoreCount++;
66360e198f2SPawel Dziepak	fIdleCoreCount++;
66460e198f2SPawel Dziepak	fIdleCores.Add(core);
66560e198f2SPawel Dziepak
66660e198f2SPawel Dziepak	if (fCoreCount == 1)
66760e198f2SPawel Dziepak		gIdlePackageList.Add(this);
66860e198f2SPawel Dziepak}
66960e198f2SPawel Dziepak
67060e198f2SPawel Dziepak
67160e198f2SPawel Dziepakvoid
67260e198f2SPawel DziepakPackageEntry::RemoveIdleCore(CoreEntry* core)
67360e198f2SPawel Dziepak{
67460e198f2SPawel Dziepak	fIdleCores.Remove(core);
67560e198f2SPawel Dziepak	fIdleCoreCount--;
67660e198f2SPawel Dziepak	fCoreCount--;
67760e198f2SPawel Dziepak
67860e198f2SPawel Dziepak	if (fCoreCount == 0)
67960e198f2SPawel Dziepak		gIdlePackageList.Remove(this);
68060e198f2SPawel Dziepak}
68160e198f2SPawel Dziepak
68260e198f2SPawel Dziepak
683a08b40d4SPawel Dziepak/* static */ void
684a08b40d4SPawel DziepakDebugDumper::DumpCPURunQueue(CPUEntry* cpu)
685a08b40d4SPawel Dziepak{
686a08b40d4SPawel Dziepak	ThreadRunQueue::ConstIterator iterator = cpu->fRunQueue.GetConstIterator();
687a08b40d4SPawel Dziepak
688a08b40d4SPawel Dziepak	if (iterator.HasNext()
689a08b40d4SPawel Dziepak		&& !thread_is_idle_thread(iterator.Next()->GetThread())) {
690a08b40d4SPawel Dziepak		kprintf("\nCPU %" B_PRId32 " run queue:\n", cpu->ID());
691a08b40d4SPawel Dziepak		cpu->fRunQueue.Dump();
692a08b40d4SPawel Dziepak	}
693a08b40d4SPawel Dziepak}
694a08b40d4SPawel Dziepak
695a08b40d4SPawel Dziepak
696e1e7235cSPawel Dziepak/* static */ void
697e1e7235cSPawel DziepakDebugDumper::DumpCoreRunQueue(CoreEntry* core)
698e1e7235cSPawel Dziepak{
699e1e7235cSPawel Dziepak	core->fRunQueue.Dump();
700e1e7235cSPawel Dziepak}
701e1e7235cSPawel Dziepak
702e1e7235cSPawel Dziepak
7036155ab7bSPawel Dziepak/* static */ void
7046155ab7bSPawel DziepakDebugDumper::DumpCoreLoadHeapEntry(CoreEntry* entry)
7056155ab7bSPawel Dziepak{
7066155ab7bSPawel Dziepak	CoreThreadsData threadsData;
7076155ab7bSPawel Dziepak	threadsData.fCore = entry;
7086155ab7bSPawel Dziepak	threadsData.fLoad = 0;
7096155ab7bSPawel Dziepak	thread_map(DebugDumper::_AnalyzeCoreThreads, &threadsData);
7106155ab7bSPawel Dziepak
7116155ab7bSPawel Dziepak	kprintf("%4" B_PRId32 " %11" B_PRId32 "%% %11" B_PRId32 "%% %11" B_PRId32
7126155ab7bSPawel Dziepak		"%% %7" B_PRId32 " %5" B_PRIu32 "\n", entry->ID(), entry->fLoad / 10,
7136155ab7bSPawel Dziepak		entry->fCurrentLoad / 10, threadsData.fLoad, entry->ThreadCount(),
7146155ab7bSPawel Dziepak		entry->fLoadMeasurementEpoch);
7156155ab7bSPawel Dziepak}
7166155ab7bSPawel Dziepak
7176155ab7bSPawel Dziepak
71860e198f2SPawel Dziepak/* static */ void
71960e198f2SPawel DziepakDebugDumper::DumpIdleCoresInPackage(PackageEntry* package)
72060e198f2SPawel Dziepak{
72160e198f2SPawel Dziepak	kprintf("%-7" B_PRId32 " ", package->fPackageID);
72260e198f2SPawel Dziepak
72360e198f2SPawel Dziepak	DoublyLinkedList<CoreEntry>::ReverseIterator iterator
72460e198f2SPawel Dziepak		= package->fIdleCores.GetReverseIterator();
72560e198f2SPawel Dziepak	if (iterator.HasNext()) {
72660e198f2SPawel Dziepak		while (iterator.HasNext()) {
72760e198f2SPawel Dziepak			CoreEntry* coreEntry = iterator.Next();
728e1e7235cSPawel Dziepak			kprintf("%" B_PRId32 "%s", coreEntry->ID(),
72960e198f2SPawel Dziepak				iterator.HasNext() ? ", " : "");
73060e198f2SPawel Dziepak		}
73160e198f2SPawel Dziepak	} else
73260e198f2SPawel Dziepak		kprintf("-");
73360e198f2SPawel Dziepak	kprintf("\n");
73460e198f2SPawel Dziepak}
73560e198f2SPawel Dziepak
73660e198f2SPawel Dziepak
7376155ab7bSPawel Dziepak/* static */ void
7386155ab7bSPawel DziepakDebugDumper::_AnalyzeCoreThreads(Thread* thread, void* data)
7396155ab7bSPawel Dziepak{
7406155ab7bSPawel Dziepak	CoreThreadsData* threadsData = static_cast<CoreThreadsData*>(data);
7416155ab7bSPawel Dziepak	if (thread->scheduler_data->Core() == threadsData->fCore)
7426155ab7bSPawel Dziepak		threadsData->fLoad += thread->scheduler_data->GetLoad();
7436155ab7bSPawel Dziepak}
7446155ab7bSPawel Dziepak
7456155ab7bSPawel Dziepak
746d287274dSPawel Dziepakstatic int
7479c465cc8SPawel Dziepakdump_run_queue(int /* argc */, char** /* argv */)
748d287274dSPawel Dziepak{
749d287274dSPawel Dziepak	int32 cpuCount = smp_get_num_cpus();
750d287274dSPawel Dziepak	int32 coreCount = gCoreCount;
751d287274dSPawel Dziepak
752d287274dSPawel Dziepak	for (int32 i = 0; i < coreCount; i++) {
753d287274dSPawel Dziepak		kprintf("%sCore %" B_PRId32 " run queue:\n", i > 0 ? "\n" : "", i);
754e1e7235cSPawel Dziepak		DebugDumper::DumpCoreRunQueue(&gCoreEntries[i]);
755d287274dSPawel Dziepak	}
756d287274dSPawel Dziepak
757a08b40d4SPawel Dziepak	for (int32 i = 0; i < cpuCount; i++)
758a08b40d4SPawel Dziepak		DebugDumper::DumpCPURunQueue(&gCPUEntries[i]);
759d287274dSPawel Dziepak
760d287274dSPawel Dziepak	return 0;
761d287274dSPawel Dziepak}
762d287274dSPawel Dziepak
763d287274dSPawel Dziepak
764d287274dSPawel Dziepakstatic int
7659c465cc8SPawel Dziepakdump_cpu_heap(int /* argc */, char** /* argv */)
766d287274dSPawel Dziepak{
7676155ab7bSPawel Dziepak	kprintf("core average_load current_load threads_load threads epoch\n");
768d287274dSPawel Dziepak	gCoreLoadHeap.Dump();
769d287274dSPawel Dziepak	kprintf("\n");
770d287274dSPawel Dziepak	gCoreHighLoadHeap.Dump();
771d287274dSPawel Dziepak
772d287274dSPawel Dziepak	for (int32 i = 0; i < gCoreCount; i++) {
773e1e7235cSPawel Dziepak		if (gCoreEntries[i].CPUCount() < 2)
774d287274dSPawel Dziepak			continue;
775d287274dSPawel Dziepak
776d287274dSPawel Dziepak		kprintf("\nCore %" B_PRId32 " heap:\n", i);
777e1e7235cSPawel Dziepak		gCoreEntries[i].CPUHeap()->Dump();
778d287274dSPawel Dziepak	}
779d287274dSPawel Dziepak
780d287274dSPawel Dziepak	return 0;
781d287274dSPawel Dziepak}
782d287274dSPawel Dziepak
783d287274dSPawel Dziepak
784d287274dSPawel Dziepakstatic int
7859c465cc8SPawel Dziepakdump_idle_cores(int /* argc */, char** /* argv */)
786d287274dSPawel Dziepak{
787d287274dSPawel Dziepak	kprintf("Idle packages:\n");
788d287274dSPawel Dziepak	IdlePackageList::ReverseIterator idleIterator
789d287274dSPawel Dziepak		= gIdlePackageList.GetReverseIterator();
790d287274dSPawel Dziepak
791d287274dSPawel Dziepak	if (idleIterator.HasNext()) {
792d287274dSPawel Dziepak		kprintf("package cores\n");
793d287274dSPawel Dziepak
79460e198f2SPawel Dziepak		while (idleIterator.HasNext())
79560e198f2SPawel Dziepak			DebugDumper::DumpIdleCoresInPackage(idleIterator.Next());
796d287274dSPawel Dziepak	} else
797d287274dSPawel Dziepak		kprintf("No idle packages.\n");
798d287274dSPawel Dziepak
799d287274dSPawel Dziepak	return 0;
800d287274dSPawel Dziepak}
801d287274dSPawel Dziepak
802d287274dSPawel Dziepak
80360e198f2SPawel Dziepakvoid Scheduler::init_debug_commands()
804d287274dSPawel Dziepak{
805d287274dSPawel Dziepak	new(&sDebugCPUHeap) CPUPriorityHeap(smp_get_num_cpus());
806d287274dSPawel Dziepak	new(&sDebugCoreHeap) CoreLoadHeap(smp_get_num_cpus());
807d287274dSPawel Dziepak
808d287274dSPawel Dziepak	add_debugger_command_etc("run_queue", &dump_run_queue,
809d287274dSPawel Dziepak		"List threads in run queue", "\nLists threads in run queue", 0);
810d287274dSPawel Dziepak	if (!gSingleCore) {
811d287274dSPawel Dziepak		add_debugger_command_etc("cpu_heap", &dump_cpu_heap,
812d287274dSPawel Dziepak			"List CPUs in CPU priority heap",
813d287274dSPawel Dziepak			"\nList CPUs in CPU priority heap", 0);
814d287274dSPawel Dziepak		add_debugger_command_etc("idle_cores", &dump_idle_cores,
815d287274dSPawel Dziepak			"List idle cores", "\nList idle cores", 0);
816d287274dSPawel Dziepak	}
817d287274dSPawel Dziepak}
818d287274dSPawel Dziepak
819