diff options
Diffstat (limited to 'lib/chibios/os/rt/src/chregistry.c')
-rw-r--r-- | lib/chibios/os/rt/src/chregistry.c | 268 |
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 | */ | ||
83 | ROMCONST 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 | */ | ||
134 | thread_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 | */ | ||
158 | thread_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 | */ | ||
194 | thread_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 | */ | ||
221 | thread_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 | */ | ||
250 | thread_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 | /** @} */ | ||