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>
7 #include <l4/dde/ddekit/printf.h>
9 #include <l4/dde/dde.h>
10 #include <l4/log/log.h>
12 #include <l4/util/rdtsc.h>
14 #include <l4/util/util.h>
15 #include <l4/sys/thread.h>
16 #include <l4/sys/debugger.h>
20 #include <pthread-l4.h>
22 #define DDEKIT_THREAD_STACK_SIZE 0x4000 /* 16 KB */
24 #define WARN_UNIMPL ddekit_printf("unimplemented: %s\n", __FUNCTION__)
26 static struct ddekit_slab *ddekit_stack_slab = NULL;
28 struct ddekit_thread {
32 ddekit_condvar_t *sleep_cv;
37 * The thread-local-storage key for the thread struct.
39 static pthread_key_t tlskey_thread;
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
49 ddekit_thread_t *ddekit_thread_setup_myself(const char *name) {
51 int namelen = strlen(name);
54 td = ddekit_simple_malloc(sizeof(*td) + (namelen+1));
55 pname = (char *) td + sizeof(*td);
58 td->sleep_cv = ddekit_condvar_init();
59 td->pthread = pthread_self();
64 l4_debugger_set_object_name(pthread_getl4cap(pthread_self()), td->name);
66 pthread_setspecific(tlskey_thread, td);
73 * Thread startup function.
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.
80 static void *ddekit_thread_startup(void *arg) {
81 struct startup_args *su = (struct startup_args*)arg;
83 * Copy function pointer and arg ptr from su, so that
84 * ddekit_thread_create() can later on free this temporary
87 void (*_fn)(void *) = su->fun;
90 /* init dde thread structure */
91 su->td = ddekit_thread_setup_myself(su->name);
93 /* startup ready, notify parent */
94 pthread_mutex_unlock(&su->mtx);
96 /* Call thread routine */
104 * Create a new DDEKit thread (using pthreads).
106 ddekit_thread_t *ddekit_thread_create(void (*fun)(void *), void *arg, const char *name,
107 unsigned prio __attribute__((unused)))
109 struct startup_args su; // startup args we (temporarily) share with the
111 ddekit_thread_t *td; // thread descriptor
112 pthread_t l4td; // pthread
113 pthread_attr_t thread_attr; // pthread attributes -> we actually set our
116 void *stack; // thread stack
119 * Things we need to tell our new thread:
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.
130 if ((err = pthread_mutex_init(&su.mtx, NULL)) != 0)
131 ddekit_panic("Error initializing pthread_mutex");
132 pthread_mutex_lock(&su.mtx);
137 stack = ddekit_slab_alloc(ddekit_stack_slab);
139 ddekit_panic("Cannot allocate stack for new thread.");
142 * Setup new thread's attributes, namely stack address and stack size.
144 * NOTE: attr_setstack requires the _beginning_ of the stack area as
145 * parameter, not the initial stack pointer!
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))
151 ddekit_panic("error setting pthread stack: %d", err);
156 err = pthread_create(&l4td, &thread_attr, ddekit_thread_startup, &su);
158 ddekit_panic("error creating thread");
161 * Wait for child to finish startup, then destroy the handshake mtx.
163 pthread_mutex_lock(&su.mtx);
164 pthread_mutex_destroy(&su.mtx);
167 * Store stack address in thread descriptor and return it
175 ddekit_thread_t *ddekit_thread_myself(void) {
176 ddekit_thread_t *ret = (ddekit_thread_t *)pthread_getspecific(tlskey_thread);
181 void ddekit_thread_set_data(ddekit_thread_t *thread, void *data) {
186 void ddekit_thread_set_my_data(void *data) {
187 ddekit_thread_set_data(ddekit_thread_myself(), data);
190 void *ddekit_thread_get_data(ddekit_thread_t *thread) {
194 void *ddekit_thread_get_my_data() {
195 return ddekit_thread_get_data(ddekit_thread_myself());
198 void ddekit_thread_msleep(unsigned long msecs) {
202 void ddekit_thread_usleep(unsigned long usecs) {
204 l4_busy_wait_us(usecs);
209 void ddekit_thread_nsleep(unsigned long nsecs) {
211 l4_busy_wait_ns(nsecs);
215 void ddekit_thread_sleep(ddekit_lock_t *lock) {
218 td = ddekit_thread_myself();
220 ddekit_condvar_wait(td->sleep_cv, lock);
223 void ddekit_thread_wakeup(ddekit_thread_t *td) {
224 ddekit_condvar_signal(td->sleep_cv);
227 void ddekit_thread_exit() {
230 td = ddekit_thread_myself();
234 ddekit_slab_free(ddekit_stack_slab ,td->stack);
238 int ddekit_thread_terminate(ddekit_thread_t *t)
240 return pthread_cancel(t->pthread);
243 const char *ddekit_thread_get_name(ddekit_thread_t *thread) {
247 int ddekit_thread_get_id(ddekit_thread_t *t)
249 return (int)(t->pthread);
252 void ddekit_thread_schedule(void)
257 void ddekit_yield(void)
262 void ddekit_init_threads() {
263 /* register TLS key for pointer to dde thread structure */
264 int err = pthread_key_create(&tlskey_thread, NULL);
266 ddekit_panic("pthread_key_create()");
268 /* setup dde part of thread data */
269 ddekit_thread_setup_myself("main");
271 /* create slab for stacks */
272 ddekit_stack_slab = ddekit_slab_init(DDEKIT_THREAD_STACK_SIZE, 1);