-
Notifications
You must be signed in to change notification settings - Fork 89
/
Copy paths_task.h
333 lines (266 loc) · 9.39 KB
/
s_task.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
#ifndef INC_S_TASK_H_
#define INC_S_TASK_H_
/* Copyright xhawk, MIT license */
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "s_list.h"
#include "s_rbtree.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct{
int dummy;
} s_awaiter_t;
# define __await__ __awaiter_dummy__
# define __async__ s_awaiter_t *__awaiter_dummy__
/* Function type for task entrance */
typedef void(*s_task_fn_t)(__async__, void *arg);
/* #define USE_SWAP_CONTEXT */
/* #define USE_JUMP_FCONTEXT */
/* #define USE_LIST_TIMER_CONTAINER //for very small memory footprint */
/* #define USE_IN_EMBEDDED */
/* #define USE_STACK_DEBUG */
/* #define USE_DEAD_TASK_CHECKING */
#if defined __ARMCC_VERSION || (defined __GNUC__ && __USES_INITFINI__ && defined __ARM_ARCH)
# define USE_IN_EMBEDDED
# define USE_SWAP_CONTEXT
# define USE_LIST_TIMER_CONTAINER
# if defined ARDUINO
# include "s_port_atsam3x8e.h"
# elif defined STM32F10X_MD
# include "s_port_stm32f10x.h"
# elif defined STM32F302x8
# include "s_port_stm32f30x.h"
# elif defined STM32L1XX_MD
# include "s_port_stm32l1xx.h"
# elif defined STM32L431xx
# include "s_port_stm32l4xx.h"
# elif defined PICO_BUILD
# include "s_port_raspberry_pico.h"
# else
# include "s_port_m051.h"
# endif
#elif defined __ICCSTM8__
# define USE_IN_EMBEDDED
# define USE_SWAP_CONTEXT
# define USE_LIST_TIMER_CONTAINER
# if defined STM8S103
# include "s_port_stm8s.h"
# elif defined STM8L05X_LD_VL
# include "s_port_stm8l15x.h"
# endif
#elif defined USE_LIBUV
# ifdef __CYGWIN__
# define USE_SWAP_CONTEXT
# else
# define USE_JUMP_FCONTEXT
# endif
# define USE_DEAD_TASK_CHECKING
# include "s_port_libuv.h"
#elif defined _WIN32
# define USE_JUMP_FCONTEXT
# define USE_DEAD_TASK_CHECKING
# include "s_port_windows.h"
#elif defined __unix__ || defined __linux__ || defined __APPLE__
# ifdef __CYGWIN__
# define USE_SWAP_CONTEXT
# else
# define USE_JUMP_FCONTEXT
# endif
# define USE_DEAD_TASK_CHECKING
# include "s_port_posix.h"
#elif defined __AVR__
# define USE_IN_EMBEDDED
# define USE_SWAP_CONTEXT
# define USE_LIST_TIMER_CONTAINER
# include "s_port_avr.h"
#elif defined __riscv
# define USE_IN_EMBEDDED
# define USE_JUMP_FCONTEXT
# define USE_LIST_TIMER_CONTAINER
# include "s_port_gd32vf103.h"
#else
# error "no arch detected"
#endif
#if defined USE_LIBUV && defined USE_IN_EMBEDDED
# error "libuv can not used in embedded system"
#endif
typedef struct {
s_list_t wait_list;
#ifdef USE_DEAD_TASK_CHECKING
s_list_t self;
#endif
bool locked;
} s_mutex_t;
typedef struct {
s_list_t wait_list;
#ifdef USE_DEAD_TASK_CHECKING
s_list_t self;
#endif
} s_event_t;
typedef struct {
uint16_t max_count;
uint16_t begin;
uint16_t available_count;
uint16_t element_size;
s_event_t event;
} s_chan_t;
#include "s_task_internal.h"
/* Initialize the task system. */
#if defined USE_LIBUV
void s_task_init_uv_system_(uv_loop_t* uv_loop);
#define s_task_init_uv_system(uv_loop) __async__ = 0; (void)__awaiter_dummy__; s_task_init_uv_system_(uv_loop)
#else
void s_task_init_system_(void);
#define s_task_init_system() __async__ = 0; (void)__awaiter_dummy__; s_task_init_system_()
#endif
/* Create a new task */
void s_task_create(void *stack, size_t stack_size, s_task_fn_t entry, void *arg);
/* Wait a task to exit */
int s_task_join(__async__, void *stack);
/* Kill a task */
void s_task_kill(void *stack);
/* Sleep in ticks */
int s_task_sleep_ticks(__async__, my_clock_t ticks);
/* Sleep in milliseconds */
int s_task_msleep(__async__, uint32_t msec);
/* Sleep in seconds */
int s_task_sleep(__async__, uint32_t sec);
/* Yield current task */
void s_task_yield(__async__);
/* Cancel task waiting and make it running */
void s_task_cancel_wait(void* stack);
/* Get free stack size (for debug) */
size_t s_task_get_stack_free_size(void);
/* Dump task information */
/* void dump_tasks(__async__); */
/* Initialize a mutex */
void s_mutex_init(s_mutex_t *mutex);
/* Lock the mutex */
int s_mutex_lock(__async__, s_mutex_t *mutex);
/* Unlock the mutex */
void s_mutex_unlock(s_mutex_t *mutex);
/* Initialize a wait event */
void s_event_init(s_event_t *event);
/* Set event */
void s_event_set(s_event_t *event);
/* Wait event
* return 0 on event set
* return -1 on event waiting cancelled
*/
int s_event_wait(__async__, s_event_t *event);
/* Wait event with timeout */
int s_event_wait_msec(__async__, s_event_t *event, uint32_t msec);
/* Wait event with timeout */
int s_event_wait_sec(__async__, s_event_t *event, uint32_t msec);
/* macro: Declare the chan variable
* name: name of the chan
* TYPE: type of element in the chan
* count: max count of element buffer in the chan
*/
#define s_chan_declare(name,TYPE,count) \
s_chan_t name[1 + ((count)*sizeof(TYPE) + sizeof(s_chan_t) - 1) / sizeof(s_chan_t)]
/* macro: Initialize the chan (parameters same as what's in s_declare_chan).
* To make a chan, we need to use "s_chan_declare" and then call "s_chan_init".
*/
#define s_chan_init(name,TYPE,count) do { \
(&name[0])->max_count = (count); \
(&name[0])->begin = 0; \
(&name[0])->available_count = 0; \
(&name[0])->element_size = sizeof(TYPE); \
s_event_init(&(&name[0])->event); \
} while(0)
/* Put element into chan
* return 0 on chan put successfully
* return -1 on chan cancelled
*/
int s_chan_put(__async__, s_chan_t *chan, const void *in_object);
/* Put number of elements into chan
* return 0 on chan put successfully
* return -1 on chan cancelled
*/
int s_chan_put_n(__async__, s_chan_t *chan, const void *in_object, uint16_t number);
/* Get element from chan
* return 0 on chan get successfully
* return -1 on chan cancelled
*/
int s_chan_get(__async__, s_chan_t *chan, void *out_object);
/* Get number of elements from chan
* return 0 on chan get successfully
* return -1 on chan cancelled
*/
int s_chan_get_n(__async__, s_chan_t *chan, void *out_object, uint16_t number);
/* milliseconds to ticks */
my_clock_t msec_to_ticks(uint32_t msec);
/* seconds to ticks */
my_clock_t sec_to_ticks(uint32_t sec);
/* ticks to milliseconds */
uint32_t ticks_to_msec(my_clock_t ticks);
/* ticks to seconds */
uint32_t ticks_to_sec(my_clock_t ticks);
#ifdef USE_IN_EMBEDDED
/* Set event in interrupt */
void s_event_set__in_irq(s_event_t * event);
/*
* Task waits event from irq. Disable irq before call this function!
* S_IRQ_DISABLE()
* ...
* s_event_wait__from_irq(...)
* ...
* S_IRQ_ENABLE()
*/
int s_event_wait__from_irq(__async__, s_event_t * event);
/*
* Task waits event from irq. Disable irq before call this function!
* S_IRQ_DISABLE()
* ...
* s_event_wait_msec__from_irq(...)
* ...
* S_IRQ_ENABLE()
*/
int s_event_wait_msec__from_irq(__async__, s_event_t * event, uint32_t msec);
/*
* Task waits event from irq. Disable irq before call this function!
* S_IRQ_DISABLE()
* ...
* s_event_wait_sec__from_irq(...)
* ...
* S_IRQ_ENABLE()
*/
int s_event_wait_sec__from_irq(__async__, s_event_t * event, uint32_t sec);
/* Task puts element into chan and waits interrupt to read the chan */
void s_chan_put__to_irq(__async__, s_chan_t *chan, const void *in_object);
/* Task puts number of elements into chan and waits interrupt to read the chan */
void s_chan_put_n__to_irq(__async__, s_chan_t *chan, const void *in_object, uint16_t number);
/* Task waits interrupt to write the chan and then gets element from chan */
void s_chan_get__from_irq(__async__, s_chan_t *chan, void *out_object);
/* Task waits interrupt to write the chan and then gets number of elements from chan */
void s_chan_get_n__from_irq(__async__, s_chan_t *chan, void *out_object, uint16_t number);
/*
* Interrupt writes element into the chan,
* return number of element was written into chan
*/
uint16_t s_chan_put__in_irq(s_chan_t *chan, const void *in_object);
/*
* Interrupt writes number of elements into the chan,
* return number of element was written into chan
*/
uint16_t s_chan_put_n__in_irq(s_chan_t *chan, const void *in_object, uint16_t number);
/*
* Interrupt reads element from chan,
* return number of element was read from chan
*/
uint16_t s_chan_get__in_irq(s_chan_t *chan, void *out_object);
/*
* Interrupt reads number of elements from chan,
* return number of element was read from chan
*/
uint16_t s_chan_get_n__in_irq(s_chan_t *chan, void *out_object, uint16_t number);
#endif
#ifdef __cplusplus
}
#endif
#include "s_uv.h"
#endif