summaryrefslogtreecommitdiff
path: root/firmware/kernel/thread-common.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/kernel/thread-common.c')
-rw-r--r--firmware/kernel/thread-common.c152
1 files changed, 152 insertions, 0 deletions
diff --git a/firmware/kernel/thread-common.c b/firmware/kernel/thread-common.c
new file mode 100644
index 0000000000..b8b8ffbd4c
--- /dev/null
+++ b/firmware/kernel/thread-common.c
@@ -0,0 +1,152 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Ulf Ralberg
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "thread-internal.h"
22#include "system.h"
23
24/*---------------------------------------------------------------------------
25 * Wakeup an entire queue of threads - returns bitwise-or of return bitmask
26 * from each operation or THREAD_NONE of nothing was awakened. Object owning
27 * the queue must be locked first.
28 *
29 * INTERNAL: Intended for use by kernel objects and not for programs.
30 *---------------------------------------------------------------------------
31 */
32unsigned int thread_queue_wake(struct thread_entry **list)
33{
34 unsigned result = THREAD_NONE;
35
36 for (;;)
37 {
38 unsigned int rc = wakeup_thread(list, WAKEUP_DEFAULT);
39
40 if (rc == THREAD_NONE)
41 break; /* No more threads */
42
43 result |= rc;
44 }
45
46 return result;
47}
48
49
50/** Debug screen stuff **/
51
52/*---------------------------------------------------------------------------
53 * returns the stack space used in bytes
54 *---------------------------------------------------------------------------
55 */
56static unsigned int stack_usage(uintptr_t *stackptr, size_t stack_size)
57{
58 unsigned int usage = 0;
59 unsigned int stack_words = stack_size / sizeof (uintptr_t);
60
61 for (unsigned int i = 0; i < stack_words; i++)
62 {
63 if (stackptr[i] != DEADBEEF)
64 {
65 usage = (stack_words - i) * 100 / stack_words;
66 break;
67 }
68 }
69
70 return usage;
71}
72
73#if NUM_CORES > 1
74/*---------------------------------------------------------------------------
75 * Returns the maximum percentage of the core's idle stack ever used during
76 * runtime.
77 *---------------------------------------------------------------------------
78 */
79int core_get_debug_info(unsigned int core, struct core_debug_info *infop)
80{
81 extern uintptr_t * const idle_stacks[NUM_CORES];
82
83 if (core >= NUM_CORES || !infop)
84 return -1;
85
86 infop->idle_stack_usage = stack_usage(idle_stacks[core], IDLE_STACK_SIZE);
87 return 1;
88}
89#endif /* NUM_CORES > 1 */
90
91int thread_get_debug_info(unsigned int thread_id,
92 struct thread_debug_info *infop)
93{
94 static const char status_chars[THREAD_NUM_STATES+1] =
95 {
96 [0 ... THREAD_NUM_STATES] = '?',
97 [STATE_RUNNING] = 'R',
98 [STATE_BLOCKED] = 'B',
99 [STATE_SLEEPING] = 'S',
100 [STATE_BLOCKED_W_TMO] = 'T',
101 [STATE_FROZEN] = 'F',
102 [STATE_KILLED] = 'K',
103 };
104
105 if (!infop)
106 return -1;
107
108 unsigned int slot = THREAD_ID_SLOT(thread_id);
109 if (slot >= MAXTHREADS)
110 return -1;
111
112 extern struct thread_entry threads[MAXTHREADS];
113 struct thread_entry *thread = &threads[slot];
114
115 int oldlevel = disable_irq_save();
116 LOCK_THREAD(thread);
117
118 unsigned int state = thread->state;
119
120 if (state != STATE_KILLED)
121 {
122 const char *name = thread->name;
123 if (!name)
124 name = "";
125
126 bool cpu_boost = false;
127#ifdef HAVE_SCHEDULER_BOOSTCTRL
128 cpu_boost = thread->cpu_boost;
129#endif
130 infop->stack_usage = stack_usage(thread->stack, thread->stack_size);
131#if NUM_CORES > 1
132 infop->core = thread->core;
133#endif
134#ifdef HAVE_PRIORITY_SCHEDULING
135 infop->base_priority = thread->base_priority;
136 infop->current_priority = thread->priority;
137#endif
138
139 snprintf(infop->statusstr, sizeof (infop->statusstr), "%c%c",
140 cpu_boost ? '+' : (state == STATE_RUNNING ? '*' : ' '),
141 status_chars[state]);
142
143 const char *fmt = *name ? "%s" : "%s%08lX";
144 snprintf(infop->name, sizeof (infop->name), fmt, name,
145 thread->id);
146 }
147
148 UNLOCK_THREAD(thread);
149 restore_irq(oldlevel);
150
151 return state == STATE_KILLED ? 0 : 1;
152}