Commit 645f0744 authored by Christian Dietrich's avatar Christian Dietrich

osek-v: traditional osek implementation

In order to compare the wired version of OSEK-V with something, we
implement a non-wired version (tradtional SW implementation) for osek-v.

Change-Id: Id5dbc865974f2cf44cd4104cb7ebcd83830fb89f
parent e791941c
......@@ -5,6 +5,7 @@ set(SRCS
constructors.cc
interrupt.cc
timer.cc
dispatch.cc
)
# Create arch library
......
#include "dispatch.h"
#ifndef CONFIG_OS_SYSTEMCALLS_WIRED
static char __attribute__(( aligned (16) )) idlestack[arch::IDLESTACKSIZE];
arch::TCB::dynamic_state idle_dynamic_state;
arch::TCB arch::Dispatcher::m_idle(Dispatcher::idleEntry, idlestack, idle_dynamic_state, arch::IDLESTACKSIZE);
const arch::TCB* arch::Dispatcher::m_current = 0;
#endif
......@@ -2,11 +2,89 @@
#define __OSEK_V_DISPATCHER_H__
#include "os/scheduler/task.h"
#include "output.h"
#include "tcb.h"
namespace arch {
static constexpr const int IDLESTACKSIZE = 4096;
struct Dispatcher {
#ifndef CONFIG_OS_SYSTEMCALLS_WIRED
static const TCB* m_current;
static TCB m_idle;
static noinline void idleEntry(void) {
CALL_HOOK(PreIdleHook);
while(true){
Machine::sleep();
}
}
static forceinline void doDispatch(const TCB *from, const TCB *to) {
// update current context
m_current = to;
/* If we do not reset the idle loop, when leaving it the
PreIdleHook is not called correctly on the next dispatch
to idle */
if (from == &m_idle && to != &m_idle) {
m_idle.reset();
}
CALL_HOOK(PreTaskHook);
if ((from == 0) || !from->is_running()) {
to->start(from);
} else {
from->switchTo(to);
}
}
public:
static forceinline void init(void) {
m_idle.reset();
}
static forceinline void Idle(void) {
doDispatch(m_current, &m_idle);
}
static forceinline void Prepare(const os::scheduler::Task& task) {
task.tcb.reset();
}
static forceinline void Destroy(const os::scheduler::Task& task) {
task.tcb.reset();
}
static forceinline void Dispatch(const os::scheduler::Task &next,
const os::scheduler::Task *current = 0) {
const TCB *cur = current ? &current->tcb : m_current;
if(cur == &next.tcb) {
return;
}
doDispatch(cur, &next.tcb);
}
static forceinline void ResumeToTask(const os::scheduler::Task &next,
const os::scheduler::Task *current = 0) {
Dispatch(next, current);
}
static forceinline void StartToTask(const os::scheduler::Task next,
const os::scheduler::Task *current = 0) {
Dispatch(next, current);
}
#else // os.systemcalls == wired
static void ResumeToTask(const os::scheduler::Task &x) {};
#endif
};
}
#endif
......@@ -2,8 +2,23 @@
#include "machine.h"
#include "timer.h"
#include "interrupt.h"
#include "os/scheduler/scheduler.h"
#ifndef CONFIG_OS_SYSTEMCALLS_WIRED
static bool ast_requested;
static int ast_level;
void arch::request_reschedule_ast() {
ast_requested = true;
}
bool arch::in_syscall() {
return ast_level == 0;
}
#endif
unsigned char Machine::soft_irq_cause;
extern "C" void bad_trap() {
......@@ -21,25 +36,29 @@ void arch::bad_soft_irq(unsigned char cause) {
extern "C" void interrupt_handler(long long mcause, uintptr_t sp) {
#ifndef CONFIG_OS_SYSTEMCALLS_WIRED
ast_level ++;
#endif
(void) sp;
if (mcause < 0) { // Interrupt
uintptr_t device = mcause & 0xffffffff;
if (device == 2) { // htif
uintptr_t fromhost = Machine::swap_csr(mfromhost, 0);
if (fromhost == 0) {
return;
goto out;
}
kout << "htif interrupt " << hex << fromhost << endl;
bad_trap();
} else if (device == 1) {
arch::Timer::tick();
return;
goto out;
} else if (device == 0) {
// ack the interrupt;
// kout << "Soft IRQ " << Machine::soft_irq_cause << endl;
Machine::clear_csr_bit(mip, MIP_MSIP);
arch::isr_table[Machine::soft_irq_cause](Machine::soft_irq_cause);
return;
goto out;
}
kout << "device " << device << endl;
bad_trap();
......@@ -47,4 +66,13 @@ extern "C" void interrupt_handler(long long mcause, uintptr_t sp) {
kout << "trap" << endl;
bad_trap();
}
out:
#ifndef CONFIG_OS_SYSTEMCALLS_WIRED
ast_level --;
if (ast_requested) {
ast_requested = false;
__OS_ASTSchedule(0);
}
#endif
return;
}
......@@ -6,6 +6,8 @@ namespace arch{
extern interrupt_handler_t isr_table[];
void bad_soft_irq(unsigned char);
bool in_syscall();
}
#endif
......@@ -163,6 +163,11 @@ public:
static forceinline void sync() {
asm volatile ("fence");
}
static forceinline void sleep() {
asm volatile ("wfi");
}
};
#define __asm_label(a) #a
......
......@@ -5,6 +5,7 @@
HTIFOutputStream kout;
void noinline HTIFOutputStream::putchar(char ch) {
// bool enabled = Machine::disable_interrupts();
while (Machine::swap_csr(mtohost, TOHOST_CMD(1, 1, ch)) != 0);
while (1) {
uintptr_t fromhost = Machine::read_csr(mfromhost);
......@@ -16,4 +17,7 @@ void noinline HTIFOutputStream::putchar(char ch) {
Machine::write_csr(mfromhost, 0);
break;
}
// if (enabled)
// Machine::enable_interrupts();
}
/**
* @file
* @ingroup posix
* @brief Posix reschedule AST interface
*/
#ifndef __RESCHEDULE_AST_H__
#define __RESCHEDULE_AST_H__
#include "os/util/inline.h"
#include "interrupt.h"
namespace arch {
/** \brief Request the reschedule AST to run after all other interrupts compelete. */
void request_reschedule_ast();
} // namespace arch
#endif // __RESCHEDULE_AST_H__
......@@ -130,3 +130,61 @@ interrupt_handler_asm:
eret
.size interrupt_handler_asm, . - interrupt_handler_asm
.global __switch_to
__switch_to:
/* Save context into prev->thread */
sd ra, 0*8(a0)
sd sp, 1*8(a0)
sd s0, 2*8(a0)
sd s1, 3*8(a0)
sd s2, 4*8(a0)
sd s3, 5*8(a0)
sd s4, 6*8(a0)
sd s5, 7*8(a0)
sd s6, 8*8(a0)
sd s7, 9*8(a0)
sd s8, 10*8(a0)
sd s9, 11*8(a0)
sd s10, 12*8(a0)
sd s11, 13*8(a0)
__switch_to__half:
/* Restore context from next->thread */
ld ra, 0*8(a1)
ld sp, 1*8(a1)
ld s0, 2*8(a1)
ld s1, 3*8(a1)
ld s2, 4*8(a1)
ld s3, 5*8(a1)
ld s4, 6*8(a1)
ld s5, 7*8(a1)
ld s6, 8*8(a1)
ld s7, 9*8(a1)
ld s8, 10*8(a1)
ld s9, 11*8(a1)
ld s10, 12*8(a1)
ld s11, 13*8(a1)
mv tp, a1 /* Next current pointer */
ret
.size __switch_to, . - __switch_to
.global __start_to
__start_to:
/* Restore context from next->thread */
ld ra, 0*8(a0)
ld sp, 1*8(a0)
ld s0, 2*8(a0)
ld s1, 3*8(a0)
ld s2, 4*8(a0)
ld s3, 5*8(a0)
ld s4, 6*8(a0)
ld s5, 7*8(a0)
ld s6, 8*8(a0)
ld s7, 9*8(a0)
ld s8, 10*8(a0)
ld s9, 11*8(a0)
ld s10, 12*8(a0)
ld s11, 13*8(a0)
mv tp, a1 /* Next current pointer */
ret
.size __start_to, . - __start_to
#include "constructors.h"
#include "timer.h"
#include "machine.h"
#include "dispatch.h"
extern "C" {
......@@ -18,7 +20,12 @@ extern "C" {
//// Should be MIP_MSIE (same constant)
Machine::set_csr_bit(mie, MIP_MSIP);
#ifdef CONFIG_OS_SYSTEMCALLS_WIRED
// arch::Timer::init is called in StartOS
#else
arch::Dispatcher::init();
arch::Timer::init();
#endif
init_generic();
}
......
#ifndef __OSEK_V_SYSCALL
#define __OSEK_V_SYSCALL
#define syscall(sys) do { (sys)(0);} while(0)
#endif
#ifndef __OSEKV_TCB_H
#define __OSEKV_TCB_H
#include "output.h"
extern "C" {
void __switch_to(void * from, void *to);
void __start_to(void *to);
}
namespace arch {
struct TCB { TCB(){} };
struct TCB {
#ifndef CONFIG_OS_SYSTEMCALLS_WIRED
/* CPU-specific state of a task */
struct dynamic_state {
/* Callee-saved registers */
unsigned long ra;
unsigned long sp; /* Kernel mode stack */
unsigned long s[12]; /* s[0]: frame pointer */
bool running_marker;
};
private:
typedef void (* const fptr_t)(void);
// task function
fptr_t fun;
// task stack
void * const stack;
// reference to saved stack pointer
const int stacksize;
public:
dynamic_state &state;
inline bool is_running(void) const {
return state.running_marker;
}
inline void set_running() const {
state.running_marker = true;
}
inline void reset(void) const {
state.running_marker = false;
// kout << "Fun: " << (void*)fun << endl;
state.ra = reinterpret_cast<unsigned long>(fun);
state.sp = reinterpret_cast<unsigned long>(stack) + stacksize;
}
void start(const TCB *old) const {
(void) old;
set_running();
// kout << "Start to RA " << hex << this->state.ra << endl;
// Lets go to an extended stack
__start_to(&this->state);
}
void switchTo(const TCB *other) const {
other->set_running();
// kout << "Switch to RA " << hex << this->state.ra << " to " << other->state.ra << endl;
__switch_to(&this->state, &other->state);
}
constexpr TCB(fptr_t f, void *stack_ptr, dynamic_state &state, int stacksize)
: fun(f), stack(stack_ptr), stacksize(stacksize), state(state) {}
#else
TCB(){}
#endif
};
}
#endif
......@@ -32,7 +32,8 @@ model = ConfigurationTree({
'systemcalls': OneOf(["normal", "fsm", "fsm_pla", "wired"],
short_help = "System Call Implementation",),
'specialize': Boolean(short_help = "Generate Specialized Systemcalls"),
'inline-scheduler': Boolean(short_help = "Partial Scheduler", default_value = True),
'inline-scheduler': Boolean(short_help = "Partial Scheduler",
default_value = expr("!(/arch.self == osek-v)")),
'basic-tasks': Boolean(short_help = "Should Basic Tasks be optimized?"),
# config-constraint-: os.basic-tasks -> (arch.self == posix || arch.self == i386)
......
......@@ -16,18 +16,56 @@ class OSEKVArch(GenericArch):
def generate_dataobjects(self):
"""Generate all dataobjects for the system"""
self.logic = self.system_graph.get_pass("LogicMinimizer")
self.generate_dataobjects_task_stacks() # From SimpleArch
conf_wired = self.system_graph.conf.os.systemcalls == "wired"
if conf_wired:
self.logic = self.system_graph.get_pass("LogicMinimizer")
# Generate Stacks
self.generate_dataobjects_task_stacks()
for subtask in self.system_graph.real_subtasks:
subtask.impl.stack.allocation_prefix +=" __attribute__((aligned(16))) "
self.generate_dataobjects_task_entries()
self.generate_dataobjects_task_descriptors()
self.generate_rocket_config()
if conf_wired:
self.generate_wired_task_descriptors()
self.generate_rocket_config()
else:
self.generate_dataobjects_tcbs()
# For dummy ResumeToTask
self.generator.source_file.include("dispatch.h")
def generate_dataobjects_task_descriptors(self):
def generate_dataobjects_tcbs(self):
self.generator.source_file.include("tcb.h")
tcb_arr = DataObjectArray("const TCB * const", "OS_tcbs", "")
tcb_arr.add_static_initializer("0")
for subtask in self.system_graph.subtasks:
# Ignore the Idle thread
if not subtask.is_real_thread():
continue
# Dynamic state area
dynamic_state = DataObject("arch::TCB::dynamic_state", "OS_" + subtask.name + "_tcb_dynamic")
self.generator.source_file.data_manager.add(dynamic_state, namespace = ("arch",))
# Static TCB
initializer = "(&%s, %s, %s, %s)" % (
subtask.impl.entry_function.name,
subtask.impl.stack.name,
dynamic_state.name,
subtask.impl.stacksize
)
desc = DataObject("const arch::TCB", "OS_" + subtask.name + "_tcb",
initializer)
desc.allocation_prefix = "constexpr "
self.generator.source_file.data_manager.add(desc, namespace = ("arch",))
subtask.impl.tcb_descriptor = desc
tcb_arr.add_static_initializer("&" + desc.name)
self.generator.source_file.data_manager.add(tcb_arr, namespace = ("arch",))
def generate_wired_task_descriptors(self):
self.generator.source_file.include("os/scheduler/task.h")
self.generator.source_file.include("tcb.h")
self.system_graph.idle_subtask.impl.task_id = 0
......
......@@ -105,7 +105,8 @@ class UnencodedOS(GenericOS):
pre_hook = None
post_hook = None
self.arch_rules.asm_marker(userspace, "syscall_start_%s" % userspace.name)
if not abb.subtask.conf.is_isr:
self.arch_rules.asm_marker(userspace, "syscall_start_%s" % userspace.name)
self.__instantiate_kernelspace(abb)
......@@ -120,7 +121,8 @@ class UnencodedOS(GenericOS):
else:
assert False, "Not yet supported %s"% abb.syscall_type
self.arch_rules.asm_marker(userspace, "syscall_end_%s" % userspace.name)
if not abb.subtask.conf.is_isr:
self.arch_rules.asm_marker(userspace, "syscall_end_%s" % userspace.name)
# Fill up the hooks
self.system_enter_hook(abb, abb.impl.pre_hook)
......
......@@ -181,17 +181,15 @@ if __name__ == "__main__":
arch_rules = PosixArch()
elif conf.arch.self == "osek-v":
arch_rules = OSEKVArch()
os_rules = WiredOS()
else:
panic("Unknown --arch=%s", conf.arch.self)
# config-constraint-: (arch.self == osek-v) -> !dependability.encoded
# config-constraint-: (arch.self == osek-v) -> !os.specialize
if conf.arch.self != "osek-v":
if conf.dependability.encoded:
os_rules = EncodedOS()
else:
os_rules = UnencodedOS()
# config-constraint-: (arch.self == osek-v) -> !os.basic_tasks
if conf.dependability.encoded:
os_rules = EncodedOS()
else:
os_rules = UnencodedOS()
if conf.os.systemcalls == "normal":
if conf.os.specialize:
......@@ -218,12 +216,13 @@ if __name__ == "__main__":
pass_manager.get_pass("sse").use_app_fsm = True
pass_manager.enqueue_analysis("fsm")
syscall_rules = FSMSystemCalls()
# config-constraint-: (arch.self == osek-v) -> (os.systemcalls == wired)
# config-constraint-: (os.systemcalls == wired) -> (arch.self == osek-v)
elif conf.os.systemcalls == "wired":
pass_manager.get_pass("sse").use_app_fsm = True
pass_manager.enqueue_analysis("LogicMinimizer")
pass_manager.enqueue_analysis("fsm")
pass_manager.enqueue_analysis("static-alarms")
os_rules = WiredOS()
syscall_rules = WiredSystemCalls()
else:
assert False
......
......@@ -152,7 +152,7 @@ class ClassicTMR {
return true;
}
kout << "Trying to fix" << endl;
//kout << "Trying to fix" << endl;
fault_detected_port = 42;
if(orig == rep1) { // rep2 wrong
rep2 = orig; // fix
......@@ -169,7 +169,7 @@ class ClassicTMR {
return true;
}
kout << "TMR: oO :( " << endl;
// kout << "TMR: oO :( " << endl;
return false;
}
};
......
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