aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios/os/rt/src/chregistry.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios/os/rt/src/chregistry.c')
-rw-r--r--lib/chibios/os/rt/src/chregistry.c268
1 files changed, 268 insertions, 0 deletions
diff --git a/lib/chibios/os/rt/src/chregistry.c b/lib/chibios/os/rt/src/chregistry.c
new file mode 100644
index 000000000..d074a99ba
--- /dev/null
+++ b/lib/chibios/os/rt/src/chregistry.c
@@ -0,0 +1,268 @@
1/*
2 ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014,
3 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio.
4
5 This file is part of ChibiOS.
6
7 ChibiOS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation version 3 of the License.
10
11 ChibiOS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20/**
21 * @file rt/src/chregistry.c
22 * @brief Threads registry code.
23 *
24 * @addtogroup registry
25 * @details Threads Registry related APIs and services.
26 * <h2>Operation mode</h2>
27 * The Threads Registry is a double linked list that holds all the
28 * active threads in the system.<br>
29 * Operations defined for the registry:
30 * - <b>First</b>, returns the first, in creation order, active thread
31 * in the system.
32 * - <b>Next</b>, returns the next, in creation order, active thread
33 * in the system.
34 * .
35 * The registry is meant to be mainly a debug feature, for example,
36 * using the registry a debugger can enumerate the active threads
37 * in any given moment or the shell can print the active threads
38 * and their state.<br>
39 * Another possible use is for centralized threads memory management,
40 * terminating threads can pulse an event source and an event handler
41 * can perform a scansion of the registry in order to recover the
42 * memory.
43 * @pre In order to use the threads registry the @p CH_CFG_USE_REGISTRY
44 * option must be enabled in @p chconf.h.
45 * @{
46 */
47
48#include <string.h>
49
50#include "ch.h"
51
52#if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
53
54/*===========================================================================*/
55/* Module exported variables. */
56/*===========================================================================*/
57
58/*===========================================================================*/
59/* Module local types. */
60/*===========================================================================*/
61
62/*===========================================================================*/
63/* Module local variables. */
64/*===========================================================================*/
65
66/*===========================================================================*/
67/* Module local functions. */
68/*===========================================================================*/
69
70#define _offsetof(st, m) \
71 /*lint -save -e9005 -e9033 -e413 [11.8, 10.8 1.3] Normal pointers
72 arithmetic, it is safe.*/ \
73 ((size_t)((char *)&((st *)0)->m - (char *)0)) \
74 /*lint -restore*/
75
76/*===========================================================================*/
77/* Module exported functions. */
78/*===========================================================================*/
79
80/*
81 * OS signature in ROM plus debug-related information.
82 */
83ROMCONST chdebug_t ch_debug = {
84 {'m', 'a', 'i', 'n'},
85 (uint8_t)0,
86 (uint8_t)sizeof (chdebug_t),
87 (uint16_t)(((unsigned)CH_KERNEL_MAJOR << 11U) |
88 ((unsigned)CH_KERNEL_MINOR << 6U) |
89 ((unsigned)CH_KERNEL_PATCH << 0U)),
90 (uint8_t)sizeof (void *),
91 (uint8_t)sizeof (systime_t),
92 (uint8_t)sizeof (thread_t),
93 (uint8_t)_offsetof(thread_t, hdr.pqueue.prio),
94 (uint8_t)_offsetof(thread_t, ctx),
95 (uint8_t)_offsetof(thread_t, newer),
96 (uint8_t)_offsetof(thread_t, older),
97 (uint8_t)_offsetof(thread_t, name),
98#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE)
99 (uint8_t)_offsetof(thread_t, wabase),
100#else
101 (uint8_t)0,
102#endif
103 (uint8_t)_offsetof(thread_t, state),
104 (uint8_t)_offsetof(thread_t, flags),
105#if CH_CFG_USE_DYNAMIC == TRUE
106 (uint8_t)_offsetof(thread_t, refs),
107#else
108 (uint8_t)0,
109#endif
110#if CH_CFG_TIME_QUANTUM > 0
111 (uint8_t)_offsetof(thread_t, ticks),
112#else
113 (uint8_t)0,
114#endif
115#if CH_DBG_THREADS_PROFILING == TRUE
116 (uint8_t)_offsetof(thread_t, time)
117#else
118 (uint8_t)0
119#endif
120};
121
122/**
123 * @brief Returns the first thread in the system.
124 * @details Returns the most ancient thread in the system, usually this is
125 * the main thread unless it terminated. A reference is added to the
126 * returned thread in order to make sure its status is not lost.
127 * @note This function cannot return @p NULL because there is always at
128 * least one thread in the system.
129 *
130 * @return A reference to the most ancient thread.
131 *
132 * @api
133 */
134thread_t *chRegFirstThread(void) {
135 thread_t *tp;
136
137 chSysLock();
138 tp = ch.rlist.newer;
139#if CH_CFG_USE_DYNAMIC == TRUE
140 tp->refs++;
141#endif
142 chSysUnlock();
143
144 return tp;
145}
146
147/**
148 * @brief Returns the thread next to the specified one.
149 * @details The reference counter of the specified thread is decremented and
150 * the reference counter of the returned thread is incremented.
151 *
152 * @param[in] tp pointer to the thread
153 * @return A reference to the next thread.
154 * @retval NULL if there is no next thread.
155 *
156 * @api
157 */
158thread_t *chRegNextThread(thread_t *tp) {
159 thread_t *ntp;
160
161 chSysLock();
162 ntp = tp->newer;
163 /*lint -save -e9087 -e740 [11.3, 1.3] Cast required by list handling.*/
164 if (ntp == (thread_t *)&ch.rlist) {
165 /*lint -restore*/
166 ntp = NULL;
167 }
168#if CH_CFG_USE_DYNAMIC == TRUE
169 else {
170 chDbgAssert(ntp->refs < (trefs_t)255, "too many references");
171 ntp->refs++;
172 }
173#endif
174 chSysUnlock();
175#if CH_CFG_USE_DYNAMIC == TRUE
176 chThdRelease(tp);
177#endif
178
179 return ntp;
180}
181
182/**
183 * @brief Retrieves a thread pointer by name.
184 * @note The reference counter of the found thread is increased by one so
185 * it cannot be disposed incidentally after the pointer has been
186 * returned.
187 *
188 * @param[in] name the thread name
189 * @return A pointer to the found thread.
190 * @retval NULL if a matching thread has not been found.
191 *
192 * @api
193 */
194thread_t *chRegFindThreadByName(const char *name) {
195 thread_t *ctp;
196
197 /* Scanning registry.*/
198 ctp = chRegFirstThread();
199 do {
200 if (strcmp(chRegGetThreadNameX(ctp), name) == 0) {
201 return ctp;
202 }
203 ctp = chRegNextThread(ctp);
204 } while (ctp != NULL);
205
206 return NULL;
207}
208
209/**
210 * @brief Confirms that a pointer is a valid thread pointer.
211 * @note The reference counter of the found thread is increased by one so
212 * it cannot be disposed incidentally after the pointer has been
213 * returned.
214 *
215 * @param[in] tp pointer to the thread
216 * @return A pointer to the found thread.
217 * @retval NULL if a matching thread has not been found.
218 *
219 * @api
220 */
221thread_t *chRegFindThreadByPointer(thread_t *tp) {
222 thread_t *ctp;
223
224 /* Scanning registry.*/
225 ctp = chRegFirstThread();
226 do {
227 if (ctp == tp) {
228 return ctp;
229 }
230 ctp = chRegNextThread(ctp);
231 } while (ctp != NULL);
232
233 return NULL;
234}
235
236#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE) || \
237 defined(__DOXYGEN__)
238/**
239 * @brief Confirms that a working area is being used by some active thread.
240 * @note The reference counter of the found thread is increased by one so
241 * it cannot be disposed incidentally after the pointer has been
242 * returned.
243 *
244 * @param[in] wa pointer to a static working area
245 * @return A pointer to the found thread.
246 * @retval NULL if a matching thread has not been found.
247 *
248 * @api
249 */
250thread_t *chRegFindThreadByWorkingArea(stkalign_t *wa) {
251 thread_t *ctp;
252
253 /* Scanning registry.*/
254 ctp = chRegFirstThread();
255 do {
256 if (chThdGetWorkingAreaX(ctp) == wa) {
257 return ctp;
258 }
259 ctp = chRegNextThread(ctp);
260 } while (ctp != NULL);
261
262 return NULL;
263}
264#endif
265
266#endif /* CH_CFG_USE_REGISTRY == TRUE */
267
268/** @} */