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//------------------------------------------------------------------------------
57typedef struct list {
58 struct list *next;
59 struct list *prev;
60 void *element;
61} list_t;
62
63//------------------------------------------------------------------------------
64// Thread attirbutes
65//------------------------------------------------------------------------------
66typedef 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//------------------------------------------------------------------------------
78typedef 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//------------------------------------------------------------------------------
107typedef struct
108{
109 uint8_t type;
110 uint8_t protocol;
111 uint8_t prioceiling;
112} tbthread_mutexattr_t;
113
114//------------------------------------------------------------------------------
115// Mutex
116//------------------------------------------------------------------------------
117typedef 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//------------------------------------------------------------------------------
133typedef int tbthread_once_t;
134
135#define TBTHREAD_ONCE_INIT 0
136
137//------------------------------------------------------------------------------
138// RW lock
139//------------------------------------------------------------------------------
140typedef 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//------------------------------------------------------------------------------
154typedef 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//------------------------------------------------------------------------------
168void tbthread_init();
169void tbthread_finit();
170void tbthread_attr_init(tbthread_attr_t *attr);
171int tbthread_attr_setdetachstate(tbthread_attr_t *attr, int state);
172int tbthread_create(tbthread_t *thread, const tbthread_attr_t *attrs,
173 void *(*f)(void *), void *arg);
174void tbthread_exit(void *retval);
175int tbthread_detach(tbthread_t thread);
176int tbthread_join(tbthread_t thread, void **retval);
177int tbthread_equal(tbthread_t t1, tbthread_t t2);
178int tbthread_once(tbthread_once_t *once, void (*func)(void));
179int tbthread_cancel(tbthread_t thread);
180void tbthread_cleanup_push(void (*func)(void *), void *arg);
181void tbthread_cleanup_pop(int execute);
182int tbthread_setcancelstate(int state, int *oldstate);
183int tbthread_setcanceltype(int type, int *oldtype);
184void tbthread_testcancel();
185
186//------------------------------------------------------------------------------
187// TLS
188//------------------------------------------------------------------------------
189typedef uint16_t tbthread_key_t;
190tbthread_t tbthread_self();
191int tbthread_key_create(tbthread_key_t *key, void (*destructor)(void *));
192int tbthread_key_delete(tbthread_key_t key);
193void *tbthread_getspecific(tbthread_key_t key);
194int tbthread_setspecific(tbthread_key_t kay, void *value);
195
196//------------------------------------------------------------------------------
197// Mutexes
198//------------------------------------------------------------------------------
199int tbthread_mutexattr_init(tbthread_mutexattr_t *attr);
200int tbthread_mutexattr_destroy(tbthread_mutexattr_t *attr);
201int tbthread_mutexattr_gettype(const tbthread_mutexattr_t *attr, int *type);
202int tbthread_mutexattr_settype(tbthread_mutexattr_t *attr, int type);
203
204int tbthread_mutex_init(tbthread_mutex_t *mutex,
205 const tbthread_mutexattr_t *attr);
206int tbthread_mutex_destroy(tbthread_mutex_t *mutex);
207int tbthread_mutex_lock(tbthread_mutex_t *mutex);
208int tbthread_mutex_trylock(tbthread_mutex_t *mutex);
209int tbthread_mutex_unlock(tbthread_mutex_t *mutex);
210
211//------------------------------------------------------------------------------
212// Scheduling
213//------------------------------------------------------------------------------
214int tbthread_setschedparam(tbthread_t thread, int policy, int priority);
215int tbthread_getschedparam(tbthread_t thread, int *policy, int *priority);
216
217int tbthread_attr_setschedpolicy(tbthread_attr_t *attr, int policy);
218int tbthread_attr_setschedpriority(tbthread_attr_t *attr, int priority);
219int tbthread_attr_setinheritsched(tbthread_attr_t *attr, int inheritsched);
220
221int tbthread_mutexattr_setprioceiling(tbthread_mutexattr_t *attr, int ceiling);
222int tbthread_mutexattr_setprotocol(tbthread_mutexattr_t *attr, int protocol);
223
224int tbthread_mutex_getprioceiling(const tbthread_mutex_t *mutex, int *ceiling);
225int tbthread_mutex_setprioceiling(tbthread_mutex_t *mutex, int ceiling,
226 int *old_ceiling);
227
228//------------------------------------------------------------------------------
229// RW Lock
230//-----------------------------------------------------------------------------
231int tbthread_rwlock_init(tbthread_rwlock_t *rwlock);
232int tbthread_rwlock_destroy(tbthread_rwlock_t *rwlock);
233
234int tbthread_rwlock_rdlock(tbthread_rwlock_t *rwlock);
235int tbthread_rwlock_wrlock(tbthread_rwlock_t *rwlock);
236int tbthread_rwlock_unlock(tbthread_rwlock_t *rwlock);
237
238int tbthread_rwlock_tryrdlock(tbthread_rwlock_t *rwlock);
239int tbthread_rwlock_trywrlock(tbthread_rwlock_t *rwlock);
240
241//------------------------------------------------------------------------------
242// Condvar
243//------------------------------------------------------------------------------
244int tbthread_cond_broadcast(tbthread_cond_t *cond);
245int tbthread_cond_signal(tbthread_cond_t *cond);
246int tbthread_cond_wait(tbthread_cond_t *cond, tbthread_mutex_t *mutex);
247
248//------------------------------------------------------------------------------
249// Utility functions
250//------------------------------------------------------------------------------
251void *malloc(size_t size);
252void free(void *ptr);
253void *realloc(void *ptr, size_t size);
254void *calloc(size_t nmemb, size_t size);
255void tbprint(const char *format, ...);
256int tbwrite(int fd, const char *buffer, unsigned long len);
257void tbsleep(int secs);
258void *tbmmap(void *addr, unsigned long length, int prot, int flags, int fd,
259 unsigned long offset);
260int tbmunmap(void *addr, unsigned long length);
261
262int tbclone(int (*fn)(void *), void *arg, int flags, void *child_stack, ...
263 /* pid_t *ptid, pid_t *ctid, void *tls */ );
264
265void *tbbrk(void *addr);
266
267uint64_t tbtime();
268uint32_t tbrandom(uint32_t *seed);
269const char *tbstrerror(int errno);
270
271int 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//------------------------------------------------------------------------------
317int list_add_elem(list_t *list, void *element, int front);
318void list_add(list_t *list, list_t *node, int front);
319void list_add_here(list_t *list, list_t *node, int (*here)(void*, void*));
320void list_rm(list_t *node);
321list_t *list_find_elem(list_t *list, void *element);
322list_t *list_find_elem_func(list_t *list, void *element,
323 int (*func)(void*, void*));
324void list_for_each_elem(list_t *list, void (*func)(void *));
325void list_clear(list_t *list);
326