forked from len0rd/rockbox
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
This commit is contained in:
parent
31bf5cc8e5
commit
fadbf0a6f7
8 changed files with 46 additions and 56 deletions
|
|
@ -563,7 +563,6 @@ static bool yield_codec(void)
|
||||||
while (pcmbuf_is_lowdata() && !buffer_is_low())
|
while (pcmbuf_is_lowdata() && !buffer_is_low())
|
||||||
{
|
{
|
||||||
sleep(2);
|
sleep(2);
|
||||||
trigger_cpu_boost();
|
|
||||||
|
|
||||||
if (!queue_empty(&buffering_queue))
|
if (!queue_empty(&buffering_queue))
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -1267,6 +1266,7 @@ void buffering_thread(void)
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
cancel_cpu_boost();
|
||||||
queue_wait_w_tmo(&buffering_queue, &ev, filling?5:HZ/2);
|
queue_wait_w_tmo(&buffering_queue, &ev, filling?5:HZ/2);
|
||||||
|
|
||||||
switch (ev.id)
|
switch (ev.id)
|
||||||
|
|
|
||||||
|
|
@ -124,16 +124,14 @@ static char thread_status_char(unsigned status)
|
||||||
static char* threads_getname(int selected_item, void * data, char *buffer)
|
static char* threads_getname(int selected_item, void * data, char *buffer)
|
||||||
{
|
{
|
||||||
(void)data;
|
(void)data;
|
||||||
|
struct thread_entry *thread;
|
||||||
char name[32];
|
char name[32];
|
||||||
struct thread_entry *thread = NULL;
|
|
||||||
unsigned status;
|
|
||||||
int usage;
|
|
||||||
|
|
||||||
#if NUM_CORES > 1
|
#if NUM_CORES > 1
|
||||||
if (selected_item < (int)NUM_CORES)
|
if (selected_item < (int)NUM_CORES)
|
||||||
{
|
{
|
||||||
usage = idle_stack_usage(selected_item);
|
snprintf(buffer, MAX_PATH, "Idle (%d): %2d%%", selected_item,
|
||||||
snprintf(buffer, MAX_PATH, "Idle (%d): %2d%%", selected_item, usage);
|
idle_stack_usage(selected_item));
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,25 +139,26 @@ static char* threads_getname(int selected_item, void * data, char *buffer)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
thread = &threads[selected_item];
|
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);
|
snprintf(buffer, MAX_PATH, "%2d: ---", selected_item);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_get_name(name, 32, thread);
|
thread_get_name(name, 32, thread);
|
||||||
usage = thread_stack_usage(thread);
|
|
||||||
|
|
||||||
snprintf(buffer, MAX_PATH,
|
snprintf(buffer, MAX_PATH,
|
||||||
"%2d: " IF_COP("(%d) ") "%c%c " IF_PRIO("%d ") "%2d%% %s",
|
"%2d: " IF_COP("(%d) ") "%c%c " IF_PRIO("%d ") "%2d%% %s",
|
||||||
selected_item,
|
selected_item,
|
||||||
IF_COP(thread->core,)
|
IF_COP(thread->core,)
|
||||||
(status == STATE_RUNNING) ? '*' : ' ',
|
#ifdef HAVE_SCHEDULER_BOOSTCTRL
|
||||||
thread_status_char(status),
|
(thread->boosted) ? '+' :
|
||||||
|
#endif
|
||||||
|
((thread->state == STATE_RUNNING) ? '*' : ' '),
|
||||||
|
thread_status_char(thread->state),
|
||||||
IF_PRIO(thread->priority,)
|
IF_PRIO(thread->priority,)
|
||||||
usage, name);
|
thread_stack_usage(thread), name);
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -848,6 +848,7 @@ static bool codec_pcmbuf_insert_callback(
|
||||||
|
|
||||||
while ((dest = pcmbuf_request_buffer(&out_count)) == NULL)
|
while ((dest = pcmbuf_request_buffer(&out_count)) == NULL)
|
||||||
{
|
{
|
||||||
|
cancel_cpu_boost();
|
||||||
sleep(1);
|
sleep(1);
|
||||||
if (ci.seek_time || ci.new_track || ci.stop_codec)
|
if (ci.seek_time || ci.new_track || ci.stop_codec)
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -1277,6 +1278,7 @@ static void codec_thread(void)
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
status = 0;
|
status = 0;
|
||||||
|
cancel_cpu_boost();
|
||||||
queue_wait(&codec_queue, &ev);
|
queue_wait(&codec_queue, &ev);
|
||||||
|
|
||||||
switch (ev.id) {
|
switch (ev.id) {
|
||||||
|
|
@ -2388,6 +2390,7 @@ static void audio_thread(void)
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
cancel_cpu_boost();
|
||||||
queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
|
queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
|
||||||
|
|
||||||
switch (ev.id) {
|
switch (ev.id) {
|
||||||
|
|
|
||||||
|
|
@ -553,6 +553,11 @@ int radio_screen(void)
|
||||||
trigger_cpu_boost();
|
trigger_cpu_boost();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!update_screen)
|
||||||
|
{
|
||||||
|
cancel_cpu_boost();
|
||||||
|
}
|
||||||
|
|
||||||
#if CONFIG_CODEC != SWCODEC
|
#if CONFIG_CODEC != SWCODEC
|
||||||
/* TODO: Can we timeout at HZ when recording since peaks aren't
|
/* TODO: Can we timeout at HZ when recording since peaks aren't
|
||||||
displayed? This should quiet recordings too. */
|
displayed? This should quiet recordings too. */
|
||||||
|
|
|
||||||
|
|
@ -1034,6 +1034,7 @@ bool create_playlist(void)
|
||||||
add_dir(filename, sizeof(filename), fd);
|
add_dir(filename, sizeof(filename), fd);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
|
cancel_cpu_boost();
|
||||||
sleep(HZ);
|
sleep(HZ);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -249,7 +249,7 @@ static void voice_message(struct voice_thread_data *td)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cancel boost */
|
/* Cancel boost */
|
||||||
sleep(0);
|
cancel_cpu_boost();
|
||||||
|
|
||||||
td->state = TSTATE_STOPPED;
|
td->state = TSTATE_STOPPED;
|
||||||
event_set_state(&voice_event, STATE_SIGNALED);
|
event_set_state(&voice_event, STATE_SIGNALED);
|
||||||
|
|
|
||||||
|
|
@ -469,8 +469,10 @@ struct thread_entry*
|
||||||
|
|
||||||
#ifdef HAVE_SCHEDULER_BOOSTCTRL
|
#ifdef HAVE_SCHEDULER_BOOSTCTRL
|
||||||
void trigger_cpu_boost(void);
|
void trigger_cpu_boost(void);
|
||||||
|
void cancel_cpu_boost(void);
|
||||||
#else
|
#else
|
||||||
#define trigger_cpu_boost()
|
#define trigger_cpu_boost()
|
||||||
|
#define cancel_cpu_boost()
|
||||||
#endif
|
#endif
|
||||||
void thread_thaw(struct thread_entry *thread);
|
void thread_thaw(struct thread_entry *thread);
|
||||||
void thread_wait(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
|
#if NUM_CORES > 1
|
||||||
int idle_stack_usage(unsigned int core);
|
int idle_stack_usage(unsigned int core);
|
||||||
#endif
|
#endif
|
||||||
unsigned thread_get_status(const struct thread_entry *thread);
|
|
||||||
void thread_get_name(char *buffer, int size,
|
void thread_get_name(char *buffer, int size,
|
||||||
struct thread_entry *thread);
|
struct thread_entry *thread);
|
||||||
#ifdef RB_PROFILE
|
#ifdef RB_PROFILE
|
||||||
|
|
|
||||||
|
|
@ -92,9 +92,6 @@
|
||||||
/* Cast to the the machine int type, whose size could be < 4. */
|
/* Cast to the the machine int type, whose size could be < 4. */
|
||||||
struct core_entry cores[NUM_CORES] IBSS_ATTR;
|
struct core_entry cores[NUM_CORES] IBSS_ATTR;
|
||||||
struct thread_entry threads[MAXTHREADS] 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";
|
static const char main_thread_name[] = "main";
|
||||||
extern int stackbegin[];
|
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
|
* Change the boost state of a thread boosting or unboosting the CPU
|
||||||
* of boosted threads reaches zero. Requires thread slot to be locked first.
|
* 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
|
#ifdef HAVE_SCHEDULER_BOOSTCTRL
|
||||||
if (thread->boosted != 0)
|
if ((thread->boosted != 0) != boost)
|
||||||
{
|
{
|
||||||
thread->boosted = 0;
|
thread->boosted = boost;
|
||||||
if (--boosted_threads == 0)
|
cpu_boost(boost);
|
||||||
{
|
|
||||||
cpu_boost(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
(void)thread;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------
|
||||||
|
|
@ -1627,9 +1620,6 @@ void sleep_thread(int ticks)
|
||||||
GET_THREAD_STATE(current);
|
GET_THREAD_STATE(current);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Remove our boosted status if any */
|
|
||||||
unboost_thread(current);
|
|
||||||
|
|
||||||
/* Set our timeout, change lists, and finally switch threads.
|
/* Set our timeout, change lists, and finally switch threads.
|
||||||
* Unlock during switch on mulicore. */
|
* Unlock during switch on mulicore. */
|
||||||
current->tmo_tick = current_tick + ticks + 1;
|
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);
|
GET_THREAD_STATE(current);
|
||||||
#endif
|
#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 */
|
/* Set the state to blocked with the specified timeout */
|
||||||
current->tmo_tick = current_tick + timeout;
|
current->tmo_tick = current_tick + timeout;
|
||||||
/* Set the list for explicit wakeup */
|
/* Set the list for explicit wakeup */
|
||||||
|
|
@ -2030,17 +2015,21 @@ void trigger_cpu_boost(void)
|
||||||
unsigned state;
|
unsigned state;
|
||||||
|
|
||||||
state = GET_THREAD_STATE(current);
|
state = GET_THREAD_STATE(current);
|
||||||
|
boost_thread(current, true);
|
||||||
if (current->boosted == 0)
|
|
||||||
{
|
|
||||||
current->boosted = 1;
|
|
||||||
if (++boosted_threads == 1)
|
|
||||||
{
|
|
||||||
cpu_boost(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UNLOCK_THREAD(current, state);
|
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;
|
(void)state;
|
||||||
}
|
}
|
||||||
#endif /* HAVE_SCHEDULER_BOOSTCTRL */
|
#endif /* HAVE_SCHEDULER_BOOSTCTRL */
|
||||||
|
|
@ -2130,6 +2119,8 @@ void remove_thread(struct thread_entry *thread)
|
||||||
remove_from_list_tmo(thread);
|
remove_from_list_tmo(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost_thread(thread, false);
|
||||||
|
|
||||||
if (thread == cores[core].running)
|
if (thread == cores[core].running)
|
||||||
{
|
{
|
||||||
/* Suicide - thread has unconditional rights to do this */
|
/* Suicide - thread has unconditional rights to do this */
|
||||||
|
|
@ -2613,16 +2604,6 @@ int idle_stack_usage(unsigned int core)
|
||||||
}
|
}
|
||||||
#endif
|
#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,
|
* 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
|
* empty, or the thread is in destruct state a formatted ID is written
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue