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