ChibiOS/RT
2.5.1
chregistry.c
Go to the documentation of this file.
00001 /*
00002     ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
00003                  2011,2012 Giovanni Di Sirio.
00004 
00005     This file is part of ChibiOS/RT.
00006 
00007     ChibiOS/RT is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 3 of the License, or
00010     (at your option) any later version.
00011 
00012     ChibiOS/RT is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015     GNU General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00019 */
00020 
00021 /**
00022  * @file    chregistry.c
00023  * @brief   Threads registry code.
00024  *
00025  * @addtogroup registry
00026  * @details Threads Registry related APIs and services.
00027  *
00028  *          <h2>Operation mode</h2>
00029  *          The Threads Registry is a double linked list that holds all the
00030  *          active threads in the system.<br>
00031  *          Operations defined for the registry:
00032  *          - <b>First</b>, returns the first, in creation order, active thread
00033  *            in the system.
00034  *          - <b>Next</b>, returns the next, in creation order, active thread
00035  *            in the system.
00036  *          .
00037  *          The registry is meant to be mainly a debug feature, for example,
00038  *          using the registry a debugger can enumerate the active threads
00039  *          in any given moment or the shell can print the active threads
00040  *          and their state.<br>
00041  *          Another possible use is for centralized threads memory management,
00042  *          terminating threads can pulse an event source and an event handler
00043  *          can perform a scansion of the registry in order to recover the
00044  *          memory.
00045  * @pre     In order to use the threads registry the @p CH_USE_REGISTRY option
00046  *          must be enabled in @p chconf.h.
00047  * @{
00048  */
00049 #include "ch.h"
00050 
00051 #if CH_USE_REGISTRY || defined(__DOXYGEN__)
00052 
00053 #define _offsetof(st, m)                                                     \
00054   ((size_t)((char *)&((st *)0)->m - (char *)0))
00055 
00056 /*
00057  * OS signature in ROM plus debug-related information.
00058  */
00059 ROMCONST chdebug_t ch_debug = {
00060   "main",
00061   (uint8_t)0,
00062   (uint8_t)sizeof (chdebug_t),
00063   (uint16_t)((CH_KERNEL_MAJOR << 11) |
00064              (CH_KERNEL_MINOR << 6) |
00065              (CH_KERNEL_PATCH) << 0),
00066   (uint8_t)sizeof (void *),
00067   (uint8_t)sizeof (systime_t),
00068   (uint8_t)sizeof (Thread),
00069   (uint8_t)_offsetof(Thread, p_prio),
00070   (uint8_t)_offsetof(Thread, p_ctx),
00071   (uint8_t)_offsetof(Thread, p_newer),
00072   (uint8_t)_offsetof(Thread, p_older),
00073   (uint8_t)_offsetof(Thread, p_name),
00074 #if CH_DBG_ENABLE_STACK_CHECK
00075   (uint8_t)_offsetof(Thread, p_stklimit),
00076 #else
00077   (uint8_t)0,
00078 #endif
00079   (uint8_t)_offsetof(Thread, p_state),
00080   (uint8_t)_offsetof(Thread, p_flags),
00081 #if CH_USE_DYNAMIC
00082   (uint8_t)_offsetof(Thread, p_refs),
00083 #else
00084   (uint8_t)0,
00085 #endif
00086 #if CH_TIME_QUANTUM > 0
00087   (uint8_t)_offsetof(Thread, p_preempt),
00088 #else
00089   (uint8_t)0,
00090 #endif
00091 #if CH_DBG_THREADS_PROFILING
00092   (uint8_t)_offsetof(Thread, p_time)
00093 #else
00094   (uint8_t)0
00095 #endif
00096 };
00097 
00098 /**
00099  * @brief   Returns the first thread in the system.
00100  * @details Returns the most ancient thread in the system, usually this is
00101  *          the main thread unless it terminated. A reference is added to the
00102  *          returned thread in order to make sure its status is not lost.
00103  * @note    This function cannot return @p NULL because there is always at
00104  *          least one thread in the system.
00105  *
00106  * @return              A reference to the most ancient thread.
00107  *
00108  * @api
00109  */
00110 Thread *chRegFirstThread(void) {
00111   Thread *tp;
00112 
00113   chSysLock();
00114   tp = rlist.r_newer;
00115 #if CH_USE_DYNAMIC
00116   tp->p_refs++;
00117 #endif
00118   chSysUnlock();
00119   return tp;
00120 }
00121 
00122 /**
00123  * @brief   Returns the thread next to the specified one.
00124  * @details The reference counter of the specified thread is decremented and
00125  *          the reference counter of the returned thread is incremented.
00126  *
00127  * @param[in] tp        pointer to the thread
00128  * @return              A reference to the next thread.
00129  * @retval NULL         if there is no next thread.
00130  *
00131  * @api
00132  */
00133 Thread *chRegNextThread(Thread *tp) {
00134   Thread *ntp;
00135 
00136   chSysLock();
00137   ntp = tp->p_newer;
00138   if (ntp == (Thread *)&rlist)
00139     ntp = NULL;
00140 #if CH_USE_DYNAMIC
00141   else {
00142     chDbgAssert(ntp->p_refs < 255, "chRegNextThread(), #1",
00143                 "too many references");
00144     ntp->p_refs++;
00145   }
00146 #endif
00147   chSysUnlock();
00148 #if CH_USE_DYNAMIC
00149   chThdRelease(tp);
00150 #endif
00151   return ntp;
00152 }
00153 
00154 #endif /* CH_USE_REGISTRY */
00155 
00156 /** @} */