/* ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, 2011,2012 Giovanni Di Sirio. This file is part of ChibiOS/RT. ChibiOS/RT is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. ChibiOS/RT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . --- A special exception to the GPL can be applied should you wish to distribute a combined work that includes ChibiOS/RT, without being obliged to provide the source code for any proprietary components. See the file exception.txt for full details of how and when the exception can be applied. */ /** * @file chdynamic.c * @brief Dynamic threads code. * * @addtogroup dynamic_threads * @details Dynamic threads related APIs and services. * @{ */ #include "ch.h" #if CH_USE_DYNAMIC || defined(__DOXYGEN__) /** * @brief Adds a reference to a thread object. * @pre The configuration option @p CH_USE_DYNAMIC must be enabled in order * to use this function. * * @param[in] tp pointer to the thread * @return The same thread pointer passed as parameter * representing the new reference. * * @api */ Thread *chThdAddRef(Thread *tp) { chSysLock(); chDbgAssert(tp->p_refs < 255, "chThdAddRef(), #1", "too many references"); tp->p_refs++; chSysUnlock(); return tp; } /** * @brief Releases a reference to a thread object. * @details If the references counter reaches zero and the thread * is in the @p THD_STATE_FINAL state then the thread's memory is * returned to the proper allocator. * @pre The configuration option @p CH_USE_DYNAMIC must be enabled in order * to use this function. * @note Static threads are not affected. * * @param[in] tp pointer to the thread * * @api */ void chThdRelease(Thread *tp) { trefs_t refs; chSysLock(); chDbgAssert(tp->p_refs > 0, "chThdRelease(), #1", "not referenced"); refs = --tp->p_refs; chSysUnlock(); /* If the references counter reaches zero and the thread is in its terminated state then the memory can be returned to the proper allocator. Of course static threads are not affected.*/ if ((refs == 0) && (tp->p_state == THD_STATE_FINAL)) { switch (tp->p_flags & THD_MEM_MODE_MASK) { #if CH_USE_HEAP case THD_MEM_MODE_HEAP: #if CH_USE_REGISTRY REG_REMOVE(tp); #endif chHeapFree(tp); break; #endif #if CH_USE_MEMPOOLS case THD_MEM_MODE_MEMPOOL: #if CH_USE_REGISTRY REG_REMOVE(tp); #endif chPoolFree(tp->p_mpool, tp); break; #endif } } } #if CH_USE_HEAP || defined(__DOXYGEN__) /** * @brief Creates a new thread allocating the memory from the heap. * @pre The configuration options @p CH_USE_DYNAMIC and @p CH_USE_HEAP * must be enabled in order to use this function. * @note A thread can terminate by calling @p chThdExit() or by simply * returning from its main function. * @note The memory allocated for the thread is not released when the thread * terminates but when a @p chThdWait() is performed. * * @param[in] heapp heap from which allocate the memory or @p NULL for the * default heap * @param[in] size size of the working area to be allocated * @param[in] prio the priority level for the new thread * @param[in] pf the thread function * @param[in] arg an argument passed to the thread function. It can be * @p NULL. * @return The pointer to the @p Thread structure allocated for * the thread into the working space area. * @retval NULL if the memory cannot be allocated. * * @api */ Thread *chThdCreateFromHeap(MemoryHeap *heapp, size_t size, tprio_t prio, tfunc_t pf, void *arg) { void *wsp; Thread *tp; wsp = chHeapAlloc(heapp, size); if (wsp == NULL) return NULL; #if CH_DBG_FILL_THREADS _thread_memfill((uint8_t *)wsp, (uint8_t *)wsp + sizeof(Thread), CH_THREAD_FILL_VALUE); _thread_memfill((uint8_t *)wsp + sizeof(Thread), (uint8_t *)wsp + size, CH_STACK_FILL_VALUE); #endif chSysLock(); tp = chThdCreateI(wsp, size, prio, pf, arg); tp->p_flags = THD_MEM_MODE_HEAP; chSchWakeupS(tp, RDY_OK); chSysUnlock(); return tp; } #endif /* CH_USE_HEAP */ #if CH_USE_MEMPOOLS || defined(__DOXYGEN__) /** * @brief Creates a new thread allocating the memory from the specified * memory pool. * @pre The configuration options @p CH_USE_DYNAMIC and @p CH_USE_MEMPOOLS * must be enabled in order to use this function. * @note A thread can terminate by calling @p chThdExit() or by simply * returning from its main function. * @note The memory allocated for the thread is not released when the thread * terminates but when a @p chThdWait() is performed. * * @param[in] mp pointer to the memory pool object * @param[in] prio the priority level for the new thread * @param[in] pf the thread function * @param[in] arg an argument passed to the thread function. It can be * @p NULL. * @return The pointer to the @p Thread structure allocated for * the thread into the working space area. * @retval NULL if the memory pool is empty. * * @api */ Thread *chThdCreateFromMemoryPool(MemoryPool *mp, tprio_t prio, tfunc_t pf, void *arg) { void *wsp; Thread *tp; chDbgCheck(mp != NULL, "chThdCreateFromMemoryPool"); wsp = chPoolAlloc(mp); if (wsp == NULL) return NULL; #if CH_DBG_FILL_THREADS _thread_memfill((uint8_t *)wsp, (uint8_t *)wsp + sizeof(Thread), CH_THREAD_FILL_VALUE); _thread_memfill((uint8_t *)wsp + sizeof(Thread), (uint8_t *)wsp + mp->mp_object_size, CH_STACK_FILL_VALUE); #endif chSysLock(); tp = chThdCreateI(wsp, mp->mp_object_size, prio, pf, arg); tp->p_flags = THD_MEM_MODE_MEMPOOL; tp->p_mpool = mp; chSchWakeupS(tp, RDY_OK); chSysUnlock(); return tp; } #endif /* CH_USE_MEMPOOLS */ #endif /* CH_USE_DYNAMIC */ /** @} */