-
Notifications
You must be signed in to change notification settings - Fork 2
/
avrcoro_impl.h
86 lines (75 loc) · 2.07 KB
/
avrcoro_impl.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
/*
Author: Artem Boldariev <artem@boldariev.com>
The software distributed under the terms of the MIT/Expat license.
See LICENSE.txt for license details.
*/
#ifndef AVRCORO_IMPL_H
#define AVRCORO_IMPL_H
#ifdef __AVR__
#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus */
static void avr_coro_trampoline(avr_coro_t *coro);
#ifdef __cplusplus
}
#endif /*__cplusplus */
static void avr_coro_trampoline(avr_coro_t *coro)
{
avr_coro_func_t funcp = (avr_coro_func_t)coro->funcp;
void *ret = funcp(coro, coro->data);
coro->data = ret;
coro->status = (char)AVR_CORO_DEAD;
}
int avr_coro_init(avr_coro_t *coro,
void *stackp, const size_t stack_size,
avr_coro_func_t funcp)
{
if (coro == NULL || stackp == NULL || stack_size == 0 || funcp == NULL)
{
return 1;
}
coro->status = (char)AVR_CORO_SUSPENDED;
coro->funcp = (void *)funcp;
avr_getcontext(&coro->exec);
avr_makecontext(&coro->exec,
stackp, stack_size,
&coro->ret,
(void(*)(void *))avr_coro_trampoline, coro);
return 0;
}
int avr_coro_resume(avr_coro_t *coro, void **data)
{
if (coro == NULL || coro->status != (char)AVR_CORO_SUSPENDED)
{
return 1;
}
coro->status = (char)AVR_CORO_RUNNING;
coro->data = data == NULL ? NULL : *data;
avr_swapcontext(&coro->ret, &coro->exec);
if (data != NULL)
{
*data = coro->data;
}
return 0;
}
int avr_coro_yield(avr_coro_t *self, void **data)
{
if (self == NULL || self->status != (char)AVR_CORO_RUNNING)
{
return 1;
}
self->status = (char)AVR_CORO_SUSPENDED;
self->data = data == NULL ? NULL : *data;
avr_swapcontext(&self->exec, &self->ret);
if (data != NULL)
{
*data = self->data;
}
return 0;
}
avr_coro_state_t avr_coro_state(const avr_coro_t *coro)
{
return coro == NULL || coro->status < AVR_CORO_SUSPENDED || coro->status >= AVR_CORO_ILLEGAL ? AVR_CORO_ILLEGAL : (avr_coro_state_t)coro->status;
}
#endif /* __AVR__ */
#endif /* AVRCORO_IMPL_H */