Commit 4d9f11e5 authored by Christian Dietrich's avatar Christian Dietrich

os/scheduler: make schedule inlinable again

Inlining the scheduler reveals a high potential for specialization and
and SDC reduction. In the implementation of the zedboard benchmark, we
dropped the inlinability support. This is now possible again. With
inline-scheduler+specialization the scheduler is paritally instansiated
whereever possible.

Test-Config: --arch i386 --encoded=no --inline-scheduler=yes --specialize=yes
Test-Config: --arch i386 --encoded=no --inline-scheduler=yes --specialize=no
Test-Config: --arch i386 --encoded=no --inline-scheduler=no --specialize=yes
Test-Config: --arch i386 --encoded=no --inline-scheduler=no --specialize=no
Test-Config: --arch i386 --encoded=yes --inline-scheduler=yes --specialize=yes
Test-Config: --arch i386 --encoded=yes --inline-scheduler=yes --specialize=no
Test-Config: --arch i386 --encoded=yes --inline-scheduler=no --specialize=yes
Test-Config: --arch i386 --encoded=yes --inline-scheduler=no --specialize=no

Change-Id: I2749078a3cc4ebeeb19bde14eb769b5781ac409f
parent 5b4cd7d8
if(BUILD_ARM)
config_valid(VALID --equal --arch ARM --inline-scheduler=no)
if(VALID)
DOSEK_BINARY(
NAME zedboard
SYSTEM_DESC system.oil
......
......@@ -29,6 +29,7 @@ model = ConfigurationTree({
'systemcalls': OneOf(["normal", "fsm", "fsm_pla"],
short_help = "System Call Implementation",),
'specialize': Boolean(short_help = "Generate Specialized Systemcalls"),
'inline-scheduler': Boolean(short_help = "Partial Scheduler", default_value = True),
'basic-tasks': Boolean(short_help = "Should Basic Tasks be optimized?"),
# config-constraint-: os.basic-tasks -> (arch.self == posix || arch.self == i386)
......
......@@ -16,6 +16,11 @@ if __name__ == "__main__":
parser.add_option('-c', '--config',
help="Base configuration")
parser.add_option('-e', '--equal',
help="Configured values must be equal",
action='store_true', default=False)
default_config = empty_configuration(model)
cmdline_config = ConfigurationTree(readonly = False)
into_optparse(model, parser, cmdline_config)
......@@ -24,12 +29,23 @@ if __name__ == "__main__":
if options.config:
global_config = from_file(options.config)
actual_conf = ConfigurationTreeStack([default_config, global_config], model)
conf = ConfigurationTreeStack([default_config, global_config, cmdline_config], model)
else:
actual_conf = ConfigurationTreeStack([default_config], model)
conf = ConfigurationTreeStack([default_config, cmdline_config], model)
if options.equal:
for path, value in cmdline_config:
actual_value = actual_conf.get(path)[0]
if actual_value != value:
sys.exit(1)
sys.exit(0)
try:
check_constraints(constraints, conf, silent = True)
except:
sys.exit(1)
......@@ -77,13 +77,22 @@ class FullSystemCalls(BaseCoder):
def InitialSyscall(self, kernelspace):
kernelspace.unused_parameter(0)
self.call_function(kernelspace, "scheduler_.Reschedule",
"void", [])
if self.system_graph.conf.os.inline_scheduler:
self.call_function(kernelspace, "scheduler_.InlinedReschedule",
"void", [])
else:
self.call_function(kernelspace, "scheduler_.Reschedule",
"void", [])
def ASTSchedule(self, kernelspace):
kernelspace.unused_parameter(0)
self.call_function(kernelspace, "scheduler_.Reschedule",
"void", [])
if self.system_graph.conf.os.inline_scheduler:
self.call_function(kernelspace, "scheduler_.InlinedReschedule",
"void", [])
else:
self.call_function(kernelspace, "scheduler_.Reschedule",
"void", [])
def kickoff(self, syscall, userspace, kernelspace):
userspace.attributes.append("inlinehint")
......
from .syscall_full import FullSystemCalls
from .elements import Statement, Comment
from .elements import Statement, Comment, DataObjectArray
from generator.tools import unwrap_seq
from generator.analysis.AtomicBasicBlock import E,S
from generator.analysis.SystemSemantic import SystemState
......@@ -139,9 +139,32 @@ class SpecializedSystemCalls(FullSystemCalls):
tasks)
self.stats.add_data(abb, "opt:Schedule:possible-tasks", len(tasks))
self.call_function(kernelspace,
"scheduler_.Reschedule",
"void", [])
self.Reschedule(kernelspace, tasks)
def Reschedule(self, block, possible_tasks):
if self.system_graph.conf.os.inline_scheduler:
# Build an Array with N+1 entries
array = ["false"] * (len(self.system_graph.real_subtasks) + 1)
for subtask in possible_tasks:
if not subtask in self.system_graph.real_subtasks:
continue
array[subtask.impl.task_id] = "true"
# We need an external reference if we want to use
var = DataObjectArray("constexpr const bool",
"possible_tasks_%s" % id(block),
"")
var.source_element_declaration = lambda: ""
var.static_initializer = array
self.generator.source_file.data_manager.add(var)
block.add(Comment(str(var.static_initializer)))
self.call_function(block,
"scheduler_.PartialReschedule<%s>" % var.name,
"void", [])
else:
self.call_function(block,
"scheduler_.Reschedule",
"void", [])
def ASTSchedule(self, kernelspace):
kernelspace.unused_parameter(0)
......@@ -163,9 +186,7 @@ class SpecializedSystemCalls(FullSystemCalls):
"opt:ASTSchedule:possible-tasks", len(maybe_ready))
if(len(maybe_ready) > 0):
self.call_function(kernelspace,
"scheduler_.Reschedule",
"void", [])
self.Reschedule(kernelspace, maybe_ready)
else:
self.call_function(kernelspace,
"Machine::unreachable",
......
......@@ -15,13 +15,31 @@ struct Scheduler {
os::scheduler::TaskList::current_prio_t current_prio;
os::scheduler::TaskList::current_task_t current_task;
noinline void Reschedule(void);
template<const bool *possible_tasks = nullptr>
forceinline void PartialReschedule() {
tlist.head<possible_tasks>(current_task, current_prio);
dispatchToCurrentTask();
}
forceinline void InlinedReschedule(void) {
// update current_task
tlist.head(current_task, current_prio);
// dispatch
dispatchToCurrentTask();
}
noinline void Reschedule(void);
forceinline void Schedule_impl(void) {
if(in_syscall()) {
// in syscall: reschedule directly
Reschedule();
#ifdef CONFIG_OS_INLINE_SCHEDULER
InlinedReschedule();
#else
Reschedule();
#endif
} else {
// not in syscall (probably in ISR): request reschedule AST
// Calls also Reschedule()
......@@ -127,29 +145,36 @@ struct Scheduler {
return tlist.decode_task_id(current_task);
}
void dispatchToCurrentTask(void) {
// dispatch or enter idle
{{{!foreach_subtask|
if(current_task == {{{!subtask_id}}}) {
{{{!if_not_preemptable|
// promote non-preemptable task to RES_SCHEDULER
tlist.set({{{!subtask_id}}}, tlist.scheduler_prio);
current_prio = tlist.scheduler_prio;
state_replicator_.update();
}}} \
Dispatcher::Dispatch({{{!subtask_desc}}});
} else \
}}} if(current_task == TaskList::idle_id) {
Dispatcher::Idle();
} else {
CALL_HOOK(FaultDetectedHook, LOGIC_ERRORdetected, 0, 0);
}
}
};
void Scheduler::Reschedule() {
// update current_task
tlist.head(current_task, current_prio);
// dispatch or enter idle
{{{!foreach_subtask|
if(current_task == {{{!subtask_id}}}) {
{{{!if_not_preemptable|
// promote non-preemptable task to RES_SCHEDULER
tlist.set({{{!subtask_id}}}, tlist.scheduler_prio);
current_prio = tlist.scheduler_prio;
state_replicator_.update();
}}}\
Dispatcher::Dispatch({{{!subtask_desc}}});
} else \
}}} if(current_task == TaskList::idle_id) {
Dispatcher::Idle();
} else {
CALL_HOOK(FaultDetectedHook, LOGIC_ERRORdetected, 0, 0);
}
// dispatch
dispatchToCurrentTask();
}
Scheduler scheduler_;
extern "C" StatusType OSEKOS_GetTaskID(TaskRefType a) {
......
......@@ -78,18 +78,21 @@ struct TaskList : public UnencodedTaskListStatic {
}
}
forceinline void head(Task::id_t& id, Task::prio_t& prio) const {
template<const bool* possible_tasks = nullptr>
forceinline void head(Task::id_t& id, Task::prio_t& prio) const {
// start with idle id/priority
id = idle_id;
prio = idle_prio;
{{{!foreach_subtask|
if (possible_tasks == nullptr || possible_tasks[{{{!subtask_id}}}]) {
if({{{!subtask}}} > prio {{{!if_events|\
&& (({{{!subtask}}}_events_waiting == 0) || ({{{!subtask}}}_events_waiting & {{{!subtask}}}_events_set) != 0)\
}}}) {
prio = {{{!subtask}}};
id = {{{!subtask_id}}};
}
}
}}}
}
......
......@@ -188,7 +188,7 @@ struct TaskList : public TaskListStatic {
}
}
template<typename T, typename S>
template<const bool * possible_tasks = nullptr, typename T, typename S>
forceinline value_coded_t head(T& id, S& prio) const {
B_t sigId = id.getB();
B_t sigPrio = prio.getB();
......@@ -211,32 +211,34 @@ struct TaskList : public TaskListStatic {
prio.vc = {{{!subtask}}}_prio.vc + (sigPrio - {{{!subtask}}}_prio.getB());
}}}\
{{{!if_comp_idx_gt_zero|
// {{{!subtask}}} >= prio?
auto {{{!subtask}}}_delta = Event<>::must_wait_p({{{!event_list}}});
auto {{{!subtask}}}_prio = {{{!subtask}}} - {{{!subtask}}}_delta;
// kout << "{{{!subtask}}} " << {{{!subtask}}}.vc / A0 << " " << ({{{!subtask}}}_delta.vc / A0) << endl;
updateMax(sigPrio, sigId, 3, &prio, {{{!subtask}}}_prio, &id, EC({{{!subtask_id_sig}}}, {{{!subtask_id}}}));
if (MOD((prio.vc + id.vc), A0) != (sigPrio + sigId)) {
{{{!head_fail:prio.vc,id.vc}}}
}
/* Recode if sigID got too big */
if (sigId > A0 / 2) {
id.vc = id.vc - sigId + 3;
sigId = 3;
}
if (possible_tasks == nullptr || possible_tasks[{{{!subtask_id}}}]) {
// {{{!subtask}}} >= prio?
auto {{{!subtask}}}_delta = Event<>::must_wait_p({{{!event_list}}});
auto {{{!subtask}}}_prio = {{{!subtask}}} - {{{!subtask}}}_delta;
// kout << "{{{!subtask}}} " << {{{!subtask}}}.vc / A0 << " " << ({{{!subtask}}}_delta.vc / A0) << endl;
updateMax(sigPrio, sigId, 3, &prio, {{{!subtask}}}_prio, &id, EC({{{!subtask_id_sig}}}, {{{!subtask_id}}}));
if (MOD((prio.vc + id.vc), A0) != (sigPrio + sigId)) {
{{{!head_fail:prio.vc,id.vc}}}
}
/* Recode if sigID got too big */
if (sigId > A0 / 2) {
id.vc = id.vc - sigId + 3;
sigId = 3;
}
}
}}}\
}}}
{{{generate:head_update_max_cascade}}}
{{{!if_comp_idx_eq_zero|
id=idle_id;
prio=idle_prio;
id = idle_id;
prio = idle_prio;
}}}
{{{!if_comp_idx_gt_zero|
// restore idle_id if idle_id >= prio
updateMax(sigPrio, sigId, 3, &prio, idle_prio, &id, idle_id);
// last comparison, needs no assert
// restore idle_id if idle_id >= prio
updateMax(sigPrio, sigId, 3, &prio, idle_prio, &id, idle_id);
// last comparison, needs no assert
}}}
pseudo_static_assert(sigId > 0, "constant sigId not optimized away completely");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment