forked from len0rd/rockbox
Add a lightweight wakeup object for fast processors.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16885 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
8a6fd3ff4e
commit
bc192c953e
3 changed files with 105 additions and 0 deletions
|
|
@ -335,6 +335,10 @@
|
||||||
#endif /* SIMULATOR */
|
#endif /* SIMULATOR */
|
||||||
#define HAVE_SEMAPHORE_OBJECTS
|
#define HAVE_SEMAPHORE_OBJECTS
|
||||||
#define HAVE_EVENT_OBJECTS
|
#define HAVE_EVENT_OBJECTS
|
||||||
|
|
||||||
|
#if defined (TOSHIBA_GIGABEAT_F) || defined (TOSHIBA_GIGABEAT_S)
|
||||||
|
#define HAVE_WAKEUP_OBJECTS
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* define for all cpus from SH family */
|
/* define for all cpus from SH family */
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,11 @@
|
||||||
|
|
||||||
#define IS_SYSEVENT(ev) ((ev & SYS_EVENT) == SYS_EVENT)
|
#define IS_SYSEVENT(ev) ((ev & SYS_EVENT) == SYS_EVENT)
|
||||||
|
|
||||||
|
#ifndef TIMEOUT_BLOCK
|
||||||
|
#define TIMEOUT_BLOCK -1
|
||||||
|
#define TIMEOUT_NOBLOCK 0
|
||||||
|
#endif
|
||||||
|
|
||||||
struct queue_event
|
struct queue_event
|
||||||
{
|
{
|
||||||
long id;
|
long id;
|
||||||
|
|
@ -178,6 +183,17 @@ struct event
|
||||||
};
|
};
|
||||||
#endif
|
#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 */
|
/* global tick variable */
|
||||||
#if defined(CPU_PP) && defined(BOOTLOADER)
|
#if defined(CPU_PP) && defined(BOOTLOADER)
|
||||||
/* We don't enable interrupts in the iPod bootloader, so we need to fake
|
/* 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 STATE_SIGNALED 1
|
||||||
|
|
||||||
#define WAIT_TIMEDOUT (-1)
|
#define WAIT_TIMEDOUT (-1)
|
||||||
|
#define WAIT_FAILED 0
|
||||||
#define WAIT_SUCCEEDED 1
|
#define WAIT_SUCCEEDED 1
|
||||||
|
|
||||||
extern void queue_init(struct event_queue *q, bool register_queue);
|
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);
|
extern void event_set_state(struct event *e, unsigned int state);
|
||||||
#endif /* HAVE_EVENT_OBJECTS */
|
#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_ */
|
#endif /* _KERNEL_H_ */
|
||||||
|
|
|
||||||
|
|
@ -1368,3 +1368,81 @@ void event_set_state(struct event *e, unsigned int state)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif /* HAVE_EVENT_OBJECTS */
|
#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 */
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue