From bc192c953eb2fe80cac471ea4601c27e23512440 Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Sun, 30 Mar 2008 04:59:51 +0000 Subject: Add a lightweight wakeup object for fast processors. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16885 a1c6a512-1295-4272-9138-f99709370657 --- firmware/export/config.h | 4 +++ firmware/export/kernel.h | 23 ++++++++++++++ firmware/kernel.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+) diff --git a/firmware/export/config.h b/firmware/export/config.h index 1a288dd590..cd98fc9dca 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -335,6 +335,10 @@ #endif /* SIMULATOR */ #define HAVE_SEMAPHORE_OBJECTS #define HAVE_EVENT_OBJECTS + +#if defined (TOSHIBA_GIGABEAT_F) || defined (TOSHIBA_GIGABEAT_S) +#define HAVE_WAKEUP_OBJECTS +#endif #endif /* define for all cpus from SH family */ diff --git a/firmware/export/kernel.h b/firmware/export/kernel.h index 78403c8b7d..337f249dfe 100644 --- a/firmware/export/kernel.h +++ b/firmware/export/kernel.h @@ -78,6 +78,11 @@ #define IS_SYSEVENT(ev) ((ev & SYS_EVENT) == SYS_EVENT) +#ifndef TIMEOUT_BLOCK +#define TIMEOUT_BLOCK -1 +#define TIMEOUT_NOBLOCK 0 +#endif + struct queue_event { long id; @@ -178,6 +183,17 @@ struct event }; #endif + +#ifdef HAVE_WAKEUP_OBJECTS +struct wakeup +{ + struct thread_entry *queue; /* waiter list */ + unsigned char signalled; /* signalled status */ + IF_COP( struct corelock cl; ) /* multiprocessor sync */ +}; +#endif + + /* global tick variable */ #if defined(CPU_PP) && defined(BOOTLOADER) /* We don't enable interrupts in the iPod bootloader, so we need to fake @@ -225,6 +241,7 @@ void timeout_cancel(struct timeout *tmo); #define STATE_SIGNALED 1 #define WAIT_TIMEDOUT (-1) +#define WAIT_FAILED 0 #define WAIT_SUCCEEDED 1 extern void queue_init(struct event_queue *q, bool register_queue); @@ -274,4 +291,10 @@ extern void event_wait(struct event *e, unsigned int for_state); extern void event_set_state(struct event *e, unsigned int state); #endif /* HAVE_EVENT_OBJECTS */ +#ifdef HAVE_WAKEUP_OBJECTS +extern void wakeup_init(struct wakeup *w); +extern int wakeup_wait(struct wakeup *w, int timeout); +extern int wakeup_signal(struct wakeup *w); +#endif /* HAVE_WAKEUP_OBJECTS */ + #endif /* _KERNEL_H_ */ diff --git a/firmware/kernel.c b/firmware/kernel.c index 184d29fe93..439aea584a 100644 --- a/firmware/kernel.c +++ b/firmware/kernel.c @@ -1368,3 +1368,81 @@ void event_set_state(struct event *e, unsigned int state) #endif } #endif /* HAVE_EVENT_OBJECTS */ + + +#ifdef HAVE_WAKEUP_OBJECTS +/**************************************************************************** + * Lightweight IRQ-compatible wakeup object + */ + +/* Initialize the wakeup object */ +void wakeup_init(struct wakeup *w) +{ + w->queue = NULL; + w->signalled = 0; + IF_COP( corelock_init(&w->cl); ) +} + +/* Wait for a signal blocking indefinitely or for a specified period */ +int wakeup_wait(struct wakeup *w, int timeout) +{ + int ret = WAIT_SUCCEEDED; /* Presume success */ + int oldlevel = disable_irq_save(); + + corelock_lock(&w->cl); + + if(w->signalled == 0 && timeout != TIMEOUT_NOBLOCK) + { + struct thread_entry * current = cores[CURRENT_CORE].running; + + IF_COP( current->obj_cl = &w->cl; ) + current->bqp = &w->queue; + + if (timeout != TIMEOUT_BLOCK) + block_thread_w_tmo(current, timeout); + else + block_thread(current); + + corelock_unlock(&w->cl); + switch_thread(); + + oldlevel = disable_irq_save(); + corelock_lock(&w->cl); + } + + if(w->signalled == 0) + { + /* Timed-out or failed */ + ret = (timeout != TIMEOUT_BLOCK) ? WAIT_TIMEDOUT : WAIT_FAILED; + } + + w->signalled = 0; /* Reset */ + + corelock_unlock(&w->cl); + restore_irq(oldlevel); + + return ret; +} + +/* Signal the thread waiting or leave the signal if the thread hasn't + * waited yet. + * + * returns THREAD_NONE or THREAD_OK + */ +int wakeup_signal(struct wakeup *w) +{ + int oldlevel = disable_irq_save(); + int ret; + + corelock_lock(&w->cl); + + w->signalled = 1; + ret = wakeup_thread(&w->queue); + + corelock_unlock(&w->cl); + restore_irq(oldlevel); + + return ret; +} +#endif /* HAVE_WAKEUP_OBJECTS */ + -- cgit v1.2.3