ChibiOS/RT  5.1.0
chregistry.c
Go to the documentation of this file.
1 /*
2  ChibiOS - Copyright (C) 2006..2018 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; either version 3 of the License, or
9  (at your option) any later version.
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 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, 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
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  */
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  */
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  */
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  */
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 /** @} */
thread_t * chRegFindThreadByName(const char *name)
Retrieves a thread pointer by name.
Definition: chregistry.c:194
uint64_t systime_t
Type of system time.
Definition: chtime.h:138
static void chSysLock(void)
Enters the kernel lock state.
Definition: chsys.h:353
static const char * chRegGetThreadNameX(thread_t *tp)
Returns the name of the specified thread.
Definition: chregistry.h:153
thread_t * chRegFindThreadByPointer(thread_t *tp)
Confirms that a pointer is a valid thread pointer.
Definition: chregistry.c:221
trefs_t refs
References to this thread.
Definition: chschd.h:189
static void chSysUnlock(void)
Leaves the kernel lock state.
Definition: chsys.h:365
static stkalign_t * chThdGetWorkingAreaX(thread_t *tp)
Returns the working area base of the specified thread.
Definition: chthreads.h:317
#define CH_DBG_THREADS_PROFILING
Debug option, threads profiling.
Definition: chconf.h:557
thread_t * chRegFindThreadByWorkingArea(stkalign_t *wa)
Confirms that a working area is being used by some active thread.
Definition: chregistry.c:250
ChibiOS/RT memory signature record.
Definition: chregistry.h:52
thread_t * chRegFirstThread(void)
Returns the first thread in the system.
Definition: chregistry.c:134
ready_list_t rlist
Ready list header.
Definition: chschd.h:415
ch_system_t ch
System data structures.
Definition: chschd.c:42
#define chDbgAssert(c, r)
Condition assertion.
Definition: chdebug.h:127
#define TRUE
Generic &#39;true&#39; preprocessor boolean constant.
Definition: ch.h:85
#define CH_CFG_TIME_QUANTUM
Round robin interval.
Definition: chconf.h:108
#define CH_KERNEL_MAJOR
Kernel version major number.
Definition: ch.h:56
thread_t * chRegNextThread(thread_t *tp)
Returns the thread next to the specified one.
Definition: chregistry.c:158
struct ch_thread thread_t
Type of a thread structure.
Definition: chsystypes.h:52
void chThdRelease(thread_t *tp)
Releases a reference to a thread object.
Definition: chthreads.c:427
ChibiOS/RT main include file.
#define CH_KERNEL_PATCH
Kernel version patch number.
Definition: ch.h:66
thread_t * newer
Newer registry element.
Definition: chschd.h:158
#define CH_KERNEL_MINOR
Kernel version minor number.
Definition: ch.h:61
Structure representing a thread.
Definition: chschd.h:153