kernel: Introduce scheduler modes of operation

This commit is contained in:
Pawel Dziepak
2013-10-21 02:17:00 +02:00
parent 4b446279e6
commit cd8d4e39fd
3 changed files with 83 additions and 2 deletions
+11
View File
@@ -17,6 +17,13 @@ struct scheduling_analysis;
struct SchedulerListener; struct SchedulerListener;
typedef enum scheduler_mode {
SCHEDULER_MODE_PERFORMANCE,
SCHEDULER_MODE_POWER_SAVING,
// ...
SCHEDULER_MODE_COUNT
} scheduler_mode;
struct scheduler_ops { struct scheduler_ops {
/*! Enqueues the thread in the ready-to-run queue. /*! Enqueues the thread in the ready-to-run queue.
The caller must hold the scheduler lock (with disabled interrupts). The caller must hold the scheduler lock (with disabled interrupts).
@@ -68,6 +75,10 @@ struct scheduler_ops {
*/ */
void (*start)(void); void (*start)(void);
/*! Sets scheduler operation mode.
*/
status_t (*set_operation_mode)(scheduler_mode mode);
/*! Dumps scheduler specific thread information. /*! Dumps scheduler specific thread information.
*/ */
void (*dump_thread_data)(Thread* thread); void (*dump_thread_data)(Thread* thread);
@@ -49,6 +49,11 @@ const bigtime_t kMinThreadQuantum = 3000;
const bigtime_t kMaxThreadQuantum = 10000; const bigtime_t kMaxThreadQuantum = 10000;
static scheduler_mode sSchedulerMode;
static int32 (*sChooseCore)(void);
// Heaps in sCPUPriorityHeaps are used for load balancing on a core the logical // Heaps in sCPUPriorityHeaps are used for load balancing on a core the logical
// processors in the heap belong to. Since there are no cache affinity issues // processors in the heap belong to. Since there are no cache affinity issues
// at this level and the run queue is shared among all logical processors on // at this level and the run queue is shared among all logical processors on
@@ -523,8 +528,8 @@ affine_update_priority_heaps(int32 cpu, int32 priority)
} }
static inline int32 static int32
affine_choose_core(void) affine_choose_core_performance(void)
{ {
CoreEntry* entry; CoreEntry* entry;
@@ -546,6 +551,37 @@ affine_choose_core(void)
} }
static int32
affine_choose_core_power_saving(void)
{
CoreEntry* entry;
// TODO: small tasks packing
if (sPackageUsageHeap->PeekMinimum() != NULL) {
// wake new core
PackageEntry* package = sPackageUsageHeap->PeekMinimum();
entry = package->fIdleCores.Last();
} else if (sIdlePackageList->Last() != NULL) {
// wake new package
PackageEntry* package = sIdlePackageList->Last();
entry = package->fIdleCores.Last();
} else {
// no idle cores, use least occupied core
entry = sCorePriorityHeap->PeekRoot();
}
ASSERT(entry != NULL);
return entry->fCoreID;
}
static inline int32
affine_choose_core(void)
{
return sChooseCore();
}
static inline int32 static inline int32
affine_choose_cpu(int32 core) affine_choose_cpu(int32 core)
{ {
@@ -1092,6 +1128,37 @@ affine_start(void)
} }
static status_t
affine_set_operation_mode(scheduler_mode mode)
{
if (mode != SCHEDULER_MODE_PERFORMANCE
&& mode != SCHEDULER_MODE_POWER_SAVING) {
return B_BAD_VALUE;
}
#ifdef TRACE_SCHEDULER
const char* modeNames = { "performance", "power saving" };
#endif
TRACE("switching scheduler to %s mode\n", modeNames[mode]);
sSchedulerMode = mode;
switch (mode) {
case SCHEDULER_MODE_PERFORMANCE:
sChooseCore = affine_choose_core_performance;
break;
case SCHEDULER_MODE_POWER_SAVING:
sChooseCore = affine_choose_core_power_saving;
break;
default:
break;
}
return B_OK;
}
static scheduler_ops kAffineOps = { static scheduler_ops kAffineOps = {
affine_enqueue_in_run_queue, affine_enqueue_in_run_queue,
affine_reschedule, affine_reschedule,
@@ -1101,6 +1168,7 @@ static scheduler_ops kAffineOps = {
affine_on_thread_init, affine_on_thread_init,
affine_on_thread_destroy, affine_on_thread_destroy,
affine_start, affine_start,
affine_set_operation_mode,
affine_dump_thread_data affine_dump_thread_data
}; };
@@ -1278,6 +1346,7 @@ scheduler_affine_init()
return result; return result;
} }
affine_set_operation_mode(SCHEDULER_MODE_PERFORMANCE);
gScheduler = &kAffineOps; gScheduler = &kAffineOps;
add_debugger_command_etc("run_queue", &dump_run_queue, add_debugger_command_etc("run_queue", &dump_run_queue,
@@ -720,6 +720,7 @@ static scheduler_ops kSimpleOps = {
simple_on_thread_init, simple_on_thread_init,
simple_on_thread_destroy, simple_on_thread_destroy,
simple_start, simple_start,
NULL,
simple_dump_thread_data simple_dump_thread_data
}; };