xref: /haiku/src/system/kernel/scheduler/scheduler_cpu.h (revision cb66faef24f64af40a51f23300ff546d975535b3)
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 #ifndef KERNEL_SCHEDULER_CPU_H
6d287274dSPawel Dziepak #define KERNEL_SCHEDULER_CPU_H
7d287274dSPawel Dziepak 
8d287274dSPawel Dziepak 
9d287274dSPawel Dziepak #include <OS.h>
10d287274dSPawel Dziepak 
11d287274dSPawel Dziepak #include <thread.h>
12e1e7235cSPawel Dziepak #include <util/AutoLock.h>
13ef8e55a1SPawel Dziepak #include <util/Heap.h>
147c92dffeSPawel Dziepak #include <util/MinMaxHeap.h>
15d287274dSPawel Dziepak 
16d287274dSPawel Dziepak #include <cpufreq.h>
17d287274dSPawel Dziepak 
18d287274dSPawel Dziepak #include "RunQueue.h"
19d287274dSPawel Dziepak #include "scheduler_common.h"
20d287274dSPawel Dziepak #include "scheduler_modes.h"
2196dcc73bSPawel Dziepak #include "scheduler_profiler.h"
22d287274dSPawel Dziepak 
23d287274dSPawel Dziepak 
24d287274dSPawel Dziepak namespace Scheduler {
25d287274dSPawel Dziepak 
26d287274dSPawel Dziepak 
2760e198f2SPawel Dziepak class DebugDumper;
2860e198f2SPawel Dziepak 
29d287274dSPawel Dziepak struct ThreadData;
30e1e7235cSPawel Dziepak class ThreadProcessing;
31d287274dSPawel Dziepak 
32d287274dSPawel Dziepak struct CPUEntry;
33d287274dSPawel Dziepak struct CoreEntry;
34d287274dSPawel Dziepak struct PackageEntry;
35d287274dSPawel Dziepak 
36d287274dSPawel Dziepak // The run queues. Holds the threads ready to run ordered by priority.
37d287274dSPawel Dziepak // One queue per schedulable target per core. Additionally, each
38d287274dSPawel Dziepak // logical processor has its sPinnedRunQueues used for scheduling
39d287274dSPawel Dziepak // pinned threads.
40d287274dSPawel Dziepak class ThreadRunQueue : public RunQueue<ThreadData, THREAD_MAX_SET_PRIORITY> {
41d287274dSPawel Dziepak public:
42d287274dSPawel Dziepak 						void			Dump() const;
43d287274dSPawel Dziepak };
44d287274dSPawel Dziepak 
45ef8e55a1SPawel Dziepak class CPUEntry : public HeapLinkImpl<CPUEntry, int32> {
46a08b40d4SPawel Dziepak public:
47d287274dSPawel Dziepak 										CPUEntry();
48d287274dSPawel Dziepak 
49a08b40d4SPawel Dziepak 						void			Init(int32 id, CoreEntry* core);
50a08b40d4SPawel Dziepak 
51a08b40d4SPawel Dziepak 	inline				int32			ID() const	{ return fCPUNumber; }
52a08b40d4SPawel Dziepak 	inline				CoreEntry*		Core() const	{ return fCore; }
53a08b40d4SPawel Dziepak 
54a08b40d4SPawel Dziepak 						void			Start();
55a08b40d4SPawel Dziepak 						void			Stop();
56a08b40d4SPawel Dziepak 
57a08b40d4SPawel Dziepak 	inline				void			EnterScheduler();
58a08b40d4SPawel Dziepak 	inline				void			ExitScheduler();
59a08b40d4SPawel Dziepak 
60a08b40d4SPawel Dziepak 	inline				void			LockScheduler();
61a08b40d4SPawel Dziepak 	inline				void			UnlockScheduler();
62a08b40d4SPawel Dziepak 
6326592750SPawel Dziepak 	inline				void			LockRunQueue();
6426592750SPawel Dziepak 	inline				void			UnlockRunQueue();
6526592750SPawel Dziepak 
66a08b40d4SPawel Dziepak 						void			PushFront(ThreadData* thread,
67a08b40d4SPawel Dziepak 											int32 priority);
68a08b40d4SPawel Dziepak 						void			PushBack(ThreadData* thread,
69a08b40d4SPawel Dziepak 											int32 priority);
70a08b40d4SPawel Dziepak 						void			Remove(ThreadData* thread);
71a08b40d4SPawel Dziepak 	inline				ThreadData*		PeekThread() const;
72a08b40d4SPawel Dziepak 						ThreadData*		PeekIdleThread() const;
73a08b40d4SPawel Dziepak 
74d287274dSPawel Dziepak 						void			UpdatePriority(int32 priority);
75d287274dSPawel Dziepak 
76a08b40d4SPawel Dziepak 	inline				int32			GetLoad() const	{ return fLoad; }
77d287274dSPawel Dziepak 						void			ComputeLoad();
78d287274dSPawel Dziepak 
79d287274dSPawel Dziepak 						ThreadData*		ChooseNextThread(ThreadData* oldThread,
80d287274dSPawel Dziepak 											bool putAtBack);
81d287274dSPawel Dziepak 
82d287274dSPawel Dziepak 						void			TrackActivity(ThreadData* oldThreadData,
83d287274dSPawel Dziepak 											ThreadData* nextThreadData);
84d287274dSPawel Dziepak 
85a08b40d4SPawel Dziepak 	static inline		CPUEntry*		GetCPU(int32 cpu);
86a08b40d4SPawel Dziepak 
87a08b40d4SPawel Dziepak private:
88*cb66faefSPawel Dziepak 						void			_RequestPerformanceLevel(
89a08b40d4SPawel Dziepak 											ThreadData* threadData);
90a08b40d4SPawel Dziepak 
91d287274dSPawel Dziepak 						int32			fCPUNumber;
92d287274dSPawel Dziepak 						CoreEntry*		fCore;
93d287274dSPawel Dziepak 
94d287274dSPawel Dziepak 						rw_spinlock 	fSchedulerModeLock;
95d287274dSPawel Dziepak 
96d287274dSPawel Dziepak 						ThreadRunQueue	fRunQueue;
9726592750SPawel Dziepak 						spinlock		fQueueLock;
98d287274dSPawel Dziepak 
99d287274dSPawel Dziepak 						int32			fLoad;
100d287274dSPawel Dziepak 
101d287274dSPawel Dziepak 						bigtime_t		fMeasureActiveTime;
102d287274dSPawel Dziepak 						bigtime_t		fMeasureTime;
103d287274dSPawel Dziepak 
104a08b40d4SPawel Dziepak 						friend class DebugDumper;
105d287274dSPawel Dziepak } CACHE_LINE_ALIGN;
106d287274dSPawel Dziepak 
107ef8e55a1SPawel Dziepak class CPUPriorityHeap : public Heap<CPUEntry, int32> {
108d287274dSPawel Dziepak public:
109d287274dSPawel Dziepak 										CPUPriorityHeap() { }
110d287274dSPawel Dziepak 										CPUPriorityHeap(int32 cpuCount);
111d287274dSPawel Dziepak 
112d287274dSPawel Dziepak 						void			Dump();
113d287274dSPawel Dziepak };
114d287274dSPawel Dziepak 
11526592750SPawel Dziepak 
116e1e7235cSPawel Dziepak class CoreEntry : public MinMaxHeapLinkImpl<CoreEntry, int32>,
117e1e7235cSPawel Dziepak 	public DoublyLinkedListLinkImpl<CoreEntry> {
118e1e7235cSPawel Dziepak public:
119d287274dSPawel Dziepak 										CoreEntry();
120d287274dSPawel Dziepak 
121e1e7235cSPawel Dziepak 						void			Init(int32 id, PackageEntry* package);
122e1e7235cSPawel Dziepak 
123e1e7235cSPawel Dziepak 	inline				int32			ID() const	{ return fCoreID; }
124e1e7235cSPawel Dziepak 	inline				PackageEntry*	Package() const	{ return fPackage; }
125e1e7235cSPawel Dziepak 	inline				int32			CPUCount() const
126e1e7235cSPawel Dziepak 											{ return fCPUCount; }
127e1e7235cSPawel Dziepak 
128e1e7235cSPawel Dziepak 	inline				void			LockCPUHeap();
129e1e7235cSPawel Dziepak 	inline				void			UnlockCPUHeap();
130e1e7235cSPawel Dziepak 
131e1e7235cSPawel Dziepak 	inline				CPUPriorityHeap*	CPUHeap();
132e1e7235cSPawel Dziepak 
133e1e7235cSPawel Dziepak 	inline				int32			ThreadCount() const
134e1e7235cSPawel Dziepak 											{ return fThreadCount; }
135e1e7235cSPawel Dziepak 
136e1e7235cSPawel Dziepak 	inline				void			LockRunQueue();
137e1e7235cSPawel Dziepak 	inline				void			UnlockRunQueue();
138e1e7235cSPawel Dziepak 
139e1e7235cSPawel Dziepak 						void			PushFront(ThreadData* thread,
140e1e7235cSPawel Dziepak 											int32 priority);
141e1e7235cSPawel Dziepak 						void			PushBack(ThreadData* thread,
142e1e7235cSPawel Dziepak 											int32 priority);
143b24ea642SPawel Dziepak 						void			Remove(ThreadData* thread);
144e1e7235cSPawel Dziepak 	inline				ThreadData*		PeekThread() const;
145e1e7235cSPawel Dziepak 
146e1e7235cSPawel Dziepak 	inline				bigtime_t		GetActiveTime() const;
147e1e7235cSPawel Dziepak 	inline				void			IncreaseActiveTime(
148e1e7235cSPawel Dziepak 											bigtime_t activeTime);
149e1e7235cSPawel Dziepak 
150d287274dSPawel Dziepak 	inline				int32			GetLoad() const;
151e1e7235cSPawel Dziepak 						void			UpdateLoad(int32 delta);
152e1e7235cSPawel Dziepak 
153e1e7235cSPawel Dziepak 	inline				int32			StarvationCounter() const;
154e1e7235cSPawel Dziepak 
155ef8e55a1SPawel Dziepak 	inline				void			CPUGoesIdle(CPUEntry* cpu);
156ef8e55a1SPawel Dziepak 	inline				void			CPUWakesUp(CPUEntry* cpu);
157ef8e55a1SPawel Dziepak 
158e1e7235cSPawel Dziepak 						void			AddCPU(CPUEntry* cpu);
159e1e7235cSPawel Dziepak 						void			RemoveCPU(CPUEntry* cpu,
160e1e7235cSPawel Dziepak 											ThreadProcessing&
161e1e7235cSPawel Dziepak 												threadPostProcessing);
162d287274dSPawel Dziepak 
163d287274dSPawel Dziepak 	static inline		CoreEntry*		GetCore(int32 cpu);
164d287274dSPawel Dziepak 
165e1e7235cSPawel Dziepak private:
166e1e7235cSPawel Dziepak 	static				void			_UnassignThread(Thread* thread,
167e1e7235cSPawel Dziepak 											void* core);
168e1e7235cSPawel Dziepak 
169d287274dSPawel Dziepak 						int32			fCoreID;
170d287274dSPawel Dziepak 						PackageEntry*	fPackage;
171d287274dSPawel Dziepak 
172d287274dSPawel Dziepak 						int32			fCPUCount;
173ef8e55a1SPawel Dziepak 						int32			fCPUIdleCount;
174d287274dSPawel Dziepak 						CPUPriorityHeap	fCPUHeap;
175d287274dSPawel Dziepak 						spinlock		fCPULock;
176d287274dSPawel Dziepak 
177d287274dSPawel Dziepak 						int32			fStarvationCounter;
178d287274dSPawel Dziepak 						DoublyLinkedList<ThreadData>	fThreadList;
179d287274dSPawel Dziepak 
180d287274dSPawel Dziepak 						int32			fThreadCount;
181d287274dSPawel Dziepak 						ThreadRunQueue	fRunQueue;
182d287274dSPawel Dziepak 						spinlock		fQueueLock;
183d287274dSPawel Dziepak 
184d287274dSPawel Dziepak 						bigtime_t		fActiveTime;
185e1e7235cSPawel Dziepak 	mutable				seqlock			fActiveTimeLock;
186d287274dSPawel Dziepak 
187d287274dSPawel Dziepak 						int32			fLoad;
188d287274dSPawel Dziepak 						bool			fHighLoad;
189e1e7235cSPawel Dziepak 
190e1e7235cSPawel Dziepak 						friend class DebugDumper;
191d287274dSPawel Dziepak } CACHE_LINE_ALIGN;
192d287274dSPawel Dziepak 
193e1e7235cSPawel Dziepak 
194d287274dSPawel Dziepak class CoreLoadHeap : public MinMaxHeap<CoreEntry, int32> {
195d287274dSPawel Dziepak public:
196d287274dSPawel Dziepak 										CoreLoadHeap() { }
197d287274dSPawel Dziepak 										CoreLoadHeap(int32 coreCount);
198d287274dSPawel Dziepak 
199d287274dSPawel Dziepak 						void			Dump();
200d287274dSPawel Dziepak };
201d287274dSPawel Dziepak 
202d287274dSPawel Dziepak // gPackageEntries are used to decide which core should be woken up from the
203d287274dSPawel Dziepak // idle state. When aiming for performance we should use as many packages as
204d287274dSPawel Dziepak // possible with as little cores active in each package as possible (so that the
205d287274dSPawel Dziepak // package can enter any boost mode if it has one and the active core have more
206d287274dSPawel Dziepak // of the shared cache for themselves. If power saving is the main priority we
207d287274dSPawel Dziepak // should keep active cores on as little packages as possible (so that other
208d287274dSPawel Dziepak // packages can go to the deep state of sleep). The heap stores only packages
209d287274dSPawel Dziepak // with at least one core active and one core idle. The packages with all cores
210d287274dSPawel Dziepak // idle are stored in gPackageIdleList (in LIFO manner).
21160e198f2SPawel Dziepak class PackageEntry : public DoublyLinkedListLinkImpl<PackageEntry> {
21260e198f2SPawel Dziepak public:
213d287274dSPawel Dziepak 											PackageEntry();
214d287274dSPawel Dziepak 
21560e198f2SPawel Dziepak 						void				Init(int32 id);
21660e198f2SPawel Dziepak 
21760e198f2SPawel Dziepak 	inline				void				CoreGoesIdle(CoreEntry* core);
21860e198f2SPawel Dziepak 	inline				void				CoreWakesUp(CoreEntry* core);
21960e198f2SPawel Dziepak 
22060e198f2SPawel Dziepak 	inline				CoreEntry*			GetIdleCore() const;
22160e198f2SPawel Dziepak 
22260e198f2SPawel Dziepak 						void				AddIdleCore(CoreEntry* core);
22360e198f2SPawel Dziepak 						void				RemoveIdleCore(CoreEntry* core);
22460e198f2SPawel Dziepak 
22560e198f2SPawel Dziepak 	static inline		PackageEntry*		GetMostIdlePackage();
22660e198f2SPawel Dziepak 	static inline		PackageEntry*		GetLeastIdlePackage();
22760e198f2SPawel Dziepak 
22860e198f2SPawel Dziepak private:
229d287274dSPawel Dziepak 						int32				fPackageID;
230d287274dSPawel Dziepak 
231d287274dSPawel Dziepak 						DoublyLinkedList<CoreEntry>	fIdleCores;
232d287274dSPawel Dziepak 						int32				fIdleCoreCount;
233d287274dSPawel Dziepak 						int32				fCoreCount;
234d287274dSPawel Dziepak 						rw_spinlock			fCoreLock;
23560e198f2SPawel Dziepak 
23660e198f2SPawel Dziepak 						friend class DebugDumper;
237d287274dSPawel Dziepak } CACHE_LINE_ALIGN;
238d287274dSPawel Dziepak typedef DoublyLinkedList<PackageEntry> IdlePackageList;
239d287274dSPawel Dziepak 
240d287274dSPawel Dziepak extern CPUEntry* gCPUEntries;
241d287274dSPawel Dziepak 
242d287274dSPawel Dziepak extern CoreEntry* gCoreEntries;
243d287274dSPawel Dziepak extern CoreLoadHeap gCoreLoadHeap;
244d287274dSPawel Dziepak extern CoreLoadHeap gCoreHighLoadHeap;
245d287274dSPawel Dziepak extern rw_spinlock gCoreHeapsLock;
246d287274dSPawel Dziepak extern int32 gCoreCount;
247d287274dSPawel Dziepak 
248d287274dSPawel Dziepak extern PackageEntry* gPackageEntries;
249d287274dSPawel Dziepak extern IdlePackageList gIdlePackageList;
250d287274dSPawel Dziepak extern rw_spinlock gIdlePackageLock;
251d287274dSPawel Dziepak extern int32 gPackageCount;
252d287274dSPawel Dziepak 
253d287274dSPawel Dziepak 
254e1e7235cSPawel Dziepak inline void
255a08b40d4SPawel Dziepak CPUEntry::EnterScheduler()
256a08b40d4SPawel Dziepak {
25796dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
258a08b40d4SPawel Dziepak 	acquire_read_spinlock(&fSchedulerModeLock);
259a08b40d4SPawel Dziepak }
260a08b40d4SPawel Dziepak 
261a08b40d4SPawel Dziepak 
262a08b40d4SPawel Dziepak inline void
263a08b40d4SPawel Dziepak CPUEntry::ExitScheduler()
264a08b40d4SPawel Dziepak {
26596dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
266a08b40d4SPawel Dziepak 	release_read_spinlock(&fSchedulerModeLock);
267a08b40d4SPawel Dziepak }
268a08b40d4SPawel Dziepak 
269a08b40d4SPawel Dziepak 
270a08b40d4SPawel Dziepak inline void
271a08b40d4SPawel Dziepak CPUEntry::LockScheduler()
272a08b40d4SPawel Dziepak {
27396dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
274a08b40d4SPawel Dziepak 	acquire_write_spinlock(&fSchedulerModeLock);
275a08b40d4SPawel Dziepak }
276a08b40d4SPawel Dziepak 
277a08b40d4SPawel Dziepak 
278a08b40d4SPawel Dziepak inline void
279a08b40d4SPawel Dziepak CPUEntry::UnlockScheduler()
280a08b40d4SPawel Dziepak {
28196dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
282a08b40d4SPawel Dziepak 	release_write_spinlock(&fSchedulerModeLock);
283a08b40d4SPawel Dziepak }
284a08b40d4SPawel Dziepak 
285a08b40d4SPawel Dziepak 
28626592750SPawel Dziepak inline void
28726592750SPawel Dziepak CPUEntry::LockRunQueue()
28826592750SPawel Dziepak {
28926592750SPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
29026592750SPawel Dziepak 	acquire_spinlock(&fQueueLock);
29126592750SPawel Dziepak }
29226592750SPawel Dziepak 
29326592750SPawel Dziepak 
29426592750SPawel Dziepak inline void
29526592750SPawel Dziepak CPUEntry::UnlockRunQueue()
29626592750SPawel Dziepak {
29726592750SPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
29826592750SPawel Dziepak 	release_spinlock(&fQueueLock);
29926592750SPawel Dziepak }
30026592750SPawel Dziepak 
30126592750SPawel Dziepak 
302a08b40d4SPawel Dziepak /* static */ inline CPUEntry*
303a08b40d4SPawel Dziepak CPUEntry::GetCPU(int32 cpu)
304a08b40d4SPawel Dziepak {
30596dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
306a08b40d4SPawel Dziepak 	return &gCPUEntries[cpu];
307a08b40d4SPawel Dziepak }
308a08b40d4SPawel Dziepak 
309a08b40d4SPawel Dziepak 
310a08b40d4SPawel Dziepak inline void
311e1e7235cSPawel Dziepak CoreEntry::LockCPUHeap()
312e1e7235cSPawel Dziepak {
31396dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
314e1e7235cSPawel Dziepak 	acquire_spinlock(&fCPULock);
315e1e7235cSPawel Dziepak }
316e1e7235cSPawel Dziepak 
317e1e7235cSPawel Dziepak 
318e1e7235cSPawel Dziepak inline void
319e1e7235cSPawel Dziepak CoreEntry::UnlockCPUHeap()
320e1e7235cSPawel Dziepak {
32196dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
322e1e7235cSPawel Dziepak 	release_spinlock(&fCPULock);
323e1e7235cSPawel Dziepak }
324e1e7235cSPawel Dziepak 
325e1e7235cSPawel Dziepak 
326e1e7235cSPawel Dziepak inline CPUPriorityHeap*
327e1e7235cSPawel Dziepak CoreEntry::CPUHeap()
328e1e7235cSPawel Dziepak {
32996dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
330e1e7235cSPawel Dziepak 	return &fCPUHeap;
331e1e7235cSPawel Dziepak }
332e1e7235cSPawel Dziepak 
333e1e7235cSPawel Dziepak 
334e1e7235cSPawel Dziepak inline void
335e1e7235cSPawel Dziepak CoreEntry::LockRunQueue()
336e1e7235cSPawel Dziepak {
33796dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
338e1e7235cSPawel Dziepak 	acquire_spinlock(&fQueueLock);
339e1e7235cSPawel Dziepak }
340e1e7235cSPawel Dziepak 
341e1e7235cSPawel Dziepak 
342e1e7235cSPawel Dziepak inline void
343e1e7235cSPawel Dziepak CoreEntry::UnlockRunQueue()
344e1e7235cSPawel Dziepak {
34596dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
346e1e7235cSPawel Dziepak 	release_spinlock(&fQueueLock);
347e1e7235cSPawel Dziepak }
348e1e7235cSPawel Dziepak 
349e1e7235cSPawel Dziepak 
350e1e7235cSPawel Dziepak inline void
351e1e7235cSPawel Dziepak CoreEntry::IncreaseActiveTime(bigtime_t activeTime)
352e1e7235cSPawel Dziepak {
35396dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
354e1e7235cSPawel Dziepak 	WriteSequentialLocker _(fActiveTimeLock);
355e1e7235cSPawel Dziepak 	fActiveTime += activeTime;
356e1e7235cSPawel Dziepak }
357e1e7235cSPawel Dziepak 
358e1e7235cSPawel Dziepak 
359*cb66faefSPawel Dziepak inline ThreadData*
360*cb66faefSPawel Dziepak CoreEntry::PeekThread() const
361*cb66faefSPawel Dziepak {
362*cb66faefSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
363*cb66faefSPawel Dziepak 	return fRunQueue.PeekMaximum();
364*cb66faefSPawel Dziepak }
365*cb66faefSPawel Dziepak 
366*cb66faefSPawel Dziepak 
367e1e7235cSPawel Dziepak inline bigtime_t
368e1e7235cSPawel Dziepak CoreEntry::GetActiveTime() const
369e1e7235cSPawel Dziepak {
37096dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
371e1e7235cSPawel Dziepak 
37296dcc73bSPawel Dziepak 	bigtime_t activeTime;
373e1e7235cSPawel Dziepak 	uint32 count;
374e1e7235cSPawel Dziepak 	do {
375e1e7235cSPawel Dziepak 		count = acquire_read_seqlock(&fActiveTimeLock);
376e1e7235cSPawel Dziepak 		activeTime = fActiveTime;
377e1e7235cSPawel Dziepak 	} while (!release_read_seqlock(&fActiveTimeLock, count));
378e1e7235cSPawel Dziepak 	return activeTime;
379e1e7235cSPawel Dziepak }
380e1e7235cSPawel Dziepak 
381e1e7235cSPawel Dziepak 
382d287274dSPawel Dziepak inline int32
383d287274dSPawel Dziepak CoreEntry::GetLoad() const
384d287274dSPawel Dziepak {
38596dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
38696dcc73bSPawel Dziepak 
3878aa1539bSPawel Dziepak 	ASSERT(fCPUCount > 0);
388d287274dSPawel Dziepak 	return fLoad / fCPUCount;
389d287274dSPawel Dziepak }
390d287274dSPawel Dziepak 
391d287274dSPawel Dziepak 
392e1e7235cSPawel Dziepak inline int32
393e1e7235cSPawel Dziepak CoreEntry::StarvationCounter() const
394e1e7235cSPawel Dziepak {
39596dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
396e1e7235cSPawel Dziepak 	return fStarvationCounter;
397e1e7235cSPawel Dziepak }
398e1e7235cSPawel Dziepak 
399e1e7235cSPawel Dziepak 
400*cb66faefSPawel Dziepak /* PackageEntry::CoreGoesIdle and PackageEntry::CoreWakesUp have to be defined
401*cb66faefSPawel Dziepak    before CoreEntry::CPUGoesIdle and CoreEntry::CPUWakesUp. If they weren't
402*cb66faefSPawel Dziepak    GCC2 wouldn't inline them as, apparently, it doesn't do enough optimization
403*cb66faefSPawel Dziepak    passes.
404*cb66faefSPawel Dziepak */
405*cb66faefSPawel Dziepak inline void
406*cb66faefSPawel Dziepak PackageEntry::CoreGoesIdle(CoreEntry* core)
407*cb66faefSPawel Dziepak {
408*cb66faefSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
409*cb66faefSPawel Dziepak 
410*cb66faefSPawel Dziepak 	WriteSpinLocker _(fCoreLock);
411*cb66faefSPawel Dziepak 
412*cb66faefSPawel Dziepak 	ASSERT(fIdleCoreCount >= 0);
413*cb66faefSPawel Dziepak 	ASSERT(fIdleCoreCount < fCoreCount);
414*cb66faefSPawel Dziepak 
415*cb66faefSPawel Dziepak 	fIdleCoreCount++;
416*cb66faefSPawel Dziepak 	fIdleCores.Add(core);
417*cb66faefSPawel Dziepak 
418*cb66faefSPawel Dziepak 	if (fIdleCoreCount == fCoreCount) {
419*cb66faefSPawel Dziepak 		// package goes idle
420*cb66faefSPawel Dziepak 		WriteSpinLocker _(gIdlePackageLock);
421*cb66faefSPawel Dziepak 		gIdlePackageList.Add(this);
422*cb66faefSPawel Dziepak 	}
423*cb66faefSPawel Dziepak }
424*cb66faefSPawel Dziepak 
425*cb66faefSPawel Dziepak 
426*cb66faefSPawel Dziepak inline void
427*cb66faefSPawel Dziepak PackageEntry::CoreWakesUp(CoreEntry* core)
428*cb66faefSPawel Dziepak {
429*cb66faefSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
430*cb66faefSPawel Dziepak 
431*cb66faefSPawel Dziepak 	WriteSpinLocker _(fCoreLock);
432*cb66faefSPawel Dziepak 
433*cb66faefSPawel Dziepak 	ASSERT(fIdleCoreCount > 0);
434*cb66faefSPawel Dziepak 	ASSERT(fIdleCoreCount <= fCoreCount);
435*cb66faefSPawel Dziepak 
436*cb66faefSPawel Dziepak 	fIdleCoreCount--;
437*cb66faefSPawel Dziepak 	fIdleCores.Remove(core);
438*cb66faefSPawel Dziepak 
439*cb66faefSPawel Dziepak 	if (fIdleCoreCount + 1 == fCoreCount) {
440*cb66faefSPawel Dziepak 		// package wakes up
441*cb66faefSPawel Dziepak 		WriteSpinLocker _(gIdlePackageLock);
442*cb66faefSPawel Dziepak 		gIdlePackageList.Remove(this);
443*cb66faefSPawel Dziepak 	}
444*cb66faefSPawel Dziepak }
445*cb66faefSPawel Dziepak 
446*cb66faefSPawel Dziepak 
447*cb66faefSPawel Dziepak inline void
448*cb66faefSPawel Dziepak CoreEntry::CPUGoesIdle(CPUEntry* /* cpu */)
449*cb66faefSPawel Dziepak {
450*cb66faefSPawel Dziepak 	ASSERT(fCPUIdleCount < fCPUCount);
451*cb66faefSPawel Dziepak 
452*cb66faefSPawel Dziepak 	if (++fCPUIdleCount == fCPUCount)
453*cb66faefSPawel Dziepak 		fPackage->CoreGoesIdle(this);
454*cb66faefSPawel Dziepak }
455*cb66faefSPawel Dziepak 
456*cb66faefSPawel Dziepak 
457*cb66faefSPawel Dziepak inline void
458*cb66faefSPawel Dziepak CoreEntry::CPUWakesUp(CPUEntry* /* cpu */)
459*cb66faefSPawel Dziepak {
460*cb66faefSPawel Dziepak 	ASSERT(fCPUIdleCount > 0);
461*cb66faefSPawel Dziepak 
462*cb66faefSPawel Dziepak 	if (fCPUIdleCount-- == fCPUCount)
463*cb66faefSPawel Dziepak 		fPackage->CoreWakesUp(this);
464*cb66faefSPawel Dziepak }
465*cb66faefSPawel Dziepak 
466*cb66faefSPawel Dziepak 
467d287274dSPawel Dziepak /* static */ inline CoreEntry*
468d287274dSPawel Dziepak CoreEntry::GetCore(int32 cpu)
469d287274dSPawel Dziepak {
47096dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
471a08b40d4SPawel Dziepak 	return gCPUEntries[cpu].Core();
472d287274dSPawel Dziepak }
473d287274dSPawel Dziepak 
474d287274dSPawel Dziepak 
47560e198f2SPawel Dziepak inline CoreEntry*
47660e198f2SPawel Dziepak PackageEntry::GetIdleCore() const
47760e198f2SPawel Dziepak {
47896dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
47960e198f2SPawel Dziepak 	return fIdleCores.Last();
48060e198f2SPawel Dziepak }
48160e198f2SPawel Dziepak 
48260e198f2SPawel Dziepak 
48360e198f2SPawel Dziepak /* static */ inline PackageEntry*
48460e198f2SPawel Dziepak PackageEntry::GetMostIdlePackage()
48560e198f2SPawel Dziepak {
48696dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
48796dcc73bSPawel Dziepak 
48860e198f2SPawel Dziepak 	PackageEntry* current = &gPackageEntries[0];
48960e198f2SPawel Dziepak 	for (int32 i = 1; i < gPackageCount; i++) {
49060e198f2SPawel Dziepak 		if (gPackageEntries[i].fIdleCoreCount > current->fIdleCoreCount)
49160e198f2SPawel Dziepak 			current = &gPackageEntries[i];
49260e198f2SPawel Dziepak 	}
49360e198f2SPawel Dziepak 
49460e198f2SPawel Dziepak 	if (current->fIdleCoreCount == 0)
49560e198f2SPawel Dziepak 		return NULL;
49660e198f2SPawel Dziepak 
49760e198f2SPawel Dziepak 	return current;
49860e198f2SPawel Dziepak }
49960e198f2SPawel Dziepak 
50060e198f2SPawel Dziepak 
50160e198f2SPawel Dziepak /* static */ inline PackageEntry*
50260e198f2SPawel Dziepak PackageEntry::GetLeastIdlePackage()
50360e198f2SPawel Dziepak {
50496dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
50596dcc73bSPawel Dziepak 
50660e198f2SPawel Dziepak 	PackageEntry* package = NULL;
50760e198f2SPawel Dziepak 
50860e198f2SPawel Dziepak 	for (int32 i = 0; i < gPackageCount; i++) {
50960e198f2SPawel Dziepak 		PackageEntry* current = &gPackageEntries[i];
51060e198f2SPawel Dziepak 
51160e198f2SPawel Dziepak 		int32 currentIdleCoreCount = current->fIdleCoreCount;
51260e198f2SPawel Dziepak 		if (currentIdleCoreCount != 0 && (package == NULL
51360e198f2SPawel Dziepak 				|| currentIdleCoreCount < package->fIdleCoreCount)) {
51460e198f2SPawel Dziepak 			package = current;
51560e198f2SPawel Dziepak 		}
51660e198f2SPawel Dziepak 	}
51760e198f2SPawel Dziepak 
51860e198f2SPawel Dziepak 	return package;
51960e198f2SPawel Dziepak }
52060e198f2SPawel Dziepak 
52160e198f2SPawel Dziepak 
522d287274dSPawel Dziepak }	// namespace Scheduler
523d287274dSPawel Dziepak 
524d287274dSPawel Dziepak 
525d287274dSPawel Dziepak #endif	// KERNEL_SCHEDULER_CPU_H
526d287274dSPawel Dziepak 
527