ChibiOS 21.11.4
chregistry.c
Go to the documentation of this file.
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/*===========================================================================*/
71/* Module exported functions. */
72/*===========================================================================*/
73
74/*
75 * OS signature in ROM plus debug-related information.
76 */
78 .identifier = {'m', 'a', 'i', 'n'},
79 .zero = (uint8_t)0,
80 .size = (uint8_t)sizeof (chdebug_t),
81 .version = (uint16_t)(((unsigned)CH_KERNEL_MAJOR << 11U) |
82 ((unsigned)CH_KERNEL_MINOR << 6U) |
83 ((unsigned)CH_KERNEL_PATCH << 0U)),
84 .ptrsize = (uint8_t)sizeof (void *),
85 .timesize = (uint8_t)sizeof (systime_t),
86 .intervalsize = (uint8_t)sizeof (sysinterval_t),
87 .threadsize = (uint8_t)sizeof (thread_t),
88 .intctxsize = (uint8_t)sizeof (struct port_intctx),
89 .off_prio = (uint8_t)__CH_OFFSETOF(thread_t, hdr.pqueue.prio),
90 .off_ctx = (uint8_t)__CH_OFFSETOF(thread_t, ctx),
91 .off_newer = (uint8_t)__CH_OFFSETOF(thread_t, rqueue.next),
92 .off_older = (uint8_t)__CH_OFFSETOF(thread_t, rqueue.prev),
93 .off_name = (uint8_t)__CH_OFFSETOF(thread_t, name),
94#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE)
95 .off_stklimit = (uint8_t)__CH_OFFSETOF(thread_t, wabase),
96#else
97 .off_stklimit = (uint8_t)0,
98#endif
99 .off_state = (uint8_t)__CH_OFFSETOF(thread_t, state),
100 .off_flags = (uint8_t)__CH_OFFSETOF(thread_t, flags),
101#if CH_CFG_USE_DYNAMIC == TRUE
102 .off_refs = (uint8_t)__CH_OFFSETOF(thread_t, refs),
103#else
104 .off_refs = (uint8_t)0,
105#endif
107 .off_preempt = (uint8_t)__CH_OFFSETOF(thread_t, ticks),
108#else
109 .off_preempt = (uint8_t)0,
110#endif
112 .off_time = (uint8_t)__CH_OFFSETOF(thread_t, time),
113#else
114 .off_time = (uint8_t)0,
115#endif
116 .off_reserved = {(uint8_t)0, (uint8_t)0, (uint8_t)0, (uint8_t)0},
117 .instancesnum = (uint8_t)PORT_CORES_NUMBER,
118 .off_sys_state = (uint8_t)__CH_OFFSETOF(ch_system_t, state),
119 .off_sys_instances = (uint8_t)__CH_OFFSETOF(ch_system_t, instances[0]),
120#if (CH_CFG_USE_REGISTRY == TRUE) && (CH_CFG_SMP_MODE == TRUE)
121 .off_sys_reglist = (uint8_t)__CH_OFFSETOF(ch_system_t, reglist),
122#else
123 .off_sys_reglist = (uint8_t)0,
124#endif
126 .off_sys_rfcu = (uint8_t)__CH_OFFSETOF(ch_system_t, rfcu),
127#else
128 .off_sys_rfcu = (uint8_t)0,
129#endif
130 .off_sys_reserved = {(uint8_t)0, (uint8_t)0, (uint8_t)0, (uint8_t)0},
131 .off_inst_rlist_current = (uint8_t)__CH_OFFSETOF(os_instance_t, rlist.current),
132 .off_inst_rlist = (uint8_t)__CH_OFFSETOF(os_instance_t, rlist),
133 .off_inst_vtlist = (uint8_t)__CH_OFFSETOF(os_instance_t, vtlist),
134#if ((CH_CFG_USE_REGISTRY == TRUE) && (CH_CFG_SMP_MODE == FALSE))
135 .off_inst_reglist = (uint8_t)__CH_OFFSETOF(os_instance_t, reglist),
136#else
137 .off_inst_reglist = (uint8_t)0,
138#endif
139 .off_inst_core_id = (uint8_t)__CH_OFFSETOF(os_instance_t, core_id),
140#if CH_CFG_SMP_MODE == FALSE
141 .off_inst_rfcu = (uint8_t)__CH_OFFSETOF(os_instance_t, rfcu)
142#else
143 .off_inst_rfcu = (uint8_t)0
144#endif
145};
146
147/**
148 * @brief Returns the first thread in the system.
149 * @details Returns the most ancient thread in the system, usually this is
150 * the main thread unless it terminated. A reference is added to the
151 * returned thread in order to make sure its status is not lost.
152 * @note This function cannot return @p NULL because there is always at
153 * least one thread in the system.
154 *
155 * @return A reference to the most ancient thread.
156 *
157 * @api
158 */
160 thread_t *tp;
161 uint8_t *p;
162
163 chSysLock();
164 p = (uint8_t *)REG_HEADER(currcore)->next;
165 /*lint -save -e413 [1.3] Safe to subtract a calculated offset.*/
166 tp = threadref((p - __CH_OFFSETOF(thread_t, rqueue)));
167 /*lint -restore*/
168#if CH_CFG_USE_DYNAMIC == TRUE
169 tp->refs++;
170#endif
171 chSysUnlock();
172
173 return tp;
174}
175
176/**
177 * @brief Returns the thread next to the specified one.
178 * @details The reference counter of the specified thread is decremented and
179 * the reference counter of the returned thread is incremented.
180 *
181 * @param[in] tp pointer to the thread
182 * @return A reference to the next thread.
183 * @retval NULL if there is no next thread.
184 *
185 * @api
186 */
188 thread_t *ntp;
189 ch_queue_t *nqp;
190
191 chSysLock();
192
193 /* Next element in the registry queue.*/
194 nqp = tp->rqueue.next;
195 if (nqp == REG_HEADER(currcore)) {
196 ntp = NULL;
197 }
198 else {
199 uint8_t *p = (uint8_t *)nqp;
200 /*lint -save -e413 [1.3] Safe to subtract a calculated offset.*/
201 ntp = threadref((p - __CH_OFFSETOF(thread_t, rqueue)));
202 /*lint -restore*/
203
204#if CH_CFG_USE_DYNAMIC == TRUE
205 chDbgAssert(ntp->refs < (trefs_t)255, "too many references");
206
207 ntp->refs++;
208#endif
209 }
210 chSysUnlock();
211#if CH_CFG_USE_DYNAMIC == TRUE
212 chThdRelease(tp);
213#endif
214
215 return ntp;
216}
217
218/**
219 * @brief Retrieves a thread pointer by name.
220 * @note The reference counter of the found thread is increased by one so
221 * it cannot be disposed incidentally after the pointer has been
222 * returned.
223 *
224 * @param[in] name the thread name
225 * @return A pointer to the found thread.
226 * @retval NULL if a matching thread has not been found.
227 *
228 * @api
229 */
230thread_t *chRegFindThreadByName(const char *name) {
231 thread_t *ctp;
232
233 /* Scanning registry.*/
234 ctp = chRegFirstThread();
235 do {
236 if (strcmp(chRegGetThreadNameX(ctp), name) == 0) {
237 return ctp;
238 }
239 ctp = chRegNextThread(ctp);
240 } while (ctp != NULL);
241
242 return NULL;
243}
244
245/**
246 * @brief Confirms that a pointer is a valid thread pointer.
247 * @note The reference counter of the found thread is increased by one so
248 * it cannot be disposed incidentally after the pointer has been
249 * returned.
250 *
251 * @param[in] tp pointer to the thread
252 * @return A pointer to the found thread.
253 * @retval NULL if a matching thread has not been found.
254 *
255 * @api
256 */
258 thread_t *ctp;
259
260 /* Scanning registry.*/
261 ctp = chRegFirstThread();
262 do {
263 if (ctp == tp) {
264 return ctp;
265 }
266 ctp = chRegNextThread(ctp);
267 } while (ctp != NULL);
268
269 return NULL;
270}
271
272#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE) || \
273 defined(__DOXYGEN__)
274/**
275 * @brief Confirms that a working area is being used by some active thread.
276 * @note The reference counter of the found thread is increased by one so
277 * it cannot be disposed incidentally after the pointer has been
278 * returned.
279 *
280 * @param[in] wa pointer to a static working area
281 * @return A pointer to the found thread.
282 * @retval NULL if a matching thread has not been found.
283 *
284 * @api
285 */
287 thread_t *ctp;
288
289 /* Scanning registry.*/
290 ctp = chRegFirstThread();
291 do {
292 if (chThdGetWorkingAreaX(ctp) == wa) {
293 return ctp;
294 }
295 ctp = chRegNextThread(ctp);
296 } while (ctp != NULL);
297
298 return NULL;
299}
300#endif
301
302#endif /* CH_CFG_USE_REGISTRY == TRUE */
303
304/** @} */
#define chSysUnlock()
Leaves the kernel lock state.
#define chSysLock()
Enters the kernel lock state.
#define chDbgAssert(c, r)
Condition assertion.
Definition chdebug.h:144
#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:63
#define threadref(p)
Safe cast of a queue pointer to a thread pointer.
Definition chearly.h:206
#define __CH_OFFSETOF(st, m)
Structure field offset utility.
Definition chearly.h:158
uint8_t trefs_t
Definition chearly.h:85
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:138
port_stkalign_t stkalign_t
Definition chearly.h:80
struct ch_thread thread_t
Type of a thread structure.
Definition chearly.h:133
#define ROMCONST
ROM constant modifier.
Definition chtypes.h:84
#define PORT_CORES_NUMBER
Definition chport.h:126
#define REG_HEADER(oip)
Access to the registry list header.
Definition chregistry.h:98
ROMCONST chdebug_t ch_debug
Definition chregistry.c:77
thread_t * chRegFirstThread(void)
Returns the first thread in the system.
Definition chregistry.c:159
thread_t * chRegNextThread(thread_t *tp)
Returns the thread next to the specified one.
Definition chregistry.c:187
thread_t * chRegFindThreadByName(const char *name)
Retrieves a thread pointer by name.
Definition chregistry.c:230
static const char * chRegGetThreadNameX(thread_t *tp)
Returns the name of the specified thread.
Definition chregistry.h:185
thread_t * chRegFindThreadByWorkingArea(stkalign_t *wa)
Confirms that a working area is being used by some active thread.
Definition chregistry.c:286
thread_t * chRegFindThreadByPointer(thread_t *tp)
Confirms that a pointer is a valid thread pointer.
Definition chregistry.c:257
#define currcore
Access to current core's instance structure.
Definition chsys.h:90
void chThdRelease(thread_t *tp)
Releases a reference to a thread object.
Definition chthreads.c:429
static stkalign_t * chThdGetWorkingAreaX(thread_t *tp)
Returns the working area base of the specified thread.
Definition chthreads.h:386
uint64_t systime_t
Type of system time.
Definition chtime.h:107
uint64_t sysinterval_t
Type of time interval.
Definition chtime.h:119
ch_queue_t * next
Next in the list/queue.
Definition chlists.h:70
trefs_t refs
References to this thread.
Definition chobjects.h:215
ch_queue_t rqueue
Registry queue element.
Definition chobjects.h:182
ChibiOS/RT memory signature record.
Definition chregistry.h:52
System saved context.
Definition chcore.h:161