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
|
#include <l4/dde/ddekit/thread.h>
#include <l4/dde/ddekit/condvar.h>
#include <l4/dde/ddekit/panic.h>
#include <l4/dde/ddekit/memory.h>
#include <l4/dde/ddekit/printf.h>
#include <l4/dde/dde.h>
#include <l4/thread/thread.h>
#include <l4/log/l4log.h>
#include <l4/sys/syscalls.h>
#include <l4/util/rdtsc.h>
#include <stdio.h>
#include <string.h>
#define DDEKIT_THREAD_STACK_SIZE 0x2000 /* 8 KB */
static struct ddekit_slab *ddekit_stack_slab = NULL;
struct ddekit_thread {
l4thread_t l4thread;
void *data;
void *stack;
ddekit_condvar_t *sleep_cv;
const char *name;
};
/**
* The thread-local-storage key for the BSD struct thread.
*/
static int tlskey_thread;
struct startup_args {
void (*fun)(void *);
void *arg;
const char *name;
};
ddekit_thread_t *ddekit_thread_setup_myself(const char *name) {
ddekit_thread_t *td;
int namelen = strlen(name);
char *pname;
td = ddekit_simple_malloc(sizeof(*td) + (namelen+1));
pname = (char *) td + sizeof(*td);
td->data=NULL;
td->sleep_cv = ddekit_condvar_init();
td->l4thread = l4thread_myself();
td->name = pname;
strcpy(pname, name);
l4thread_data_set_current(tlskey_thread, td);
return td;
}
static void ddekit_thread_startup(void *arg) {
struct startup_args su;
ddekit_thread_t *td;
/* copy arg to su so that it can bee freed by caller */
su = *((struct startup_args*)arg);
/* init dde thread structure */
td = ddekit_thread_setup_myself(su.name);
/* inform caller of initialization */
l4thread_started(td);
/* call thread routine */
su.fun(su.arg);
}
ddekit_thread_t *ddekit_thread_create(void (*fun)(void *), void *arg, const char *name) {
struct startup_args su;
ddekit_thread_t *td;
l4thread_t l4td;
char l4name[20];
void *stack;
su.fun = fun;
su.arg = arg;
su.name = name;
snprintf(l4name, 20, ".%s", name);
stack = ddekit_slab_alloc(ddekit_stack_slab);
l4td = l4thread_create_long(L4THREAD_INVALID_ID, ddekit_thread_startup, l4name,
(l4_addr_t) stack + (DDEKIT_THREAD_STACK_SIZE-1 )* sizeof (void *),
DDEKIT_THREAD_STACK_SIZE,
L4THREAD_DEFAULT_PRIO, &su, L4THREAD_CREATE_SYNC);
if (l4td < 0)
ddekit_panic("error creating thread");
td = (ddekit_thread_t*) l4thread_startup_return(l4td);
td->stack = stack;
return td;
}
ddekit_thread_t *ddekit_thread_myself(void) {
return (ddekit_thread_t *) l4thread_data_get_current(tlskey_thread);
}
void ddekit_thread_set_data(ddekit_thread_t *thread, void *data) {
thread->data = data;
}
void ddekit_thread_set_my_data(void *data) {
ddekit_thread_set_data(ddekit_thread_myself(), data);
}
void *ddekit_thread_get_data(ddekit_thread_t *thread) {
return thread->data;
}
void *ddekit_thread_get_my_data() {
return ddekit_thread_get_data(ddekit_thread_myself());
}
void ddekit_thread_msleep(unsigned long msecs) {
l4thread_sleep(msecs);
}
void ddekit_thread_usleep(unsigned long usecs) {
l4_busy_wait_us(usecs);
}
void ddekit_thread_nsleep(unsigned long nsecs) {
l4_busy_wait_ns(nsecs);
}
void ddekit_thread_sleep(ddekit_lock_t *lock) {
ddekit_thread_t *td;
td = ddekit_thread_myself();
ddekit_condvar_wait(td->sleep_cv, lock);
}
void ddekit_thread_wakeup(ddekit_thread_t *td) {
ddekit_condvar_signal(td->sleep_cv);
}
void ddekit_thread_exit() {
ddekit_thread_t *td;
td = ddekit_thread_myself();
l4thread_exit();
ddekit_slab_free(ddekit_stack_slab ,td->stack);
}
void ddekit_thread_terminate(ddekit_thread_t *t)
{
l4thread_shutdown(t->l4thread);
}
const char *ddekit_thread_get_name(ddekit_thread_t *thread) {
return thread->name;
}
int ddekit_thread_get_id(ddekit_thread_t *t)
{
return t->l4thread;
}
void ddekit_thread_schedule(void)
{
l4_yield();
}
void ddekit_yield(void)
{
l4_yield();
}
void ddekit_init_threads() {
/* register TLS key for pointer to dde thread structure */
tlskey_thread = l4thread_data_allocate_key();
/* setup dde part of thread data */
ddekit_thread_setup_myself("main");
/* create slab for stacks */
ddekit_stack_slab = ddekit_slab_init(DDEKIT_THREAD_STACK_SIZE, 1);
}
|