ChibiOS 21.11.5
chregistry.c
Go to the documentation of this file.
1/*
2 ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio.
3
4 This file is part of ChibiOS.
5
6 ChibiOS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation version 3 of the License.
9
10 ChibiOS is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/**
20 * @file rt/src/chregistry.c
21 * @brief Threads registry code.
22 *
23 * @addtogroup registry
24 * @details Threads Registry related APIs and services.
25 * <h2>Operation mode</h2>
26 * The Threads Registry is a double linked list that holds all the
27 * active threads in the system.<br>
28 * Operations defined for the registry:
29 * - <b>First</b>, returns the first, in creation order, active thread
30 * in the system.
31 * - <b>Next</b>, returns the next, in creation order, active thread
32 * in the system.
33 * .
34 * The registry is meant to be mainly a debug feature, for example,
35 * using the registry a debugger can enumerate the active threads
36 * in any given moment or the shell can print the active threads
37 * and their state.<br>
38 * Another possible use is for centralized threads memory management,
39 * terminating threads can pulse an event source and an event handler
40 * can perform a scansion of the registry in order to recover the
41 * memory.
42 * @pre In order to use the threads registry the @p CH_CFG_USE_REGISTRY
43 * option must be enabled in @p chconf.h.
44 * @{
45 */
46
47#include <string.h>
48
49#include "ch.h"
50
51#if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
52
53/*===========================================================================*/
54/* Module exported variables. */
55/*===========================================================================*/
56
57/*===========================================================================*/
58/* Module local types. */
59/*===========================================================================*/
60
61/*===========================================================================*/
62/* Module local variables. */
63/*===========================================================================*/
64
65/*===========================================================================*/
66/* Module local functions. */
67/*===========================================================================*/
68
69/*===========================================================================*/
70/* Module exported functions. */
71/*===========================================================================*/
72
73/*
74 * OS signature in ROM plus debug-related information.
75 */
77 .identifier = {'m', 'a', 'i', 'n'},
78 .zero = (uint8_t)0,
79 .size = (uint8_t)sizeof (chdebug_t),
80 .version = (uint16_t)(((unsigned)CH_KERNEL_MAJOR << 11U) |
81 ((unsigned)CH_KERNEL_MINOR << 6U) |
82 ((unsigned)CH_KERNEL_PATCH << 0U)),
83 .ptrsize = (uint8_t)sizeof (void *),
84 .timesize = (uint8_t)sizeof (systime_t),
85 .intervalsize = (uint8_t)sizeof (sysinterval_t),
86 .threadsize = (uint8_t)sizeof (thread_t),
87 .intctxsize = (uint8_t)sizeof (struct port_intctx),
88 .off_prio = (uint8_t)__CH_OFFSETOF(thread_t, hdr.pqueue.prio),
89 .off_ctx = (uint8_t)__CH_OFFSETOF(thread_t, ctx),
90 .off_newer = (uint8_t)__CH_OFFSETOF(thread_t, rqueue.next),
91 .off_older = (uint8_t)__CH_OFFSETOF(thread_t, rqueue.prev),
92 .off_name = (uint8_t)__CH_OFFSETOF(thread_t, name),
93#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE)
94 .off_stklimit = (uint8_t)__CH_OFFSETOF(thread_t, wabase),
95#else
96 .off_stklimit = (uint8_t)0,
97#endif
98 .off_state = (uint8_t)__CH_OFFSETOF(thread_t, state),
99 .off_flags = (uint8_t)__CH_OFFSETOF(thread_t, flags),
100#if CH_CFG_USE_DYNAMIC == TRUE
101 .off_refs = (uint8_t)__CH_OFFSETOF(thread_t, refs),
102#else
103 .off_refs = (uint8_t)0,
104#endif
106 .off_preempt = (uint8_t)__CH_OFFSETOF(thread_t, ticks),
107#else
108 .off_preempt = (uint8_t)0,
109#endif
111 .off_time = (uint8_t)__CH_OFFSETOF(thread_t, time),
112#else
113 .off_time = (uint8_t)0,
114#endif
115 .off_reserved = {(uint8_t)0, (uint8_t)0, (uint8_t)0, (uint8_t)0},
116 .instancesnum = (uint8_t)PORT_CORES_NUMBER,
117 .off_sys_state = (uint8_t)__CH_OFFSETOF(ch_system_t, state),
118 .off_sys_instances = (uint8_t)__CH_OFFSETOF(ch_system_t, instances[0]),
119#if (CH_CFG_USE_REGISTRY == TRUE) && (CH_CFG_SMP_MODE == TRUE)
120 .off_sys_reglist = (uint8_t)__CH_OFFSETOF(ch_system_t, reglist),
121#else
122 .off_sys_reglist = (uint8_t)0,
123#endif
125 .off_sys_rfcu = (uint8_t)__CH_OFFSETOF(ch_system_t, rfcu),
126#else
127 .off_sys_rfcu = (uint8_t)0,
128#endif
129 .off_sys_reserved = {(uint8_t)0, (uint8_t)0, (uint8_t)0, (uint8_t)0},
130 .off_inst_rlist_current = (uint8_t)__CH_OFFSETOF(os_instance_t, rlist.current),
131 .off_inst_rlist = (uint8_t)__CH_OFFSETOF(os_instance_t, rlist),
132 .off_inst_vtlist = (uint8_t)__CH_OFFSETOF(os_instance_t, vtlist),
133#if ((CH_CFG_USE_REGISTRY == TRUE) && (CH_CFG_SMP_MODE == FALSE))
134 .off_inst_reglist = (uint8_t)__CH_OFFSETOF(os_instance_t, reglist),
135#else
136 .off_inst_reglist = (uint8_t)0,
137#endif
138 .off_inst_core_id = (uint8_t)__CH_OFFSETOF(os_instance_t, core_id),
139#if CH_CFG_SMP_MODE == FALSE
140 .off_inst_rfcu = (uint8_t)__CH_OFFSETOF(os_instance_t, rfcu)
141#else
142 .off_inst_rfcu = (uint8_t)0
143#endif
144};
145
146/**
147 * @brief Returns the first thread in the system.
148 * @details Returns the most ancient thread in the system, usually this is
149 * the main thread unless it terminated. A reference is added to the
150 * returned thread in order to make sure its status is not lost.
151 * @note This function cannot return @p NULL because there is always at
152 * least one thread in the system.
153 *
154 * @return A reference to the most ancient thread.
155 *
156 * @api
157 */
159 thread_t *tp;
160 uint8_t *p;
161
162 chSysLock();
163 p = (uint8_t *)REG_HEADER(currcore)->next;
164 /*lint -save -e413 [1.3] Safe to subtract a calculated offset.*/
165 tp = threadref((p - __CH_OFFSETOF(thread_t, rqueue)));
166 /*lint -restore*/
167#if CH_CFG_USE_DYNAMIC == TRUE
168 tp->refs++;
169#endif
170 chSysUnlock();
171
172 return tp;
173}
174
175/**
176 * @brief Returns the thread next to the specified one.
177 * @details The reference counter of the specified thread is decremented and
178 * the reference counter of the returned thread is incremented.
179 *
180 * @param[in] tp pointer to the thread
181 * @return A reference to the next thread.
182 * @retval NULL if there is no next thread.
183 *
184 * @api
185 */
187 thread_t *ntp;
188 ch_queue_t *nqp;
189
190 chSysLock();
191
192 /* Next element in the registry queue.*/
193 nqp = tp->rqueue.next;
194 if (nqp == REG_HEADER(currcore)) {
195 ntp = NULL;
196 }
197 else {
198 uint8_t *p = (uint8_t *)nqp;
199 /*lint -save -e413 [1.3] Safe to subtract a calculated offset.*/
200 ntp = threadref((p - __CH_OFFSETOF(thread_t, rqueue)));
201 /*lint -restore*/
202
203#if CH_CFG_USE_DYNAMIC == TRUE
204 chDbgAssert(ntp->refs < (trefs_t)255, "too many references");
205
206 ntp->refs++;
207#endif
208 }
209 chSysUnlock();
210#if CH_CFG_USE_DYNAMIC == TRUE
211 chThdRelease(tp);
212#endif
213
214 return ntp;
215}
216
217/**
218 * @brief Retrieves a thread pointer by name.
219 * @note The reference counter of the found thread is increased by one so
220 * it cannot be disposed incidentally after the pointer has been
221 * returned.
222 *
223 * @param[in] name the thread name
224 * @return A pointer to the found thread.
225 * @retval NULL if a matching thread has not been found.
226 *
227 * @api
228 */
229thread_t *chRegFindThreadByName(const char *name) {
230 thread_t *ctp;
231
232 /* Scanning registry.*/
233 ctp = chRegFirstThread();
234 do {
235 if (strcmp(chRegGetThreadNameX(ctp), name) == 0) {
236 return ctp;
237 }
238 ctp = chRegNextThread(ctp);
239 } while (ctp != NULL);
240
241 return NULL;
242}
243
244/**
245 * @brief Confirms that a pointer is a valid thread pointer.
246 * @note The reference counter of the found thread is increased by one so
247 * it cannot be disposed incidentally after the pointer has been
248 * returned.
249 *
250 * @param[in] tp pointer to the thread
251 * @return A pointer to the found thread.
252 * @retval NULL if a matching thread has not been found.
253 *
254 * @api
255 */
257 thread_t *ctp;
258
259 /* Scanning registry.*/
260 ctp = chRegFirstThread();
261 do {
262 if (ctp == tp) {
263 return ctp;
264 }
265 ctp = chRegNextThread(ctp);
266 } while (ctp != NULL);
267
268 return NULL;
269}
270
271#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE) || \
272 defined(__DOXYGEN__)
273/**
274 * @brief Confirms that a working area is being used by some active thread.
275 * @note The reference counter of the found thread is increased by one so
276 * it cannot be disposed incidentally after the pointer has been
277 * returned.
278 *
279 * @param[in] wa pointer to a static working area
280 * @return A pointer to the found thread.
281 * @retval NULL if a matching thread has not been found.
282 *
283 * @api
284 */
286 thread_t *ctp;
287
288 /* Scanning registry.*/
289 ctp = chRegFirstThread();
290 do {
291 if (chThdGetWorkingAreaX(ctp) == wa) {
292 return ctp;
293 }
294 ctp = chRegNextThread(ctp);
295 } while (ctp != NULL);
296
297 return NULL;
298}
299#endif
300
301#endif /* CH_CFG_USE_REGISTRY == TRUE */
302
303/** @} */
#define chSysUnlock()
Leaves the kernel lock state.
#define chSysLock()
Enters the kernel lock state.
#define chDbgAssert(c, r)
Condition assertion.
Definition chdebug.h:143
#define CH_CFG_TIME_QUANTUM
Round robin interval.
#define CH_DBG_THREADS_PROFILING
Debug option, threads profiling.
#define CH_CFG_SMP_MODE
Handling of instances.
#define CH_KERNEL_PATCH
Kernel version patch number.
#define TRUE
Generic 'true' preprocessor boolean constant.
#define CH_KERNEL_MAJOR
Kernel version major number.
#define CH_KERNEL_MINOR
Kernel version minor number.
struct ch_queue ch_queue_t
Type of a generic bidirectional linked list header and element.
Definition chlists.h:62
#define threadref(p)
Safe cast of a queue pointer to a thread pointer.
Definition chearly.h:205
#define __CH_OFFSETOF(st, m)
Structure field offset utility.
Definition chearly.h:157
uint8_t trefs_t
Definition chearly.h:84
struct ch_system ch_system_t
Type of system data structure.
struct ch_os_instance os_instance_t
Type of an OS instance structure.
Definition chearly.h:137
port_stkalign_t stkalign_t
Definition chearly.h:79
struct ch_thread thread_t
Type of a thread structure.
Definition chearly.h:132
#define ROMCONST
ROM constant modifier.
Definition chtypes.h:83
#define PORT_CORES_NUMBER
Definition chport.h:125
#define REG_HEADER(oip)
Access to the registry list header.
Definition chregistry.h:97
ROMCONST chdebug_t ch_debug
Definition chregistry.c:76
thread_t * chRegFirstThread(void)
Returns the first thread in the system.
Definition chregistry.c:158
thread_t * chRegNextThread(thread_t *tp)
Returns the thread next to the specified one.
Definition chregistry.c:186
thread_t * chRegFindThreadByName(const char *name)
Retrieves a thread pointer by name.
Definition chregistry.c:229
static const char * chRegGetThreadNameX(thread_t *tp)
Returns the name of the specified thread.
Definition chregistry.h:184
thread_t * chRegFindThreadByWorkingArea(stkalign_t *wa)
Confirms that a working area is being used by some active thread.
Definition chregistry.c:285
thread_t * chRegFindThreadByPointer(thread_t *tp)
Confirms that a pointer is a valid thread pointer.
Definition chregistry.c:256
#define currcore
Access to current core's instance structure.
Definition chsys.h:89
void chThdRelease(thread_t *tp)
Releases a reference to a thread object.
Definition chthreads.c:428
static stkalign_t * chThdGetWorkingAreaX(thread_t *tp)
Returns the working area base of the specified thread.
Definition chthreads.h:385
uint64_t systime_t
Type of system time.
Definition chtime.h:106
uint64_t sysinterval_t
Type of time interval.
Definition chtime.h:118
ch_queue_t * next
Next in the list/queue.
Definition chlists.h:69
trefs_t refs
References to this thread.
Definition chobjects.h:212
ch_queue_t rqueue
Registry queue element.
Definition chobjects.h:179
ChibiOS/RT memory signature record.
Definition chregistry.h:51
System saved context.
Definition chcore.h:160