kernel: Introduce scheduler modes of operation
This commit is contained in:
@@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user