/
tb.h
255 lines (228 loc) · 9.66 KB
/
tb.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
//------------------------------------------------------------------------------
// Copyright (c) 2016 by Lukasz Janyst <lukasz@jany.st>
//------------------------------------------------------------------------------
// This file is part of thread-bites.
//
// thread-bites is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// thread-bites is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with thread-bites. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------
#pragma once
#include <stdint.h>
#include <asm/unistd_64.h>
#include <asm-generic/errno.h>
#include <stddef.h>
#include <asm/signal.h>
#include <asm-generic/siginfo.h>
#include <linux/sched.h>
//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
#define TBTHREAD_MAX_KEYS 1024
#define TBTHREAD_MUTEX_NORMAL 0
#define TBTHREAD_MUTEX_ERRORCHECK 1
#define TBTHREAD_MUTEX_RECURSIVE 2
#define TBTHREAD_MUTEX_DEFAULT 0
#define TBTHREAD_CREATE_DETACHED 0
#define TBTHREAD_CREATE_JOINABLE 1
#define TBTHREAD_CANCEL_ENABLE 1
#define TBTHREAD_CANCEL_DISABLE 0
#define TBTHREAD_CANCEL_DEFERRED 1
#define TBTHREAD_CANCEL_ASYNCHRONOUS 0
#define TBTHREAD_CANCELED ((void*)-1)
#define TBTHREAD_INHERIT_SCHED 1
#define TBTHREAD_EXPLICIT_SCHED 0
//------------------------------------------------------------------------------
// List struct
//------------------------------------------------------------------------------
typedef struct list {
struct list *next;
struct list *prev;
void *element;
} list_t;
//------------------------------------------------------------------------------
// Thread attirbutes
//------------------------------------------------------------------------------
typedef struct
{
uint32_t stack_size;
uint8_t joinable;
uint8_t sched_inherit;
uint8_t sched_policy;
uint8_t sched_priority;
} tbthread_attr_t;
//------------------------------------------------------------------------------
// Thread descriptor
//------------------------------------------------------------------------------
typedef struct tbthread
{
struct tbthread *self;
void *stack;
uint32_t stack_size;
uint32_t exit_futex;
void *(*fn)(void *);
void *arg;
void *retval;
struct
{
uint64_t seq;
void *data;
} tls[TBTHREAD_MAX_KEYS];
uint8_t join_status;
uint8_t cancel_status;
uint8_t sched_policy;
uint8_t sched_priority;
struct tbthread *joiner;
list_t cleanup_handlers;
uint32_t start_status;
} *tbthread_t;
//------------------------------------------------------------------------------
// Mutex attributes
//------------------------------------------------------------------------------
typedef struct
{
uint8_t type;
} tbthread_mutexattr_t;
//------------------------------------------------------------------------------
// Mutex
//------------------------------------------------------------------------------
typedef struct
{
int futex;
uint8_t type;
tbthread_t owner;
uint64_t counter;
} tbthread_mutex_t;
#define TBTHREAD_MUTEX_INITIALIZER {0, 0, 0, 0}
//------------------------------------------------------------------------------
// Once
//------------------------------------------------------------------------------
typedef int tbthread_once_t;
#define TBTHREAD_ONCE_INIT 0
//------------------------------------------------------------------------------
// General threading
//------------------------------------------------------------------------------
void tbthread_init();
void tbthread_finit();
void tbthread_attr_init(tbthread_attr_t *attr);
int tbthread_attr_setdetachstate(tbthread_attr_t *attr, int state);
int tbthread_create(tbthread_t *thread, const tbthread_attr_t *attrs,
void *(*f)(void *), void *arg);
void tbthread_exit(void *retval);
int tbthread_detach(tbthread_t thread);
int tbthread_join(tbthread_t thread, void **retval);
int tbthread_equal(tbthread_t t1, tbthread_t t2);
int tbthread_once(tbthread_once_t *once, void (*func)(void));
int tbthread_cancel(tbthread_t thread);
void tbthread_cleanup_push(void (*func)(void *), void *arg);
void tbthread_cleanup_pop(int execute);
int tbthread_setcancelstate(int state, int *oldstate);
int tbthread_setcanceltype(int type, int *oldtype);
void tbthread_testcancel();
//------------------------------------------------------------------------------
// TLS
//------------------------------------------------------------------------------
typedef uint16_t tbthread_key_t;
tbthread_t tbthread_self();
int tbthread_key_create(tbthread_key_t *key, void (*destructor)(void *));
int tbthread_key_delete(tbthread_key_t key);
void *tbthread_getspecific(tbthread_key_t key);
int tbthread_setspecific(tbthread_key_t kay, void *value);
//------------------------------------------------------------------------------
// Mutexes
//------------------------------------------------------------------------------
int tbthread_mutexattr_init(tbthread_mutexattr_t *attr);
int tbthread_mutexattr_destroy(tbthread_mutexattr_t *attr);
int tbthread_mutexattr_gettype(const tbthread_mutexattr_t *attr, int *type);
int tbthread_mutexattr_settype(tbthread_mutexattr_t *attr, int type);
int tbthread_mutex_init(tbthread_mutex_t *mutex,
const tbthread_mutexattr_t *attr);
int tbthread_mutex_destroy(tbthread_mutex_t *mutex);
int tbthread_mutex_lock(tbthread_mutex_t *mutex);
int tbthread_mutex_trylock(tbthread_mutex_t *mutex);
int tbthread_mutex_unlock(tbthread_mutex_t *mutex);
//------------------------------------------------------------------------------
// Scheduling
//------------------------------------------------------------------------------
int tbthread_setschedparam(tbthread_t thread, int policy, int priority);
int tbthread_getschedparam(tbthread_t thread, int *policy, int *priority);
int tbthread_attr_setschedpolicy(tbthread_attr_t *attr, int policy);
int tbthread_attr_setschedpriority(tbthread_attr_t *attr, int priority);
int tbthread_attr_setinheritsched(tbthread_attr_t *attr, int inheritsched);
//------------------------------------------------------------------------------
// Utility functions
//------------------------------------------------------------------------------
void *malloc(size_t size);
void free(void *ptr);
void *realloc(void *ptr, size_t size);
void *calloc(size_t nmemb, size_t size);
void tbprint(const char *format, ...);
int tbwrite(int fd, const char *buffer, unsigned long len);
void tbsleep(int secs);
void *tbmmap(void *addr, unsigned long length, int prot, int flags, int fd,
unsigned long offset);
int tbmunmap(void *addr, unsigned long length);
int tbclone(int (*fn)(void *), void *arg, int flags, void *child_stack, ...
/* pid_t *ptid, pid_t *ctid, void *tls */ );
void *tbbrk(void *addr);
uint64_t tbtime();
uint32_t tbrandom(uint32_t *seed);
const char *tbstrerror(int errno);
int tbsigaction(int signum, struct sigaction *act, struct sigaction *old);
//------------------------------------------------------------------------------
// Syscall interface
//------------------------------------------------------------------------------
#define SYSCALL(name, a1, a2, a3, a4, a5, a6) \
({ \
long result; \
long __a1 = (long)(a1); \
long __a2 = (long)(a2); \
long __a3 = (long)(a3); \
long __a4 = (long)(a4); \
long __a5 = (long)(a5); \
long __a6 = (long)(a6); \
register long _a1 asm("rdi") = __a1; \
register long _a2 asm("rsi") = __a2; \
register long _a3 asm("rdx") = __a3; \
register long _a4 asm("r10") = __a4; \
register long _a5 asm("r8") = __a5; \
register long _a6 asm("r9") = __a6; \
asm volatile ( \
"syscall\n\t" \
: "=a" (result) \
: "0" (name), "r" (_a1), "r" (_a2), "r" (_a3), \
"r" (_a4), "r" (_a5), "r" (_a6) \
: "memory", "cc", "r11", "cx"); \
(long) result; })
#define SYSCALL0(name) \
SYSCALL(name, 0, 0, 0, 0, 0, 0)
#define SYSCALL1(name, a1) \
SYSCALL(name, a1, 0, 0, 0, 0, 0)
#define SYSCALL2(name, a1, a2) \
SYSCALL(name, a1, a2, 0, 0, 0, 0)
#define SYSCALL3(name, a1, a2, a3) \
SYSCALL(name, a1, a2, a3, 0, 0, 0)
#define SYSCALL4(name, a1, a2, a3, a4) \
SYSCALL(name, a1, a2, a3, a4, 0, 0)
#define SYSCALL5(name, a1, a2, a3, a4, a5) \
SYSCALL(name, a1, a2, a3, a4, a5, 0)
#define SYSCALL6(name, a1, a2, a3, a4, a5, a6) \
SYSCALL(name, a1, a2, a3, a4, a5, a6)
//------------------------------------------------------------------------------
// List ops
//------------------------------------------------------------------------------
int list_add_elem(list_t *list, void *element, int front);
void list_add(list_t *list, list_t *node, int front);
void list_rm(list_t *node);
list_t *list_find_elem(list_t *list, void *element);
void list_for_each_elem(list_t *list, void (*func)(void *));
void list_clear(list_t *list);