diff options
author | Zheng Da <zhengda1936@gmail.com> | 2009-11-18 01:45:36 +0100 |
---|---|---|
committer | Zheng Da <zhengda1936@gmail.com> | 2009-11-18 01:45:36 +0100 |
commit | 35881fb690c341f53ea3fb969e8d87b69401e49c (patch) | |
tree | 4d1a37876a75d3bf4f8d868b0f3f2680152c7299 /libddekit | |
parent | 8ac96c5d189d0259317e38c1d92bb901d1c98e14 (diff) |
Adapt the implementation of DDEKit threads.
Diffstat (limited to 'libddekit')
-rw-r--r-- | libddekit/include/ddekit/thread.h | 19 | ||||
-rw-r--r-- | libddekit/thread.c | 213 |
2 files changed, 97 insertions, 135 deletions
diff --git a/libddekit/include/ddekit/thread.h b/libddekit/include/ddekit/thread.h index ecd399d9..6e505818 100644 --- a/libddekit/include/ddekit/thread.h +++ b/libddekit/include/ddekit/thread.h @@ -3,8 +3,6 @@ /** \defgroup DDEKit_threads */ -#include <l4/dde/ddekit/lock.h> - struct ddekit_thread; typedef struct ddekit_thread ddekit_thread_t; @@ -118,29 +116,12 @@ void ddekit_thread_wakeup(ddekit_thread_t *thread); */ void ddekit_thread_exit(void) __attribute__((noreturn)); -/** Terminate a thread - * - * \ingroup DDEKit_threads - */ -void ddekit_thread_terminate(ddekit_thread_t *thread); - /** Get the name, a thread registered with DDEKit. * * \ingroup DDEKit_threads */ const char *ddekit_thread_get_name(ddekit_thread_t *thread); -/** Get unique ID of a DDEKit thread. - * - * \ingroup DDEKit_threads - * - * DDEKit does not allow direct access to the thread data - * structure, since this struct contains L4-specific data types. - * However, applications might want to get some kind of ID related - * to a ddekit_thread, for instance to use it as a Linux-like PID. - */ -int ddekit_thread_get_id(ddekit_thread_t *thread); - /** Hint that this thread is done and may be scheduled somehow. * * \ingroup DDEKit_threads diff --git a/libddekit/thread.c b/libddekit/thread.c index db767dc9..a4566d77 100644 --- a/libddekit/thread.c +++ b/libddekit/thread.c @@ -1,114 +1,68 @@ -#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> +#include <cthreads.h> +#include <time.h> +#include <error.h> + +#include "ddekit/thread.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; + struct cthread thread; }; -/** - * 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); +static void setup_thread (cthread_t *t, const char *name) { + if (name) { + const char *cpy = NULL; - td->data=NULL; - td->sleep_cv = ddekit_condvar_init(); - td->l4thread = l4thread_myself(); - td->name = pname; + cpy = malloc (strlen (name) + 1); + if (cpy == NULL) + error (0, 0, "fail to allocate memory"); + else + strcpy (cpy, name); - strcpy(pname, name); + cthread_set_name (t, name); + } - l4thread_data_set_current(tlskey_thread, td); - - return td; + /* + * ldata isn't used by cthread. Since cthread isn't exposed to + * the user of this library. It's very safe to store + * the condition variable in ldata. + */ + sleep_cond = condition_alloc (); + condition_init (sleep_cond); + cthread_set_ldata (t, sleep_cond); } -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); +ddekit_thread_t *ddekit_thread_setup_myself(const char *name) { + ddekit_thread_t *td = ddekit_thread_myself(); - /* call thread routine */ - su.fun(su.arg); + setup_thread (&td->thread, name); + return td; } 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; - + condition_t sleep_cond; + + // TODO not very sure whether I should let the thread suspend + // before initialization is completed. + td = (ddekit_thread_t *) cthread_fork (fun, arg); + setup_thread (&td->thread, name); return td; } ddekit_thread_t *ddekit_thread_myself(void) { - return (ddekit_thread_t *) l4thread_data_get_current(tlskey_thread); + return (ddekit_thread_t *) cthread_self (); } void ddekit_thread_set_data(ddekit_thread_t *thread, void *data) { - thread->data = data; + // TODO not very sure whether I should call cthread_set_ldata + // or cthread_set_data. + cthread_set_data ((cthread_t) thread, data); } void ddekit_thread_set_my_data(void *data) { @@ -116,7 +70,7 @@ void ddekit_thread_set_my_data(void *data) { } void *ddekit_thread_get_data(ddekit_thread_t *thread) { - return thread->data; + return cthread_data ((cthread_t) thread); } void *ddekit_thread_get_my_data() { @@ -124,72 +78,99 @@ void *ddekit_thread_get_my_data() { } void ddekit_thread_msleep(unsigned long msecs) { - l4thread_sleep(msecs); + int ret; + struct timespec rgt; + + rgt.tv_sec = (time_t) (msecs / 1000); + rgt.tv_nsec = (msecs % 1000) * 1000 * 1000; + ret = nanosleep (&rgt , NULL); + if (ret < 0) + error (0, errno, "nanosleep"); } void ddekit_thread_usleep(unsigned long usecs) { - l4_busy_wait_us(usecs); + int ret; + struct timespec rgt; + + rgt.tv_sec = (time_t) (usecs / 1000 / 1000); + rgt.tv_nsec = (usecs % (1000 * 1000)) * 1000; + ret = nanosleep (&rgt , NULL); + if (ret < 0) + error (0, errno, "nanosleep"); } void ddekit_thread_nsleep(unsigned long nsecs) { - l4_busy_wait_ns(nsecs); + int ret; + struct timespec rgt; + + rgt.tv_sec = (time_t) (nsecs / 1000 / 1000 / 1000); + rgt.tv_nsec = nsecs % (1000 * 1000 * 1000); + ret = nanosleep (&rgt , NULL); + if (ret < 0) + error (0, errno, "nanosleep"); } void ddekit_thread_sleep(ddekit_lock_t *lock) { ddekit_thread_t *td; + condition_t sleep_cond; td = ddekit_thread_myself(); + sleep_cond = ddekit_thread_get_data (&td->thread); - ddekit_condvar_wait(td->sleep_cv, lock); + mutex_lock (lock); + // TODO condition_wait cannot guarantee that the thread is + // woke up by another thread, maybe by signals. + // Does it matter here? + condition_wait (sleep_cond, lock); + mutex_unlock (lock); } void ddekit_thread_wakeup(ddekit_thread_t *td) { - ddekit_condvar_signal(td->sleep_cv); -} - -void ddekit_thread_exit() { ddekit_thread_t *td; + condition_t sleep_cond; td = ddekit_thread_myself(); - - l4thread_exit(); + sleep_cond = ddekit_thread_get_data (&td->thread); - ddekit_slab_free(ddekit_stack_slab ,td->stack); - + condition_signal (sleep_cond); } -void ddekit_thread_terminate(ddekit_thread_t *t) -{ - l4thread_shutdown(t->l4thread); -} +void ddekit_thread_exit() { + const char *name; + condition_t sleep_cond; + cthread_t t = cthread_self (); -const char *ddekit_thread_get_name(ddekit_thread_t *thread) { - return thread->name; + // TODO I hope I don't need a lock to protect ldata and name. + + /* I have to free the sleep condition variable + * before the thread exits. */ + sleep_cond = cthread_ldata (t); + cthread_set_ldata (t, NULL); + condition_free (sleep_cond); + + name = cthread_name (t); + cthread_set_name (t, NULL); + free (name); + + cthread_exit (0); } -int ddekit_thread_get_id(ddekit_thread_t *t) -{ - return t->l4thread; +const char *ddekit_thread_get_name(ddekit_thread_t *thread) { + return cthread_name ((cthread_t) thread); } void ddekit_thread_schedule(void) { - l4_yield(); + cthread_yield(); } void ddekit_yield(void) { - l4_yield(); + cthread_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); + // TODO maybe the name has already been set. + cthread_set_name (cthread_self (), "main"); } |