summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2008-03-30 04:59:51 +0000
committerMichael Sevakis <jethead71@rockbox.org>2008-03-30 04:59:51 +0000
commitbc192c953eb2fe80cac471ea4601c27e23512440 (patch)
tree42b17a28635526d32560e14875865a88b2a6dac8
parent8a6fd3ff4e63c81d7d50af535791318481280f95 (diff)
downloadrockbox-bc192c953eb2fe80cac471ea4601c27e23512440.tar.gz
rockbox-bc192c953eb2fe80cac471ea4601c27e23512440.zip
Add a lightweight wakeup object for fast processors.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16885 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/export/config.h4
-rw-r--r--firmware/export/kernel.h23
-rw-r--r--firmware/kernel.c78
3 files changed, 105 insertions, 0 deletions
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 @@
335#endif /* SIMULATOR */ 335#endif /* SIMULATOR */
336#define HAVE_SEMAPHORE_OBJECTS 336#define HAVE_SEMAPHORE_OBJECTS
337#define HAVE_EVENT_OBJECTS 337#define HAVE_EVENT_OBJECTS
338
339#if defined (TOSHIBA_GIGABEAT_F) || defined (TOSHIBA_GIGABEAT_S)
340#define HAVE_WAKEUP_OBJECTS
341#endif
338#endif 342#endif
339 343
340/* define for all cpus from SH family */ 344/* 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 @@
78 78
79#define IS_SYSEVENT(ev) ((ev & SYS_EVENT) == SYS_EVENT) 79#define IS_SYSEVENT(ev) ((ev & SYS_EVENT) == SYS_EVENT)
80 80
81#ifndef TIMEOUT_BLOCK
82#define TIMEOUT_BLOCK -1
83#define TIMEOUT_NOBLOCK 0
84#endif
85
81struct queue_event 86struct queue_event
82{ 87{
83 long id; 88 long id;
@@ -178,6 +183,17 @@ struct event
178}; 183};
179#endif 184#endif
180 185
186
187#ifdef HAVE_WAKEUP_OBJECTS
188struct wakeup
189{
190 struct thread_entry *queue; /* waiter list */
191 unsigned char signalled; /* signalled status */
192 IF_COP( struct corelock cl; ) /* multiprocessor sync */
193};
194#endif
195
196
181/* global tick variable */ 197/* global tick variable */
182#if defined(CPU_PP) && defined(BOOTLOADER) 198#if defined(CPU_PP) && defined(BOOTLOADER)
183/* We don't enable interrupts in the iPod bootloader, so we need to fake 199/* We don't enable interrupts in the iPod bootloader, so we need to fake
@@ -225,6 +241,7 @@ void timeout_cancel(struct timeout *tmo);
225#define STATE_SIGNALED 1 241#define STATE_SIGNALED 1
226 242
227#define WAIT_TIMEDOUT (-1) 243#define WAIT_TIMEDOUT (-1)
244#define WAIT_FAILED 0
228#define WAIT_SUCCEEDED 1 245#define WAIT_SUCCEEDED 1
229 246
230extern void queue_init(struct event_queue *q, bool register_queue); 247extern 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);
274extern void event_set_state(struct event *e, unsigned int state); 291extern void event_set_state(struct event *e, unsigned int state);
275#endif /* HAVE_EVENT_OBJECTS */ 292#endif /* HAVE_EVENT_OBJECTS */
276 293
294#ifdef HAVE_WAKEUP_OBJECTS
295extern void wakeup_init(struct wakeup *w);
296extern int wakeup_wait(struct wakeup *w, int timeout);
297extern int wakeup_signal(struct wakeup *w);
298#endif /* HAVE_WAKEUP_OBJECTS */
299
277#endif /* _KERNEL_H_ */ 300#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)
1368#endif 1368#endif
1369} 1369}
1370#endif /* HAVE_EVENT_OBJECTS */ 1370#endif /* HAVE_EVENT_OBJECTS */
1371
1372
1373#ifdef HAVE_WAKEUP_OBJECTS
1374/****************************************************************************
1375 * Lightweight IRQ-compatible wakeup object
1376 */
1377
1378/* Initialize the wakeup object */
1379void wakeup_init(struct wakeup *w)
1380{
1381 w->queue = NULL;
1382 w->signalled = 0;
1383 IF_COP( corelock_init(&w->cl); )
1384}
1385
1386/* Wait for a signal blocking indefinitely or for a specified period */
1387int wakeup_wait(struct wakeup *w, int timeout)
1388{
1389 int ret = WAIT_SUCCEEDED; /* Presume success */
1390 int oldlevel = disable_irq_save();
1391
1392 corelock_lock(&w->cl);
1393
1394 if(w->signalled == 0 && timeout != TIMEOUT_NOBLOCK)
1395 {
1396 struct thread_entry * current = cores[CURRENT_CORE].running;
1397
1398 IF_COP( current->obj_cl = &w->cl; )
1399 current->bqp = &w->queue;
1400
1401 if (timeout != TIMEOUT_BLOCK)
1402 block_thread_w_tmo(current, timeout);
1403 else
1404 block_thread(current);
1405
1406 corelock_unlock(&w->cl);
1407 switch_thread();
1408
1409 oldlevel = disable_irq_save();
1410 corelock_lock(&w->cl);
1411 }
1412
1413 if(w->signalled == 0)
1414 {
1415 /* Timed-out or failed */
1416 ret = (timeout != TIMEOUT_BLOCK) ? WAIT_TIMEDOUT : WAIT_FAILED;
1417 }
1418
1419 w->signalled = 0; /* Reset */
1420
1421 corelock_unlock(&w->cl);
1422 restore_irq(oldlevel);
1423
1424 return ret;
1425}
1426
1427/* Signal the thread waiting or leave the signal if the thread hasn't
1428 * waited yet.
1429 *
1430 * returns THREAD_NONE or THREAD_OK
1431 */
1432int wakeup_signal(struct wakeup *w)
1433{
1434 int oldlevel = disable_irq_save();
1435 int ret;
1436
1437 corelock_lock(&w->cl);
1438
1439 w->signalled = 1;
1440 ret = wakeup_thread(&w->queue);
1441
1442 corelock_unlock(&w->cl);
1443 restore_irq(oldlevel);
1444
1445 return ret;
1446}
1447#endif /* HAVE_WAKEUP_OBJECTS */
1448