summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZheng Da <zhengda1936@gmail.com>2009-11-18 01:45:36 +0100
committerZheng Da <zhengda1936@gmail.com>2009-11-18 01:45:36 +0100
commit35881fb690c341f53ea3fb969e8d87b69401e49c (patch)
tree4d1a37876a75d3bf4f8d868b0f3f2680152c7299
parent8ac96c5d189d0259317e38c1d92bb901d1c98e14 (diff)
Adapt the implementation of DDEKit threads.
-rw-r--r--libddekit/include/ddekit/thread.h19
-rw-r--r--libddekit/thread.c213
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");
}