From a9b2fb5ee3114fe835f6515b6aeae7454f66d821 Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Tue, 16 Oct 2007 01:25:17 +0000 Subject: Finally full multicore support for PortalPlayer 502x targets with an eye towards the possibility of other types. All SVN targets the low-lag code to speed up blocking operations. Most files are modified here simple due to a name change to actually support a real event object and a param change to create_thread. Add some use of new features but just sit on things for a bit and leave full integration for later. Work will continue on to address size on sensitive targets and simplify things if possible. Any PP target having problems with SWP can easily be changed to sw corelocks with one #define change in config.h though only PP5020 has shown an issue and seems to work without any difficulties. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15134 a1c6a512-1295-4272-9138-f99709370657 --- firmware/export/kernel.h | 103 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 86 insertions(+), 17 deletions(-) (limited to 'firmware/export/kernel.h') diff --git a/firmware/export/kernel.h b/firmware/export/kernel.h index 3d70e49a4c..a72e004b33 100644 --- a/firmware/export/kernel.h +++ b/firmware/export/kernel.h @@ -23,6 +23,8 @@ #include #include "config.h" +#include "thread.h" + /* wrap-safe macros for tick comparison */ #define TIME_AFTER(a,b) ((long)(b) - (long)(a) < 0) #define TIME_BEFORE(a,b) TIME_AFTER(b,a) @@ -31,6 +33,7 @@ #define MAX_NUM_TICK_TASKS 8 +#define MAX_NUM_QUEUES 32 #define QUEUE_LENGTH 16 /* MUST be a power of 2 */ #define QUEUE_LENGTH_MASK (QUEUE_LENGTH - 1) @@ -72,7 +75,7 @@ #define SYS_SCREENDUMP MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 0) #define SYS_CAR_ADAPTER_RESUME MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 1) -struct event +struct queue_event { long id; intptr_t data; @@ -91,20 +94,66 @@ struct queue_sender_list struct event_queue { - struct event events[QUEUE_LENGTH]; - struct thread_entry *thread; - unsigned int read; - unsigned int write; + struct thread_queue queue; /* Waiter list */ + struct queue_event events[QUEUE_LENGTH]; /* list of events */ + unsigned int read; /* head of queue */ + unsigned int write; /* tail of queue */ #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME - struct queue_sender_list *send; + struct queue_sender_list *send; /* list of threads waiting for + reply to an event */ +#endif +#if NUM_CORES > 1 + struct corelock cl; /* inter-core sync */ #endif }; struct mutex { - uint32_t locked; - struct thread_entry *thread; + struct thread_entry *queue; /* Waiter list */ +#if CONFIG_CORELOCK == SW_CORELOCK + struct corelock cl; /* inter-core sync */ +#endif + struct thread_entry *thread; /* thread that owns lock */ + int count; /* lock owner recursion count */ + unsigned char locked; /* locked semaphore */ +}; + +struct spinlock +{ +#if NUM_CORES > 1 + struct corelock cl; /* inter-core sync */ +#endif + struct thread_entry *thread; /* lock owner */ + int count; /* lock owner recursion count */ + unsigned char locked; /* is locked if nonzero */ +#if NUM_CORES > 1 + unsigned char task_switch; /* can task switch? */ +#endif +}; + +#ifdef HAVE_SEMAPHORE_OBJECTS +struct semaphore +{ + struct thread_entry *queue; /* Waiter list */ +#if CONFIG_CORELOCK == SW_CORELOCK + struct corelock cl; /* inter-core sync */ +#endif + int count; /* # of waits remaining before unsignaled */ + int max; /* maximum # of waits to remain signaled */ +}; +#endif + +#ifdef HAVE_EVENT_OBJECTS +struct event +{ + struct thread_entry *queues[2]; /* waiters for each state */ +#if CONFIG_CORELOCK == SW_CORELOCK + struct corelock cl; /* inter-core sync */ +#endif + unsigned char automatic; /* event performs auto-reset */ + unsigned char state; /* state: 1 = signaled */ }; +#endif /* global tick variable */ #if defined(CPU_PP) && defined(BOOTLOADER) @@ -127,6 +176,7 @@ extern void yield(void); extern void sleep(int ticks); int tick_add_task(void (*f)(void)); int tick_remove_task(void (*f)(void)); +extern void tick_start(unsigned int interval_in_ms); struct timeout; @@ -150,10 +200,17 @@ void timeout_register(struct timeout *tmo, timeout_cb_type callback, int ticks, intptr_t data); void timeout_cancel(struct timeout *tmo); +#define STATE_NONSIGNALED 0 +#define STATE_SIGNALED 1 + +#define WAIT_TIMEDOUT (-1) +#define WAIT_SUCCEEDED 1 + extern void queue_init(struct event_queue *q, bool register_queue); extern void queue_delete(struct event_queue *q); -extern void queue_wait(struct event_queue *q, struct event *ev); -extern void queue_wait_w_tmo(struct event_queue *q, struct event *ev, int ticks); +extern void queue_wait(struct event_queue *q, struct queue_event *ev); +extern void queue_wait_w_tmo(struct event_queue *q, struct queue_event *ev, + int ticks); extern void queue_post(struct event_queue *q, long id, intptr_t data); #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME extern void queue_enable_queue_send(struct event_queue *q, struct queue_sender_list *send); @@ -168,14 +225,26 @@ extern int queue_count(const struct event_queue *q); extern int queue_broadcast(long id, intptr_t data); extern void mutex_init(struct mutex *m); -static inline void spinlock_init(struct mutex *m) -{ mutex_init(m); } /* Same thing for now */ extern void mutex_lock(struct mutex *m); extern void mutex_unlock(struct mutex *m); -extern void spinlock_lock(struct mutex *m); -extern void spinlock_unlock(struct mutex *m); -extern void tick_start(unsigned int interval_in_ms); - +#define SPINLOCK_TASK_SWITCH 0x10 +#define SPINLOCK_NO_TASK_SWITCH 0x00 +extern void spinlock_init(struct spinlock *l IF_COP(, unsigned int flags)); +extern void spinlock_lock(struct spinlock *l); +extern void spinlock_unlock(struct spinlock *l); +extern int spinlock_lock_w_tmo(struct spinlock *l, int ticks); +#ifdef HAVE_SEMAPHORE_OBJECTS +extern void semaphore_init(struct semaphore *s, int max, int start); +extern void semaphore_wait(struct semaphore *s); +extern void semaphore_release(struct semaphore *s); +#endif /* HAVE_SEMAPHORE_OBJECTS */ +#ifdef HAVE_EVENT_OBJECTS +#define EVENT_AUTOMATIC 0x10 +#define EVENT_MANUAL 0x00 +extern void event_init(struct event *e, unsigned int flags); +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 */ #define IS_SYSEVENT(ev) ((ev & SYS_EVENT) == SYS_EVENT) -#endif +#endif /* _KERNEL_H_ */ -- cgit v1.2.3