-
-
Notifications
You must be signed in to change notification settings - Fork 66
/
thrd.h
479 lines (433 loc) · 13.2 KB
/
thrd.h
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
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2018, Erik Moqvist
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* This file is part of the Simba project.
*/
#ifndef __KERNEL_THRD_H__
#define __KERNEL_THRD_H__
#include "simba.h"
#include "thrd_port.h"
/**
* Macro to declare a thread stack with given name and size. All
* thread stacks must be defined using this macro.
*
* @param[in] name The name of the stack. A variable is declared with
* this name that should be passed to `thrd_spawn()`.
* @param[in] size Size of the stack in bytes.
*/
#define THRD_STACK(name, size) THRD_PORT_STACK(name, size)
/**
* Push all callee-save registers not part of the context struct. The
* preemptive scheduler requires this macro before the
* `thrd_yield_isr()` function is called from interrupt context.
*/
#define THRD_CONTEXT_STORE_ISR THRD_PORT_CONTEXT_STORE_ISR
/**
* Pop all callee-save registers not part of the context struct. The
* preemptive scheduler requires this macro after the thrd_yield_isr()
* function is called from interrupt context.
*/
#define THRD_CONTEXT_LOAD_ISR THRD_PORT_CONTEXT_LOAD_ISR
/**
* Reschuedule from isr. Used by preemptive systems to interrupt low
* priority threads in favour of high priority threads.
*/
#define THRD_RESCHEDULE_ISR \
do { \
THRD_CONTEXT_STORE_ISR; \
thrd_yield_isr(); \
THRD_CONTEXT_LOAD_ISR; \
} while (0)
/**
* A thread environment variable.
*/
struct thrd_environment_variable_t {
const char *name_p;
const char *value_p;
};
struct thrd_environment_t {
struct thrd_environment_variable_t *variables_p;
size_t number_of_variables;
size_t max_number_of_variables;
};
struct thrd_t {
struct {
struct thrd_prio_list_elem_t elem;
} scheduler;
struct thrd_port_t port;
int8_t prio;
int8_t state;
int err;
uint8_t log_mask;
struct timer_t *timer_p;
const char *name_p;
struct thrd_t *next_p;
#if CONFIG_THRD_TERMINATE == 1
struct sem_t join_sem;
#endif
struct {
#if CONFIG_THRD_CPU_USAGE == 1
struct {
#if CONFIG_FLOAT == 1
float usage;
#else
int usage;
#endif
} cpu;
#endif
#if CONFIG_THRD_SCHEDULED == 1
uint32_t scheduled;
#endif
} statistics;
#if CONFIG_THRD_ENV == 1
struct thrd_environment_t env;
#endif
size_t stack_size;
#if CONFIG_PANIC_ASSERT == 1
uint16_t stack_low_magic;
#endif
};
/**
* Initialize the thread module. This function must be called before
* calling any other function in this module.
*
* The module will only be initialized once even if this function is
* called multiple times.
*
* @return zero(0) or negative error code
*/
int thrd_module_init(void);
/**
* Spawn a thread with given main (entry) function and argument. The
* thread is initialized and added to the ready queue in the scheduler
* for execution when prioritized.
*
* @param[in] main Thread main (entry) function. This function
* normally contains an infinate loop waiting for
* events to occur.
* @param[in] arg_p Main function argument. Passed as arg_p to the
* main function.
* @param[in] prio Thread scheduling priority. [-127..127], where -127
* is the highest priority and 127 is the lowest.
* @param[in] stack_p Stack pointer. The pointer to a stack created
* with the macro `THRD_STACK()`.
* @param[in] stack_size The stack size in number of bytes.
*
* @return Thread id, or NULL on error.
*/
struct thrd_t *thrd_spawn(void *(*main)(void *),
void *arg_p,
int prio,
void *stack_p,
size_t stack_size);
/**
* Suspend current thread and wait to be resumed or a timeout occurs
* (if given).
*
* @param[in] timeout_p Time to wait to be resumed before a timeout
* occurs and the function returns.
*
* @return zero(0), -ETIMEDOUT on timeout or other negative error code.
*/
int thrd_suspend(const struct time_t *timeout_p);
/**
* Resume given thread. If resumed thread is not yet suspended it will
* not be suspended on next suspend call to `thrd_suspend()` or
* `thrd_suspend_isr()`.
*
* @param[in] thrd_p Thread id to resume.
* @param[in] err Error code to be returned by `thrd_suspend()` or
* `thrd_suspend_isr()`.
*
* @return zero(0) or negative error code.
*/
int thrd_resume(struct thrd_t *thrd_p, int err);
/**
* Put the currently executing thread on the ready list and
* reschedule.
*
* This function is often called periodically from low priority work
* heavy threads to give higher priority threads the chance to
* execute.
*
* @return zero(0) or negative error code.
*/
int thrd_yield(void);
/**
* Wait for given thread to terminate.
*
* @param[in] thrd_p Thread to wait for.
*
* @return zero(0) or negative error code.
*/
int thrd_join(struct thrd_t *thrd_p);
/**
* Terminate given thread. The stack of a terminated thread may _not_
* be reused in the current implementation.
*
* @param[in] thrd_p Thread to terminate.
*
* @return zero(0) or negative error code.
*/
int thrd_terminate(struct thrd_t *thrd_p);
/**
* Pauses the current thread for given number of seconds.
*
* @param[in] seconds Seconds to sleep.
*
* @return zero(0) or negative error code.
*/
int thrd_sleep(float seconds);
/**
* Pauses the current thread for given number of milliseconds.
*
* @param[in] milliseconds Milliseconds to sleep.
*
* @return zero(0) or negative error code.
*/
int thrd_sleep_ms(int milliseconds);
/**
* Pauses the current thread for given number of microseconds.
*
* @param[in] microseconds Microseconds to sleep.
*
* @return zero(0) or negative error code.
*/
int thrd_sleep_us(long microseconds);
/**
* Get current thread's id.
*
* @return Thread id.
*/
struct thrd_t *thrd_self(void);
/**
* Set the name of the current thread.
*
* @param[in] name_p New thread name.
*
* @return zero(0) or negative error code.
*/
int thrd_set_name(const char *name_p);
/**
* Get the name of the current thread.
*
* @return Current thread name.
*/
const char *thrd_get_name(void);
/**
* Get the pointer to given thread.
*
* @return Thraed pointer or NULL if the thread was not found.
*/
struct thrd_t *thrd_get_by_name(const char *name_p);
/**
* Set the log mask of given thread.
*
* @param[in] thrd_p Thread to set the log mask of.
* @param[in] mask Log mask. See the log module for available levels.
*
* @return Old log mask.
*/
int thrd_set_log_mask(struct thrd_t *thrd_p, int mask);
/**
* Get the log mask of the current thread.
*
* @return Log mask of current thread.
*/
int thrd_get_log_mask(void);
/**
* Set the priority of given thread.
*
* @param[in] thrd_p Thread to set the priority for.
* @param[in] prio Priority.
*
* @return zero(0) or negative error code.
*/
int thrd_set_prio(struct thrd_t *thrd_p, int prio);
/**
* Get the priority of the current thread.
*
* @return Priority of current thread.
*/
int thrd_get_prio(void);
/**
* Initialize the global environment variables storage. These
* variables are shared among all threads.
*
* @param[in] variables_p Variables array.
* @param[in] length Length of the variables array.
*
* @return zero(0) or negative error code.
*/
int thrd_init_global_env(struct thrd_environment_variable_t *variables_p,
int length);
/**
* Set the value of given environment variable. The pointers to given
* name and value are stored in the current global environment array.
*
* @param[in] name_p Name of the environment variable to set.
* @param[in] value_p Value of the environment variable. Set to NULL
* to remove the variable.
*
* @return zero(0) or negative error code.
*/
int thrd_set_global_env(const char *name_p, const char *value_p);
/**
* Get the value of given environment variable in the global
* environment array.
*
* @param[in] name_p Name of the environment variable to get.
*
* @return Value of given environment variable or NULL if it is not
* found.
*/
const char *thrd_get_global_env(const char *name_p);
/**
* Initialize the current threads' environment variables storage.
*
* @param[in] variables_p Variables are to be used by this therad.
* @param[in] length Length of the variables array.
*
* @return zero(0) or negative error code.
*/
int thrd_init_env(struct thrd_environment_variable_t *variables_p,
int length);
/**
* Set the value of given environment variable. The pointers to given
* name and value are stored in the current threads' environment
* array.
*
* @param[in] name_p Name of the environment variable to set.
* @param[in] value_p Value of the environment variable. Set to NULL
* to remove the variable.
*
* @return zero(0) or negative error code.
*/
int thrd_set_env(const char *name_p, const char *value_p);
/**
* Get the value of given environment variable. If given variable is
* not found in the current threads' environment array, the
* global environment array is searched.
*
* @param[in] name_p Name of the environment variable to get.
*
* @return Value of given environment variable or NULL if it is not
* found.
*/
const char *thrd_get_env(const char *name_p);
/**
* Suspend current thread with the system lock taken (see
* `sys_lock()`) and wait to be resumed or a timeout occurs (if
* given).
*
* @param[in] timeout_p Time to wait to be resumed before a timeout
* occurs and the function returns.
*
* @return zero(0), -ETIMEDOUT on timeout or other negative error code.
*/
int thrd_suspend_isr(const struct time_t *timeout_p);
/**
* Resume given thread from isr or with the system lock taken (see
* `sys_lock()`). If resumed thread is not yet suspended it will not
* be suspended on next suspend call to `thrd_suspend()` or
* `thrd_suspend_isr()`.
*
* @param[in] thrd_p Thread id to resume.
* @param[in] err Error code to be returned by `thrd_suspend()` or
* `thrd_suspend_isr()`.
*
* @return zero(0) or negative error code.
*/
int thrd_resume_isr(struct thrd_t *thrd_p, int err);
/**
* Yield current thread from isr (preemptive scheduler only) or with
* the system lock taken.
*
* @return zero(0) or negative error code.
*/
int thrd_yield_isr(void);
/**
* Allocate a thread stack of given size.
*
* @return The pointer to allocated thread stack, or NULL on error.
*/
void *thrd_stack_alloc(size_t size);
/**
* Free given thread stack.
*
* @return zero(0) or negative error code.
*/
int thrd_stack_free(void *stack_p);
/**
* Get the pointer to given threads' bottom of stack.
*
* @return The pointer to given threds' bottom of stack, or NULL on
* error.
*/
const void *thrd_get_bottom_of_stack(struct thrd_t *thrd_p);
/**
* Get the pointer to given threads' top of stack.
*
* @return The pointer to given threds' top of stack, or NULL on
* error.
*/
const void *thrd_get_top_of_stack(struct thrd_t *thrd_p);
/**
* Initialize given prio list.
*/
int thrd_prio_list_init(struct thrd_prio_list_t *self_p);
/**
* Push given element on given priority list. The priority list is a
* linked list with the highest priority thread first. The pushed
* element is added _after_ any already pushed elements with the same
* thread priority.
*
* @param[in] self_p Priority list to push on.
* @param[in] elem_p Element to push.
*
* @return void.
*/
void thrd_prio_list_push_isr(struct thrd_prio_list_t *self_p,
struct thrd_prio_list_elem_t *elem_p);
/**
* Pop the highest priority element from given priority list.
*
* @param[in] self_p Priority list to pop from.
*
* @return Poped element or NULL if the list was empty.
*/
struct thrd_prio_list_elem_t *thrd_prio_list_pop_isr(
struct thrd_prio_list_t *self_p);
/**
* Remove given element from given priority list.
*
* @param[in] self_p Priority list to remove given element from.
* @param[in] elem_p Element to remove.
*
* @return zero(0) or negative error code.
*/
int thrd_prio_list_remove_isr(struct thrd_prio_list_t *self_p,
struct thrd_prio_list_elem_t *elem_p);
#endif