From a3eba19470c09f42272dac5ca1a34bd8a5cbe834 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Tue, 17 Nov 2009 10:26:25 +0100 Subject: The original version of DDEKit. --- libddekit/thread.c | 195 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 libddekit/thread.c (limited to 'libddekit/thread.c') diff --git a/libddekit/thread.c b/libddekit/thread.c new file mode 100644 index 00000000..db767dc9 --- /dev/null +++ b/libddekit/thread.c @@ -0,0 +1,195 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#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; +}; + +/** + * 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); + + td->data=NULL; + td->sleep_cv = ddekit_condvar_init(); + td->l4thread = l4thread_myself(); + td->name = pname; + + strcpy(pname, name); + + l4thread_data_set_current(tlskey_thread, td); + + return td; +} + +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); + + /* call thread routine */ + su.fun(su.arg); +} + +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; + + return td; +} + +ddekit_thread_t *ddekit_thread_myself(void) { + return (ddekit_thread_t *) l4thread_data_get_current(tlskey_thread); +} + +void ddekit_thread_set_data(ddekit_thread_t *thread, void *data) { + thread->data = data; +} + +void ddekit_thread_set_my_data(void *data) { + ddekit_thread_set_data(ddekit_thread_myself(), data); +} + +void *ddekit_thread_get_data(ddekit_thread_t *thread) { + return thread->data; +} + +void *ddekit_thread_get_my_data() { + return ddekit_thread_get_data(ddekit_thread_myself()); +} + +void ddekit_thread_msleep(unsigned long msecs) { + l4thread_sleep(msecs); +} + +void ddekit_thread_usleep(unsigned long usecs) { + l4_busy_wait_us(usecs); +} + + +void ddekit_thread_nsleep(unsigned long nsecs) { + l4_busy_wait_ns(nsecs); +} + +void ddekit_thread_sleep(ddekit_lock_t *lock) { + ddekit_thread_t *td; + + td = ddekit_thread_myself(); + + ddekit_condvar_wait(td->sleep_cv, lock); +} + +void ddekit_thread_wakeup(ddekit_thread_t *td) { + ddekit_condvar_signal(td->sleep_cv); +} + +void ddekit_thread_exit() { + ddekit_thread_t *td; + + td = ddekit_thread_myself(); + + l4thread_exit(); + + ddekit_slab_free(ddekit_stack_slab ,td->stack); + +} + +void ddekit_thread_terminate(ddekit_thread_t *t) +{ + l4thread_shutdown(t->l4thread); +} + +const char *ddekit_thread_get_name(ddekit_thread_t *thread) { + return thread->name; +} + +int ddekit_thread_get_id(ddekit_thread_t *t) +{ + return t->l4thread; +} + +void ddekit_thread_schedule(void) +{ + l4_yield(); +} + +void ddekit_yield(void) +{ + l4_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); +} -- cgit v1.2.3 From 35881fb690c341f53ea3fb969e8d87b69401e49c Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Wed, 18 Nov 2009 01:45:36 +0100 Subject: Adapt the implementation of DDEKit threads. --- libddekit/include/ddekit/thread.h | 19 ---- libddekit/thread.c | 213 +++++++++++++++++--------------------- 2 files changed, 97 insertions(+), 135 deletions(-) (limited to 'libddekit/thread.c') 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 - 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 -#include -#include -#include -#include - -#include -#include -#include -#include -#include - #include #include +#include +#include +#include + +#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"); } -- cgit v1.2.3 From 31452a09c0cf1e9488b75bcff156923ea4fc1a08 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Wed, 18 Nov 2009 03:00:48 +0100 Subject: fix a bug in thread.c. --- libddekit/thread.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'libddekit/thread.c') diff --git a/libddekit/thread.c b/libddekit/thread.c index a4566d77..ddd5c7ef 100644 --- a/libddekit/thread.c +++ b/libddekit/thread.c @@ -116,23 +116,18 @@ void ddekit_thread_sleep(ddekit_lock_t *lock) { condition_t sleep_cond; td = ddekit_thread_myself(); - sleep_cond = ddekit_thread_get_data (&td->thread); + sleep_cond = ddekit_thread_get_data (td); - 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_thread_t *td; condition_t sleep_cond; - td = ddekit_thread_myself(); - sleep_cond = ddekit_thread_get_data (&td->thread); - + sleep_cond = ddekit_thread_get_data (td); condition_signal (sleep_cond); } -- cgit v1.2.3 From 1467ade7d8fd55511e6f94abd41078eab90b57b0 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Sat, 21 Nov 2009 12:52:14 +0100 Subject: Implement the semaphore (in thread.c). --- libddekit/Makefile | 4 +- libddekit/semaphore.c | 48 --------- libddekit/thread.c | 294 ++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 276 insertions(+), 70 deletions(-) delete mode 100644 libddekit/semaphore.c (limited to 'libddekit/thread.c') diff --git a/libddekit/Makefile b/libddekit/Makefile index b2d1a6bc..e9daa648 100644 --- a/libddekit/Makefile +++ b/libddekit/Makefile @@ -20,7 +20,7 @@ makemode := library libname = libddekit SRCS= condvar.c init.c initcall.c interrupt.c lock.c malloc.c memory.c \ - panic.c pci.c pgtab-old.c pgtab.c printf.c resources.c semaphore.c \ + panic.c pci.c pgtab-old.c pgtab.c printf.c resources.c list.c \ thread.c timer.c LCLHDRS = include/ddekit/condvar.h include/ddekit/lock.h \ include/ddekit/initcall.h include/ddekit/debug.h \ @@ -31,7 +31,7 @@ LCLHDRS = include/ddekit/condvar.h include/ddekit/lock.h \ include/ddekit/interrupt.h include/ddekit/resources.h \ include/ddekit/memory.h include/ddekit/timer.h \ include/ddekit/semaphore.h include/dde.h \ - config.h + config.h list.h installhdrs = MIGSTUBS = diff --git a/libddekit/semaphore.c b/libddekit/semaphore.c deleted file mode 100644 index 6fbb7f35..00000000 --- a/libddekit/semaphore.c +++ /dev/null @@ -1,48 +0,0 @@ -#include -#include - -#include - -struct ddekit_sem { - l4semaphore_t sem; -}; - -ddekit_sem_t *ddekit_sem_init(int value) { - ddekit_sem_t *sem; - - sem = (ddekit_sem_t *) ddekit_simple_malloc(sizeof(*sem)); - sem->sem = L4SEMAPHORE_INIT(value); - - return sem; -} - -void ddekit_sem_deinit(ddekit_sem_t *sem) { - ddekit_simple_free(sem); -} - -void ddekit_sem_down(ddekit_sem_t *sem) { -#if 0 - printf("%s:%d sem=%p l4sem=0x%08x\n", __FILE__, __LINE__, sem, sem->sem); - enter_kdebug(""); -#endif - l4semaphore_down(&sem->sem); -/*printf("%s:%d\n", __FILE__, __LINE__); */ -} - -/* returns 0 on success, != 0 when it would block */ -int ddekit_sem_down_try(ddekit_sem_t *sem) { - return l4semaphore_try_down(&sem->sem) ? 0 : 1; -} - -/* returns 0 on success, != 0 on timeout */ -int ddekit_sem_down_timed(ddekit_sem_t *sem, int timo) { - return l4semaphore_down_timed(&sem->sem, timo); -} - -void ddekit_sem_up(ddekit_sem_t *sem) { -#if 0 - printf("%s:%d sem=%p l4sem=0x%08x\n", __FILE__, __LINE__, sem, sem->sem); -#endif - l4semaphore_up(&sem->sem); -} - diff --git a/libddekit/thread.c b/libddekit/thread.c index ddd5c7ef..a095db2f 100644 --- a/libddekit/thread.c +++ b/libddekit/thread.c @@ -4,17 +4,70 @@ #include #include +#include "ddekit/semaphore.h" +#include "list.h" #include "ddekit/thread.h" #define DDEKIT_THREAD_STACK_SIZE 0x2000 /* 8 KB */ static struct ddekit_slab *ddekit_stack_slab = NULL; +struct _ddekit_private_data { + struct list list; + condition_t sleep_cond; + /* point to the thread who has the private data. */ + struct ddekit_thread *thread; + mach_msg_header_t wakeupmsg; + +} + struct ddekit_thread { struct cthread thread; }; +struct ddekit_sem +{ + spin_lock_t lock; + /* A list of thread waiting for the semaphore. */ + struct list head; + int value; +}; + +/* Prepare a wakeup message. */ +static error_t _create_wakeupmsg (struct _ddekit_private_data *data) +{ + kern_return_t err; + + /* Build wakeup message. */ + data->wakeupmsg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0); + data->wakeupmsg.msgh_size = 0; + + err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, + &data->wakeupmsg.msgh_remote_port); + if (err) + return EAGAIN; + + data->wakeupmsg.msgh_local_port = MACH_PORT_NULL; + data->wakeupmsg.msgh_seqno = 0; + data->wakeupmsg.msgh_id = 0; + + err = mach_port_insert_right (mach_task_self (), + data->wakeupmsg.msgh_remote_port, + data->wakeupmsg.msgh_remote_port, + MACH_MSG_TYPE_MAKE_SEND); + if (err) { + mach_port_destroy (mach_task_self (), + data->wakeupmsg.msgh_remote_port); + return EAGAIN; + } + + return 0; +} + static void setup_thread (cthread_t *t, const char *name) { + error_t err; + struct _ddekit_private_data *private_data; + if (name) { const char *cpy = NULL; @@ -32,9 +85,21 @@ static void setup_thread (cthread_t *t, const char *name) { * 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); + + private_data = (struct _ddekit_private_data *) + ddekit_simple_malloc (sizeof (*private_data)); + + private_data->sleep_cond = condition_alloc (); + condition_init (private_data->sleep_cond); + + private_data->list = {&private_data->list, &private_data->list}; + private_data->thread = t; + + err = _create_wakeupmsg (private_data); + // TODO I need to change this. + assert_perror (err); + + cthread_set_ldata (t, private_data); } ddekit_thread_t *ddekit_thread_setup_myself(const char *name) { @@ -46,11 +111,11 @@ ddekit_thread_t *ddekit_thread_setup_myself(const char *name) { ddekit_thread_t *ddekit_thread_create(void (*fun)(void *), void *arg, const char *name) { ddekit_thread_t *td; - condition_t sleep_cond; - // TODO not very sure whether I should let the thread suspend + // TODO I should let the thread suspend // before initialization is completed. td = (ddekit_thread_t *) cthread_fork (fun, arg); + cthread_detach (&td->thread); setup_thread (&td->thread, name); return td; } @@ -60,8 +125,6 @@ ddekit_thread_t *ddekit_thread_myself(void) { } void ddekit_thread_set_data(ddekit_thread_t *thread, void *data) { - // TODO not very sure whether I should call cthread_set_ldata - // or cthread_set_data. cthread_set_data ((cthread_t) thread, data); } @@ -112,37 +175,33 @@ void ddekit_thread_nsleep(unsigned long nsecs) { } 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); + struct _ddekit_private_data *data = cthread_ldata (cthread_self ()); // 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); + condition_wait (data->sleep_cond, lock); } -void ddekit_thread_wakeup(ddekit_thread_t *td) { - condition_t sleep_cond; +void dekit_thread_wakeup(ddekit_thread_t *td) { + struct _ddekit_private_data *data = cthread_ldata (cthread_self ()); - sleep_cond = ddekit_thread_get_data (td); - condition_signal (sleep_cond); + condition_signal (data->sleep_cond); } void ddekit_thread_exit() { const char *name; - condition_t sleep_cond; + struct _ddekit_private_data *data; cthread_t t = cthread_self (); // 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); + data = cthread_ldata (t); cthread_set_ldata (t, NULL); - condition_free (sleep_cond); + condition_free (data->sleep_cond); + ddekit_simple_free (data); name = cthread_name (t); cthread_set_name (t, NULL); @@ -169,3 +228,198 @@ void ddekit_init_threads() { // TODO maybe the name has already been set. cthread_set_name (cthread_self (), "main"); } + +/* Block THREAD. */ +static error_t _timedblock (struct _ddekit_private_data *data, + const struct timespec *abstime) +{ + error_t err; + mach_msg_header_t msg; + mach_msg_timeout_t timeout; + struct timeval now; + + /* We have an absolute time and now we have to convert it to a + relative time. Arg. */ + + err = gettimeofday(&now, NULL); + assert (! err); + + if (now.tv_sec > abstime->tv_sec + || (now.tv_sec == abstime->tv_sec + && now.tv_usec > ((abstime->tv_nsec + 999) / 1000))) + return ETIMEDOUT; + + timeout = (abstime->tv_sec - now.tv_sec) * 1000; + + if (((abstime->tv_nsec + 999) / 1000) >= now.tv_usec) + timeout -= (((abstime->tv_nsec + 999) / 1000) + - now.tv_usec + 999) / 1000; + else + /* Need to do a carry. */ + timeout -= 1000 + ((abstime->tv_nsec + 999999) / 1000000) + - (now.tv_usec + 999) / 1000; + + err = mach_msg (&msg, MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0, + sizeof msg, data->wakeupmsg.msgh_remote_port, + timeout, MACH_PORT_NULL); + if (err == EMACH_RCV_TIMED_OUT) + return ETIMEDOUT; + + assert_perror (err); + return 0; +} + +/* Block THREAD. */ +static void _block (struct _ddekit_private_data *data) +{ + mach_msg_header_t msg; + error_t err; + + err = mach_msg (&msg, MACH_RCV_MSG, 0, sizeof msg, + data->wakeupmsg.msgh_remote_port, + MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + assert_perror (err); +} + +static int _sem_timedwait_internal (sem_t *restrict sem, + const struct timespec *restrict timeout) +{ + struct ddekit_private_data *self_private_data; + + spin_lock (&sem->lock); + if (sem->value > 0) { + /* Successful down. */ + sem->value --; + spin_unlock (&sem->__lock); + return 0; + } + + if (timeout && (timeout->tv_nsec < 0 + || timeout->tv_nsec >= 1000000000)) { + errno = EINVAL; + return -1; + } + + /* Add ourselves to the queue. */ + self_private_data = cthread_ldata (cthread_self ()); + + add_entry_head (&sem->head, (struct list *) self_private_data); + spin_unlock (&sem->lock); + + /* Block the thread. */ + if (timeout) { + error_t err; + + err = _timedblock (self_private_data, timeout); + if (err) { + /* We timed out. We may need to disconnect ourself from the + waiter queue. + + FIXME: What do we do if we get a wakeup message before we + disconnect ourself? It may remain until the next time we + block. */ + assert (err == ETIMEDOUT); + + spin_lock (&sem->lock); + remove_entry ((struct list *) self_private_data); + spin_unlock (&sem->lock); + + errno = err; + return -1; + } + } + else + _block (self_private_data); + + return 0; +} + +/* Wakeup THREAD. */ +static void _thread_wakeup (struct _ddekit_private_data *data) +{ + error_t err; + + err = mach_msg (&data->wakeupmsg, MACH_SEND_MSG, + sizeof (data->wakeupmsg), 0, MACH_PORT_NULL, + MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + assert_perror (err); +} + +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->head = {&sem->head, &sem->head}; + sem->value = value; + return sem; +} + +void ddekit_sem_deinit(ddekit_sem_t *sem) { + if (!EMPTY_ENTRY (&sem->head)) { + error (0, EBUSY, "ddekit_sem_deinit"); + } + else + ddekit_simple_free(sem); +} + +void ddekit_sem_down(ddekit_sem_t *sem) { + _sem_timedwait_internal (sem, NULL); +} + +/* returns 0 on success, != 0 when it would block */ +int ddekit_sem_down_try(ddekit_sem_t *sem) { + spin_lock (&sem->lock); + if (sem->value > 0) { + /* Successful down. */ + sem->value --; + spin_unlock (&sem->lock); + return 0; + } + spin_unlock (&sem->lock); + + return -1; +} + +/* returns 0 on success, != 0 on timeout */ +int ddekit_sem_down_timed(ddekit_sem_t *sem, int timo) { + /* wait for up to timo milliseconds */ + struct timespec timeout; + + timeout.tv_sec = timo / 1000; + timeout.tv_nsec = (timo % 1000) * 1000 * 1000; + return __sem_timedwait_internal (sem, &timeout); +} + +void ddekit_sem_up(ddekit_sem_t *sem) { + struct _ddekit_thread_data *wakeup; + + spin_lock (&sem->lock); + if (sem->value > 0) { + /* Do a quick up. */ + assert (EMPTY_LIST (&sem->head)); + sem->value ++; + spin_unlock (&sem->lock); + return 0; + } + + if (EMPTY_LIST (&sem->head)) { + /* No one waiting. */ + sem->value = 1; + spin_unlock (&sem->lock); + return 0; + } + + /* Wake someone up. */ + + /* First dequeue someone. */ + wakeup = (struct _ddekit_private_data *) remove_entry_end (&sem->head); + + /* Then drop the lock and transfer control. */ + spin_unlock (&sem->lock); + if (wakeup) + _thread_wakeup (wakeup); + + return 0; +} + -- cgit v1.2.3 From b4bffcfcdf3ab7a55d664e9aa5907f88da503f38 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Sun, 6 Dec 2009 05:14:54 +0100 Subject: The code can be compiled now. --- libddekit/Makefile | 11 +- libddekit/condvar.c | 4 +- libddekit/device.defs | 204 ++++++++++ libddekit/include/Makefile | 9 - libddekit/include/ddekit/assert.h | 4 +- libddekit/include/ddekit/condvar.h | 1 + libddekit/include/ddekit/initcall.h | 42 -- libddekit/include/ddekit/thread.h | 2 + libddekit/init.c | 3 + libddekit/initcall.c | 8 - libddekit/interrupt.c | 63 ++- libddekit/kmem.c | 5 +- libddekit/list.c | 4 +- libddekit/lock.c | 3 +- libddekit/mach.defs | 779 ++++++++++++++++++++++++++++++++++++ libddekit/malloc.c | 3 + libddekit/memory.c | 5 +- libddekit/pci.c | 33 +- libddekit/printf.c | 3 + libddekit/thread.c | 68 ++-- libddekit/timer.c | 7 +- libddekit/vm_param.h | 7 + 22 files changed, 1132 insertions(+), 136 deletions(-) create mode 100644 libddekit/device.defs delete mode 100644 libddekit/include/Makefile delete mode 100644 libddekit/include/ddekit/initcall.h delete mode 100644 libddekit/initcall.c create mode 100644 libddekit/mach.defs create mode 100644 libddekit/vm_param.h (limited to 'libddekit/thread.c') diff --git a/libddekit/Makefile b/libddekit/Makefile index 1203ca38..67a3b193 100644 --- a/libddekit/Makefile +++ b/libddekit/Makefile @@ -19,22 +19,22 @@ dir := libddekit makemode := library libname = libddekit -SRCS= condvar.c init.c initcall.c interrupt.c lock.c malloc.c memory.c \ - pci.c pgtab-old.c pgtab.c printf.c resources.c list.c \ +SRCS= condvar.c init.c interrupt.c lock.c malloc.c memory.c \ + pci.c pgtab.c printf.c resources.c list.c \ thread.c timer.c kmem.c LCLHDRS = include/ddekit/condvar.h include/ddekit/lock.h \ - include/ddekit/initcall.h include/ddekit/debug.h \ + include/ddekit/semaphore.h include/ddekit/debug.h \ include/ddekit/inline.h include/ddekit/panic.h \ include/ddekit/thread.h include/ddekit/types.h \ include/ddekit/pgtab.h include/ddekit/printf.h \ include/ddekit/pci.h include/ddekit/assert.h \ include/ddekit/interrupt.h include/ddekit/resources.h \ include/ddekit/memory.h include/ddekit/timer.h \ - include/ddekit/semaphore.h include/dde.h \ + include/dde.h \ config.h list.h installhdrs = -MIGSTUBS = +MIGSTUBS = deviceUser.o machUser.o OBJS = $(sort $(SRCS:.c=.o) $(MIGSTUBS)) HURDLIBS = threads ports @@ -44,3 +44,4 @@ MIGCOMSFLAGS = -prefix dde_ include ../Makeconf LDFLAGS += -lpciaccess +CFLAGS += -Iinclude -Iinclude/ddekit diff --git a/libddekit/condvar.c b/libddekit/condvar.c index 96e28c07..bbd49417 100644 --- a/libddekit/condvar.c +++ b/libddekit/condvar.c @@ -13,12 +13,12 @@ struct ddekit_condvar { }; ddekit_condvar_t *ddekit_condvar_init() { - ddekit_condvar_t *cvp; + struct condition *cvp; cvp = condition_alloc (); condition_init (cvp); - return cvp; + return (ddekit_condvar_t *) cvp; } void ddekit_condvar_wait(ddekit_condvar_t *cvp, ddekit_lock_t *mp) { diff --git a/libddekit/device.defs b/libddekit/device.defs new file mode 100644 index 00000000..6a73853a --- /dev/null +++ b/libddekit/device.defs @@ -0,0 +1,204 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990,1989 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * File: device/device.defs + * Author: Douglas Orr + * Feb 10, 1988 + * Abstract: + * Mach device support. Mach devices are accessed through + * block and character device interfaces to the kernel. + */ + +#ifdef MACH_KERNEL +simport ; /* for obsolete routines */ +#endif + +subsystem +#if KERNEL_SERVER + KernelServer +#endif + device 2800; + +#include +#include +#include + +serverprefix ds_; + +type pci_config_data_t = array[*:4] of char; +type reply_port_t = MACH_MSG_TYPE_MAKE_SEND_ONCE | polymorphic + ctype: mach_port_t; + +routine device_open( + master_port : mach_port_t; + sreplyport reply_port : reply_port_t; + mode : dev_mode_t; + name : dev_name_t; + out device : device_t + ); + +routine device_close( + device : device_t + ); + +routine device_write( + device : device_t; + sreplyport reply_port : reply_port_t; + in mode : dev_mode_t; + in recnum : recnum_t; + in data : io_buf_ptr_t; + out bytes_written : int + ); + +routine device_write_inband( + device : device_t; + sreplyport reply_port : reply_port_t; + in mode : dev_mode_t; + in recnum : recnum_t; + in data : io_buf_ptr_inband_t; + out bytes_written : int + ); + +routine device_read( + device : device_t; + sreplyport reply_port : reply_port_t; + in mode : dev_mode_t; + in recnum : recnum_t; + in bytes_wanted : int; + out data : io_buf_ptr_t + ); + +routine device_read_inband( + device : device_t; + sreplyport reply_port : reply_port_t; + in mode : dev_mode_t; + in recnum : recnum_t; + in bytes_wanted : int; + out data : io_buf_ptr_inband_t + ); + +/* obsolete */ +routine xxx_device_set_status( + device : device_t; + in flavor : dev_flavor_t; + in status : dev_status_t, IsLong + ); + +/* obsolete */ +routine xxx_device_get_status( + device : device_t; + in flavor : dev_flavor_t; + out status : dev_status_t, IsLong + ); + +/* obsolete */ +routine xxx_device_set_filter( + device : device_t; + in receive_port : mach_port_send_t; + in priority : int; + in filter : filter_array_t, IsLong + ); + +routine device_map( + device : device_t; + in prot : vm_prot_t; + in offset : vm_offset_t; + in size : vm_size_t; + out pager : memory_object_t; + in unmap : int + ); + +routine device_set_status( + device : device_t; + in flavor : dev_flavor_t; + in status : dev_status_t + ); + +routine device_get_status( + device : device_t; + in flavor : dev_flavor_t; + out status : dev_status_t, CountInOut + ); + +routine device_set_filter( + device : device_t; + in receive_port : mach_port_send_t; + in priority : int; + in filter : filter_array_t + ); + +routine device_intr_notify( + master_port : mach_port_t; + in irq : int; + in id : int; + in receive_port : mach_port_send_t + ); + +/* + * Test whether IPC devices exist. + */ +routine pci_present( + master_port : mach_port_t); + +/* + * Find the specified PCI device. + */ +routine pci_find_device( + master_port : mach_port_t; + vendor : short; + device_id : short; + index : short; + out bus : char; + out device_fn : char); + +/* + * Read the configuration space of a IPC device. + */ +routine pci_read_config( + master_port : mach_port_t; + bus : char; + device_fn : char; + where : char; + bytes_wanted : int; + out result : pci_config_data_t); + +/* + * Write the configuration space of a IPC device. + */ +routine pci_write_config( + master_port : mach_port_t; + bus : char; + device_fn : char; + where : char; + data : pci_config_data_t); + +/* + * enable/disable the specified irq. + */ +routine device_irq_enable( + master_port : mach_port_t; + irq : int; + status : char); diff --git a/libddekit/include/Makefile b/libddekit/include/Makefile deleted file mode 100644 index 8d31023f..00000000 --- a/libddekit/include/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -PKGDIR ?= .. -L4DIR ?= $(PKGDIR)/../.. - -# All haeder files found in this directory tree will be automatically -# installed in a way that they can be included with -# #include later. -# No need to list them in this Makefile. - -include $(L4DIR)/mk/include.mk diff --git a/libddekit/include/ddekit/assert.h b/libddekit/include/ddekit/assert.h index 5d572b49..5d593662 100644 --- a/libddekit/include/ddekit/assert.h +++ b/libddekit/include/ddekit/assert.h @@ -1,8 +1,8 @@ #ifndef _ddekit_assert_h #define _ddekit_assert_h -#include -#include +#include "ddekit/printf.h" +#include "ddekit/panic.h" /** \file ddekit/assert.h */ diff --git a/libddekit/include/ddekit/condvar.h b/libddekit/include/ddekit/condvar.h index ba87358d..129a718d 100644 --- a/libddekit/include/ddekit/condvar.h +++ b/libddekit/include/ddekit/condvar.h @@ -2,6 +2,7 @@ #define _ddekit_condvar_h /** \file ddekit/condvar.h */ +#include "ddekit/lock.h" struct ddekit_condvar; typedef struct ddekit_condvar ddekit_condvar_t; diff --git a/libddekit/include/ddekit/initcall.h b/libddekit/include/ddekit/initcall.h deleted file mode 100644 index b503cc6a..00000000 --- a/libddekit/include/ddekit/initcall.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef _ddekit_initcall_h -#define _ddekit_initcall_h - -// from l4/sys/compiler.h -#if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || __GNUC__ >= 4 -#define L4_STICKY(x) __attribute__((used)) x -#else -#define L4_STICKY(x) __attribute__((unused)) x -#endif - -#define l4str(s) #s - -// from dde_linux/ARCH-x86/ctor.h -typedef void (*l4ddekit_initcall_t)(void); - -#define __l4ddekit_initcall(p) \ - __attribute__ ((__section__ (".l4dde_ctors." #p))) - -/** Define a function to be a DDEKit initcall. - * - * Define a function to be a DDEKit initcall. This function will then be placed - * in a separate linker section of the binary (called .l4dde_ctors). The L4Env - * construction mechanism will execute all constructors in this section during - * application startup. - * - * This is the right place to place Linux' module_init functions & Co. - * - * \param fn function - */ -#define DDEKIT_INITCALL(fn) DDEKIT_CTOR(fn, 1) - -#define DDEKIT_CTOR(fn, prio) \ - static l4ddekit_initcall_t \ - L4_STICKY(__l4ddekit_initcall_##fn) \ - __l4ddekit_initcall(prio) = (void *)fn - -/** - * Runs all registered initcalls. - */ -void ddekit_do_initcalls(void); - -#endif diff --git a/libddekit/include/ddekit/thread.h b/libddekit/include/ddekit/thread.h index 6e505818..8ed52013 100644 --- a/libddekit/include/ddekit/thread.h +++ b/libddekit/include/ddekit/thread.h @@ -3,6 +3,8 @@ /** \defgroup DDEKit_threads */ +#include "ddekit/lock.h" + struct ddekit_thread; typedef struct ddekit_thread ddekit_thread_t; diff --git a/libddekit/init.c b/libddekit/init.c index 6bc9d8ff..9114ff46 100644 --- a/libddekit/init.c +++ b/libddekit/init.c @@ -9,8 +9,11 @@ void ddekit_init(void) { extern void linux_kmem_init (); extern int log_init (); + extern void interrupt_init (); + ddekit_init_threads(); linux_kmem_init (); log_init (); + interrupt_init (); } diff --git a/libddekit/initcall.c b/libddekit/initcall.c deleted file mode 100644 index 49e1fec1..00000000 --- a/libddekit/initcall.c +++ /dev/null @@ -1,8 +0,0 @@ -#include - -#include - -void ddekit_do_initcalls() { - crt0_dde_construction(); -} - diff --git a/libddekit/interrupt.c b/libddekit/interrupt.c index 6a8b3fd8..5a778f9b 100644 --- a/libddekit/interrupt.c +++ b/libddekit/interrupt.c @@ -8,9 +8,17 @@ * FIXME use consume flag to indicate IRQ was handled */ +#include +#include +#include +#include + #include "ddekit/interrupt.h" +#include "ddekit/semaphore.h" +#include "ddekit/printf.h" +#include "ddekit/memory.h" -#include +#include "device_U.h" #define DEBUG_INTERRUPTS 0 @@ -18,6 +26,15 @@ #define BLOCK_IRQ 0 +#define MACH_NOTIFY_IRQ 100 + +typedef struct +{ + mach_msg_header_t irq_header; + mach_msg_type_t irq_type; + int irq; +} mach_irq_notification_t; + /* * Internal type for interrupt loop parameters */ @@ -35,19 +52,14 @@ struct intloop_params static struct { - int handle_irq; /* nested irq disable count */ - ddekit_lock_t *irqlock; + int handle_irq; /* nested irq disable count */ + ddekit_lock_t irqlock; ddekit_thread_t *irq_thread; /* thread ID for detaching from IRQ later on */ boolean_t thread_exit; thread_t mach_thread; } ddekit_irq_ctrl[MAX_INTERRUPTS]; - -static void ddekit_irq_exit_fn(l4thread_t thread, void *data) -{ - // TODO we can remove the port for delivery of interrupt explicitly, - // though it cannot cause any harm even if we don't remove it. -} +static mach_port_t master_device; /** * Interrupt service loop @@ -57,26 +69,25 @@ static void intloop(void *arg) { kern_return_t ret; struct intloop_params *params = arg; - mach_port_t delivery_port; + mach_port_t delivery_port = mach_reply_port (); int my_index; my_index = params->irq; - ddekit_irq_ctrl[my_index]->mach_thread = mach_thread_self (); + ddekit_irq_ctrl[my_index].mach_thread = mach_thread_self (); ret = thread_priority (mach_thread_self (), DDEKIT_IRQ_PRIO, 0); if (ret) error (0, ret, "thread_priority"); // TODO I should give another parameter to show whether // the interrupt can be shared. - ret = device_intr_notify (master_device, dev->irq, - dev->dev_id, delivery_port, + ret = device_intr_notify (master_device, params->irq, + 0, delivery_port, MACH_MSG_TYPE_MAKE_SEND); if (!ret) { /* inform thread creator of error */ /* XXX does omega0 error code have any meaning to DDEKit users? */ params->start_err = ret; ddekit_sem_up(params->started); - return NULL; } #if 0 @@ -104,23 +115,25 @@ static void intloop(void *arg) /* It's an interrupt not for us. It shouldn't happen. */ if (irq_header->irq != params->irq) { - LOG("We get interrupt %d, %d is expected", - irq_header->irq, params->irq); + ddekit_printf ("We get interrupt %d, %d is expected", + irq_header->irq, params->irq); return 1; } /* only call registered handler function, if IRQ is not disabled */ ddekit_lock_lock (&ddekit_irq_ctrl[my_index].irqlock); if (ddekit_irq_ctrl[my_index].handle_irq > 0) { - LOGd(DEBUG_INTERRUPTS, "IRQ %x, handler %p", my_index,params->handler); + ddekit_printf ("IRQ %x, handler %p", + my_index,params->handler); params->handler(params->priv); } else - LOGd(DEBUG_INTERRUPTS, "not handling IRQ %x, because it is disabled.", my_index); + ddekit_printf ("not handling IRQ %x, because it is disabled.", + my_index); // ((mig_reply_header_t *) outp)->RetCode = MIG_NO_REPLY; - if (ddekit_irq_ctrl[irq].thread_exit) { + if (ddekit_irq_ctrl[my_index].thread_exit) { ddekit_lock_unlock (&ddekit_irq_ctrl[my_index].irqlock); ddekit_thread_exit(); return 1; @@ -129,7 +142,7 @@ static void intloop(void *arg) return 1; } - mach_msg_server (int_server, 0, delivery_port); + mach_msg_server (irq_server, 0, delivery_port); } @@ -238,3 +251,13 @@ void ddekit_interrupt_enable(int irq) ddekit_lock_unlock (&ddekit_irq_ctrl[irq].irqlock); } } + +void interrupt_init () +{ + + error_t err; + + err = get_privileged_ports (0, &master_device); + if (err) + error (1, err, "get_privileged_ports"); +} diff --git a/libddekit/kmem.c b/libddekit/kmem.c index 4769190e..2e6f7340 100644 --- a/libddekit/kmem.c +++ b/libddekit/kmem.c @@ -28,9 +28,12 @@ #include #include -#include "util.h" #include "vm_param.h" +#include "ddekit/panic.h" + +#define debug ddekit_debug + extern int printf (const char *, ...); /* Amount of memory to reserve for Linux memory allocator. diff --git a/libddekit/list.c b/libddekit/list.c index 992ea9ad..4f163584 100644 --- a/libddekit/list.c +++ b/libddekit/list.c @@ -48,7 +48,7 @@ struct list *remove_entry_head (struct list *head) { struct list *entry = head->next; - if (EMPTY_ENTRY (entry)) + if (EMPTY_LIST (entry)) return NULL; remove_entry (entry); @@ -59,7 +59,7 @@ struct list *remove_entry_end (struct list *head) { struct list *entry = head->prev; - if (EMPTY_ENTRY (entry)) + if (EMPTY_LIST (entry)) return NULL; remove_entry (entry); diff --git a/libddekit/lock.c b/libddekit/lock.c index bf643e65..4c4cff01 100644 --- a/libddekit/lock.c +++ b/libddekit/lock.c @@ -1,6 +1,7 @@ #include #include "ddekit/lock.h" +#include "ddekit/memory.h" #define DDEKIT_DEBUG_LOCKS 0 @@ -48,6 +49,6 @@ int _ddekit_lock_owner(struct ddekit_lock **mtx) { /* The return value is the address of the holder. * I hope it will be OK. At least, it is OK * for the current implementation of DDE Linux/BSD */ - return (int) (*mtx)->holder; + return (int) (*mtx)->helder; } diff --git a/libddekit/mach.defs b/libddekit/mach.defs new file mode 100644 index 00000000..764bd451 --- /dev/null +++ b/libddekit/mach.defs @@ -0,0 +1,779 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University. + * Copyright (c) 1993,1994 The University of Utah and + * the Computer Systems Laboratory (CSL). + * All rights reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF + * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY + * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF + * THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * Matchmaker definitions file for Mach kernel interface. + */ + +#ifdef MACH_KERNEL +simport ; /* for obsolete routines */ +#endif /* MACH_KERNEL */ + +subsystem +#if KERNEL_USER + KernelUser +#endif /* KERNEL_USER */ +#if KERNEL_SERVER + KernelServer +#endif /* KERNEL_SERVER */ + mach 2000; + +#ifdef KERNEL_USER +userprefix r_; +#endif /* KERNEL_USER */ + +#include +#include + +skip; /* old port_allocate */ +skip; /* old port_deallocate */ +skip; /* old port_enable */ +skip; /* old port_disable */ +skip; /* old port_select */ +skip; /* old port_set_backlog */ +skip; /* old port_status */ + +/* + * Create a new task with an empty set of IPC rights, + * and having an address space constructed from the + * target task (or empty, if inherit_memory is FALSE). + */ +routine task_create( + target_task : task_t; + inherit_memory : boolean_t; + out child_task : task_t); + +/* + * Destroy the target task, causing all of its threads + * to be destroyed, all of its IPC rights to be deallocated, + * and all of its address space to be deallocated. + */ +routine task_terminate( + target_task : task_t); + +/* + * Get user-level handler entry points for all + * emulated system calls. + */ +routine task_get_emulation_vector( + task : task_t; + out vector_start : int; + out emulation_vector: emulation_vector_t); + +/* + * Establish user-level handlers for the specified + * system calls. Non-emulated system calls are specified + * with emulation_vector[i] == EML_ROUTINE_NULL. + */ +routine task_set_emulation_vector( + task : task_t; + vector_start : int; + emulation_vector: emulation_vector_t); + + +/* + * Returns the set of threads belonging to the target task. + */ +routine task_threads( + target_task : task_t; + out thread_list : thread_array_t); + +/* + * Returns information about the target task. + */ +routine task_info( + target_task : task_t; + flavor : int; + out task_info_out : task_info_t, CountInOut); + + +skip; /* old task_status */ +skip; /* old task_set_notify */ +skip; /* old thread_create */ + +/* + * Destroy the target thread. + */ +routine thread_terminate( + target_thread : thread_t); + +/* + * Return the selected state information for the target + * thread. If the thread is currently executing, the results + * may be stale. [Flavor THREAD_STATE_FLAVOR_LIST provides a + * list of valid flavors for the target thread.] + */ +routine thread_get_state( + target_thread : thread_t; + flavor : int; + out old_state : thread_state_t, CountInOut); + +/* + * Set the selected state information for the target thread. + * If the thread is currently executing, the state change + * may be ill-defined. + */ +routine thread_set_state( + target_thread : thread_t; + flavor : int; + new_state : thread_state_t); + +/* + * Returns information about the target thread. + */ +routine thread_info( + target_thread : thread_t; + flavor : int; + out thread_info_out : thread_info_t, CountInOut); + +skip; /* old thread_mutate */ + +/* + * Allocate zero-filled memory in the address space + * of the target task, either at the specified address, + * or wherever space can be found (if anywhere is TRUE), + * of the specified size. The address at which the + * allocation actually took place is returned. + */ +#ifdef EMULATOR +skip; /* the emulator redefines vm_allocate using vm_map */ +#else /* EMULATOR */ +routine vm_allocate( + target_task : vm_task_t; + inout address : vm_address_t; + size : vm_size_t; + anywhere : boolean_t); +#endif /* EMULATOR */ + +skip; /* old vm_allocate_with_pager */ + +/* + * Deallocate the specified range from the virtual + * address space of the target task. + */ +routine vm_deallocate( + target_task : vm_task_t; + address : vm_address_t; + size : vm_size_t); + +/* + * Set the current or maximum protection attribute + * for the specified range of the virtual address + * space of the target task. The current protection + * limits the memory access rights of threads within + * the task; the maximum protection limits the accesses + * that may be given in the current protection. + * Protections are specified as a set of {read, write, execute} + * *permissions*. + */ +routine vm_protect( + target_task : vm_task_t; + address : vm_address_t; + size : vm_size_t; + set_maximum : boolean_t; + new_protection : vm_prot_t); + +/* + * Set the inheritance attribute for the specified range + * of the virtual address space of the target task. + * The inheritance value is one of {none, copy, share}, and + * specifies how the child address space should acquire + * this memory at the time of a task_create call. + */ +routine vm_inherit( + target_task : vm_task_t; + address : vm_address_t; + size : vm_size_t; + new_inheritance : vm_inherit_t); + +/* + * Returns the contents of the specified range of the + * virtual address space of the target task. [The + * range must be aligned on a virtual page boundary, + * and must be a multiple of pages in extent. The + * protection on the specified range must permit reading.] + */ +routine vm_read( + target_task : vm_task_t; + address : vm_address_t; + size : vm_size_t; + out data : pointer_t); + +/* + * Writes the contents of the specified range of the + * virtual address space of the target task. [The + * range must be aligned on a virtual page boundary, + * and must be a multiple of pages in extent. The + * protection on the specified range must permit writing.] + */ +routine vm_write( + target_task : vm_task_t; + address : vm_address_t; + data : pointer_t); + +/* + * Copy the contents of the source range of the virtual + * address space of the target task to the destination + * range in that same address space. [Both of the + * ranges must be aligned on a virtual page boundary, + * and must be multiples of pages in extent. The + * protection on the source range must permit reading, + * and the protection on the destination range must + * permit writing.] + */ +routine vm_copy( + target_task : vm_task_t; + source_address : vm_address_t; + size : vm_size_t; + dest_address : vm_address_t); + +/* + * Returns information about the contents of the virtual + * address space of the target task at the specified + * address. The returned protection, inheritance, sharing + * and memory object values apply to the entire range described + * by the address range returned; the memory object offset + * corresponds to the beginning of the address range. + * [If the specified address is not allocated, the next + * highest address range is described. If no addresses beyond + * the one specified are allocated, the call returns KERN_NO_SPACE.] + */ +routine vm_region( + target_task : vm_task_t; + inout address : vm_address_t; + out size : vm_size_t; + out protection : vm_prot_t; + out max_protection : vm_prot_t; + out inheritance : vm_inherit_t; + out is_shared : boolean_t; + /* avoid out-translation of the argument */ + out object_name : memory_object_name_t = + MACH_MSG_TYPE_MOVE_SEND + ctype: mach_port_t; + out offset : vm_offset_t); + +/* + * Return virtual memory statistics for the host + * on which the target task resides. [Note that the + * statistics are not specific to the target task.] + */ +routine vm_statistics( + target_task : vm_task_t; + out vm_stats : vm_statistics_data_t); + +skip; /* old task_by_u*x_pid */ +skip; /* old vm_pageable */ + +/* + * Stash a handful of ports for the target task; child + * tasks inherit this stash at task_create time. + */ +routine mach_ports_register( + target_task : task_t; + init_port_set : mach_port_array_t = + ^array[] of mach_port_t); + +/* + * Retrieve the stashed ports for the target task. + */ +routine mach_ports_lookup( + target_task : task_t; + out init_port_set : mach_port_array_t = + ^array[] of mach_port_t); + +skip; /* old u*x_pid */ +skip; /* old netipc_listen */ +skip; /* old netipc_ignore */ + +/* + * Provide the data contents of a range of the given memory + * object, with the access restriction specified. [Only + * whole virtual pages of data can be accepted; partial pages + * will be discarded. Data should be provided on request, but + * may be provided in advance as desired. When data already + * held by this kernel is provided again, the new data is ignored. + * The access restriction is the subset of {read, write, execute} + * which are prohibited. The kernel may not provide any data (or + * protection) consistency among pages with different virtual page + * alignments within the same object.] + */ +simpleroutine memory_object_data_provided( + memory_control : memory_object_control_t; + offset : vm_offset_t; + data : pointer_t; + lock_value : vm_prot_t); + +/* + * Indicate that a range of the given temporary memory object does + * not exist, and that the backing memory object should be used + * instead (or zero-fill memory be used, if no backing object exists). + * [This call is intended for use only by the default memory manager. + * It should not be used to indicate a real error -- + * memory_object_data_error should be used for that purpose.] + */ +simpleroutine memory_object_data_unavailable( + memory_control : memory_object_control_t; + offset : vm_offset_t; + size : vm_size_t); + +/* + * Retrieves the attributes currently associated with + * a memory object. + */ +routine memory_object_get_attributes( + memory_control : memory_object_control_t; + out object_ready : boolean_t; + out may_cache : boolean_t; + out copy_strategy : memory_object_copy_strategy_t); + +/* + * Sets the default memory manager, the port to which + * newly-created temporary memory objects are delivered. + * [See (memory_object_default)memory_object_create.] + * The old memory manager port is returned. + */ +routine vm_set_default_memory_manager( + host_priv : host_priv_t; + inout default_manager : mach_port_make_send_t); + +skip; /* old pager_flush_request */ + +/* + * Control use of the data associated with the given + * memory object. For each page in the given range, + * perform the following operations, in order: + * 1) restrict access to the page (disallow + * forms specified by "prot"); + * 2) write back modifications (if "should_return" + * is RETURN_DIRTY and the page is dirty, or + * "should_return" is RETURN_ALL and the page + * is either dirty or precious); and, + * 3) flush the cached copy (if "should_flush" + * is asserted). + * The set of pages is defined by a starting offset + * ("offset") and size ("size"). Only pages with the + * same page alignment as the starting offset are + * considered. + * + * A single acknowledgement is sent (to the "reply_to" + * port) when these actions are complete. + * + * There are two versions of this routine because IPC distinguishes + * between booleans and integers (a 2-valued integer is NOT a + * boolean). The new routine is backwards compatible at the C + * language interface. + */ +simpleroutine xxx_memory_object_lock_request( + memory_control : memory_object_control_t; + offset : vm_offset_t; + size : vm_size_t; + should_clean : boolean_t; + should_flush : boolean_t; + lock_value : vm_prot_t; + reply_to : mach_port_t = + MACH_MSG_TYPE_MAKE_SEND_ONCE|polymorphic); + + +simpleroutine memory_object_lock_request( + memory_control : memory_object_control_t; + offset : vm_offset_t; + size : vm_size_t; + should_return : memory_object_return_t; + should_flush : boolean_t; + lock_value : vm_prot_t; + reply_to : mach_port_t = + MACH_MSG_TYPE_MAKE_SEND_ONCE|polymorphic); + +/* obsolete */ +routine xxx_task_get_emulation_vector( + task : task_t; + out vector_start : int; + out emulation_vector: xxx_emulation_vector_t, IsLong); + +/* obsolete */ +routine xxx_task_set_emulation_vector( + task : task_t; + vector_start : int; + emulation_vector: xxx_emulation_vector_t, IsLong); + +/* + * Returns information about the host on which the + * target object resides. [This object may be + * a task, thread, or memory_object_control port.] + */ +routine xxx_host_info( + target_task : mach_port_t; + out info : machine_info_data_t); + +/* + * Returns information about a particular processor on + * the host on which the target task resides. + */ +routine xxx_slot_info( + target_task : task_t; + slot : int; + out info : machine_slot_data_t); + +/* + * Performs control operations (currently only + * turning off or on) on a particular processor on + * the host on which the target task resides. + */ +routine xxx_cpu_control( + target_task : task_t; + cpu : int; + running : boolean_t); + +skip; /* old thread_statistics */ +skip; /* old task_statistics */ +skip; /* old netport_init */ +skip; /* old netport_enter */ +skip; /* old netport_remove */ +skip; /* old thread_set_priority */ + +/* + * Increment the suspend count for the target task. + * No threads within a task may run when the suspend + * count for that task is non-zero. + */ +routine task_suspend( + target_task : task_t); + +/* + * Decrement the suspend count for the target task, + * if the count is currently non-zero. If the resulting + * suspend count is zero, then threads within the task + * that also have non-zero suspend counts may execute. + */ +routine task_resume( + target_task : task_t); + +/* + * Returns the current value of the selected special port + * associated with the target task. + */ +routine task_get_special_port( + task : task_t; + which_port : int; + out special_port : mach_port_t); + +/* + * Set one of the special ports associated with the + * target task. + */ +routine task_set_special_port( + task : task_t; + which_port : int; + special_port : mach_port_t); + +/* obsolete */ +routine xxx_task_info( + target_task : task_t; + flavor : int; + out task_info_out : task_info_t, IsLong); + + +/* + * Create a new thread within the target task, returning + * the port representing that new thread. The + * initial execution state of the thread is undefined. + */ +routine thread_create( + parent_task : task_t; + out child_thread : thread_t); + +/* + * Increment the suspend count for the target thread. + * Once this call has completed, the thread will not + * execute any further user or meta- instructions. + * Once suspended, a thread may not execute again until + * its suspend count is zero, and the suspend count + * for its task is also zero. + */ +routine thread_suspend( + target_thread : thread_t); + +/* + * Decrement the suspend count for the target thread, + * if that count is not already zero. + */ +routine thread_resume( + target_thread : thread_t); + +/* + * Cause any user or meta- instructions currently being + * executed by the target thread to be aborted. [Meta- + * instructions consist of the basic traps for IPC + * (e.g., msg_send, msg_receive) and self-identification + * (e.g., task_self, thread_self, thread_reply). Calls + * described by MiG interfaces are not meta-instructions + * themselves.] + */ +routine thread_abort( + target_thread : thread_t); + +/* obsolete */ +routine xxx_thread_get_state( + target_thread : thread_t; + flavor : int; + out old_state : thread_state_t, IsLong); + +/* obsolete */ +routine xxx_thread_set_state( + target_thread : thread_t; + flavor : int; + new_state : thread_state_t, IsLong); + +/* + * Returns the current value of the selected special port + * associated with the target thread. + */ +routine thread_get_special_port( + thread : thread_t; + which_port : int; + out special_port : mach_port_t); + +/* + * Set one of the special ports associated with the + * target thread. + */ +routine thread_set_special_port( + thread : thread_t; + which_port : int; + special_port : mach_port_t); + +/* obsolete */ +routine xxx_thread_info( + target_thread : thread_t; + flavor : int; + out thread_info_out : thread_info_t, IsLong); + +/* + * Establish a user-level handler for the specified + * system call. + */ +routine task_set_emulation( + target_port : task_t; + routine_entry_pt: vm_address_t; + routine_number : int); + +/* + * Establish restart pc for interrupted atomic sequences. + * This reuses the message number for the old task_get_io_port. + * See task_info.h for description of flavors. + * + */ +routine task_ras_control( + target_task : task_t; + basepc : vm_address_t; + boundspc : vm_address_t; + flavor : int); + + + +skip; /* old host_ipc_statistics */ +skip; /* old port_names */ +skip; /* old port_type */ +skip; /* old port_rename */ +skip; /* old port_allocate */ +skip; /* old port_deallocate */ +skip; /* old port_set_backlog */ +skip; /* old port_status */ +skip; /* old port_set_allocate */ +skip; /* old port_set_deallocate */ +skip; /* old port_set_add */ +skip; /* old port_set_remove */ +skip; /* old port_set_status */ +skip; /* old port_insert_send */ +skip; /* old port_extract_send */ +skip; /* old port_insert_receive */ +skip; /* old port_extract_receive */ + +/* + * Map a user-defined memory object into the virtual address + * space of the target task. If desired (anywhere is TRUE), + * the kernel will find a suitable address range of the + * specified size; else, the specific address will be allocated. + * + * The beginning address of the range will be aligned on a virtual + * page boundary, be at or beyond the address specified, and + * meet the mask requirements (bits turned on in the mask must not + * be turned on in the result); the size of the range, in bytes, + * will be rounded up to an integral number of virtual pages. + * + * The memory in the resulting range will be associated with the + * specified memory object, with the beginning of the memory range + * referring to the specified offset into the memory object. + * + * The mapping will take the current and maximum protections and + * the inheritance attributes specified; see the vm_protect and + * vm_inherit calls for a description of these attributes. + * + * If desired (copy is TRUE), the memory range will be filled + * with a copy of the data from the memory object; this copy will + * be private to this mapping in this target task. Otherwise, + * the memory in this mapping will be shared with other mappings + * of the same memory object at the same offset (in this task or + * in other tasks). [The Mach kernel only enforces shared memory + * consistency among mappings on one host with similar page alignments. + * The user-defined memory manager for this object is responsible + * for further consistency.] + */ +#ifdef EMULATOR +routine htg_vm_map( + target_task : vm_task_t; + ureplyport reply_port : mach_port_make_send_once_t; + inout address : vm_address_t; + size : vm_size_t; + mask : vm_address_t; + anywhere : boolean_t; + memory_object : memory_object_t; + offset : vm_offset_t; + copy : boolean_t; + cur_protection : vm_prot_t; + max_protection : vm_prot_t; + inheritance : vm_inherit_t); +#else /* EMULATOR */ +routine vm_map( + target_task : vm_task_t; + inout address : vm_address_t; + size : vm_size_t; + mask : vm_address_t; + anywhere : boolean_t; + memory_object : memory_object_t; + offset : vm_offset_t; + copy : boolean_t; + cur_protection : vm_prot_t; + max_protection : vm_prot_t; + inheritance : vm_inherit_t); +#endif /* EMULATOR */ + +/* + * Indicate that a range of the specified memory object cannot + * be provided at this time. [Threads waiting for memory pages + * specified by this call will experience a memory exception. + * Only threads waiting at the time of the call are affected.] + */ +simpleroutine memory_object_data_error( + memory_control : memory_object_control_t; + offset : vm_offset_t; + size : vm_size_t; + error_value : kern_return_t); + +/* + * Make decisions regarding the use of the specified + * memory object. + */ +simpleroutine memory_object_set_attributes( + memory_control : memory_object_control_t; + object_ready : boolean_t; + may_cache : boolean_t; + copy_strategy : memory_object_copy_strategy_t); + +/* + */ +simpleroutine memory_object_destroy( + memory_control : memory_object_control_t; + reason : kern_return_t); + +/* + * Provide the data contents of a range of the given memory + * object, with the access restriction specified, optional + * precious attribute, and reply message. [Only + * whole virtual pages of data can be accepted; partial pages + * will be discarded. Data should be provided on request, but + * may be provided in advance as desired. When data already + * held by this kernel is provided again, the new data is ignored. + * The access restriction is the subset of {read, write, execute} + * which are prohibited. The kernel may not provide any data (or + * protection) consistency among pages with different virtual page + * alignments within the same object. The precious value controls + * how the kernel treats the data. If it is FALSE, the kernel treats + * its copy as a temporary and may throw it away if it hasn't been + * changed. If the precious value is TRUE, the kernel treats its + * copy as a data repository and promises to return it to the manager; + * the manager may tell the kernel to throw it away instead by flushing + * and not cleaning the data -- see memory_object_lock_request. The + * reply_to port is for a compeletion message; it will be + * memory_object_supply_completed.] + */ + +simpleroutine memory_object_data_supply( + memory_control : memory_object_control_t; + offset : vm_offset_t; + data : pointer_t, Dealloc[]; + lock_value : vm_prot_t; + precious : boolean_t; + reply_to : mach_port_t = + MACH_MSG_TYPE_MAKE_SEND_ONCE|polymorphic); + +simpleroutine memory_object_ready( + memory_control : memory_object_control_t; + may_cache : boolean_t; + copy_strategy : memory_object_copy_strategy_t); + +simpleroutine memory_object_change_attributes( + memory_control : memory_object_control_t; + may_cache : boolean_t; + copy_strategy : memory_object_copy_strategy_t; + reply_to : mach_port_t = + MACH_MSG_TYPE_MAKE_SEND_ONCE|polymorphic); + +skip; /* old host_callout_statistics_reset */ +skip; /* old port_set_select */ +skip; /* old port_set_backup */ + +/* + * Set/Get special properties of memory associated + * to some virtual address range, such as cachability, + * migrability, replicability. Machine-dependent. + */ +routine vm_machine_attribute( + target_task : vm_task_t; + address : vm_address_t; + size : vm_size_t; + attribute : vm_machine_attribute_t; + inout value : vm_machine_attribute_val_t); + +/*skip;*/ /* old host_fpa_counters_reset */ + +/* + * This routine is created for allocating DMA buffers. + * We are going to get a contiguous physical memory + * and its physical address in addition to the virtual address. + */ +routine vm_dma_buff_alloc( + host_priv : host_priv_t; + target_task : vm_task_t; + size : vm_size_t; + out vaddr : vm_address_t; + out paddr : vm_address_t); + +/* + * There is no more room in this interface for additional calls. + */ diff --git a/libddekit/malloc.c b/libddekit/malloc.c index c3735bdb..a30cd7b7 100644 --- a/libddekit/malloc.c +++ b/libddekit/malloc.c @@ -29,6 +29,9 @@ * * Each chunk stores its size in the first word for free() to work. */ + +#include + void *ddekit_simple_malloc(unsigned size) { return malloc (size); diff --git a/libddekit/memory.c b/libddekit/memory.c index 93853e55..27be4eeb 100644 --- a/libddekit/memory.c +++ b/libddekit/memory.c @@ -11,8 +11,10 @@ */ #include "ddekit/memory.h" +#include "ddekit/panic.h" extern void * linux_kmalloc (unsigned int size, int priority); +extern void linux_kfree (void *p); /**************** @@ -110,6 +112,7 @@ void *ddekit_slab_get_data(struct ddekit_slab * slab) #if 0 return l4slab_get_data(&slab->cache); #endif + return NULL; } @@ -154,7 +157,7 @@ struct ddekit_slab * ddekit_slab_init(unsigned size, int contiguous) */ void ddekit_large_free(void *objp) { - return linux_kfree (objp); + linux_kfree (objp); } diff --git a/libddekit/pci.c b/libddekit/pci.c index 32e02b84..5c3f4ef6 100644 --- a/libddekit/pci.c +++ b/libddekit/pci.c @@ -1,4 +1,8 @@ +#include #include + +#include "ddekit/assert.h" +#include "ddekit/printf.h" #include "ddekit/pci.h" #include "config.h" @@ -43,8 +47,8 @@ void ddekit_pci_init(void) dev_iter = pci_slot_match_iterator_create (NULL); while ((pci_dev = pci_device_next (dev_iter)) != NULL) { if (slots_found == MAX_PCI_DEVS) { - LOGd(dbg_this, "find more than %d pci devices", - slots_found); + ddekit_printf ("find more than %d pci devices", + slots_found); break; } /* Pretend all our devices are chained to exactly one bus. */ @@ -68,7 +72,7 @@ int ddekit_pci_get_device(int nr, int *bus, int *slot, int *func) { ddekit_pci_dev_t *dev; - LOGd(dbg_this, "searching for dev #%d", nr); + ddekit_printf ("searching for dev #%d", nr); if (nr >= 0 && nr < MAX_PCI_DEVS && !invalid_device(&ddekit_pci_bus[nr])) { dev = &ddekit_pci_bus[nr]; @@ -89,7 +93,8 @@ ddekit_pci_dev_t *ddekit_pci_find_device(int *bus, int *slot, int *func, Assert(slot); Assert(func); - LOGd(dbg_this, "start %p (slot %d)", start, start ? start->slot : -1); + ddekit_printf ("start %p (slot %d)", + start, start ? start->slot : -1); int idx = start ? start->slot + 1 : 0; for ( ; idx < MAX_PCI_DEVS; ++idx) { @@ -214,7 +219,8 @@ int ddekit_pci_writel(int bus, int slot, int func, int pos, ddekit_uint32_t val int ddekit_pci_enable_device(struct ddekit_pci_dev *dev) { - return pci_device_enable (dev->dev); + pci_device_enable (dev->dev); + return 0; } int ddekit_pci_disable_device(struct ddekit_pci_dev *dev) @@ -238,7 +244,7 @@ int ddekit_pci_disable_device(struct ddekit_pci_dev *dev) */ unsigned short ddekit_pci_get_vendor(struct ddekit_pci_dev *dev) { - return dev->dev.vendor_id; + return dev->dev->vendor_id; } @@ -251,7 +257,7 @@ unsigned short ddekit_pci_get_vendor(struct ddekit_pci_dev *dev) */ unsigned short ddekit_pci_get_device_id(struct ddekit_pci_dev *dev) { - return dev->dev.device_id; + return dev->dev->device_id; } @@ -264,7 +270,7 @@ unsigned short ddekit_pci_get_device_id(struct ddekit_pci_dev *dev) */ unsigned short ddekit_pci_get_sub_vendor(struct ddekit_pci_dev *dev) { - return dev->dev.subvendor_id; + return dev->dev->subvendor_id; } @@ -277,7 +283,7 @@ unsigned short ddekit_pci_get_sub_vendor(struct ddekit_pci_dev *dev) */ unsigned short ddekit_pci_get_sub_device(struct ddekit_pci_dev *dev) { - return dev->dev.subdevice_id; + return dev->dev->subdevice_id; } @@ -290,7 +296,7 @@ unsigned short ddekit_pci_get_sub_device(struct ddekit_pci_dev *dev) */ unsigned ddekit_pci_get_dev_class(struct ddekit_pci_dev *dev) { - return dev->dev.device_class; + return dev->dev->device_class; } @@ -303,7 +309,7 @@ unsigned ddekit_pci_get_dev_class(struct ddekit_pci_dev *dev) */ unsigned long ddekit_pci_get_irq(struct ddekit_pci_dev *dev) { - return dev->dev.irq; + return dev->dev->irq; } @@ -345,10 +351,11 @@ char *ddekit_pci_get_slot_name(struct ddekit_pci_dev *dev) */ ddekit_pci_res_t *ddekit_pci_get_resource(struct ddekit_pci_dev *dev, unsigned int idx) { - if (idx > L4IO_PCIDEV_RES) + // TODO +// if (idx > L4IO_PCIDEV_RES) return NULL; - //TODO return (ddekit_pci_res_t *)(&(dev->l4dev.res[idx])); +// return (ddekit_pci_res_t *)(&(dev->l4dev.res[idx])); } diff --git a/libddekit/printf.c b/libddekit/printf.c index bbd58863..72ff5003 100644 --- a/libddekit/printf.c +++ b/libddekit/printf.c @@ -4,7 +4,10 @@ * \date 2006-03-01 */ +#include +#include #include +#include #include #include "ddekit/printf.h" diff --git a/libddekit/thread.c b/libddekit/thread.c index a095db2f..081a4742 100644 --- a/libddekit/thread.c +++ b/libddekit/thread.c @@ -3,14 +3,18 @@ #include #include #include +#include +#include +#include +#include "ddekit/memory.h" #include "ddekit/semaphore.h" #include "list.h" #include "ddekit/thread.h" #define DDEKIT_THREAD_STACK_SIZE 0x2000 /* 8 KB */ -static struct ddekit_slab *ddekit_stack_slab = NULL; +//static struct ddekit_slab *ddekit_stack_slab = NULL; struct _ddekit_private_data { struct list list; @@ -18,8 +22,7 @@ struct _ddekit_private_data { /* point to the thread who has the private data. */ struct ddekit_thread *thread; mach_msg_header_t wakeupmsg; - -} +}; struct ddekit_thread { struct cthread thread; @@ -64,20 +67,20 @@ static error_t _create_wakeupmsg (struct _ddekit_private_data *data) return 0; } -static void setup_thread (cthread_t *t, const char *name) { +static void setup_thread (struct ddekit_thread *t, const char *name) { error_t err; struct _ddekit_private_data *private_data; if (name) { - const char *cpy = NULL; + char *cpy = NULL; - cpy = malloc (strlen (name) + 1); + cpy = ddekit_simple_malloc (strlen (name) + 1); if (cpy == NULL) error (0, 0, "fail to allocate memory"); else strcpy (cpy, name); - cthread_set_name (t, name); + cthread_set_name (&t->thread, name); } /* @@ -92,20 +95,21 @@ static void setup_thread (cthread_t *t, const char *name) { private_data->sleep_cond = condition_alloc (); condition_init (private_data->sleep_cond); - private_data->list = {&private_data->list, &private_data->list}; + private_data->list.prev = &private_data->list; + private_data->list.next = &private_data->list; private_data->thread = t; err = _create_wakeupmsg (private_data); - // TODO I need to change this. - assert_perror (err); + if (err) + error (1, err, "_create_wakeupmsg"); - cthread_set_ldata (t, private_data); + cthread_set_ldata (&t->thread, private_data); } ddekit_thread_t *ddekit_thread_setup_myself(const char *name) { ddekit_thread_t *td = ddekit_thread_myself(); - setup_thread (&td->thread, name); + setup_thread (td, name); return td; } @@ -116,7 +120,7 @@ ddekit_thread_t *ddekit_thread_create(void (*fun)(void *), void *arg, const char // before initialization is completed. td = (ddekit_thread_t *) cthread_fork (fun, arg); cthread_detach (&td->thread); - setup_thread (&td->thread, name); + setup_thread (td, name); return td; } @@ -180,7 +184,7 @@ void ddekit_thread_sleep(ddekit_lock_t *lock) { // TODO condition_wait cannot guarantee that the thread is // woke up by another thread, maybe by signals. // Does it matter here? - condition_wait (data->sleep_cond, lock); + condition_wait (data->sleep_cond, (struct mutex *) *lock); } void dekit_thread_wakeup(ddekit_thread_t *td) { @@ -205,7 +209,7 @@ void ddekit_thread_exit() { name = cthread_name (t); cthread_set_name (t, NULL); - free (name); + ddekit_simple_free ((char *) name); cthread_exit (0); } @@ -225,10 +229,18 @@ void ddekit_yield(void) } void ddekit_init_threads() { + char *str = "main"; + char *name = ddekit_simple_malloc (strlen (str) + 1); + + strcpy (name, str); // TODO maybe the name has already been set. - cthread_set_name (cthread_self (), "main"); + cthread_set_name (cthread_self (), name); } +/********************************************************************** + * semaphore + **********************************************************************/ + /* Block THREAD. */ static error_t _timedblock (struct _ddekit_private_data *data, const struct timespec *abstime) @@ -281,16 +293,16 @@ static void _block (struct _ddekit_private_data *data) assert_perror (err); } -static int _sem_timedwait_internal (sem_t *restrict sem, +static int _sem_timedwait_internal (ddekit_sem_t *restrict sem, const struct timespec *restrict timeout) { - struct ddekit_private_data *self_private_data; + struct _ddekit_private_data *self_private_data; spin_lock (&sem->lock); if (sem->value > 0) { /* Successful down. */ sem->value --; - spin_unlock (&sem->__lock); + spin_unlock (&sem->lock); return 0; } @@ -350,13 +362,14 @@ ddekit_sem_t *ddekit_sem_init(int value) { (ddekit_sem_t *) ddekit_simple_malloc (sizeof (*sem)); sem->lock = SPIN_LOCK_INITIALIZER; - sem->head = {&sem->head, &sem->head}; + sem->head.prev = &sem->head; + sem->head.next = &sem->head; sem->value = value; return sem; } void ddekit_sem_deinit(ddekit_sem_t *sem) { - if (!EMPTY_ENTRY (&sem->head)) { + if (!EMPTY_LIST (&sem->head)) { error (0, EBUSY, "ddekit_sem_deinit"); } else @@ -388,11 +401,11 @@ int ddekit_sem_down_timed(ddekit_sem_t *sem, int timo) { timeout.tv_sec = timo / 1000; timeout.tv_nsec = (timo % 1000) * 1000 * 1000; - return __sem_timedwait_internal (sem, &timeout); + return _sem_timedwait_internal (sem, &timeout); } void ddekit_sem_up(ddekit_sem_t *sem) { - struct _ddekit_thread_data *wakeup; + struct _ddekit_private_data *wakeup; spin_lock (&sem->lock); if (sem->value > 0) { @@ -400,26 +413,25 @@ void ddekit_sem_up(ddekit_sem_t *sem) { assert (EMPTY_LIST (&sem->head)); sem->value ++; spin_unlock (&sem->lock); - return 0; + return; } if (EMPTY_LIST (&sem->head)) { /* No one waiting. */ sem->value = 1; spin_unlock (&sem->lock); - return 0; + return; } /* Wake someone up. */ /* First dequeue someone. */ - wakeup = (struct _ddekit_private_data *) remove_entry_end (&sem->head); + wakeup = LIST_ENTRY (remove_entry_end (&sem->head), + struct _ddekit_private_data, list); /* Then drop the lock and transfer control. */ spin_unlock (&sem->lock); if (wakeup) _thread_wakeup (wakeup); - - return 0; } diff --git a/libddekit/timer.c b/libddekit/timer.c index d0a6ccc0..f8bfc7a1 100644 --- a/libddekit/timer.c +++ b/libddekit/timer.c @@ -2,6 +2,9 @@ #include #include +#include "ddekit/memory.h" +#include "ddekit/assert.h" +#include "ddekit/semaphore.h" #include "ddekit/timer.h" #define __DEBUG 0 @@ -118,7 +121,7 @@ int ddekit_add_timer(void (*fn)(void *), void *args, unsigned long timeout) * necessary to notify the timer thread. */ if (t == timer_list) { - Assert(!l4_is_nil_id(timer_thread)); + Assert(timer_thread); __notify_timer_thread(); } @@ -329,6 +332,6 @@ void ddekit_init_timers(void) root_jiffies = (long long) tp.tv_sec * HZ + ((long long) tp.tv_usec * HZ) / 1000000; - timer_thread = cthread_fork ((cthread_fn_t) timer_function, 0); + timer_thread = cthread_fork ((cthread_fn_t) ddekit_timer_thread, 0); cthread_detach (timer_thread); } diff --git a/libddekit/vm_param.h b/libddekit/vm_param.h new file mode 100644 index 00000000..7b615c8a --- /dev/null +++ b/libddekit/vm_param.h @@ -0,0 +1,7 @@ +#ifndef __VM_PARAM_H__ +#define __VM_PARAM_H__ + +#define PAGE_SIZE __vm_page_size +#define PAGE_MASK (PAGE_SIZE-1) + +#endif -- cgit v1.2.3 From 0451c065a044b9791b5cfa6a2432bcb8d1342710 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Fri, 11 Dec 2009 15:14:14 +0100 Subject: destroy the port before the thread exits. --- libddekit/thread.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'libddekit/thread.c') diff --git a/libddekit/thread.c b/libddekit/thread.c index 081a4742..48720584 100644 --- a/libddekit/thread.c +++ b/libddekit/thread.c @@ -187,8 +187,8 @@ void ddekit_thread_sleep(ddekit_lock_t *lock) { condition_wait (data->sleep_cond, (struct mutex *) *lock); } -void dekit_thread_wakeup(ddekit_thread_t *td) { - struct _ddekit_private_data *data = cthread_ldata (cthread_self ()); +void ddekit_thread_wakeup(ddekit_thread_t *td) { + struct _ddekit_private_data *data = cthread_ldata (&td->thread); condition_signal (data->sleep_cond); } @@ -198,12 +198,14 @@ void ddekit_thread_exit() { struct _ddekit_private_data *data; cthread_t t = cthread_self (); - // TODO I hope I don't need a lock to protect ldata and name. + // TODO I need a lock to protect ldata and name. /* I have to free the sleep condition variable * before the thread exits. */ data = cthread_ldata (t); cthread_set_ldata (t, NULL); + mach_port_destroy (mach_task_self (), + data->wakeupmsg.msgh_remote_port); condition_free (data->sleep_cond); ddekit_simple_free (data); -- cgit v1.2.3 From 17e978089ff52a13e633dc20f7ee0ba021f46d61 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Fri, 11 Dec 2009 15:18:19 +0100 Subject: Don't set the main thread name. --- libddekit/thread.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'libddekit/thread.c') diff --git a/libddekit/thread.c b/libddekit/thread.c index 48720584..c1a9c6d5 100644 --- a/libddekit/thread.c +++ b/libddekit/thread.c @@ -231,12 +231,6 @@ void ddekit_yield(void) } void ddekit_init_threads() { - char *str = "main"; - char *name = ddekit_simple_malloc (strlen (str) + 1); - - strcpy (name, str); - // TODO maybe the name has already been set. - cthread_set_name (cthread_self (), name); } /********************************************************************** -- cgit v1.2.3 From f78cc8600bb68fe1970e1bbfbd4ffc8fffb866e2 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Sun, 13 Dec 2009 11:39:29 +0100 Subject: A new thread has been initialized when it starts. --- libddekit/thread.c | 83 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 61 insertions(+), 22 deletions(-) (limited to 'libddekit/thread.c') diff --git a/libddekit/thread.c b/libddekit/thread.c index c1a9c6d5..f9aa6e58 100644 --- a/libddekit/thread.c +++ b/libddekit/thread.c @@ -36,6 +36,28 @@ struct ddekit_sem int value; }; +static void _thread_cleanup () +{ + const char *name; + struct _ddekit_private_data *data; + cthread_t t = cthread_self (); + + // TODO I need a lock to protect ldata and name. + + /* I have to free the sleep condition variable + * before the thread exits. */ + data = cthread_ldata (t); + cthread_set_ldata (t, NULL); + mach_port_destroy (mach_task_self (), + data->wakeupmsg.msgh_remote_port); + condition_free (data->sleep_cond); + ddekit_simple_free (data); + + name = cthread_name (t); + cthread_set_name (t, NULL); + ddekit_simple_free ((char *) name); +} + /* Prepare a wakeup message. */ static error_t _create_wakeupmsg (struct _ddekit_private_data *data) { @@ -113,14 +135,49 @@ ddekit_thread_t *ddekit_thread_setup_myself(const char *name) { return td; } +typedef struct +{ + void (*fun)(void *); + void *arg; + struct condition cond; + struct mutex lock; + int status; +} priv_arg_t; + +static void* _priv_fun (void *arg) +{ + priv_arg_t *priv_arg = arg; + /* We wait until the initialization of the thread is finished. */ + mutex_lock (&priv_arg->lock); + while (!priv_arg->status) + condition_wait (&priv_arg->cond, &priv_arg->lock); + mutex_unlock (&priv_arg->lock); + + priv_arg->fun(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)); + + priv_arg->fun = fun; + priv_arg->arg = arg; + condition_init (&priv_arg->cond); + mutex_init (&priv_arg->lock); + priv_arg->status = 0; - // TODO I should let the thread suspend - // before initialization is completed. - td = (ddekit_thread_t *) cthread_fork (fun, arg); + td = (ddekit_thread_t *) cthread_fork (_priv_fun, priv_arg); cthread_detach (&td->thread); setup_thread (td, name); + + /* Tell the new thread that initialization has been finished. */ + mutex_lock (&priv_arg->lock); + priv_arg->status = 1; + cond_signal (&priv_arg->cond); + mutex_unlock (&priv_arg->lock); + return td; } @@ -194,25 +251,7 @@ void ddekit_thread_wakeup(ddekit_thread_t *td) { } void ddekit_thread_exit() { - const char *name; - struct _ddekit_private_data *data; - cthread_t t = cthread_self (); - - // TODO I need a lock to protect ldata and name. - - /* I have to free the sleep condition variable - * before the thread exits. */ - data = cthread_ldata (t); - cthread_set_ldata (t, NULL); - mach_port_destroy (mach_task_self (), - data->wakeupmsg.msgh_remote_port); - condition_free (data->sleep_cond); - ddekit_simple_free (data); - - name = cthread_name (t); - cthread_set_name (t, NULL); - ddekit_simple_free ((char *) name); - + _thread_cleanup (); cthread_exit (0); } -- cgit v1.2.3 From c02fb40c744dc0789a69432d4d0b59f65cceac34 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Sun, 13 Dec 2009 12:24:02 +0100 Subject: Use a global lock to protect a thread's local data. --- libddekit/thread.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'libddekit/thread.c') diff --git a/libddekit/thread.c b/libddekit/thread.c index f9aa6e58..b6ef987a 100644 --- a/libddekit/thread.c +++ b/libddekit/thread.c @@ -36,18 +36,20 @@ struct ddekit_sem int value; }; +static struct mutex global_lock = MUTEX_INITIALIZER; + static void _thread_cleanup () { const char *name; struct _ddekit_private_data *data; cthread_t t = cthread_self (); - // TODO I need a lock to protect ldata and name. - /* 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); condition_free (data->sleep_cond); @@ -125,7 +127,9 @@ 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); } ddekit_thread_t *ddekit_thread_setup_myself(const char *name) { @@ -236,7 +240,11 @@ void ddekit_thread_nsleep(unsigned long nsecs) { } void ddekit_thread_sleep(ddekit_lock_t *lock) { - struct _ddekit_private_data *data = cthread_ldata (cthread_self ()); + 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 // woke up by another thread, maybe by signals. @@ -245,8 +253,14 @@ void ddekit_thread_sleep(ddekit_lock_t *lock) { } void ddekit_thread_wakeup(ddekit_thread_t *td) { - struct _ddekit_private_data *data = cthread_ldata (&td->thread); + struct _ddekit_private_data *data; + + mutex_lock (&global_lock); + data = cthread_ldata (&td->thread); + mutex_unlock (&global_lock); + if (data == NULL) + return; condition_signal (data->sleep_cond); } @@ -348,7 +362,9 @@ static int _sem_timedwait_internal (ddekit_sem_t *restrict sem, } /* 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); -- cgit v1.2.3 From 5887e27b584ef586ebaa14a08ef4c5254ce373e3 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Sun, 13 Dec 2009 12:25:35 +0100 Subject: Setup the main thread when initializing ddekit. --- libddekit/thread.c | 1 + 1 file changed, 1 insertion(+) (limited to 'libddekit/thread.c') diff --git a/libddekit/thread.c b/libddekit/thread.c index b6ef987a..cc2b0d53 100644 --- a/libddekit/thread.c +++ b/libddekit/thread.c @@ -284,6 +284,7 @@ void ddekit_yield(void) } void ddekit_init_threads() { + ddekit_thread_setup_myself ("main"); } /********************************************************************** -- cgit v1.2.3 From d14ef0ec0bf54f4a3290d5df196304f2b01b5901 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Tue, 15 Dec 2009 05:52:37 +0100 Subject: fix a bug (setting a thread name). --- libddekit/thread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libddekit/thread.c') diff --git a/libddekit/thread.c b/libddekit/thread.c index cc2b0d53..84fbb1d6 100644 --- a/libddekit/thread.c +++ b/libddekit/thread.c @@ -104,7 +104,7 @@ static void setup_thread (struct ddekit_thread *t, const char *name) { else strcpy (cpy, name); - cthread_set_name (&t->thread, name); + cthread_set_name (&t->thread, cpy); } /* -- cgit v1.2.3 From 056abee2aedbcdf8f072ebaecb9487d6cdaa4f21 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Tue, 15 Dec 2009 06:34:27 +0100 Subject: Use ddekit condvar instead of the one in cthreads. --- libddekit/thread.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'libddekit/thread.c') diff --git a/libddekit/thread.c b/libddekit/thread.c index 84fbb1d6..34a293e1 100644 --- a/libddekit/thread.c +++ b/libddekit/thread.c @@ -9,6 +9,7 @@ #include "ddekit/memory.h" #include "ddekit/semaphore.h" +#include "ddekit/condvar.h" #include "list.h" #include "ddekit/thread.h" @@ -18,7 +19,7 @@ struct _ddekit_private_data { struct list list; - condition_t sleep_cond; + ddekit_condvar_t *sleep_cond; /* point to the thread who has the private data. */ struct ddekit_thread *thread; mach_msg_header_t wakeupmsg; @@ -52,7 +53,7 @@ static void _thread_cleanup () mutex_unlock (&global_lock); mach_port_destroy (mach_task_self (), data->wakeupmsg.msgh_remote_port); - condition_free (data->sleep_cond); + ddekit_condvar_deinit (data->sleep_cond); ddekit_simple_free (data); name = cthread_name (t); @@ -116,9 +117,7 @@ static void setup_thread (struct ddekit_thread *t, const char *name) { private_data = (struct _ddekit_private_data *) ddekit_simple_malloc (sizeof (*private_data)); - private_data->sleep_cond = condition_alloc (); - condition_init (private_data->sleep_cond); - + private_data->sleep_cond = ddekit_condvar_init (); private_data->list.prev = &private_data->list; private_data->list.next = &private_data->list; private_data->thread = t; @@ -249,7 +248,7 @@ void ddekit_thread_sleep(ddekit_lock_t *lock) { // TODO condition_wait cannot guarantee that the thread is // woke up by another thread, maybe by signals. // Does it matter here? - condition_wait (data->sleep_cond, (struct mutex *) *lock); + ddekit_condvar_wait (data->sleep_cond, lock); } void ddekit_thread_wakeup(ddekit_thread_t *td) { @@ -261,7 +260,7 @@ void ddekit_thread_wakeup(ddekit_thread_t *td) { if (data == NULL) return; - condition_signal (data->sleep_cond); + ddekit_condvar_signal (data->sleep_cond); } void ddekit_thread_exit() { -- cgit v1.2.3 From 21584dfe2bc05df7bc5109c3baeb0d4c794f3099 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Fri, 5 Feb 2010 14:37:33 +0100 Subject: fix a bug in ddekit: use the relative time. --- libddekit/thread.c | 38 ++++++-------------------------------- 1 file changed, 6 insertions(+), 32 deletions(-) (limited to 'libddekit/thread.c') diff --git a/libddekit/thread.c b/libddekit/thread.c index 34a293e1..10b86de8 100644 --- a/libddekit/thread.c +++ b/libddekit/thread.c @@ -292,33 +292,12 @@ void ddekit_init_threads() { /* Block THREAD. */ static error_t _timedblock (struct _ddekit_private_data *data, - const struct timespec *abstime) + const int timeout) { error_t err; mach_msg_header_t msg; - mach_msg_timeout_t timeout; - struct timeval now; - /* We have an absolute time and now we have to convert it to a - relative time. Arg. */ - - err = gettimeofday(&now, NULL); - assert (! err); - - if (now.tv_sec > abstime->tv_sec - || (now.tv_sec == abstime->tv_sec - && now.tv_usec > ((abstime->tv_nsec + 999) / 1000))) - return ETIMEDOUT; - - timeout = (abstime->tv_sec - now.tv_sec) * 1000; - - if (((abstime->tv_nsec + 999) / 1000) >= now.tv_usec) - timeout -= (((abstime->tv_nsec + 999) / 1000) - - now.tv_usec + 999) / 1000; - else - /* Need to do a carry. */ - timeout -= 1000 + ((abstime->tv_nsec + 999999) / 1000000) - - (now.tv_usec + 999) / 1000; + assert (timeout > 0); err = mach_msg (&msg, MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0, sizeof msg, data->wakeupmsg.msgh_remote_port, @@ -343,7 +322,7 @@ static void _block (struct _ddekit_private_data *data) } static int _sem_timedwait_internal (ddekit_sem_t *restrict sem, - const struct timespec *restrict timeout) + const int timeout) { struct _ddekit_private_data *self_private_data; @@ -355,8 +334,7 @@ static int _sem_timedwait_internal (ddekit_sem_t *restrict sem, return 0; } - if (timeout && (timeout->tv_nsec < 0 - || timeout->tv_nsec >= 1000000000)) { + if (timeout < 0) { errno = EINVAL; return -1; } @@ -428,7 +406,7 @@ void ddekit_sem_deinit(ddekit_sem_t *sem) { } void ddekit_sem_down(ddekit_sem_t *sem) { - _sem_timedwait_internal (sem, NULL); + _sem_timedwait_internal (sem, 0); } /* returns 0 on success, != 0 when it would block */ @@ -448,11 +426,7 @@ int ddekit_sem_down_try(ddekit_sem_t *sem) { /* returns 0 on success, != 0 on timeout */ int ddekit_sem_down_timed(ddekit_sem_t *sem, int timo) { /* wait for up to timo milliseconds */ - struct timespec timeout; - - timeout.tv_sec = timo / 1000; - timeout.tv_nsec = (timo % 1000) * 1000 * 1000; - return _sem_timedwait_internal (sem, &timeout); + return _sem_timedwait_internal (sem, timo); } void ddekit_sem_up(ddekit_sem_t *sem) { -- cgit v1.2.3