From a85044bf9eaa0a7206c1978d3cfd57ab2d7fae2f Mon Sep 17 00:00:00 2001 From: Miika Pekkarinen Date: Sat, 16 Sep 2006 16:18:11 +0000 Subject: New scheduler, with priorities for swcodec platforms. Frequent task switching should be more efficient and tasks are stored in linked lists to eliminate unnecessary task switching to improve performance. Audio should no longer skip on swcodec targets caused by too CPU hungry UI thread or background threads. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10958 a1c6a512-1295-4272-9138-f99709370657 --- firmware/export/thread.h | 88 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 67 insertions(+), 21 deletions(-) (limited to 'firmware/export/thread.h') diff --git a/firmware/export/thread.h b/firmware/export/thread.h index e102997dae..7e053bc507 100644 --- a/firmware/export/thread.h +++ b/firmware/export/thread.h @@ -21,8 +21,24 @@ #include +/* Priority scheduling (when enabled with HAVE_PRIORITY_SCHEDULING) works + * by giving high priority threads more CPU time than less priority threads + * when they need it. + * + * If software playback codec pcm buffer is going down to critical, codec + * can change it own priority to REALTIME to override user interface and + * prevent playback skipping. + */ +#define PRIORITY_REALTIME 1 +#define PRIORITY_USER_INTERFACE 4 /* The main thread */ +#define PRIORITY_RECORDING 4 /* Recording thread */ +#define PRIORITY_PLAYBACK 4 /* or REALTIME when needed */ +#define PRIORITY_BUFFERING 4 /* Codec buffering thread */ +#define PRIORITY_SYSTEM 6 /* All other firmware threads */ +#define PRIORITY_BACKGROUND 8 /* Normal application threads */ + #if CONFIG_CODEC == SWCODEC -#define MAXTHREADS 16 +#define MAXTHREADS 15 #else #define MAXTHREADS 11 #endif @@ -32,7 +48,7 @@ #ifndef SIMULATOR /* Need to keep structures inside the header file because debug_menu * needs them. */ -#ifdef CPU_COLDFIRE +# ifdef CPU_COLDFIRE struct regs { unsigned int macsr; /* EMAC status register */ @@ -41,7 +57,7 @@ struct regs void *sp; /* Stack pointer (a7) */ void *start; /* Thread start address, or NULL when started */ }; -#elif CONFIG_CPU == SH7034 +# elif CONFIG_CPU == SH7034 struct regs { unsigned int r[7]; /* Registers r8 thru r14 */ @@ -49,7 +65,7 @@ struct regs void *pr; /* Procedure register */ void *start; /* Thread start address, or NULL when started */ }; -#elif defined(CPU_ARM) +# elif defined(CPU_ARM) struct regs { unsigned int r[8]; /* Registers r4-r11 */ @@ -57,42 +73,72 @@ struct regs unsigned int lr; /* r14 (lr) */ void *start; /* Thread start address, or NULL when started */ }; -#elif CONFIG_CPU == TCC730 +# elif CONFIG_CPU == TCC730 struct regs { void *sp; /* Stack pointer (a15) */ void *start; /* Thread start address */ int started; /* 0 when not started */ }; -#endif +# endif + +#endif /* !SIMULATOR */ + +#define STATE_RUNNING 0 +#define STATE_BLOCKED 1 +#define STATE_SLEEPING 2 +#define STATE_BLOCKED_W_TMO 3 + +#define GET_STATE_ARG(state) (state & 0x3FFFFFFF) +#define GET_STATE(state) ((state >> 30) & 3) +#define SET_STATE(state,arg) ((state << 30) | (arg)) struct thread_entry { +#ifndef SIMULATOR struct regs context; +#endif const char *name; void *stack; - int stack_size; + unsigned long statearg; + unsigned short stack_size; +#ifdef HAVE_PRIORITY_SCHEDULING + unsigned short priority; + long last_run; +#endif + struct thread_entry *next, *prev; }; struct core_entry { - int num_threads; - volatile int num_sleepers; - int current_thread; struct thread_entry threads[MAXTHREADS]; + struct thread_entry *running; + struct thread_entry *sleeping; }; + +#ifdef HAVE_PRIORITY_SCHEDULING +#define IF_PRIO(empty, type) , type +#else +#define IF_PRIO(empty, type) #endif -int create_thread(void (*function)(void), void* stack, int stack_size, - const char *name); -int create_thread_on_core(unsigned int core, void (*function)(void), void* stack, int stack_size, - const char *name); -void remove_thread(int threadnum); -void remove_thread_on_core(unsigned int core, int threadnum); -void switch_thread(void); -void sleep_thread(void); -void wake_up_thread(void); +struct thread_entry* + create_thread(void (*function)(void), void* stack, int stack_size, + const char *name IF_PRIO(, int priority)); + +struct thread_entry* + create_thread_on_core(unsigned int core, void (*function)(void), + void* stack, int stack_size, + const char *name + IF_PRIO(, int priority)); + +void remove_thread(struct thread_entry *thread); +void switch_thread(bool save_context, struct thread_entry **blocked_list); +void sleep_thread(int ticks); +void block_thread(struct thread_entry **thread, int timeout); +void wakeup_thread(struct thread_entry **thread); +void thread_set_priority(struct thread_entry *thread, int priority); void init_threads(void); -int thread_stack_usage(int threadnum); -int thread_stack_usage_on_core(unsigned int core, int threadnum); +int thread_stack_usage(const struct thread_entry *thread); +int thread_get_status(const struct thread_entry *thread); #ifdef RB_PROFILE void profile_thread(void); #endif -- cgit v1.2.3