xref: /haiku/src/system/kernel/scheduler/scheduler_cpu.h (revision ef8e55a1d09185c714afac7b5d00f28064af3428)
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>
13d287274dSPawel Dziepak #include <util/MinMaxHeap.h>
14*ef8e55a1SPawel Dziepak #include <util/Heap.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 
45*ef8e55a1SPawel 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 
63a08b40d4SPawel Dziepak 						void			PushFront(ThreadData* thread,
64a08b40d4SPawel Dziepak 											int32 priority);
65a08b40d4SPawel Dziepak 						void			PushBack(ThreadData* thread,
66a08b40d4SPawel Dziepak 											int32 priority);
67a08b40d4SPawel Dziepak 						void			Remove(ThreadData* thread);
68a08b40d4SPawel Dziepak 	inline				ThreadData*		PeekThread() const;
69a08b40d4SPawel Dziepak 						ThreadData*		PeekIdleThread() const;
70a08b40d4SPawel Dziepak 
71d287274dSPawel Dziepak 						void			UpdatePriority(int32 priority);
72d287274dSPawel Dziepak 
73a08b40d4SPawel Dziepak 	inline				int32			GetLoad() const	{ return fLoad; }
74d287274dSPawel Dziepak 						void			ComputeLoad();
75d287274dSPawel Dziepak 
76d287274dSPawel Dziepak 						ThreadData*		ChooseNextThread(ThreadData* oldThread,
77d287274dSPawel Dziepak 											bool putAtBack);
78d287274dSPawel Dziepak 
79d287274dSPawel Dziepak 						void			TrackActivity(ThreadData* oldThreadData,
80d287274dSPawel Dziepak 											ThreadData* nextThreadData);
81d287274dSPawel Dziepak 
82a08b40d4SPawel Dziepak 	static inline		CPUEntry*		GetCPU(int32 cpu);
83a08b40d4SPawel Dziepak 
84a08b40d4SPawel Dziepak private:
85a08b40d4SPawel Dziepak 	inline				void			_RequestPerformanceLevel(
86a08b40d4SPawel Dziepak 											ThreadData* threadData);
87a08b40d4SPawel Dziepak 
88d287274dSPawel Dziepak 						int32			fCPUNumber;
89d287274dSPawel Dziepak 						CoreEntry*		fCore;
90d287274dSPawel Dziepak 
91d287274dSPawel Dziepak 						rw_spinlock 	fSchedulerModeLock;
92d287274dSPawel Dziepak 
93d287274dSPawel Dziepak 						ThreadRunQueue	fRunQueue;
94d287274dSPawel Dziepak 
95d287274dSPawel Dziepak 						int32			fLoad;
96d287274dSPawel Dziepak 
97d287274dSPawel Dziepak 						bigtime_t		fMeasureActiveTime;
98d287274dSPawel Dziepak 						bigtime_t		fMeasureTime;
99d287274dSPawel Dziepak 
100a08b40d4SPawel Dziepak 						friend class DebugDumper;
101d287274dSPawel Dziepak } CACHE_LINE_ALIGN;
102d287274dSPawel Dziepak 
103*ef8e55a1SPawel Dziepak class CPUPriorityHeap : public Heap<CPUEntry, int32> {
104d287274dSPawel Dziepak public:
105d287274dSPawel Dziepak 										CPUPriorityHeap() { }
106d287274dSPawel Dziepak 										CPUPriorityHeap(int32 cpuCount);
107d287274dSPawel Dziepak 
108d287274dSPawel Dziepak 						void			Dump();
109d287274dSPawel Dziepak };
110d287274dSPawel Dziepak 
111e1e7235cSPawel Dziepak class CoreEntry : public MinMaxHeapLinkImpl<CoreEntry, int32>,
112e1e7235cSPawel Dziepak 	public DoublyLinkedListLinkImpl<CoreEntry> {
113e1e7235cSPawel Dziepak public:
114d287274dSPawel Dziepak 										CoreEntry();
115d287274dSPawel Dziepak 
116e1e7235cSPawel Dziepak 						void			Init(int32 id, PackageEntry* package);
117e1e7235cSPawel Dziepak 
118e1e7235cSPawel Dziepak 	inline				int32			ID() const	{ return fCoreID; }
119e1e7235cSPawel Dziepak 	inline				PackageEntry*	Package() const	{ return fPackage; }
120e1e7235cSPawel Dziepak 	inline				int32			CPUCount() const
121e1e7235cSPawel Dziepak 											{ return fCPUCount; }
122e1e7235cSPawel Dziepak 
123e1e7235cSPawel Dziepak 	inline				void			LockCPUHeap();
124e1e7235cSPawel Dziepak 	inline				void			UnlockCPUHeap();
125e1e7235cSPawel Dziepak 
126e1e7235cSPawel Dziepak 	inline				CPUPriorityHeap*	CPUHeap();
127e1e7235cSPawel Dziepak 
128e1e7235cSPawel Dziepak 	inline				int32			ThreadCount() const
129e1e7235cSPawel Dziepak 											{ return fThreadCount; }
130e1e7235cSPawel Dziepak 
131e1e7235cSPawel Dziepak 	inline				void			LockRunQueue();
132e1e7235cSPawel Dziepak 	inline				void			UnlockRunQueue();
133e1e7235cSPawel Dziepak 
134e1e7235cSPawel Dziepak 						void			PushFront(ThreadData* thread,
135e1e7235cSPawel Dziepak 											int32 priority);
136e1e7235cSPawel Dziepak 						void			PushBack(ThreadData* thread,
137e1e7235cSPawel Dziepak 											int32 priority);
138b24ea642SPawel Dziepak 						void			Remove(ThreadData* thread);
139e1e7235cSPawel Dziepak 	inline				ThreadData*		PeekThread() const;
140e1e7235cSPawel Dziepak 
141e1e7235cSPawel Dziepak 	inline				bigtime_t		GetActiveTime() const;
142e1e7235cSPawel Dziepak 	inline				void			IncreaseActiveTime(
143e1e7235cSPawel Dziepak 											bigtime_t activeTime);
144e1e7235cSPawel Dziepak 
145d287274dSPawel Dziepak 	inline				int32			GetLoad() const;
146e1e7235cSPawel Dziepak 						void			UpdateLoad(int32 delta);
147e1e7235cSPawel Dziepak 
148e1e7235cSPawel Dziepak 	inline				int32			StarvationCounter() const;
149e1e7235cSPawel Dziepak 
150*ef8e55a1SPawel Dziepak 	inline				void			CPUGoesIdle(CPUEntry* cpu);
151*ef8e55a1SPawel Dziepak 	inline				void			CPUWakesUp(CPUEntry* cpu);
152*ef8e55a1SPawel Dziepak 
153e1e7235cSPawel Dziepak 						void			AddCPU(CPUEntry* cpu);
154e1e7235cSPawel Dziepak 						void			RemoveCPU(CPUEntry* cpu,
155e1e7235cSPawel Dziepak 											ThreadProcessing&
156e1e7235cSPawel Dziepak 												threadPostProcessing);
157d287274dSPawel Dziepak 
158d287274dSPawel Dziepak 	static inline		CoreEntry*		GetCore(int32 cpu);
159d287274dSPawel Dziepak 
160e1e7235cSPawel Dziepak private:
161e1e7235cSPawel Dziepak 	static				void			_UnassignThread(Thread* thread,
162e1e7235cSPawel Dziepak 											void* core);
163e1e7235cSPawel Dziepak 
164d287274dSPawel Dziepak 						int32			fCoreID;
165d287274dSPawel Dziepak 						PackageEntry*	fPackage;
166d287274dSPawel Dziepak 
167d287274dSPawel Dziepak 						int32			fCPUCount;
168*ef8e55a1SPawel Dziepak 						int32			fCPUIdleCount;
169d287274dSPawel Dziepak 						CPUPriorityHeap	fCPUHeap;
170d287274dSPawel Dziepak 						spinlock		fCPULock;
171d287274dSPawel Dziepak 
172d287274dSPawel Dziepak 						int32			fStarvationCounter;
173d287274dSPawel Dziepak 						DoublyLinkedList<ThreadData>	fThreadList;
174d287274dSPawel Dziepak 
175d287274dSPawel Dziepak 						int32			fThreadCount;
176d287274dSPawel Dziepak 						ThreadRunQueue	fRunQueue;
177d287274dSPawel Dziepak 						spinlock		fQueueLock;
178d287274dSPawel Dziepak 
179d287274dSPawel Dziepak 						bigtime_t		fActiveTime;
180e1e7235cSPawel Dziepak 	mutable				seqlock			fActiveTimeLock;
181d287274dSPawel Dziepak 
182d287274dSPawel Dziepak 						int32			fLoad;
183d287274dSPawel Dziepak 						bool			fHighLoad;
184e1e7235cSPawel Dziepak 
185e1e7235cSPawel Dziepak 						friend class DebugDumper;
186d287274dSPawel Dziepak } CACHE_LINE_ALIGN;
187d287274dSPawel Dziepak 
188e1e7235cSPawel Dziepak class CoreRunQueueLocking {
189e1e7235cSPawel Dziepak public:
190e1e7235cSPawel Dziepak 	inline bool Lock(CoreEntry* core)
191e1e7235cSPawel Dziepak 	{
192e1e7235cSPawel Dziepak 		core->LockRunQueue();
193e1e7235cSPawel Dziepak 		return true;
194e1e7235cSPawel Dziepak 	}
195e1e7235cSPawel Dziepak 
196e1e7235cSPawel Dziepak 	inline void Unlock(CoreEntry* core)
197e1e7235cSPawel Dziepak 	{
198e1e7235cSPawel Dziepak 		core->UnlockRunQueue();
199e1e7235cSPawel Dziepak 	}
200e1e7235cSPawel Dziepak };
201e1e7235cSPawel Dziepak 
202e1e7235cSPawel Dziepak typedef AutoLocker<CoreEntry, CoreRunQueueLocking> CoreRunQueueLocker;
203e1e7235cSPawel Dziepak 
204e1e7235cSPawel Dziepak class CoreCPUHeapLocking {
205e1e7235cSPawel Dziepak public:
206e1e7235cSPawel Dziepak 	inline bool Lock(CoreEntry* core)
207e1e7235cSPawel Dziepak 	{
208e1e7235cSPawel Dziepak 		core->LockCPUHeap();
209e1e7235cSPawel Dziepak 		return true;
210e1e7235cSPawel Dziepak 	}
211e1e7235cSPawel Dziepak 
212e1e7235cSPawel Dziepak 	inline void Unlock(CoreEntry* core)
213e1e7235cSPawel Dziepak 	{
214e1e7235cSPawel Dziepak 		core->UnlockCPUHeap();
215e1e7235cSPawel Dziepak 	}
216e1e7235cSPawel Dziepak };
217e1e7235cSPawel Dziepak 
218e1e7235cSPawel Dziepak typedef AutoLocker<CoreEntry, CoreCPUHeapLocking> CoreCPUHeapLocker;
219e1e7235cSPawel Dziepak 
220d287274dSPawel Dziepak class CoreLoadHeap : public MinMaxHeap<CoreEntry, int32> {
221d287274dSPawel Dziepak public:
222d287274dSPawel Dziepak 										CoreLoadHeap() { }
223d287274dSPawel Dziepak 										CoreLoadHeap(int32 coreCount);
224d287274dSPawel Dziepak 
225d287274dSPawel Dziepak 						void			Dump();
226d287274dSPawel Dziepak };
227d287274dSPawel Dziepak 
228d287274dSPawel Dziepak // gPackageEntries are used to decide which core should be woken up from the
229d287274dSPawel Dziepak // idle state. When aiming for performance we should use as many packages as
230d287274dSPawel Dziepak // possible with as little cores active in each package as possible (so that the
231d287274dSPawel Dziepak // package can enter any boost mode if it has one and the active core have more
232d287274dSPawel Dziepak // of the shared cache for themselves. If power saving is the main priority we
233d287274dSPawel Dziepak // should keep active cores on as little packages as possible (so that other
234d287274dSPawel Dziepak // packages can go to the deep state of sleep). The heap stores only packages
235d287274dSPawel Dziepak // with at least one core active and one core idle. The packages with all cores
236d287274dSPawel Dziepak // idle are stored in gPackageIdleList (in LIFO manner).
23760e198f2SPawel Dziepak class PackageEntry : public DoublyLinkedListLinkImpl<PackageEntry> {
23860e198f2SPawel Dziepak public:
239d287274dSPawel Dziepak 											PackageEntry();
240d287274dSPawel Dziepak 
24160e198f2SPawel Dziepak 						void				Init(int32 id);
24260e198f2SPawel Dziepak 
24360e198f2SPawel Dziepak 	inline				void				CoreGoesIdle(CoreEntry* core);
24460e198f2SPawel Dziepak 	inline				void				CoreWakesUp(CoreEntry* core);
24560e198f2SPawel Dziepak 
24660e198f2SPawel Dziepak 	inline				CoreEntry*			GetIdleCore() const;
24760e198f2SPawel Dziepak 
24860e198f2SPawel Dziepak 						void				AddIdleCore(CoreEntry* core);
24960e198f2SPawel Dziepak 						void				RemoveIdleCore(CoreEntry* core);
25060e198f2SPawel Dziepak 
25160e198f2SPawel Dziepak 	static inline		PackageEntry*		GetMostIdlePackage();
25260e198f2SPawel Dziepak 	static inline		PackageEntry*		GetLeastIdlePackage();
25360e198f2SPawel Dziepak 
25460e198f2SPawel Dziepak private:
255d287274dSPawel Dziepak 						int32				fPackageID;
256d287274dSPawel Dziepak 
257d287274dSPawel Dziepak 						DoublyLinkedList<CoreEntry>	fIdleCores;
258d287274dSPawel Dziepak 						int32				fIdleCoreCount;
259d287274dSPawel Dziepak 						int32				fCoreCount;
260d287274dSPawel Dziepak 						rw_spinlock			fCoreLock;
26160e198f2SPawel Dziepak 
26260e198f2SPawel Dziepak 						friend class DebugDumper;
263d287274dSPawel Dziepak } CACHE_LINE_ALIGN;
264d287274dSPawel Dziepak typedef DoublyLinkedList<PackageEntry> IdlePackageList;
265d287274dSPawel Dziepak 
266d287274dSPawel Dziepak extern CPUEntry* gCPUEntries;
267d287274dSPawel Dziepak 
268d287274dSPawel Dziepak extern CoreEntry* gCoreEntries;
269d287274dSPawel Dziepak extern CoreLoadHeap gCoreLoadHeap;
270d287274dSPawel Dziepak extern CoreLoadHeap gCoreHighLoadHeap;
271d287274dSPawel Dziepak extern rw_spinlock gCoreHeapsLock;
272d287274dSPawel Dziepak extern int32 gCoreCount;
273d287274dSPawel Dziepak 
274d287274dSPawel Dziepak extern PackageEntry* gPackageEntries;
275d287274dSPawel Dziepak extern IdlePackageList gIdlePackageList;
276d287274dSPawel Dziepak extern rw_spinlock gIdlePackageLock;
277d287274dSPawel Dziepak extern int32 gPackageCount;
278d287274dSPawel Dziepak 
279d287274dSPawel Dziepak 
280e1e7235cSPawel Dziepak inline void
281a08b40d4SPawel Dziepak CPUEntry::EnterScheduler()
282a08b40d4SPawel Dziepak {
28396dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
284a08b40d4SPawel Dziepak 	acquire_read_spinlock(&fSchedulerModeLock);
285a08b40d4SPawel Dziepak }
286a08b40d4SPawel Dziepak 
287a08b40d4SPawel Dziepak 
288a08b40d4SPawel Dziepak inline void
289a08b40d4SPawel Dziepak CPUEntry::ExitScheduler()
290a08b40d4SPawel Dziepak {
29196dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
292a08b40d4SPawel Dziepak 	release_read_spinlock(&fSchedulerModeLock);
293a08b40d4SPawel Dziepak }
294a08b40d4SPawel Dziepak 
295a08b40d4SPawel Dziepak 
296a08b40d4SPawel Dziepak inline void
297a08b40d4SPawel Dziepak CPUEntry::LockScheduler()
298a08b40d4SPawel Dziepak {
29996dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
300a08b40d4SPawel Dziepak 	acquire_write_spinlock(&fSchedulerModeLock);
301a08b40d4SPawel Dziepak }
302a08b40d4SPawel Dziepak 
303a08b40d4SPawel Dziepak 
304a08b40d4SPawel Dziepak inline void
305a08b40d4SPawel Dziepak CPUEntry::UnlockScheduler()
306a08b40d4SPawel Dziepak {
30796dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
308a08b40d4SPawel Dziepak 	release_write_spinlock(&fSchedulerModeLock);
309a08b40d4SPawel Dziepak }
310a08b40d4SPawel Dziepak 
311a08b40d4SPawel Dziepak 
312a08b40d4SPawel Dziepak /* static */ inline CPUEntry*
313a08b40d4SPawel Dziepak CPUEntry::GetCPU(int32 cpu)
314a08b40d4SPawel Dziepak {
31596dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
316a08b40d4SPawel Dziepak 	return &gCPUEntries[cpu];
317a08b40d4SPawel Dziepak }
318a08b40d4SPawel Dziepak 
319a08b40d4SPawel Dziepak 
320a08b40d4SPawel Dziepak inline void
321e1e7235cSPawel Dziepak CoreEntry::LockCPUHeap()
322e1e7235cSPawel Dziepak {
32396dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
324e1e7235cSPawel Dziepak 	acquire_spinlock(&fCPULock);
325e1e7235cSPawel Dziepak }
326e1e7235cSPawel Dziepak 
327e1e7235cSPawel Dziepak 
328e1e7235cSPawel Dziepak inline void
329e1e7235cSPawel Dziepak CoreEntry::UnlockCPUHeap()
330e1e7235cSPawel Dziepak {
33196dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
332e1e7235cSPawel Dziepak 	release_spinlock(&fCPULock);
333e1e7235cSPawel Dziepak }
334e1e7235cSPawel Dziepak 
335e1e7235cSPawel Dziepak 
336e1e7235cSPawel Dziepak inline CPUPriorityHeap*
337e1e7235cSPawel Dziepak CoreEntry::CPUHeap()
338e1e7235cSPawel Dziepak {
33996dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
340e1e7235cSPawel Dziepak 	return &fCPUHeap;
341e1e7235cSPawel Dziepak }
342e1e7235cSPawel Dziepak 
343e1e7235cSPawel Dziepak 
344e1e7235cSPawel Dziepak inline void
345e1e7235cSPawel Dziepak CoreEntry::LockRunQueue()
346e1e7235cSPawel Dziepak {
34796dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
348e1e7235cSPawel Dziepak 	acquire_spinlock(&fQueueLock);
349e1e7235cSPawel Dziepak }
350e1e7235cSPawel Dziepak 
351e1e7235cSPawel Dziepak 
352e1e7235cSPawel Dziepak inline void
353e1e7235cSPawel Dziepak CoreEntry::UnlockRunQueue()
354e1e7235cSPawel Dziepak {
35596dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
356e1e7235cSPawel Dziepak 	release_spinlock(&fQueueLock);
357e1e7235cSPawel Dziepak }
358e1e7235cSPawel Dziepak 
359e1e7235cSPawel Dziepak 
360e1e7235cSPawel Dziepak inline void
361e1e7235cSPawel Dziepak CoreEntry::IncreaseActiveTime(bigtime_t activeTime)
362e1e7235cSPawel Dziepak {
36396dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
364e1e7235cSPawel Dziepak 	WriteSequentialLocker _(fActiveTimeLock);
365e1e7235cSPawel Dziepak 	fActiveTime += activeTime;
366e1e7235cSPawel Dziepak }
367e1e7235cSPawel Dziepak 
368e1e7235cSPawel Dziepak 
369e1e7235cSPawel Dziepak inline bigtime_t
370e1e7235cSPawel Dziepak CoreEntry::GetActiveTime() const
371e1e7235cSPawel Dziepak {
37296dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
373e1e7235cSPawel Dziepak 
37496dcc73bSPawel Dziepak 	bigtime_t activeTime;
375e1e7235cSPawel Dziepak 	uint32 count;
376e1e7235cSPawel Dziepak 	do {
377e1e7235cSPawel Dziepak 		count = acquire_read_seqlock(&fActiveTimeLock);
378e1e7235cSPawel Dziepak 		activeTime = fActiveTime;
379e1e7235cSPawel Dziepak 	} while (!release_read_seqlock(&fActiveTimeLock, count));
380e1e7235cSPawel Dziepak 	return activeTime;
381e1e7235cSPawel Dziepak }
382e1e7235cSPawel Dziepak 
383e1e7235cSPawel Dziepak 
384d287274dSPawel Dziepak inline int32
385d287274dSPawel Dziepak CoreEntry::GetLoad() const
386d287274dSPawel Dziepak {
38796dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
38896dcc73bSPawel Dziepak 
389d287274dSPawel Dziepak 	ASSERT(fCPUCount >= 0);
390d287274dSPawel Dziepak 	return fLoad / fCPUCount;
391d287274dSPawel Dziepak }
392d287274dSPawel Dziepak 
393d287274dSPawel Dziepak 
394e1e7235cSPawel Dziepak inline int32
395e1e7235cSPawel Dziepak CoreEntry::StarvationCounter() const
396e1e7235cSPawel Dziepak {
39796dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
398e1e7235cSPawel Dziepak 	return fStarvationCounter;
399e1e7235cSPawel Dziepak }
400e1e7235cSPawel Dziepak 
401e1e7235cSPawel Dziepak 
402d287274dSPawel Dziepak /* static */ inline CoreEntry*
403d287274dSPawel Dziepak CoreEntry::GetCore(int32 cpu)
404d287274dSPawel Dziepak {
40596dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
406a08b40d4SPawel Dziepak 	return gCPUEntries[cpu].Core();
407d287274dSPawel Dziepak }
408d287274dSPawel Dziepak 
409d287274dSPawel Dziepak 
41060e198f2SPawel Dziepak inline CoreEntry*
41160e198f2SPawel Dziepak PackageEntry::GetIdleCore() const
41260e198f2SPawel Dziepak {
41396dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
41460e198f2SPawel Dziepak 	return fIdleCores.Last();
41560e198f2SPawel Dziepak }
41660e198f2SPawel Dziepak 
41760e198f2SPawel Dziepak 
41860e198f2SPawel Dziepak /* static */ inline PackageEntry*
41960e198f2SPawel Dziepak PackageEntry::GetMostIdlePackage()
42060e198f2SPawel Dziepak {
42196dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
42296dcc73bSPawel Dziepak 
42360e198f2SPawel Dziepak 	PackageEntry* current = &gPackageEntries[0];
42460e198f2SPawel Dziepak 	for (int32 i = 1; i < gPackageCount; i++) {
42560e198f2SPawel Dziepak 		if (gPackageEntries[i].fIdleCoreCount > current->fIdleCoreCount)
42660e198f2SPawel Dziepak 			current = &gPackageEntries[i];
42760e198f2SPawel Dziepak 	}
42860e198f2SPawel Dziepak 
42960e198f2SPawel Dziepak 	if (current->fIdleCoreCount == 0)
43060e198f2SPawel Dziepak 		return NULL;
43160e198f2SPawel Dziepak 
43260e198f2SPawel Dziepak 	return current;
43360e198f2SPawel Dziepak }
43460e198f2SPawel Dziepak 
43560e198f2SPawel Dziepak 
43660e198f2SPawel Dziepak /* static */ inline PackageEntry*
43760e198f2SPawel Dziepak PackageEntry::GetLeastIdlePackage()
43860e198f2SPawel Dziepak {
43996dcc73bSPawel Dziepak 	SCHEDULER_ENTER_FUNCTION();
44096dcc73bSPawel Dziepak 
44160e198f2SPawel Dziepak 	PackageEntry* package = NULL;
44260e198f2SPawel Dziepak 
44360e198f2SPawel Dziepak 	for (int32 i = 0; i < gPackageCount; i++) {
44460e198f2SPawel Dziepak 		PackageEntry* current = &gPackageEntries[i];
44560e198f2SPawel Dziepak 
44660e198f2SPawel Dziepak 		int32 currentIdleCoreCount = current->fIdleCoreCount;
44760e198f2SPawel Dziepak 		if (currentIdleCoreCount != 0 && (package == NULL
44860e198f2SPawel Dziepak 				|| currentIdleCoreCount < package->fIdleCoreCount)) {
44960e198f2SPawel Dziepak 			package = current;
45060e198f2SPawel Dziepak 		}
45160e198f2SPawel Dziepak 	}
45260e198f2SPawel Dziepak 
45360e198f2SPawel Dziepak 	return package;
45460e198f2SPawel Dziepak }
45560e198f2SPawel Dziepak 
45660e198f2SPawel Dziepak 
457d287274dSPawel Dziepak }	// namespace Scheduler
458d287274dSPawel Dziepak 
459d287274dSPawel Dziepak 
460d287274dSPawel Dziepak #endif	// KERNEL_SCHEDULER_CPU_H
461d287274dSPawel Dziepak 
462