diff options
Diffstat (limited to 'libddekit/thread.c')
-rw-r--r-- | libddekit/thread.c | 160 |
1 files changed, 66 insertions, 94 deletions
diff --git a/libddekit/thread.c b/libddekit/thread.c index 10b86de8..8f7b3ed9 100644 --- a/libddekit/thread.c +++ b/libddekit/thread.c @@ -1,8 +1,9 @@ #include <stdio.h> #include <string.h> -#include <cthreads.h> +#include <pthread.h> #include <time.h> #include <error.h> +#include <mach.h> #include <hurd.h> #include <sys/time.h> #include <assert.h> @@ -26,39 +27,30 @@ struct _ddekit_private_data { }; struct ddekit_thread { - struct cthread thread; + pthread_t thread; + char *name; + struct _ddekit_private_data *private; + void *user; }; struct ddekit_sem { - spin_lock_t lock; + pthread_spinlock_t lock; /* A list of thread waiting for the semaphore. */ struct list head; int value; }; -static struct mutex global_lock = MUTEX_INITIALIZER; +static __thread struct ddekit_thread *thread_self; static void _thread_cleanup () { - const char *name; - struct _ddekit_private_data *data; - cthread_t t = cthread_self (); - - /* I have to free the sleep condition variable - * before the thread exits. */ - mutex_lock (&global_lock); - data = cthread_ldata (t); - cthread_set_ldata (t, NULL); - mutex_unlock (&global_lock); mach_port_destroy (mach_task_self (), - data->wakeupmsg.msgh_remote_port); - ddekit_condvar_deinit (data->sleep_cond); - ddekit_simple_free (data); - - name = cthread_name (t); - cthread_set_name (t, NULL); - ddekit_simple_free ((char *) name); + thread_self->private->wakeupmsg.msgh_remote_port); + ddekit_condvar_deinit (thread_self->private->sleep_cond); + ddekit_simple_free (thread_self->private); + ddekit_simple_free (thread_self->name); + ddekit_simple_free (thread_self); } /* Prepare a wakeup message. */ @@ -105,15 +97,9 @@ static void setup_thread (struct ddekit_thread *t, const char *name) { else strcpy (cpy, name); - cthread_set_name (&t->thread, cpy); + t->name = cpy; } - /* - * 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. - */ - private_data = (struct _ddekit_private_data *) ddekit_simple_malloc (sizeof (*private_data)); @@ -126,15 +112,13 @@ static void setup_thread (struct ddekit_thread *t, const char *name) { if (err) error (1, err, "_create_wakeupmsg"); - mutex_lock (&global_lock); - cthread_set_ldata (&t->thread, private_data); - mutex_unlock (&global_lock); + t->private = private_data; } ddekit_thread_t *ddekit_thread_setup_myself(const char *name) { - ddekit_thread_t *td = ddekit_thread_myself(); - + ddekit_thread_t *td = (ddekit_thread_t *) malloc (sizeof (*td)); setup_thread (td, name); + thread_self = td; return td; } @@ -142,54 +126,58 @@ typedef struct { void (*fun)(void *); void *arg; - struct condition cond; - struct mutex lock; + struct ddekit_thread *td; + pthread_cond_t cond; + pthread_mutex_t lock; int status; } priv_arg_t; static void* _priv_fun (void *arg) { priv_arg_t *priv_arg = arg; + thread_self = priv_arg->td; /* We wait until the initialization of the thread is finished. */ - mutex_lock (&priv_arg->lock); + pthread_mutex_lock (&priv_arg->lock); while (!priv_arg->status) - condition_wait (&priv_arg->cond, &priv_arg->lock); - mutex_unlock (&priv_arg->lock); + pthread_cond_wait (&priv_arg->cond, &priv_arg->lock); + pthread_mutex_unlock (&priv_arg->lock); priv_arg->fun(priv_arg->arg); + free (priv_arg->arg); _thread_cleanup (); return NULL; } ddekit_thread_t *ddekit_thread_create(void (*fun)(void *), void *arg, const char *name) { - ddekit_thread_t *td; - priv_arg_t *priv_arg = (priv_arg_t *) malloc (sizeof (*priv_arg)); + ddekit_thread_t *td = (ddekit_thread_t *) malloc (sizeof (*td)); + setup_thread (td, name); + priv_arg_t *priv_arg = (priv_arg_t *) malloc (sizeof (*priv_arg)); priv_arg->fun = fun; priv_arg->arg = arg; - condition_init (&priv_arg->cond); - mutex_init (&priv_arg->lock); + priv_arg->td = td; + pthread_cond_init (&priv_arg->cond, NULL); + pthread_mutex_init (&priv_arg->lock, NULL); priv_arg->status = 0; - td = (ddekit_thread_t *) cthread_fork (_priv_fun, priv_arg); - cthread_detach (&td->thread); - setup_thread (td, name); + pthread_create (&td->thread, NULL, _priv_fun, priv_arg); + pthread_detach (td->thread); /* Tell the new thread that initialization has been finished. */ - mutex_lock (&priv_arg->lock); + pthread_mutex_lock (&priv_arg->lock); priv_arg->status = 1; - cond_signal (&priv_arg->cond); - mutex_unlock (&priv_arg->lock); + pthread_cond_signal (&priv_arg->cond); + pthread_mutex_unlock (&priv_arg->lock); return td; } ddekit_thread_t *ddekit_thread_myself(void) { - return (ddekit_thread_t *) cthread_self (); + return thread_self; } void ddekit_thread_set_data(ddekit_thread_t *thread, void *data) { - cthread_set_data ((cthread_t) thread, data); + thread->user = data; } void ddekit_thread_set_my_data(void *data) { @@ -197,7 +185,7 @@ void ddekit_thread_set_my_data(void *data) { } void *ddekit_thread_get_data(ddekit_thread_t *thread) { - return cthread_data ((cthread_t) thread); + return thread->user; } void *ddekit_thread_get_my_data() { @@ -239,47 +227,36 @@ void ddekit_thread_nsleep(unsigned long nsecs) { } void ddekit_thread_sleep(ddekit_lock_t *lock) { - struct _ddekit_private_data *data; - - mutex_lock (&global_lock); - data= cthread_ldata (cthread_self ()); - mutex_unlock (&global_lock); - - // TODO condition_wait cannot guarantee that the thread is + // TODO pthread_cond_wait cannot guarantee that the thread is // woke up by another thread, maybe by signals. // Does it matter here? - ddekit_condvar_wait (data->sleep_cond, lock); + // If it does, use pthread_hurd_cond_wait_np. + ddekit_condvar_wait (thread_self->private->sleep_cond, lock); } void ddekit_thread_wakeup(ddekit_thread_t *td) { - struct _ddekit_private_data *data; - - mutex_lock (&global_lock); - data = cthread_ldata (&td->thread); - mutex_unlock (&global_lock); - - if (data == NULL) + if (td->private == NULL) return; - ddekit_condvar_signal (data->sleep_cond); + ddekit_condvar_signal (td->private->sleep_cond); } void ddekit_thread_exit() { _thread_cleanup (); - cthread_exit (0); + pthread_exit (NULL); } const char *ddekit_thread_get_name(ddekit_thread_t *thread) { - return cthread_name ((cthread_t) thread); + return thread->name; } void ddekit_thread_schedule(void) { - cthread_yield(); + swtch_pri (0); } void ddekit_yield(void) { - cthread_yield(); + swtch_pri (0); } void ddekit_init_threads() { @@ -324,34 +301,29 @@ static void _block (struct _ddekit_private_data *data) static int _sem_timedwait_internal (ddekit_sem_t *restrict sem, const int timeout) { - struct _ddekit_private_data *self_private_data; - - spin_lock (&sem->lock); + pthread_spin_lock (&sem->lock); if (sem->value > 0) { /* Successful down. */ sem->value --; - spin_unlock (&sem->lock); + pthread_spin_unlock (&sem->lock); return 0; } if (timeout < 0) { + pthread_spin_unlock (&sem->lock); errno = EINVAL; return -1; } /* Add ourselves to the queue. */ - mutex_lock (&global_lock); - self_private_data = cthread_ldata (cthread_self ()); - mutex_unlock (&global_lock); - - add_entry_head (&sem->head, (struct list *) self_private_data); - spin_unlock (&sem->lock); + add_entry_head (&sem->head, &thread_self->private->list); + pthread_spin_unlock (&sem->lock); /* Block the thread. */ if (timeout) { error_t err; - err = _timedblock (self_private_data, timeout); + err = _timedblock (thread_self->private, timeout); if (err) { /* We timed out. We may need to disconnect ourself from the waiter queue. @@ -361,16 +333,16 @@ static int _sem_timedwait_internal (ddekit_sem_t *restrict sem, block. */ assert (err == ETIMEDOUT); - spin_lock (&sem->lock); - remove_entry ((struct list *) self_private_data); - spin_unlock (&sem->lock); + pthread_spin_lock (&sem->lock); + remove_entry (&thread_self->private->list); + pthread_spin_unlock (&sem->lock); errno = err; return -1; } } else - _block (self_private_data); + _block (thread_self->private); return 0; } @@ -390,7 +362,7 @@ ddekit_sem_t *ddekit_sem_init(int value) { ddekit_sem_t *sem = (ddekit_sem_t *) ddekit_simple_malloc (sizeof (*sem)); - sem->lock = SPIN_LOCK_INITIALIZER; + sem->lock = PTHREAD_SPINLOCK_INITIALIZER; sem->head.prev = &sem->head; sem->head.next = &sem->head; sem->value = value; @@ -411,14 +383,14 @@ void ddekit_sem_down(ddekit_sem_t *sem) { /* returns 0 on success, != 0 when it would block */ int ddekit_sem_down_try(ddekit_sem_t *sem) { - spin_lock (&sem->lock); + pthread_spin_lock (&sem->lock); if (sem->value > 0) { /* Successful down. */ sem->value --; - spin_unlock (&sem->lock); + pthread_spin_unlock (&sem->lock); return 0; } - spin_unlock (&sem->lock); + pthread_spin_unlock (&sem->lock); return -1; } @@ -432,19 +404,19 @@ int ddekit_sem_down_timed(ddekit_sem_t *sem, int timo) { void ddekit_sem_up(ddekit_sem_t *sem) { struct _ddekit_private_data *wakeup; - spin_lock (&sem->lock); + pthread_spin_lock (&sem->lock); if (sem->value > 0) { /* Do a quick up. */ assert (EMPTY_LIST (&sem->head)); sem->value ++; - spin_unlock (&sem->lock); + pthread_spin_unlock (&sem->lock); return; } if (EMPTY_LIST (&sem->head)) { /* No one waiting. */ sem->value = 1; - spin_unlock (&sem->lock); + pthread_spin_unlock (&sem->lock); return; } @@ -455,7 +427,7 @@ void ddekit_sem_up(ddekit_sem_t *sem) { struct _ddekit_private_data, list); /* Then drop the lock and transfer control. */ - spin_unlock (&sem->lock); + pthread_spin_unlock (&sem->lock); if (wakeup) _thread_wakeup (wakeup); } |