1 | //------------------------------------------------------------------------------ |
2 | // Copyright (c) 2016 by Lukasz Janyst <lukasz@jany.st> |
3 | //------------------------------------------------------------------------------ |
4 | // This file is part of thread-bites. |
5 | // |
6 | // thread-bites is free software: you can redistribute it and/or modify |
7 | // it under the terms of the GNU General Public License as published by |
8 | // the Free Software Foundation, either version 3 of the License, or |
9 | // (at your option) any later version. |
10 | // |
11 | // thread-bites is distributed in the hope that it will be useful, |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | // GNU General Public License for more details. |
15 | // |
16 | // You should have received a copy of the GNU General Public License |
17 | // along with thread-bites. If not, see <http://www.gnu.org/licenses/>. |
18 | //------------------------------------------------------------------------------ |
19 | |
20 | #include <tb.h> |
21 | #include <string.h> |
22 | |
23 | //------------------------------------------------------------------------------ |
24 | // Test normal mutex |
25 | //------------------------------------------------------------------------------ |
26 | void *thread_func_normal(void *arg) |
27 | { |
28 | tbthread_t self = tbthread_self(); |
29 | tbthread_mutex_t *mutex = (tbthread_mutex_t*)arg; |
30 | int locked = 0; |
31 | if(!tbthread_mutex_trylock(mutex)) { |
32 | tbprint("[thread 0x%llx] Trying to actuire the mutex succeeded\n" , self); |
33 | locked = 1; |
34 | } |
35 | else |
36 | tbprint("[thread 0x%llx] Trying to actuire the mutex failed\n" , self); |
37 | |
38 | if(!locked) |
39 | tbthread_mutex_lock(mutex); |
40 | tbprint("[thread 0x%llx] Starting normal mutex test\n" , self); |
41 | tbsleep(1); |
42 | tbprint("[thread 0x%llx] Finishing normal mutex test\n" , self); |
43 | tbthread_mutex_unlock(mutex); |
44 | return 0; |
45 | } |
46 | |
47 | //------------------------------------------------------------------------------ |
48 | // Test errorcheck mutex |
49 | //------------------------------------------------------------------------------ |
50 | void *thread_func_errorcheck1(void *arg) |
51 | { |
52 | tbthread_t self = tbthread_self(); |
53 | tbthread_mutex_t *mutex = (tbthread_mutex_t*)arg; |
54 | |
55 | tbthread_mutex_lock(mutex); |
56 | tbprint("[thread 0x%llx] Starting errorcheck mutex test\n" , self); |
57 | if(tbthread_mutex_lock(mutex) == -EDEADLK) |
58 | tbprint("[thread 0x%llx] Trying to lock again would deadlock\n" , self); |
59 | tbsleep(2); |
60 | tbprint("[thread 0x%llx] Finishing errorcheck mutex test\n" , self); |
61 | tbthread_mutex_unlock(mutex); |
62 | return 0; |
63 | } |
64 | |
65 | void *thread_func_errorcheck2(void *arg) |
66 | { |
67 | tbthread_t self = tbthread_self(); |
68 | tbthread_mutex_t *mutex = (tbthread_mutex_t*)arg; |
69 | tbsleep(1); |
70 | if(tbthread_mutex_unlock(mutex) == -EPERM) |
71 | tbprint("[thread 0x%llx] Trying to unlock a mutex we don't own\n" , self); |
72 | tbthread_mutex_lock(mutex); |
73 | tbprint("[thread 0x%llx] Starting errorcheck mutex test\n" , self); |
74 | tbsleep(1); |
75 | tbprint("[thread 0x%llx] Finishing errorcheck mutex test\n" , self); |
76 | tbthread_mutex_unlock(mutex); |
77 | if(tbthread_mutex_unlock(mutex) == -EPERM) |
78 | tbprint("[thread 0x%llx] Trying to unlock unlocked mutex\n" , self); |
79 | return 0; |
80 | } |
81 | |
82 | //------------------------------------------------------------------------------ |
83 | // Test recursive mutex |
84 | //------------------------------------------------------------------------------ |
85 | void *thread_func_recursive(void *arg) |
86 | { |
87 | tbthread_t self = tbthread_self(); |
88 | tbthread_mutex_t *mutex = (tbthread_mutex_t*)arg; |
89 | int locked = 0; |
90 | if(!tbthread_mutex_trylock(mutex)) { |
91 | tbprint("[thread 0x%llx] Trying to actuire the mutex succeeded\n" , self); |
92 | locked = 1; |
93 | } |
94 | else |
95 | tbprint("[thread 0x%llx] Trying to actuire the mutex failed\n" , self); |
96 | |
97 | if(!locked) |
98 | tbthread_mutex_lock(mutex); |
99 | tbthread_mutex_lock(mutex); |
100 | tbthread_mutex_lock(mutex); |
101 | tbprint("[thread 0x%llx] Starting recursive mutex test\n" , self); |
102 | tbsleep(1); |
103 | tbprint("[thread 0x%llx] Finishing recursive mutex test\n" , self); |
104 | tbthread_mutex_unlock(mutex); |
105 | tbthread_mutex_unlock(mutex); |
106 | tbthread_mutex_unlock(mutex); |
107 | return 0; |
108 | } |
109 | |
110 | //------------------------------------------------------------------------------ |
111 | // Start the show |
112 | //------------------------------------------------------------------------------ |
113 | int main(int argc, char **argv) |
114 | { |
115 | tbthread_init(); |
116 | |
117 | tbthread_t thread[5]; |
118 | tbthread_attr_t attr; |
119 | void *ret; |
120 | int st = 0; |
121 | |
122 | //---------------------------------------------------------------------------- |
123 | // Initialize the mutexes |
124 | //---------------------------------------------------------------------------- |
125 | tbthread_mutexattr_t mattr; |
126 | tbthread_mutex_t mutex_normal; |
127 | tbthread_mutex_t mutex_errorcheck; |
128 | tbthread_mutex_t mutex_recursive; |
129 | |
130 | tbthread_mutexattr_init(&mattr); |
131 | tbthread_mutex_init(&mutex_normal, 0); |
132 | tbthread_mutexattr_settype(&mattr, TBTHREAD_MUTEX_ERRORCHECK); |
133 | tbthread_mutex_init(&mutex_errorcheck, &mattr); |
134 | tbthread_mutexattr_settype(&mattr, TBTHREAD_MUTEX_RECURSIVE);; |
135 | tbthread_mutex_init(&mutex_recursive, &mattr); |
136 | |
137 | //---------------------------------------------------------------------------- |
138 | // Spawn the threads to test the normal mutex |
139 | //---------------------------------------------------------------------------- |
140 | tbprint("[thread main] Testing normal mutex\n" ); |
141 | tbthread_attr_init(&attr); |
142 | for(int i = 0; i < 5; ++i) { |
143 | st = tbthread_create(&thread[i], &attr, thread_func_normal, &mutex_normal); |
144 | if(st != 0) { |
145 | tbprint("Failed to spawn thread %d: %s\n" , i, tbstrerror(-st)); |
146 | goto exit; |
147 | } |
148 | tbthread_detach(thread[i]); |
149 | } |
150 | |
151 | tbprint("[thread main] Threads spawned successfully\n" ); |
152 | tbprint("[thread main] Sleeping 7 seconds\n" ); |
153 | tbsleep(7); |
154 | |
155 | //---------------------------------------------------------------------------- |
156 | // Spawn threads to thest the errorcheck mutex |
157 | //---------------------------------------------------------------------------- |
158 | void *(*errChkFunc[2])(void *) = { |
159 | thread_func_errorcheck1, thread_func_errorcheck2 }; |
160 | tbprint("---\n" ); |
161 | tbprint("[thread main] Testing errorcheck mutex\n" ); |
162 | for(int i = 0; i < 2; ++i) { |
163 | st = tbthread_create(&thread[i], &attr, errChkFunc[i], &mutex_errorcheck); |
164 | if(st != 0) { |
165 | tbprint("Failed to spawn thread %d: %s\n" , i, tbstrerror(-st)); |
166 | goto exit; |
167 | } |
168 | tbthread_detach(thread[i]); |
169 | } |
170 | |
171 | tbprint("[thread main] Threads spawned successfully\n" ); |
172 | tbprint("[thread main] Sleeping 5 seconds\n" ); |
173 | tbsleep(5); |
174 | |
175 | //---------------------------------------------------------------------------- |
176 | // Spawn the threads to test the recursive mutex |
177 | //---------------------------------------------------------------------------- |
178 | tbprint("---\n" ); |
179 | tbprint("[thread main] Testing recursive mutex\n" ); |
180 | tbthread_attr_init(&attr); |
181 | for(int i = 0; i < 5; ++i) { |
182 | st = tbthread_create(&thread[i], &attr, thread_func_recursive, |
183 | &mutex_recursive); |
184 | if(st != 0) { |
185 | tbprint("Failed to spawn thread %d: %s\n" , i, tbstrerror(-st)); |
186 | goto exit; |
187 | } |
188 | tbthread_detach(thread[i]); |
189 | } |
190 | |
191 | tbprint("[thread main] Threads spawned successfully\n" ); |
192 | tbprint("[thread main] Sleeping 7 seconds\n" ); |
193 | tbsleep(7); |
194 | |
195 | exit: |
196 | tbthread_finit(); |
197 | return st; |
198 | }; |
199 | |