5ede8d7eafa5a7cf0e32f740434872c5f9c82987
[c11tester.git] / libthreads.c
1 #include <string.h>
2 #include <stdlib.h>
3 #include <ucontext.h>
4
5 //#define CONFIG_DEBUG
6
7 #include "libthreads.h"
8
9 #define STACK_SIZE (1024 * 1024)
10
11 static struct thread *current;
12 static ucontext_t *cleanup;
13
14 static void *stack_allocate(size_t size)
15 {
16         return malloc(size);
17 }
18
19 int thread_create(struct thread *t, void (*start_routine), void *arg)
20 {
21         static int created;
22         ucontext_t local;
23
24         DBG();
25
26         t->index = created++;
27         DEBUG("create thread %d\n", t->index);
28
29         t->start_routine = start_routine;
30         t->arg = arg;
31
32         /* Initialize state */
33         getcontext(&t->context);
34         t->stack = stack_allocate(STACK_SIZE);
35         t->context.uc_stack.ss_sp = t->stack;
36         t->context.uc_stack.ss_size = STACK_SIZE;
37         t->context.uc_stack.ss_flags = 0;
38         if (current)
39                 t->context.uc_link = &current->context;
40         else
41                 t->context.uc_link = cleanup;
42         makecontext(&t->context, t->start_routine, 1, t->arg);
43
44         return 0;
45 }
46
47 void thread_start(struct thread *t)
48 {
49         DBG();
50
51         if (current) {
52                 struct thread *old = current;
53                 current = t;
54                 swapcontext(&old->context, &current->context);
55         } else {
56                 current = t;
57                 swapcontext(cleanup, &current->context);
58         }
59         DBG();
60 }
61
62 void a(int *idx)
63 {
64         int i;
65
66         for (i = 0; i < 10; i++)
67                 printf("Thread %d, loop %d\n", *idx, i);
68 }
69
70 void user_main()
71 {
72         struct thread t1, t2;
73         int i = 1, j = 2;
74
75         thread_create(&t1, &a, &i);
76         thread_create(&t2, &a, &j);
77
78         printf("user_main() is going to start 2 threads\n");
79         thread_start(&t1);
80         thread_start(&t2);
81         printf("user_main() is finished\n");
82 }
83
84 int main()
85 {
86         struct thread t;
87         ucontext_t main_context;
88
89         cleanup = &main_context;
90
91         thread_create(&t, &user_main, NULL);
92
93         thread_start(&t);
94
95         DBG();
96
97         DEBUG("Exiting\n");
98         return 0;
99 }