Merge branch 'master' of github.com:Minep/lunaix-os
[lunaix-os.git] / lunaix-os / usr / test_pthread.c
1 #include <pthread.h>
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <fcntl.h>
5 #include <errno.h>
6
7 /*
8     Test payloads
9 */
10
11 static void* 
12 __print_and_sleep_randsec(void* value)
13 {
14     pthread_t tid = pthread_self();
15     printf("thread %d: gets number %d\n", tid, (int)value);
16     
17     int fd = open("/dev/rand", O_RDONLY | O_DIRECT);
18     if (fd < 0) {
19         printf("thread %d: failed to get random source: %d\n", tid, errno);
20         return NULL;
21     }
22
23     unsigned char rand = 0;
24     if (read(fd, &rand, sizeof(rand)) != 1) {
25         printf("thread %d: failed to get random number: %d\n", tid, errno);
26         close(fd);
27         return NULL;
28     }
29
30     rand = rand % 30;
31
32     printf("thread %d: going to sleep %ds\n", tid, rand);
33     sleep(rand);
34     close(fd);
35     printf("thread %d: exit\n", tid);
36     return NULL;
37 }
38
39 static void* 
40 __print_and_sleep_seq(void* value)
41 {
42     pthread_t tid = pthread_self();
43     printf("thread %d: gets number %d\n", tid, (int)value);
44     
45     int second = (int)value % 30;
46
47     printf("thread %d: going to sleep %ds\n", tid, second);
48     sleep(second);
49
50     printf("thread %d: exit\n", tid);
51     return NULL;
52 }
53
54 static void* 
55 __print_and_sleep(void* value)
56 {
57     pthread_t tid = pthread_self();
58     printf("thread %d: gets number %d\n", tid, (int)value);
59
60     sleep(1);
61     printf("thread %d: exit\n", tid);
62     return NULL;
63 }
64
65 long long __counter_shared = 0;
66
67 static void* 
68 __inc_number(void* value)
69 {
70     for (int i = 0; i < 10000000; i++)
71     {
72         __counter_shared++;
73     }
74
75     printf("thread %d: exit\n", pthread_self());
76     return NULL;
77 }
78
79 static void* 
80 __spawn_and_quit(void* value)
81 {
82     // quit right-away
83     printf("thread %d: exit\n", pthread_self());
84     return NULL;
85 }
86
87 /*
88     Test cases
89 */
90
91 static void
92 spawn_detached_thread(void* (*fn)(void *), int amount) 
93 {
94     do {                                                                            
95         int err;                                                                    
96         pthread_t created;                                                          
97         for (int i = 0; i < amount; i++) {                                          
98             err = pthread_create(&created, NULL, fn, (void*)i);                     
99             if (err) {                                                              
100                 printf("unable to create thread: %d\n", err);                       
101                 continue;                                                           
102             }                                                                       
103             if((err = pthread_detach(created))) {                                   
104                 printf("failed to detach: %d\n", err);                              
105             }                                                                       
106             printf("created %d-th\n", i);                                           
107         }                                                                           
108     } while(0);
109 }
110
111 static void
112 pthread_test_rand_sleep(int param)
113 {
114     printf("spawning %d threads\n", param);
115     spawn_detached_thread(__print_and_sleep_randsec, param);
116     // wait for max 30 seconds
117     printf("wait for completion\n");
118     sleep(30);
119 }
120
121 static void
122 pthread_test_seq_sleep(int param)
123 {
124     printf("spawning %d threads\n", param);
125     spawn_detached_thread(__print_and_sleep_seq, param);
126     // wait for max 30 seconds
127     printf("wait for completion\n");
128     sleep(30);
129 }
130
131 static void
132 pthread_test_join(int param)
133 {
134     int err;
135     pthread_t created;
136     void* v;
137     for (int i = 0; i < param; i++)
138     {
139         err = pthread_create(&created, NULL, __print_and_sleep, (void*)i);
140         if (err) {
141             printf("unable to create thread: %d\n", err);
142         }
143
144         pthread_join(created, &v);
145     }
146 }
147
148
149 static void
150 pthread_test_shared_race(int param)
151 {
152     __counter_shared = 0;
153
154     spawn_detached_thread(__inc_number, param);
155
156     sleep(10);
157     printf("counter val: %ld\n", __counter_shared);
158 }
159
160 static void
161 pthread_test_quit(int param)
162 {
163     spawn_detached_thread(__spawn_and_quit, param);
164     sleep(5);
165 }
166
167
168 #define run_test(testn, note, ...)                  \
169     do {                                            \
170         printf("** [%s] test start\n", note);       \
171         pthread_test_##testn(__VA_ARGS__);      \
172         printf("** [%s] test passed\n");         \
173     } while (0)
174
175 int main()
176 {
177     run_test(rand_sleep, "rand_sleep5", 5);
178     run_test(rand_sleep, "rand_sleep10", 10);
179     run_test(rand_sleep, "rand_sleep50", 50);
180
181     run_test(seq_sleep, "seq_sleep50", 50);
182     run_test(seq_sleep, "seq_sleep100", 100);
183     run_test(seq_sleep, "seq_sleep200", 200);
184
185     run_test(join, "join5", 5);
186     run_test(join, "join20", 20);
187
188     run_test(quit, "quit10", 10);
189     run_test(quit, "quit50", 50);
190     run_test(quit, "quit100", 100);
191     
192     // FIXME not good, this panic the kernel upon exit, need investigate
193     run_test(shared_race, "shared_race10", 10);
194     run_test(shared_race, "shared_race40", 40);
195
196     // TODO test pthread + signal
197     printf("All test passed.\n");
198 }