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