]> git.ozlabs.org Git - ccan/blob - ccan/coroutine/test/api-3.c
coroutine: Stack allocation
[ccan] / ccan / coroutine / test / api-3.c
1 #include <stdlib.h>
2
3 #include <ccan/coroutine/coroutine.h>
4 #include <ccan/tap/tap.h>
5
6 /* Test metadata */
7 #define META_MAGIC 0x4d86aa82ec1892f6
8 #define BUFSIZE    8192
9
10 struct metadata {
11         uint64_t magic;
12 };
13
14 struct state {
15         struct coroutine_state ret;
16         unsigned long total;
17 };
18
19 /* Touch a bunch of stack */
20 static void clobber(void *p)
21 {
22         struct state *s = (struct state *)p;
23         char buf[BUFSIZE - COROUTINE_MIN_STKSZ];
24         int i;
25
26         for (i = 0; i < sizeof(buf); i++) {
27                 buf[i] = random() & 0xff;
28         }
29
30         for (i = 0; i < sizeof(buf); i++) {
31                 s->total += buf[i];
32         }
33
34         coroutine_jump(&s->ret);
35 }
36
37 static void test_metadata(struct coroutine_stack *stack)
38 {
39         struct metadata *meta;
40
41         ok1(stack != NULL);
42         ok1(coroutine_stack_check(stack, NULL) == stack);
43         ok1(coroutine_stack_size(stack)
44             == BUFSIZE - COROUTINE_STK_OVERHEAD - sizeof(struct metadata));
45
46         meta = coroutine_stack_to_metadata(stack, sizeof(*meta));
47         ok1(coroutine_stack_from_metadata(meta, sizeof(*meta)) == stack);
48
49         meta->magic = META_MAGIC;
50         ok1(meta->magic == META_MAGIC);
51
52         if (COROUTINE_AVAILABLE) {
53                 struct coroutine_state t;
54                 struct state s = {
55                         .total = 0,
56                 };
57
58                 coroutine_init(&t, clobber, &s, stack);
59                 coroutine_switch(&s.ret, &t);
60                 ok1(s.total != 0);
61         } else {
62                 skip(1, "Coroutines not available");
63         }
64
65         ok1(coroutine_stack_to_metadata(stack, sizeof(*meta)) == meta);
66         ok1(coroutine_stack_from_metadata(meta, sizeof(*meta)) == stack);
67         ok1(meta->magic == META_MAGIC);
68 }
69
70 int main(void)
71 {
72         char *buf;
73         struct coroutine_stack *stack;
74
75         /* This is how many tests you plan to run */
76         plan_tests(1 + 2 * 9);
77
78         /* Fix seed so we get consistent, though pseudo-random results */       
79         srandom(0);
80
81         stack = coroutine_stack_alloc(BUFSIZE, sizeof(struct metadata));
82         test_metadata(stack);
83         coroutine_stack_release(stack, sizeof(struct metadata));
84
85         buf = malloc(BUFSIZE);
86         ok1(buf != NULL);
87         stack = coroutine_stack_init(buf, BUFSIZE, sizeof(struct metadata));
88         test_metadata(stack);
89         coroutine_stack_release(stack, sizeof(struct metadata));
90
91         free(buf);
92
93         /* This exits depending on whether all tests passed */
94         return exit_status();
95 }