mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2024-12-25 14:27:38 +00:00
212 lines
6.9 KiB
C
212 lines
6.9 KiB
C
|
/*
|
||
|
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
|
||
|
2011,2012,2013 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 <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
---
|
||
|
|
||
|
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 <b>and</b> 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 */
|
||
|
|
||
|
/** @} */
|