From fadbf0a6f72540b025987a2b3df3f9edd4e3e411 Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Tue, 20 Nov 2007 03:44:25 +0000 Subject: [PATCH] Make threads responsible for explicit cancellation of their own boosted status. Sleeping and timeouts will no longer cancel it. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15709 a1c6a512-1295-4272-9138-f99709370657 --- apps/buffering.c | 2 +- apps/debug_menu.c | 23 +++++++-------- apps/playback.c | 3 ++ apps/recorder/radio.c | 5 ++++ apps/tree.c | 1 + apps/voice_thread.c | 2 +- firmware/export/thread.h | 3 +- firmware/thread.c | 63 ++++++++++++++-------------------------- 8 files changed, 46 insertions(+), 56 deletions(-) diff --git a/apps/buffering.c b/apps/buffering.c index d5ed4e2470..18cdb99d25 100644 --- a/apps/buffering.c +++ b/apps/buffering.c @@ -563,7 +563,6 @@ static bool yield_codec(void) while (pcmbuf_is_lowdata() && !buffer_is_low()) { sleep(2); - trigger_cpu_boost(); if (!queue_empty(&buffering_queue)) return true; @@ -1267,6 +1266,7 @@ void buffering_thread(void) while (true) { + cancel_cpu_boost(); queue_wait_w_tmo(&buffering_queue, &ev, filling?5:HZ/2); switch (ev.id) diff --git a/apps/debug_menu.c b/apps/debug_menu.c index e3f576d4f5..a8eb786f83 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c @@ -124,16 +124,14 @@ static char thread_status_char(unsigned status) static char* threads_getname(int selected_item, void * data, char *buffer) { (void)data; + struct thread_entry *thread; char name[32]; - struct thread_entry *thread = NULL; - unsigned status; - int usage; #if NUM_CORES > 1 if (selected_item < (int)NUM_CORES) { - usage = idle_stack_usage(selected_item); - snprintf(buffer, MAX_PATH, "Idle (%d): %2d%%", selected_item, usage); + snprintf(buffer, MAX_PATH, "Idle (%d): %2d%%", selected_item, + idle_stack_usage(selected_item)); return buffer; } @@ -141,25 +139,26 @@ static char* threads_getname(int selected_item, void * data, char *buffer) #endif thread = &threads[selected_item]; - status = thread_get_status(thread); - - if (status == STATE_KILLED) + + if (thread->state == STATE_KILLED) { snprintf(buffer, MAX_PATH, "%2d: ---", selected_item); return buffer; } thread_get_name(name, 32, thread); - usage = thread_stack_usage(thread); snprintf(buffer, MAX_PATH, "%2d: " IF_COP("(%d) ") "%c%c " IF_PRIO("%d ") "%2d%% %s", selected_item, IF_COP(thread->core,) - (status == STATE_RUNNING) ? '*' : ' ', - thread_status_char(status), +#ifdef HAVE_SCHEDULER_BOOSTCTRL + (thread->boosted) ? '+' : +#endif + ((thread->state == STATE_RUNNING) ? '*' : ' '), + thread_status_char(thread->state), IF_PRIO(thread->priority,) - usage, name); + thread_stack_usage(thread), name); return buffer; } diff --git a/apps/playback.c b/apps/playback.c index 5b9f5683f9..782c613452 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -848,6 +848,7 @@ static bool codec_pcmbuf_insert_callback( while ((dest = pcmbuf_request_buffer(&out_count)) == NULL) { + cancel_cpu_boost(); sleep(1); if (ci.seek_time || ci.new_track || ci.stop_codec) return true; @@ -1277,6 +1278,7 @@ static void codec_thread(void) while (1) { status = 0; + cancel_cpu_boost(); queue_wait(&codec_queue, &ev); switch (ev.id) { @@ -2388,6 +2390,7 @@ static void audio_thread(void) while (1) { + cancel_cpu_boost(); queue_wait_w_tmo(&audio_queue, &ev, HZ/2); switch (ev.id) { diff --git a/apps/recorder/radio.c b/apps/recorder/radio.c index 7a45027933..d576755ae7 100644 --- a/apps/recorder/radio.c +++ b/apps/recorder/radio.c @@ -553,6 +553,11 @@ int radio_screen(void) trigger_cpu_boost(); } + if (!update_screen) + { + cancel_cpu_boost(); + } + #if CONFIG_CODEC != SWCODEC /* TODO: Can we timeout at HZ when recording since peaks aren't displayed? This should quiet recordings too. */ diff --git a/apps/tree.c b/apps/tree.c index 13b0756cbb..52747334c9 100644 --- a/apps/tree.c +++ b/apps/tree.c @@ -1034,6 +1034,7 @@ bool create_playlist(void) add_dir(filename, sizeof(filename), fd); close(fd); + cancel_cpu_boost(); sleep(HZ); return true; diff --git a/apps/voice_thread.c b/apps/voice_thread.c index 9e7478651e..f7494f9587 100644 --- a/apps/voice_thread.c +++ b/apps/voice_thread.c @@ -249,7 +249,7 @@ static void voice_message(struct voice_thread_data *td) } /* Cancel boost */ - sleep(0); + cancel_cpu_boost(); td->state = TSTATE_STOPPED; event_set_state(&voice_event, STATE_SIGNALED); diff --git a/firmware/export/thread.h b/firmware/export/thread.h index 94c228b9ef..df18f7b095 100644 --- a/firmware/export/thread.h +++ b/firmware/export/thread.h @@ -469,8 +469,10 @@ struct thread_entry* #ifdef HAVE_SCHEDULER_BOOSTCTRL void trigger_cpu_boost(void); +void cancel_cpu_boost(void); #else #define trigger_cpu_boost() +#define cancel_cpu_boost() #endif void thread_thaw(struct thread_entry *thread); void thread_wait(struct thread_entry *thread); @@ -556,7 +558,6 @@ int thread_stack_usage(const struct thread_entry *thread); #if NUM_CORES > 1 int idle_stack_usage(unsigned int core); #endif -unsigned thread_get_status(const struct thread_entry *thread); void thread_get_name(char *buffer, int size, struct thread_entry *thread); #ifdef RB_PROFILE diff --git a/firmware/thread.c b/firmware/thread.c index 4bcea0542d..4d16e5647b 100644 --- a/firmware/thread.c +++ b/firmware/thread.c @@ -92,9 +92,6 @@ /* Cast to the the machine int type, whose size could be < 4. */ struct core_entry cores[NUM_CORES] IBSS_ATTR; struct thread_entry threads[MAXTHREADS] IBSS_ATTR; -#ifdef HAVE_SCHEDULER_BOOSTCTRL -static int boosted_threads IBSS_ATTR; -#endif static const char main_thread_name[] = "main"; extern int stackbegin[]; @@ -1590,23 +1587,19 @@ void switch_thread(struct thread_entry *old) } /*--------------------------------------------------------------------------- - * Removes the boost flag from a thread and unboosts the CPU if thread count - * of boosted threads reaches zero. Requires thread slot to be locked first. + * Change the boost state of a thread boosting or unboosting the CPU + * as required. Require thread slot to be locked first. *--------------------------------------------------------------------------- */ -static inline void unboost_thread(struct thread_entry *thread) +static inline void boost_thread(struct thread_entry *thread, bool boost) { #ifdef HAVE_SCHEDULER_BOOSTCTRL - if (thread->boosted != 0) + if ((thread->boosted != 0) != boost) { - thread->boosted = 0; - if (--boosted_threads == 0) - { - cpu_boost(false); - } + thread->boosted = boost; + cpu_boost(boost); } #endif - (void)thread; } /*--------------------------------------------------------------------------- @@ -1627,9 +1620,6 @@ void sleep_thread(int ticks) GET_THREAD_STATE(current); #endif - /* Remove our boosted status if any */ - unboost_thread(current); - /* Set our timeout, change lists, and finally switch threads. * Unlock during switch on mulicore. */ current->tmo_tick = current_tick + ticks + 1; @@ -1716,11 +1706,6 @@ void block_thread_w_tmo(struct thread_queue *list, int timeout) GET_THREAD_STATE(current); #endif - /* A block with a timeout is a sleep situation, whatever we are waiting - * for _may or may not_ happen, regardless of boost state, (user input - * for instance), so this thread no longer needs to boost */ - unboost_thread(current); - /* Set the state to blocked with the specified timeout */ current->tmo_tick = current_tick + timeout; /* Set the list for explicit wakeup */ @@ -2030,17 +2015,21 @@ void trigger_cpu_boost(void) unsigned state; state = GET_THREAD_STATE(current); - - if (current->boosted == 0) - { - current->boosted = 1; - if (++boosted_threads == 1) - { - cpu_boost(true); - } - } - + boost_thread(current, true); UNLOCK_THREAD(current, state); + + (void)state; +} + +void cancel_cpu_boost(void) +{ + struct thread_entry *current = cores[CURRENT_CORE].running; + unsigned state; + + state = GET_THREAD_STATE(current); + boost_thread(current, false); + UNLOCK_THREAD(current, state); + (void)state; } #endif /* HAVE_SCHEDULER_BOOSTCTRL */ @@ -2130,6 +2119,8 @@ void remove_thread(struct thread_entry *thread) remove_from_list_tmo(thread); } + boost_thread(thread, false); + if (thread == cores[core].running) { /* Suicide - thread has unconditional rights to do this */ @@ -2613,16 +2604,6 @@ int idle_stack_usage(unsigned int core) } #endif -/*--------------------------------------------------------------------------- - * Returns the current thread status. This is a snapshot for debugging and - * does not do any slot synchronization so it could return STATE_BUSY. - *--------------------------------------------------------------------------- - */ -unsigned thread_get_status(const struct thread_entry *thread) -{ - return thread->state; -} - /*--------------------------------------------------------------------------- * Fills in the buffer with the specified thread's name. If the name is NULL, * empty, or the thread is in destruct state a formatted ID is written