libthreads: cleanup main thread initialization
[model-checker.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
13 static void *stack_allocate(size_t size)
14 {
15         return malloc(size);
16 }
17
18 static int create_context(struct thread *t)
19 {
20         int ret;
21
22         memset(&t->context, 0, sizeof(t->context));
23         ret = getcontext(&t->context);
24         if (ret)
25                 return ret;
26
27         /* t->start_routine == NULL means this is our initial context */
28         if (!t->start_routine)
29                 return 0;
30
31         /* Initialize new managed context */
32         t->stack = stack_allocate(STACK_SIZE);
33         t->context.uc_stack.ss_sp = t->stack;
34         t->context.uc_stack.ss_size = STACK_SIZE;
35         t->context.uc_stack.ss_flags = 0;
36         t->context.uc_link = &current->context;
37         makecontext(&t->context, t->start_routine, 1, t->arg);
38
39         return 0;
40 }
41
42 static int create_initial_thread(struct thread *t)
43 {
44         memset(t, 0, sizeof(*t));
45         return create_context(t);
46 }
47
48 int thread_create(struct thread *t, void (*start_routine), void *arg)
49 {
50         static int created = 1;
51         ucontext_t local;
52
53         DBG();
54
55         t->index = created++;
56         DEBUG("create thread %d\n", t->index);
57
58         t->start_routine = start_routine;
59         t->arg = arg;
60
61         /* Initialize state */
62         return create_context(t);
63 }
64
65 void thread_start(struct thread *t)
66 {
67         struct thread *old = current;
68         DBG();
69
70         current = t;
71         swapcontext(&old->context, &current->context);
72
73         DBG();
74 }
75
76 void a(int *idx)
77 {
78         int i;
79
80         for (i = 0; i < 10; i++)
81                 printf("Thread %d, loop %d\n", *idx, i);
82 }
83
84 void user_main()
85 {
86         struct thread t1, t2;
87         int i = 1, j = 2;
88
89         thread_create(&t1, &a, &i);
90         thread_create(&t2, &a, &j);
91
92         printf("user_main() is going to start 2 threads\n");
93         thread_start(&t1);
94         thread_start(&t2);
95         printf("user_main() is finished\n");
96 }
97
98 int main()
99 {
100         struct thread main_thread, user_thread;
101
102         create_initial_thread(&main_thread);
103         current = &main_thread;
104
105         thread_create(&user_thread, &user_main, NULL);
106
107         thread_start(&user_thread);
108
109         DBG();
110
111         DEBUG("Exiting\n");
112         return 0;
113 }