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 | #pragma once |
21 | |
22 | #include <stdint.h> |
23 | #include <asm/unistd_64.h> |
24 | #include <asm-generic/errno.h> |
25 | #include <stddef.h> |
26 | #include <asm/signal.h> |
27 | #include <asm-generic/siginfo.h> |
28 | #include <linux/sched.h> |
29 | |
30 | //------------------------------------------------------------------------------ |
31 | // Constants |
32 | //------------------------------------------------------------------------------ |
33 | #define TBTHREAD_MAX_KEYS 1024 |
34 | #define TBTHREAD_MUTEX_NORMAL 0 |
35 | #define TBTHREAD_MUTEX_ERRORCHECK 1 |
36 | #define TBTHREAD_MUTEX_RECURSIVE 2 |
37 | #define TBTHREAD_MUTEX_DEFAULT 0 |
38 | #define TBTHREAD_CREATE_DETACHED 0 |
39 | #define TBTHREAD_CREATE_JOINABLE 1 |
40 | #define TBTHREAD_CANCEL_ENABLE 1 |
41 | #define TBTHREAD_CANCEL_DISABLE 0 |
42 | #define TBTHREAD_CANCEL_DEFERRED 1 |
43 | #define TBTHREAD_CANCEL_ASYNCHRONOUS 0 |
44 | |
45 | #define TBTHREAD_CANCELED ((void*)-1) |
46 | |
47 | #define TBTHREAD_INHERIT_SCHED 1 |
48 | #define TBTHREAD_EXPLICIT_SCHED 0 |
49 | |
50 | #define TBTHREAD_PRIO_NONE 3 |
51 | #define TBTHREAD_PRIO_INHERIT 4 |
52 | #define TBTHREAD_PRIO_PROTECT 5 |
53 | |
54 | //------------------------------------------------------------------------------ |
55 | // List struct |
56 | //------------------------------------------------------------------------------ |
57 | typedef struct list { |
58 | struct list *next; |
59 | struct list *prev; |
60 | void *element; |
61 | } list_t; |
62 | |
63 | //------------------------------------------------------------------------------ |
64 | // Thread attirbutes |
65 | //------------------------------------------------------------------------------ |
66 | typedef struct |
67 | { |
68 | uint32_t stack_size; |
69 | uint8_t joinable; |
70 | uint8_t sched_inherit; |
71 | uint8_t sched_policy; |
72 | uint8_t sched_priority; |
73 | } tbthread_attr_t; |
74 | |
75 | //------------------------------------------------------------------------------ |
76 | // Thread descriptor |
77 | //------------------------------------------------------------------------------ |
78 | typedef struct tbthread |
79 | { |
80 | struct tbthread *self; |
81 | void *stack; |
82 | uint32_t stack_size; |
83 | uint32_t tid; |
84 | void *(*fn)(void *); |
85 | void *arg; |
86 | void *retval; |
87 | struct |
88 | { |
89 | uint64_t seq; |
90 | void *data; |
91 | } tls[TBTHREAD_MAX_KEYS]; |
92 | uint8_t join_status; |
93 | uint8_t cancel_status; |
94 | uint16_t sched_info; |
95 | uint16_t user_sched_info; |
96 | struct tbthread *joiner; |
97 | list_t cleanup_handlers; |
98 | list_t protect_mutexes; |
99 | list_t inherit_mutexes; |
100 | uint32_t start_status; |
101 | uint32_t lock; |
102 | } *tbthread_t; |
103 | |
104 | //------------------------------------------------------------------------------ |
105 | // Mutex attributes |
106 | //------------------------------------------------------------------------------ |
107 | typedef struct |
108 | { |
109 | uint8_t type; |
110 | uint8_t protocol; |
111 | uint8_t prioceiling; |
112 | } tbthread_mutexattr_t; |
113 | |
114 | //------------------------------------------------------------------------------ |
115 | // Mutex |
116 | //------------------------------------------------------------------------------ |
117 | typedef struct |
118 | { |
119 | int futex; |
120 | uint8_t type; |
121 | uint8_t protocol; |
122 | uint16_t sched_info; |
123 | tbthread_t owner; |
124 | uint64_t counter; |
125 | uint32_t internal_futex; |
126 | } tbthread_mutex_t; |
127 | |
128 | #define TBTHREAD_MUTEX_INITIALIZER {0, 0, TBTHREAD_PRIO_NONE, 0, 0, 0, 0} |
129 | |
130 | //------------------------------------------------------------------------------ |
131 | // Once |
132 | //------------------------------------------------------------------------------ |
133 | typedef int tbthread_once_t; |
134 | |
135 | #define TBTHREAD_ONCE_INIT 0 |
136 | |
137 | //------------------------------------------------------------------------------ |
138 | // RW lock |
139 | //------------------------------------------------------------------------------ |
140 | typedef struct { |
141 | int lock; |
142 | int writers_queued; |
143 | int rd_futex; |
144 | int wr_futex; |
145 | tbthread_t writer; |
146 | int readers; |
147 | } tbthread_rwlock_t; |
148 | |
149 | #define TBTHREAD_RWLOCK_INIT {0, 0, 0, 0, 0, 0} |
150 | |
151 | //------------------------------------------------------------------------------ |
152 | // Condvar |
153 | //------------------------------------------------------------------------------ |
154 | typedef struct { |
155 | int lock; |
156 | int futex; |
157 | uint64_t waiters; |
158 | uint64_t signal_num; |
159 | uint64_t broadcast_seq; |
160 | tbthread_mutex_t *mutex; |
161 | } tbthread_cond_t; |
162 | |
163 | #define TBTHREAD_COND_INITIALIZER {0, 0, 0, 0, 0, 0} |
164 | |
165 | //------------------------------------------------------------------------------ |
166 | // General threading |
167 | //------------------------------------------------------------------------------ |
168 | void tbthread_init(); |
169 | void tbthread_finit(); |
170 | void tbthread_attr_init(tbthread_attr_t *attr); |
171 | int tbthread_attr_setdetachstate(tbthread_attr_t *attr, int state); |
172 | int tbthread_create(tbthread_t *thread, const tbthread_attr_t *attrs, |
173 | void *(*f)(void *), void *arg); |
174 | void tbthread_exit(void *retval); |
175 | int tbthread_detach(tbthread_t thread); |
176 | int tbthread_join(tbthread_t thread, void **retval); |
177 | int tbthread_equal(tbthread_t t1, tbthread_t t2); |
178 | int tbthread_once(tbthread_once_t *once, void (*func)(void)); |
179 | int tbthread_cancel(tbthread_t thread); |
180 | void tbthread_cleanup_push(void (*func)(void *), void *arg); |
181 | void tbthread_cleanup_pop(int execute); |
182 | int tbthread_setcancelstate(int state, int *oldstate); |
183 | int tbthread_setcanceltype(int type, int *oldtype); |
184 | void tbthread_testcancel(); |
185 | |
186 | //------------------------------------------------------------------------------ |
187 | // TLS |
188 | //------------------------------------------------------------------------------ |
189 | typedef uint16_t tbthread_key_t; |
190 | tbthread_t tbthread_self(); |
191 | int tbthread_key_create(tbthread_key_t *key, void (*destructor)(void *)); |
192 | int tbthread_key_delete(tbthread_key_t key); |
193 | void *tbthread_getspecific(tbthread_key_t key); |
194 | int tbthread_setspecific(tbthread_key_t kay, void *value); |
195 | |
196 | //------------------------------------------------------------------------------ |
197 | // Mutexes |
198 | //------------------------------------------------------------------------------ |
199 | int tbthread_mutexattr_init(tbthread_mutexattr_t *attr); |
200 | int tbthread_mutexattr_destroy(tbthread_mutexattr_t *attr); |
201 | int tbthread_mutexattr_gettype(const tbthread_mutexattr_t *attr, int *type); |
202 | int tbthread_mutexattr_settype(tbthread_mutexattr_t *attr, int type); |
203 | |
204 | int tbthread_mutex_init(tbthread_mutex_t *mutex, |
205 | const tbthread_mutexattr_t *attr); |
206 | int tbthread_mutex_destroy(tbthread_mutex_t *mutex); |
207 | int tbthread_mutex_lock(tbthread_mutex_t *mutex); |
208 | int tbthread_mutex_trylock(tbthread_mutex_t *mutex); |
209 | int tbthread_mutex_unlock(tbthread_mutex_t *mutex); |
210 | |
211 | //------------------------------------------------------------------------------ |
212 | // Scheduling |
213 | //------------------------------------------------------------------------------ |
214 | int tbthread_setschedparam(tbthread_t thread, int policy, int priority); |
215 | int tbthread_getschedparam(tbthread_t thread, int *policy, int *priority); |
216 | |
217 | int tbthread_attr_setschedpolicy(tbthread_attr_t *attr, int policy); |
218 | int tbthread_attr_setschedpriority(tbthread_attr_t *attr, int priority); |
219 | int tbthread_attr_setinheritsched(tbthread_attr_t *attr, int inheritsched); |
220 | |
221 | int tbthread_mutexattr_setprioceiling(tbthread_mutexattr_t *attr, int ceiling); |
222 | int tbthread_mutexattr_setprotocol(tbthread_mutexattr_t *attr, int protocol); |
223 | |
224 | int tbthread_mutex_getprioceiling(const tbthread_mutex_t *mutex, int *ceiling); |
225 | int tbthread_mutex_setprioceiling(tbthread_mutex_t *mutex, int ceiling, |
226 | int *old_ceiling); |
227 | |
228 | //------------------------------------------------------------------------------ |
229 | // RW Lock |
230 | //----------------------------------------------------------------------------- |
231 | int tbthread_rwlock_init(tbthread_rwlock_t *rwlock); |
232 | int tbthread_rwlock_destroy(tbthread_rwlock_t *rwlock); |
233 | |
234 | int tbthread_rwlock_rdlock(tbthread_rwlock_t *rwlock); |
235 | int tbthread_rwlock_wrlock(tbthread_rwlock_t *rwlock); |
236 | int tbthread_rwlock_unlock(tbthread_rwlock_t *rwlock); |
237 | |
238 | int tbthread_rwlock_tryrdlock(tbthread_rwlock_t *rwlock); |
239 | int tbthread_rwlock_trywrlock(tbthread_rwlock_t *rwlock); |
240 | |
241 | //------------------------------------------------------------------------------ |
242 | // Condvar |
243 | //------------------------------------------------------------------------------ |
244 | int tbthread_cond_broadcast(tbthread_cond_t *cond); |
245 | int tbthread_cond_signal(tbthread_cond_t *cond); |
246 | int tbthread_cond_wait(tbthread_cond_t *cond, tbthread_mutex_t *mutex); |
247 | |
248 | //------------------------------------------------------------------------------ |
249 | // Utility functions |
250 | //------------------------------------------------------------------------------ |
251 | void *malloc(size_t size); |
252 | void free(void *ptr); |
253 | void *realloc(void *ptr, size_t size); |
254 | void *calloc(size_t nmemb, size_t size); |
255 | void tbprint(const char *format, ...); |
256 | int tbwrite(int fd, const char *buffer, unsigned long len); |
257 | void tbsleep(int secs); |
258 | void *tbmmap(void *addr, unsigned long length, int prot, int flags, int fd, |
259 | unsigned long offset); |
260 | int tbmunmap(void *addr, unsigned long length); |
261 | |
262 | int tbclone(int (*fn)(void *), void *arg, int flags, void *child_stack, ... |
263 | /* pid_t *ptid, pid_t *ctid, void *tls */ ); |
264 | |
265 | void *tbbrk(void *addr); |
266 | |
267 | uint64_t tbtime(); |
268 | uint32_t tbrandom(uint32_t *seed); |
269 | const char *tbstrerror(int errno); |
270 | |
271 | int tbsigaction(int signum, struct sigaction *act, struct sigaction *old); |
272 | |
273 | //------------------------------------------------------------------------------ |
274 | // Syscall interface |
275 | //------------------------------------------------------------------------------ |
276 | #define SYSCALL(name, a1, a2, a3, a4, a5, a6) \ |
277 | ({ \ |
278 | long result; \ |
279 | long __a1 = (long)(a1); \ |
280 | long __a2 = (long)(a2); \ |
281 | long __a3 = (long)(a3); \ |
282 | long __a4 = (long)(a4); \ |
283 | long __a5 = (long)(a5); \ |
284 | long __a6 = (long)(a6); \ |
285 | register long _a1 asm("rdi") = __a1; \ |
286 | register long _a2 asm("rsi") = __a2; \ |
287 | register long _a3 asm("rdx") = __a3; \ |
288 | register long _a4 asm("r10") = __a4; \ |
289 | register long _a5 asm("r8") = __a5; \ |
290 | register long _a6 asm("r9") = __a6; \ |
291 | asm volatile ( \ |
292 | "syscall\n\t" \ |
293 | : "=a" (result) \ |
294 | : "0" (name), "r" (_a1), "r" (_a2), "r" (_a3), \ |
295 | "r" (_a4), "r" (_a5), "r" (_a6) \ |
296 | : "memory", "cc", "r11", "cx"); \ |
297 | (long) result; }) |
298 | |
299 | #define SYSCALL0(name) \ |
300 | SYSCALL(name, 0, 0, 0, 0, 0, 0) |
301 | #define SYSCALL1(name, a1) \ |
302 | SYSCALL(name, a1, 0, 0, 0, 0, 0) |
303 | #define SYSCALL2(name, a1, a2) \ |
304 | SYSCALL(name, a1, a2, 0, 0, 0, 0) |
305 | #define SYSCALL3(name, a1, a2, a3) \ |
306 | SYSCALL(name, a1, a2, a3, 0, 0, 0) |
307 | #define SYSCALL4(name, a1, a2, a3, a4) \ |
308 | SYSCALL(name, a1, a2, a3, a4, 0, 0) |
309 | #define SYSCALL5(name, a1, a2, a3, a4, a5) \ |
310 | SYSCALL(name, a1, a2, a3, a4, a5, 0) |
311 | #define SYSCALL6(name, a1, a2, a3, a4, a5, a6) \ |
312 | SYSCALL(name, a1, a2, a3, a4, a5, a6) |
313 | |
314 | //------------------------------------------------------------------------------ |
315 | // List ops |
316 | //------------------------------------------------------------------------------ |
317 | int list_add_elem(list_t *list, void *element, int front); |
318 | void list_add(list_t *list, list_t *node, int front); |
319 | void list_add_here(list_t *list, list_t *node, int (*here)(void*, void*)); |
320 | void list_rm(list_t *node); |
321 | list_t *list_find_elem(list_t *list, void *element); |
322 | list_t *list_find_elem_func(list_t *list, void *element, |
323 | int (*func)(void*, void*)); |
324 | void list_for_each_elem(list_t *list, void (*func)(void *)); |
325 | void list_clear(list_t *list); |
326 | |