-
Notifications
You must be signed in to change notification settings - Fork 0
/
riot-round-robin.patch
324 lines (287 loc) · 10.3 KB
/
riot-round-robin.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
diff --git a/core/include/sched.h b/core/include/sched.h
index f37092cc4..df2cb7c31 100644
--- a/core/include/sched.h
+++ b/core/include/sched.h
@@ -90,6 +90,8 @@
extern "C" {
#endif
+extern clist_node_t list_all_threads;
+
/**
* @brief forward declaration for thread_t, defined in thread.h
*/
diff --git a/core/include/thread.h b/core/include/thread.h
index e3dc3ef8d..f437fcdbc 100644
--- a/core/include/thread.h
+++ b/core/include/thread.h
@@ -145,7 +145,8 @@ struct _thread {
char *sp; /**< thread's stack pointer */
thread_status_t status; /**< thread's status */
uint8_t priority; /**< thread's priority */
-
+ uint64_t max_service_time; /**< thread's max total time */
+ uint64_t service_time; /**< thread's total run time */
kernel_pid_t pid; /**< thread's process id */
#if defined(MODULE_CORE_THREAD_FLAGS) || defined(DOXYGEN)
diff --git a/core/sched.c b/core/sched.c
index 011171861..0c77b1e25 100644
--- a/core/sched.c
+++ b/core/sched.c
@@ -27,6 +27,8 @@
#include "irq.h"
#include "thread.h"
#include "log.h"
+#include "xtimer.h"
+#include "stdbool.h"
#ifdef MODULE_MPU_STACK_GUARD
#include "mpu.h"
@@ -42,6 +44,8 @@
volatile int sched_num_threads = 0;
+bool isIdle = false;
+
volatile unsigned int sched_context_switch_request;
volatile thread_t *sched_threads[KERNEL_PID_LAST + 1];
@@ -50,7 +54,15 @@ volatile thread_t *sched_active_thread;
volatile kernel_pid_t sched_active_pid = KERNEL_PID_UNDEF;
clist_node_t sched_runqueues[SCHED_PRIO_LEVELS];
-static uint32_t runqueue_bitcache = 0;
+//static uint32_t runqueue_bitcache = 0;
+
+clist_node_t list_all_threads;
+
+/* xtimer for scheduling and service time calculations */
+void sched_switch_callback (void *arg);
+xtimer_t timer_rr = {NULL, 0, 0, 0, 0, sched_switch_callback, NULL};
+#define ROUND_ROBIN_TIME_QUANTUM 500000 // in microseconds
+uint64_t service_time_start = 0; // time when current thread woke up
/* Needed by OpenOCD to read sched_threads */
#if defined(__APPLE__) && defined(__MACH__)
@@ -101,34 +113,43 @@ int __attribute__((used)) sched_run(void)
{
sched_context_switch_request = 0;
thread_t *active_thread = (thread_t *)sched_active_thread;
+ thread_t *next_thread = NULL;
if (!IS_USED(MODULE_CORE_IDLE_THREAD)) {
- if (!runqueue_bitcache) {
+ if (clist_count(&list_all_threads) == 1) {
if (active_thread) {
_unschedule(active_thread);
active_thread = NULL;
}
- while (!runqueue_bitcache) {
+ while (clist_count(&list_all_threads) == 1) {
sched_arch_idle();
}
}
}
- int nextrq = bitarithm_lsb(runqueue_bitcache);
- thread_t *next_thread = container_of(sched_runqueues[nextrq].next->next,
- thread_t, rq_entry);
+ // Thread selection
+ if (active_thread) {
+ if (clist_count(&list_all_threads) == 1) {
+ next_thread = active_thread;
+ } else {
+ next_thread = container_of((&active_thread->rq_entry)->next,
+ thread_t, rq_entry);
+ }
+ } else {
+ // Only accept threads in PENDING state
+ next_thread = container_of((list_all_threads.next)->next, thread_t, rq_entry);
+ }
- DEBUG(
- "sched_run: active thread: %" PRIkernel_pid ", next thread: %" PRIkernel_pid "\n",
- (kernel_pid_t)((active_thread == NULL)
- ? KERNEL_PID_UNDEF
- : active_thread->pid),
- next_thread->pid);
+ // Only accept threads in PENDING state
+ if (clist_count(&list_all_threads) > 1) {
+ while (next_thread->status != STATUS_PENDING || next_thread->priority == 15) {
+ next_thread = container_of((&next_thread->rq_entry)->next,
+ thread_t, rq_entry);
- if (active_thread == next_thread) {
- DEBUG("sched_run: done, sched_active_thread was not changed.\n");
- return 0;
+ if (next_thread->status == STATUS_RUNNING)
+ break;
+ }
}
if (active_thread) {
@@ -142,9 +163,40 @@ int __attribute__((used)) sched_run(void)
#endif
next_thread->status = STATUS_RUNNING;
+
+ if (service_time_start != 0) {
+ next_thread->service_time += xtimer_now64().ticks64 - service_time_start;
+ }
+
+ if (next_thread->priority != 7) { // if NOT main thread
+ service_time_start = xtimer_now64().ticks64;
+ }
+
sched_active_pid = next_thread->pid;
sched_active_thread = (volatile thread_t *)next_thread;
+ #ifdef DEVELHELP
+ if(!isIdle) {
+ printf("\nThread Name: %s\n", sched_active_thread->name);
+ }
+
+ if(next_thread->priority == 15) {
+ isIdle = true;
+ } else {
+ isIdle = false;
+ }
+ #endif
+
+ if(next_thread->max_service_time != 0) {
+ if (next_thread->max_service_time > next_thread->service_time) {
+ // Avoid overflow from subtracting unsigned numbers
+ float time = (float) ((next_thread->max_service_time - next_thread->service_time));
+ printf("Thread service time remaining: %.2fs\n", (float) time / 1000000);
+ } else {
+ printf("Thread service time remaining: 0.00s\n");
+ }
+ }
+
#ifdef MODULE_MPU_STACK_GUARD
mpu_configure(
2, /* MPU region 2 */
@@ -157,61 +209,26 @@ int __attribute__((used)) sched_run(void)
DEBUG("sched_run: done, changed sched_active_thread.\n");
+ xtimer_set(&timer_rr, ROUND_ROBIN_TIME_QUANTUM);
+
return 1;
}
void sched_set_status(thread_t *process, thread_status_t status)
{
- if (status >= STATUS_ON_RUNQUEUE) {
- if (!(process->status >= STATUS_ON_RUNQUEUE)) {
- DEBUG(
- "sched_set_status: adding thread %" PRIkernel_pid " to runqueue %" PRIu8 ".\n",
- process->pid, process->priority);
- clist_rpush(&sched_runqueues[process->priority],
- &(process->rq_entry));
- runqueue_bitcache |= 1 << process->priority;
- }
- }
- else {
- if (process->status >= STATUS_ON_RUNQUEUE) {
- DEBUG(
- "sched_set_status: removing thread %" PRIkernel_pid " from runqueue %" PRIu8 ".\n",
- process->pid, process->priority);
- clist_lpop(&sched_runqueues[process->priority]);
-
- if (!sched_runqueues[process->priority].next) {
- runqueue_bitcache &= ~(1 << process->priority);
- }
- }
- }
-
process->status = status;
}
+void sched_switch_callback (void *arg)
+{
+ (void) arg;
+ sched_switch(1);
+}
+
void sched_switch(uint16_t other_prio)
{
- thread_t *active_thread = (thread_t *)sched_active_thread;
- uint16_t current_prio = active_thread->priority;
- int on_runqueue = (active_thread->status >= STATUS_ON_RUNQUEUE);
-
- DEBUG("sched_switch: active pid=%" PRIkernel_pid " prio=%" PRIu16 " on_runqueue=%i "
- ", other_prio=%" PRIu16 "\n",
- active_thread->pid, current_prio, on_runqueue,
- other_prio);
-
- if (!on_runqueue || (current_prio > other_prio)) {
- if (irq_is_in()) {
- DEBUG("sched_switch: setting sched_context_switch_request.\n");
- sched_context_switch_request = 1;
- }
- else {
- DEBUG("sched_switch: yielding immediately.\n");
- thread_yield_higher();
- }
- }
- else {
- DEBUG("sched_switch: continuing without yield.\n");
- }
+ (void)other_prio;
+ sched_context_switch_request = 1;
}
NORETURN void sched_task_exit(void)
@@ -224,6 +241,7 @@ NORETURN void sched_task_exit(void)
sched_num_threads--;
sched_set_status((thread_t *)sched_active_thread, STATUS_STOPPED);
+ clist_remove(&list_all_threads, &(((thread_t *)sched_active_thread)->rq_entry));
sched_active_thread = NULL;
cpu_switch_context_exit();
diff --git a/core/thread.c b/core/thread.c
index 48bd2debb..af54b943b 100644
--- a/core/thread.c
+++ b/core/thread.c
@@ -30,6 +30,8 @@
#include "bitarithm.h"
#include "sched.h"
+// clist_node_t list_all_threads;
+
volatile thread_t *thread_get(kernel_pid_t pid)
{
if (pid_is_valid(pid)) {
@@ -142,15 +144,16 @@ int thread_wakeup(kernel_pid_t pid)
void thread_yield(void)
{
- unsigned old_state = irq_disable();
- thread_t *me = (thread_t *)sched_active_thread;
+ unsigned int old_state = irq_disable();
+ thread_t *me = (thread_t *) sched_active_thread;
- if (me->status >= STATUS_ON_RUNQUEUE) {
- clist_lpoprpush(&sched_runqueues[me->priority]);
- }
- irq_restore(old_state);
+ if (me->status >= STATUS_ON_RUNQUEUE) {
+ clist_lpoprpush(&list_all_threads);
+ }
- thread_yield_higher();
+ irq_restore(old_state);
+
+ thread_yield_higher();
}
void thread_add_to_list(list_node_t *list, thread_t *thread)
@@ -274,6 +277,7 @@ kernel_pid_t thread_create(char *stack, int stacksize, uint8_t priority,
thread->priority = priority;
thread->status = STATUS_STOPPED;
+ thread->service_time = 0;
thread->rq_entry.next = NULL;
@@ -284,6 +288,8 @@ kernel_pid_t thread_create(char *stack, int stacksize, uint8_t priority,
thread->msg_array = NULL;
#endif
+ clist_rpush(&list_all_threads, &(thread->rq_entry));
+
sched_num_threads++;
DEBUG("Created thread %s. PID: %" PRIkernel_pid ". Priority: %u.\n", name,
diff --git a/examples/hello-world/Makefile b/examples/hello-world/Makefile
index 258d8e9ba..c8c1b3806 100644
--- a/examples/hello-world/Makefile
+++ b/examples/hello-world/Makefile
@@ -15,4 +15,7 @@ DEVELHELP ?= 1
# Change this to 0 show compiler invocation lines by default:
QUIET ?= 1
+
+USEMOUDLE += xtimer
+
include $(RIOTBASE)/Makefile.include
diff --git a/examples/ipc_pingpong/main.c b/examples/ipc_pingpong/main.c
index 655ff39a7..7670f44a2 100644
--- a/examples/ipc_pingpong/main.c
+++ b/examples/ipc_pingpong/main.c
@@ -50,7 +50,7 @@ int main(void)
msg_t m;
- kernel_pid_t pid = thread_create(second_thread_stack, sizeof(second_thread_stack),
+ kernel_pid_t pid = thread_create(second_thread_stack, sizeof(second_thread_stack),
THREAD_PRIORITY_MAIN - 1, THREAD_CREATE_STACKTEST,
second_thread, NULL, "pong");