Skip to content

Commit 8875f3d

Browse files
committed
moved syscall enum to syscalls + sleep changes tasks
1 parent 9db4853 commit 8875f3d

File tree

4 files changed

+103
-58
lines changed

4 files changed

+103
-58
lines changed

rtos/base_task.hpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@ namespace klib::rtos::detail {
1919
// pointer to a waitable object the task is waiting on
2020
klib::rtos::waitable* waitable;
2121

22-
// time to sleep for the task
23-
volatile klib::time::ms time_to_sleep;
22+
// flag indicating if the task is sleeping
23+
bool is_sleeping;
24+
25+
// wakeup time for the task
26+
klib::time::ms wakup_time;
2427

2528
// pointer to the current stack position
2629
size_t* stack_pointer;
@@ -38,7 +41,8 @@ namespace klib::rtos::detail {
3841
*/
3942
base_task(uint8_t priority = 0):
4043
waitable(nullptr),
41-
time_to_sleep(0),
44+
is_sleeping(false),
45+
wakup_time(0),
4246
stack_pointer(nullptr),
4347
current_priority(priority),
4448
priority(priority)

rtos/scheduler.hpp

Lines changed: 60 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,8 @@
1111
#include "syscall.hpp"
1212

1313
namespace klib::rtos {
14+
template <uint32_t CpuId, typename Irq>
1415
class scheduler {
15-
public:
16-
/**
17-
* @brief All the available syscalls
18-
*
19-
*/
20-
enum class syscalls {
21-
create_task = 0,
22-
delete_task = 1,
23-
yield = 2,
24-
sleep = 3,
25-
malloc = 4,
26-
free = 5
27-
};
28-
2916
protected:
3017
// make sure we can register our callback with the systick handler
3118
static_assert(SYSTICK_CALLBACK_ENABLED, "Systick callback needs to be enabled to switch tasks");
@@ -67,14 +54,6 @@ namespace klib::rtos {
6754
return;
6855
}
6956

70-
// TODO: implement tick count for tasks
71-
// decrement sleep time for all tasks
72-
for (size_t i = 0; i < tasks.size(); i++) {
73-
if (tasks[i]->time_to_sleep.value > 0) {
74-
tasks[i]->time_to_sleep.value--;
75-
}
76-
}
77-
7857
// call the scheduler to pick the next task
7958
schedule();
8059
}
@@ -85,41 +64,67 @@ namespace klib::rtos {
8564
*
8665
*/
8766
static void schedule() {
67+
// get the current time
68+
const auto now = io::systick<CpuId, SYSTICK_CALLBACK_ENABLED>::get_runtime();
69+
8870
// schedule the next task. We use the priority to pick
8971
// the next task to run. We always pick the first task
9072
// with the highest priority that is not sleeping. If no
9173
// task is ready we run the idle task.
92-
next_task = (current_task == nullptr ? &idle_task : (
93-
current_task->time_to_sleep.value == 0 ? current_task : &idle_task
94-
));
74+
if (current_task == nullptr) {
75+
next_task = &idle_task;
76+
}
77+
else if (current_task->is_sleeping && current_task->wakup_time > now) {
78+
// current task is sleeping, switch to idle
79+
next_task = &idle_task;
80+
}
81+
else if (current_task->waitable != nullptr) {
82+
next_task = &idle_task;
83+
}
84+
else {
85+
next_task = current_task;
86+
}
9587

9688
// TODO: implement a better scheduling algorithm
9789
for (size_t i = 0; i < tasks.size(); i++) {
98-
if (tasks[i]->time_to_sleep.value > 0) {
99-
// task is sleeping
90+
// get a reference to the task
91+
auto& task = *tasks[i];
92+
93+
// no need to check the next_task again. We checked
94+
// it above to determine if we need to switch to the
95+
// idle task
96+
if (&task == next_task) {
10097
continue;
10198
}
102-
103-
// do not check the current task again
104-
if (tasks[i] == current_task) {
105-
continue;
99+
100+
// check if the task is sleeping
101+
if (task.is_sleeping) {
102+
// check if the sleep time has elapsed
103+
if (task.wakup_time <= now) {
104+
// wake up the task
105+
task.is_sleeping = false;
106+
}
107+
else {
108+
// task is still sleeping
109+
continue;
110+
}
106111
}
107112

108113
// check if the task is waiting on a waitable
109-
if (tasks[i]->waitable != nullptr) {
110-
if (tasks[i]->waitable->is_waiting()) {
114+
if (task.waitable != nullptr) {
115+
if (task.waitable->is_waiting()) {
111116
// task is waiting on a waitable
112117
continue;
113118
}
114119
else {
115120
// clear the waitable as it is no longer waiting
116-
tasks[i]->waitable = nullptr;
121+
task.waitable = nullptr;
117122
}
118123
}
119124

120125
// task is not sleeping, check priority
121-
if (tasks[i]->current_priority >= next_task->current_priority) {
122-
next_task = tasks[i];
126+
if (task.current_priority >= next_task->current_priority) {
127+
next_task = &task;
123128
break;
124129
}
125130
}
@@ -147,7 +152,6 @@ namespace klib::rtos {
147152
* @brief Start the scheduler
148153
*
149154
*/
150-
template <uint32_t CpuId, typename Irq>
151155
static void start() {
152156
// update the callback to our scheduler
153157
io::systick<CpuId, SYSTICK_CALLBACK_ENABLED>::set_callback(schedule_irq);
@@ -189,14 +193,14 @@ namespace klib::rtos {
189193
* @param arg2
190194
* @return uint32_t
191195
*/
192-
static uint32_t syscall_handler(syscalls number, uint32_t arg0, uint32_t arg1, uint32_t arg2) {
196+
static uint32_t syscall_handler(detail::syscalls number, uint32_t arg0, uint32_t arg1, uint32_t arg2) {
193197
switch (number) {
194-
case syscalls::create_task:
198+
case detail::syscalls::create_task:
195199
// add the task to the scheduler
196200
tasks.push_back(reinterpret_cast<detail::base_task*>(arg0));
197201
break;
198202

199-
case syscalls::delete_task:
203+
case detail::syscalls::delete_task:
200204
// find and remove the task from the scheduler. We move backwards
201205
// to not mess up the indexing when erasing. Note this is something
202206
// that is specific to our dynamic array implementation.
@@ -224,21 +228,31 @@ namespace klib::rtos {
224228
// task not found
225229
return false;
226230

227-
case syscalls::yield:
228-
// yield the cpu to the next task
229-
current_task->waitable = reinterpret_cast<rtos::waitable*>(arg0);
231+
case detail::syscalls::sleep:
232+
// set the time to sleep for the current task
233+
current_task->wakup_time = (
234+
io::systick<CpuId, SYSTICK_CALLBACK_ENABLED>::get_runtime() +
235+
klib::time::ms(arg0)
236+
);
237+
238+
// mark the task as sleeping
239+
current_task->is_sleeping = true;
230240

231241
// switch to the next task
232242
schedule();
233243
break;
234244

235-
case syscalls::sleep:
236-
// set the time to sleep for the current task
237-
current_task->time_to_sleep.value = arg0;
245+
case detail::syscalls::yield:
246+
// yield the cpu to the next task
247+
current_task->waitable = reinterpret_cast<rtos::waitable*>(arg0);
238248

239249
// switch to the next task
240250
schedule();
241251
break;
252+
253+
case detail::syscalls::get_time:
254+
// get the current time in ms
255+
return io::systick<CpuId, SYSTICK_CALLBACK_ENABLED>::get_runtime().value;
242256
}
243257

244258
return true;

rtos/syscall.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#include <rtos/rtos.hpp>
22

33
#include "syscall.hpp"
4-
#include "scheduler.hpp"
54

65
namespace klib::rtos::syscall {
76
/**
@@ -14,7 +13,7 @@ namespace klib::rtos::syscall {
1413
* @return Return
1514
*/
1615
template <typename Return, typename... Args>
17-
static Return syscall_invoke(scheduler::syscalls number, Args... args) {
16+
static Return syscall_invoke(detail::syscalls number, Args... args) {
1817
// Call the target specific syscall invoke function
1918
return klib::target::rtos::detail::syscall_invoke<Return, Args...>(
2019
static_cast<uint32_t>(number), args...
@@ -23,22 +22,22 @@ namespace klib::rtos::syscall {
2322

2423
bool create_task(detail::base_task* task) {
2524
// invoke the create_task syscall
26-
return syscall_invoke<bool, detail::base_task*>(scheduler::syscalls::create_task, task);
25+
return syscall_invoke<bool, detail::base_task*>(detail::syscalls::create_task, task);
2726
}
2827

2928
bool delete_task(detail::base_task* task) {
3029
// invoke the delete_task syscall
31-
return syscall_invoke<bool, detail::base_task*>(scheduler::syscalls::delete_task, task);
30+
return syscall_invoke<bool, detail::base_task*>(detail::syscalls::delete_task, task);
3231
}
3332

3433
void yield() {
3534
// invoke the yield syscall
36-
syscall_invoke<void, rtos::waitable*>(scheduler::syscalls::yield, nullptr);
35+
syscall_invoke<void, rtos::waitable*>(detail::syscalls::yield, nullptr);
3736
}
3837

3938
void yield(rtos::waitable& waitable) {
4039
// invoke the yield syscall
41-
syscall_invoke<void, rtos::waitable*>(scheduler::syscalls::yield, &waitable);
40+
syscall_invoke<void, rtos::waitable*>(detail::syscalls::yield, &waitable);
4241
}
4342

4443
void sleep(klib::time::ms time) {
@@ -48,16 +47,21 @@ namespace klib::rtos::syscall {
4847
}
4948

5049
// invoke the sleep syscall
51-
syscall_invoke<void, klib::time::ms>(scheduler::syscalls::sleep, time.value);
50+
syscall_invoke<void, uint32_t>(detail::syscalls::sleep, time.value);
51+
}
52+
53+
klib::time::ms get_time() {
54+
// invoke the get_time syscall
55+
return klib::time::ms(syscall_invoke<uint32_t>(detail::syscalls::get_time));
5256
}
5357

5458
void* malloc(uint32_t size) {
5559
// invoke the malloc syscall
56-
return syscall_invoke<void*, uint32_t>(scheduler::syscalls::malloc, size);
60+
return syscall_invoke<void*, uint32_t>(detail::syscalls::malloc, size);
5761
}
5862

5963
void free(const void *const ptr) {
6064
// invoke the free syscall
61-
syscall_invoke<void, const void*>(scheduler::syscalls::free, ptr);
65+
syscall_invoke<void, const void*>(detail::syscalls::free, ptr);
6266
}
6367
}

rtos/syscall.hpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,22 @@
88
#include "base_task.hpp"
99
#include "waitable.hpp"
1010

11+
namespace klib::rtos::detail {
12+
/**
13+
* @brief All the available syscalls
14+
*
15+
*/
16+
enum class syscalls {
17+
create_task,
18+
delete_task,
19+
yield,
20+
sleep,
21+
get_time,
22+
malloc,
23+
free,
24+
};
25+
}
26+
1127
namespace klib::rtos::syscall {
1228
/**
1329
* @brief Create a task object
@@ -46,6 +62,13 @@ namespace klib::rtos::syscall {
4662
*/
4763
void sleep(klib::time::ms time);
4864

65+
/**
66+
* @brief Get the time object
67+
*
68+
* @return klib::time::ms
69+
*/
70+
klib::time::ms get_time();
71+
4972
/**
5073
* @brief Allocate size amount of memory
5174
*

0 commit comments

Comments
 (0)