]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/dde/ddekit/src/thread.c
Inital import
[l4.git] / l4 / pkg / dde / ddekit / src / thread.c
1 #include <l4/dde/ddekit/thread.h>
2 #include <l4/dde/ddekit/condvar.h>
3 #include <l4/dde/ddekit/panic.h>
4 #include <l4/dde/ddekit/assert.h>
5 #include <l4/dde/ddekit/memory.h>
6 #include "config.h"
7 #include <l4/dde/ddekit/printf.h>
8
9 #include <l4/dde/dde.h>
10 #include <l4/log/log.h>
11 #ifndef ARCH_arm
12 #include <l4/util/rdtsc.h>
13 #endif
14 #include <l4/util/util.h>
15 #include <l4/sys/thread.h>
16 #include <l4/sys/debugger.h>
17
18 #include <stdio.h>
19 #include <string.h>
20 #include <pthread-l4.h>
21
22 #define DDEKIT_THREAD_STACK_SIZE 0x4000 /* 16 KB */
23
24 #define WARN_UNIMPL         ddekit_printf("unimplemented: %s\n", __FUNCTION__)
25
26 static struct ddekit_slab *ddekit_stack_slab = NULL;
27
28 struct ddekit_thread {
29         pthread_t pthread;
30         void *data;
31         void *stack;
32         ddekit_condvar_t *sleep_cv;
33         const char *name;
34 };
35
36 /**
37  * The thread-local-storage key for the thread struct.
38  */
39 static pthread_key_t tlskey_thread;
40
41 struct startup_args {
42         void (*fun)(void *); ///< real function to run
43         void *arg;           ///< startup arguments to fun
44         const char *name;    ///< thread name
45         pthread_mutex_t mtx; ///< mutex to sync starter with new thread
46         ddekit_thread_t *td; ///< thread data return value
47 };
48
49 ddekit_thread_t *ddekit_thread_setup_myself(const char *name) {
50         ddekit_thread_t *td;
51         int namelen = strlen(name);
52         char *pname;
53         
54         td = ddekit_simple_malloc(sizeof(*td) + (namelen+1));
55         pname = (char *) td + sizeof(*td);
56
57         td->data=NULL;
58         td->sleep_cv = ddekit_condvar_init();
59         td->pthread = pthread_self();
60         td->name = pname;
61
62         strcpy(pname, name);
63
64         l4_debugger_set_object_name(pthread_getl4cap(pthread_self()), td->name);
65
66         pthread_setspecific(tlskey_thread, td);
67
68         return td;
69 }
70
71
72 /* 
73  * Thread startup function.
74  *
75  * In the beginning of starting a thread, we need to setup some additional
76  * data structures, so we do reroute call flow through this function. It 
77  * performs setup, then notifies the caller of its success and thereafter
78  * runs the real thread function.
79  */
80 static void *ddekit_thread_startup(void *arg) {
81         struct startup_args *su = (struct startup_args*)arg;
82         /*
83          * Copy function pointer and arg ptr from su, so that
84          * ddekit_thread_create() can later on free this temporary
85          * object.
86          */
87         void (*_fn)(void *) = su->fun;
88         void *_arg = su->arg;
89
90         /* init dde thread structure */
91         su->td = ddekit_thread_setup_myself(su->name);
92
93         /* startup ready, notify parent */
94         pthread_mutex_unlock(&su->mtx);
95
96         /* Call thread routine */
97         _fn(_arg);
98
99         return NULL;
100 }
101
102
103 /*
104  * Create a new DDEKit thread (using pthreads).
105  */
106 ddekit_thread_t *ddekit_thread_create(void (*fun)(void *), void *arg, const char *name,
107                                       unsigned prio __attribute__((unused)))
108 {
109         struct startup_args su;      // startup args we (temporarily) share with the
110                                      // new thread
111         ddekit_thread_t *td;         // thread descriptor
112         pthread_t l4td;              // pthread
113         pthread_attr_t thread_attr;  // pthread attributes -> we actually set our
114                                      // our own stack
115         int err;
116         void *stack;                 // thread stack
117         
118         /*
119          * Things we need to tell our new thread:
120          */
121         su.fun  = fun;
122         su.arg  = arg;
123         su.name = name;
124
125         /*
126          * Initialize the handshake mutex. We lock it and then wait for it being
127          * unlocked. The latter is done by the newly created thread after it has
128          * successfully set up everything.
129          */
130         if ((err = pthread_mutex_init(&su.mtx, NULL)) != 0)
131                 ddekit_panic("Error initializing pthread_mutex");
132         pthread_mutex_lock(&su.mtx);
133
134         /*
135          * Allocate a stack
136          */
137         stack  = ddekit_slab_alloc(ddekit_stack_slab);
138         if (stack == NULL)
139                 ddekit_panic("Cannot allocate stack for new thread.");
140
141         /*
142          * Setup new thread's attributes, namely stack address and stack size.
143          *
144          * NOTE: attr_setstack requires the _beginning_ of the stack area as
145          * parameter, not the initial stack pointer!
146          */
147         if ((err = pthread_attr_init(&thread_attr)) != 0)
148                 ddekit_panic("error initializing pthread attr: %d", err);
149         if ((err = pthread_attr_setstack(&thread_attr, stack, DDEKIT_THREAD_STACK_SIZE))
150                 != 0)
151                 ddekit_panic("error setting pthread stack: %d", err);
152
153         /*
154          * Create thread
155          */
156         err = pthread_create(&l4td, &thread_attr, ddekit_thread_startup, &su);
157         if (err != 0)
158                 ddekit_panic("error creating thread");
159
160         /*
161          * Wait for child to finish startup, then destroy the handshake mtx.
162          */
163         pthread_mutex_lock(&su.mtx);
164         pthread_mutex_destroy(&su.mtx);
165
166         /*
167          * Store stack address in thread descriptor and return it
168          */
169         td = su.td;
170         td->stack = stack;
171         
172         return td;
173 }
174
175 ddekit_thread_t *ddekit_thread_myself(void) {
176         ddekit_thread_t *ret = (ddekit_thread_t *)pthread_getspecific(tlskey_thread);
177         Assert(ret);
178         return ret;
179 }
180
181 void ddekit_thread_set_data(ddekit_thread_t *thread, void *data) {
182         Assert(thread);
183         thread->data = data;
184 }
185
186 void ddekit_thread_set_my_data(void *data) {
187         ddekit_thread_set_data(ddekit_thread_myself(), data);
188 }
189
190 void *ddekit_thread_get_data(ddekit_thread_t *thread) {
191         return thread->data;
192 }
193
194 void *ddekit_thread_get_my_data() {
195         return ddekit_thread_get_data(ddekit_thread_myself());
196 }
197
198 void ddekit_thread_msleep(unsigned long msecs) {
199         l4_sleep(msecs);
200 }
201
202 void ddekit_thread_usleep(unsigned long usecs) {
203 #ifndef ARCH_arm
204         l4_busy_wait_us(usecs);
205 #endif
206 }
207
208
209 void ddekit_thread_nsleep(unsigned long nsecs) {
210 #ifndef ARCH_arm
211         l4_busy_wait_ns(nsecs);
212 #endif
213 }
214
215 void ddekit_thread_sleep(ddekit_lock_t *lock) {
216         ddekit_thread_t *td;
217
218         td = ddekit_thread_myself();
219
220         ddekit_condvar_wait(td->sleep_cv, lock);
221 }
222
223 void  ddekit_thread_wakeup(ddekit_thread_t *td) {
224         ddekit_condvar_signal(td->sleep_cv);
225 }
226
227 void  ddekit_thread_exit() {
228         ddekit_thread_t *td;
229
230         td = ddekit_thread_myself();
231         
232         pthread_exit(0);
233
234         ddekit_slab_free(ddekit_stack_slab ,td->stack);
235         
236 }
237
238 int ddekit_thread_terminate(ddekit_thread_t *t)
239 {
240         return pthread_cancel(t->pthread);
241 }
242
243 const char *ddekit_thread_get_name(ddekit_thread_t *thread) {
244         return thread->name;
245 }
246
247 int ddekit_thread_get_id(ddekit_thread_t *t)
248 {
249         return (int)(t->pthread);
250 }
251
252 void ddekit_thread_schedule(void)
253 {
254         l4_thread_yield();
255 }
256
257 void ddekit_yield(void)
258 {
259         l4_thread_yield();
260 }
261
262 void ddekit_init_threads() {
263         /* register TLS key for pointer to dde thread structure */
264         int err = pthread_key_create(&tlskey_thread, NULL);
265         if (err != 0)
266                 ddekit_panic("pthread_key_create()");
267         
268         /* setup dde part of thread data */
269         ddekit_thread_setup_myself("main");
270         
271         /* create slab for stacks */
272         ddekit_stack_slab = ddekit_slab_init(DDEKIT_THREAD_STACK_SIZE, 1);
273 }