1
0
Fork 0
forked from len0rd/rockbox
foxbox/firmware/kernel/thread-common.c
Michael Sevakis 981d028c09 Do some kernel cleanup
* Seal away private thread and kernel definitions and declarations
into the internal headers in order to better hide internal structure.

* Add a thread-common.c file that keeps shared functions together.
List functions aren't messed with since that's about to be changed to
different ones.

* It is necessary to modify some ARM/PP stuff since GCC was complaining
about constant pool distance and I would rather not force dump it. Just
bl the cache calls in the startup and exit code and let it use veneers
if it must.

* Clean up redundant #includes in relevant areas and reorganize them.

* Expunge useless and dangerous stuff like remove_thread().

Change-Id: I6e22932fad61a9fac30fd1363c071074ee7ab382
2014-08-08 01:59:59 -04:00

152 lines
4.6 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 by Ulf Ralberg
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "thread-internal.h"
#include "system.h"
/*---------------------------------------------------------------------------
* Wakeup an entire queue of threads - returns bitwise-or of return bitmask
* from each operation or THREAD_NONE of nothing was awakened. Object owning
* the queue must be locked first.
*
* INTERNAL: Intended for use by kernel objects and not for programs.
*---------------------------------------------------------------------------
*/
unsigned int thread_queue_wake(struct thread_entry **list)
{
unsigned result = THREAD_NONE;
for (;;)
{
unsigned int rc = wakeup_thread(list, WAKEUP_DEFAULT);
if (rc == THREAD_NONE)
break; /* No more threads */
result |= rc;
}
return result;
}
/** Debug screen stuff **/
/*---------------------------------------------------------------------------
* returns the stack space used in bytes
*---------------------------------------------------------------------------
*/
static unsigned int stack_usage(uintptr_t *stackptr, size_t stack_size)
{
unsigned int usage = 0;
unsigned int stack_words = stack_size / sizeof (uintptr_t);
for (unsigned int i = 0; i < stack_words; i++)
{
if (stackptr[i] != DEADBEEF)
{
usage = (stack_words - i) * 100 / stack_words;
break;
}
}
return usage;
}
#if NUM_CORES > 1
/*---------------------------------------------------------------------------
* Returns the maximum percentage of the core's idle stack ever used during
* runtime.
*---------------------------------------------------------------------------
*/
int core_get_debug_info(unsigned int core, struct core_debug_info *infop)
{
extern uintptr_t * const idle_stacks[NUM_CORES];
if (core >= NUM_CORES || !infop)
return -1;
infop->idle_stack_usage = stack_usage(idle_stacks[core], IDLE_STACK_SIZE);
return 1;
}
#endif /* NUM_CORES > 1 */
int thread_get_debug_info(unsigned int thread_id,
struct thread_debug_info *infop)
{
static const char status_chars[THREAD_NUM_STATES+1] =
{
[0 ... THREAD_NUM_STATES] = '?',
[STATE_RUNNING] = 'R',
[STATE_BLOCKED] = 'B',
[STATE_SLEEPING] = 'S',
[STATE_BLOCKED_W_TMO] = 'T',
[STATE_FROZEN] = 'F',
[STATE_KILLED] = 'K',
};
if (!infop)
return -1;
unsigned int slot = THREAD_ID_SLOT(thread_id);
if (slot >= MAXTHREADS)
return -1;
extern struct thread_entry threads[MAXTHREADS];
struct thread_entry *thread = &threads[slot];
int oldlevel = disable_irq_save();
LOCK_THREAD(thread);
unsigned int state = thread->state;
if (state != STATE_KILLED)
{
const char *name = thread->name;
if (!name)
name = "";
bool cpu_boost = false;
#ifdef HAVE_SCHEDULER_BOOSTCTRL
cpu_boost = thread->cpu_boost;
#endif
infop->stack_usage = stack_usage(thread->stack, thread->stack_size);
#if NUM_CORES > 1
infop->core = thread->core;
#endif
#ifdef HAVE_PRIORITY_SCHEDULING
infop->base_priority = thread->base_priority;
infop->current_priority = thread->priority;
#endif
snprintf(infop->statusstr, sizeof (infop->statusstr), "%c%c",
cpu_boost ? '+' : (state == STATE_RUNNING ? '*' : ' '),
status_chars[state]);
const char *fmt = *name ? "%s" : "%s%08lX";
snprintf(infop->name, sizeof (infop->name), fmt, name,
thread->id);
}
UNLOCK_THREAD(thread);
restore_irq(oldlevel);
return state == STATE_KILLED ? 0 : 1;
}