diff --git a/os/hal/ports/STM32/OTGv1/usb_lld.c b/os/hal/ports/STM32/OTGv1/usb_lld.c index a6197feb8..39464b367 100644 --- a/os/hal/ports/STM32/OTGv1/usb_lld.c +++ b/os/hal/ports/STM32/OTGv1/usb_lld.c @@ -305,7 +305,7 @@ static void otg_fifo_write_from_queue(volatile uint32_t *fifop, /* Updating queue.*/ osalSysLock(); oqp->q_counter += n; - osalQueueWakeupAllI(&oqp->q_waiting, Q_OK); + osalThreadDequeueAllI(&oqp->q_waiting, Q_OK); osalOsRescheduleS(); osalSysUnlock(); } @@ -416,7 +416,7 @@ static void otg_fifo_read_to_queue(volatile uint32_t *fifop, /* Updating queue.*/ osalSysLock(); iqp->q_counter += n; - osalQueueWakeupAllI(&iqp->q_waiting, Q_OK); + osalThreadDequeueAllI(&iqp->q_waiting, Q_OK); osalOsRescheduleS(); osalSysUnlock(); } diff --git a/os/rt/include/ch.h b/os/rt/include/ch.h index e96bc797c..c1360d4c4 100644 --- a/os/rt/include/ch.h +++ b/os/rt/include/ch.h @@ -66,15 +66,6 @@ typedef struct thread thread_t; typedef struct virtual_timer virtual_timer_t; -/* This function is special, it must be accessible from all modules.*/ -#ifdef __cplusplus -extern "C" { -#endif - void chSysHalt(const char *reason); -#ifdef __cplusplus -} -#endif - /* Inclusion of all the kernel sub-headers.*/ #include "chtypes.h" #include "chconf.h" @@ -82,11 +73,9 @@ extern "C" { #include "chdebug.h" #include "chtm.h" #include "chstats.h" -#include "chglobal.h" +#include "chschd.h" #include "chsys.h" #include "chvt.h" -#include "chlists.h" -#include "chschd.h" #include "chthreads.h" #include "chregistry.h" #include "chsem.h" diff --git a/os/rt/include/chglobal.h b/os/rt/include/chglobal.h deleted file mode 100644 index 3d8458f02..000000000 --- a/os/rt/include/chglobal.h +++ /dev/null @@ -1,321 +0,0 @@ -/* - 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 . -*/ - -/** - * @file chglobal.h - * @brief Data structures with global scope header. - * - * @addtogroup global - */ - -#ifndef _CHGLOBAL_H_ -#define _CHGLOBAL_H_ - -/*===========================================================================*/ -/* Module constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Generic threads single link list, it works like a stack. - */ -typedef struct { - thread_t *p_next; /**< @brief Next in the list/queue. */ -} threads_list_t; - -/** - * @extends threads_list_t - * - * @brief Generic threads bidirectional linked list header and element. - */ -typedef struct { - thread_t *p_next; /**< @brief Next in the list/queue. */ - thread_t *p_prev; /**< @brief Previous in the queue. */ -} threads_queue_t; - -/** - * @extends threads_queue_t - * - * @brief Ready list header. - */ -typedef struct { - threads_queue_t r_queue; /**< @brief Threads queue. */ - tprio_t r_prio; /**< @brief This field must be - initialized to zero. */ - struct context r_ctx; /**< @brief Not used, present because - offsets. */ -#if CH_CFG_USE_REGISTRY || defined(__DOXYGEN__) - thread_t *r_newer; /**< @brief Newer registry element. */ - thread_t *r_older; /**< @brief Older registry element. */ -#endif - /* End of the fields shared with the thread_t structure.*/ - thread_t *r_current; /**< @brief The currently running - thread. */ -} ready_list_t; - -/** - * @extends threads_queue_t - * - * @brief Structure representing a thread. - * @note Not all the listed fields are always needed, by switching off some - * not needed ChibiOS/RT subsystems it is possible to save RAM space - * by shrinking the @p thread_t structure. - */ -typedef struct thread { - thread_t *p_next; /**< @brief Next in the list/queue. */ - /* End of the fields shared with the threads_list_t structure.*/ - thread_t *p_prev; /**< @brief Previous in the queue. */ - /* End of the fields shared with the threads_queue_t structure.*/ - tprio_t p_prio; /**< @brief Thread priority. */ - struct context p_ctx; /**< @brief Processor context. */ -#if CH_CFG_USE_REGISTRY || defined(__DOXYGEN__) - thread_t *p_newer; /**< @brief Newer registry element. */ - thread_t *p_older; /**< @brief Older registry element. */ -#endif - /* End of the fields shared with the ReadyList structure. */ -#if CH_CFG_USE_REGISTRY || defined(__DOXYGEN__) - /** - * @brief Thread name or @p NULL. - */ - const char *p_name; -#endif -#if CH_DBG_ENABLE_STACK_CHECK || defined(__DOXYGEN__) - /** - * @brief Thread stack boundary. - */ - stkalign_t *p_stklimit; -#endif - /** - * @brief Current thread state. - */ - tstate_t p_state; - /** - * @brief Various thread flags. - */ - tmode_t p_flags; -#if CH_CFG_USE_DYNAMIC || defined(__DOXYGEN__) - /** - * @brief References to this thread. - */ - trefs_t p_refs; -#endif - /** - * @brief Number of ticks remaining to this thread. - */ -#if (CH_CFG_TIME_QUANTUM > 0) || defined(__DOXYGEN__) - tslices_t p_preempt; -#endif -#if CH_DBG_THREADS_PROFILING || defined(__DOXYGEN__) - /** - * @brief Thread consumed time in ticks. - * @note This field can overflow. - */ - volatile systime_t p_time; -#endif - /** - * @brief State-specific fields. - * @note All the fields declared in this union are only valid in the - * specified state or condition and are thus volatile. - */ - union { - /** - * @brief Thread wakeup code. - * @note This field contains the low level message sent to the thread - * by the waking thread or interrupt handler. The value is valid - * after exiting the @p chSchWakeupS() function. - */ - msg_t rdymsg; - /** - * @brief Thread exit code. - * @note The thread termination code is stored in this field in order - * to be retrieved by the thread performing a @p chThdWait() on - * this thread. - */ - msg_t exitcode; - /** - * @brief Pointer to a generic "wait" object. - * @note This field is used to get a generic pointer to a synchronization - * object and is valid when the thread is in one of the wait - * states. - */ - void *wtobjp; -#if CH_CFG_USE_EVENTS || defined(__DOXYGEN__) - /** - * @brief Enabled events mask. - * @note This field is only valid while the thread is in the - * @p CH_STATE_WTOREVT or @p CH_STATE_WTANDEVT states. - */ - eventmask_t ewmask; -#endif - } p_u; -#if CH_CFG_USE_WAITEXIT || defined(__DOXYGEN__) - /** - * @brief Termination waiting list. - */ - threads_list_t p_waiting; -#endif -#if CH_CFG_USE_MESSAGES || defined(__DOXYGEN__) - /** - * @brief Messages queue. - */ - threads_queue_t p_msgqueue; - /** - * @brief Thread message. - */ - msg_t p_msg; -#endif -#if CH_CFG_USE_EVENTS || defined(__DOXYGEN__) - /** - * @brief Pending events mask. - */ - eventmask_t p_epending; -#endif -#if CH_CFG_USE_MUTEXES || defined(__DOXYGEN__) - /** - * @brief List of the mutexes owned by this thread. - * @note The list is terminated by a @p NULL in this field. - */ - struct mutex *p_mtxlist; - /** - * @brief Thread's own, non-inherited, priority. - */ - tprio_t p_realprio; -#endif -#if (CH_CFG_USE_DYNAMIC && CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__) - /** - * @brief Memory Pool where the thread workspace is returned. - */ - void *p_mpool; -#endif -#if CH_DBG_STATISTICS || defined(__DOXYGEN__) - time_measurement_t p_stats; -#endif -#if defined(CH_CFG_THREAD_EXTRA_FIELDS) - /* Extra fields defined in chconf.h.*/ - CH_CFG_THREAD_EXTRA_FIELDS -#endif -} thread_t; - -/** - * @brief Virtual timers list header. - * @note The timers list is implemented as a double link bidirectional list - * in order to make the unlink time constant, the reset of a virtual - * timer is often used in the code. - */ -typedef struct { - virtual_timer_t *vt_next; /**< @brief Next timer in the delta - list. */ - virtual_timer_t *vt_prev; /**< @brief Last timer in the delta - list. */ - systime_t vt_delta; /**< @brief Must be initialized to -1. */ -#if CH_CFG_ST_TIMEDELTA == 0 || defined(__DOXYGEN__) - volatile systime_t vt_systime; /**< @brief System Time counter. */ -#endif -#if CH_CFG_ST_TIMEDELTA > 0 || defined(__DOXYGEN__) - /** - * @brief System time of the last tick event. - */ - systime_t vt_lasttime;/**< @brief System time of the last - tick event. */ -#endif -} virtual_timers_list_t; - -/** - * @brief System data structure. - * @note This structure contain all the data areas used by the OS except - * stacks. - */ -typedef struct ch_system { - /** - * @brief Ready list header. - */ - ready_list_t rlist; - /** - * @brief Virtual timers delta list header. - */ - virtual_timers_list_t vtlist; -#if CH_CFG_USE_TM || defined(__DOXYGEN__) - /** - * @brief Measurement calibration value. - */ - rtcnt_t measurement_offset; -#endif -#if CH_DBG_STATISTICS || defined(__DOXYGEN__) - /** - * @brief Global kernel statistics. - */ - kernel_stats_t kernel_stats; -#endif -#if CH_DBG_ENABLED || defined(__DOXYGEN__) - /** - * @brief Pointer to the panic message. - * @details This pointer is meant to be accessed through the debugger, it is - * written once and then the system is halted. - */ - const char *dbg_panic_msg; -#endif -#if CH_DBG_SYSTEM_STATE_CHECK || defined(__DOXYGEN__) - /** - * @brief ISR nesting level. - */ - cnt_t dbg_isr_cnt; - /** - * @brief Lock nesting level. - */ - cnt_t dbg_lock_cnt; -#endif -#if CH_DBG_ENABLE_TRACE || defined(__DOXYGEN__) - /** - * @brief Public trace buffer. - */ - ch_trace_buffer_t dbg_trace_buffer; -#endif -} ch_system_t; - -/*===========================================================================*/ -/* Module macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -extern ch_system_t ch; -#endif - -/*===========================================================================*/ -/* Module inline functions. */ -/*===========================================================================*/ - -#endif /* _CHGLOBAL_H_ */ - -/** @} */ diff --git a/os/rt/include/chlists.h b/os/rt/include/chlists.h deleted file mode 100644 index f49ce679f..000000000 --- a/os/rt/include/chlists.h +++ /dev/null @@ -1,217 +0,0 @@ -/* - 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 . -*/ - -/** - * @file chlists.h - * @brief Thread queues and lists header. - * - * @addtogroup queues_list - * @{ - */ - -#ifndef _CHLISTS_H_ -#define _CHLISTS_H_ - -/*===========================================================================*/ -/* Module constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module macros. */ -/*===========================================================================*/ - -/** - * @brief Data part of a static threads queue initializer. - * @details This macro should be used when statically initializing a threads - * queue that is part of a bigger structure. - * - * @param[in] name the name of the threads queue variable - */ -#define _threads_queue_t_DATA(name) {(thread_t *)&name, (thread_t *)&name} - -/** - * @brief Static threads queue initializer. - * @details Statically initialized threads queues require no explicit - * initialization using @p queue_init(). - * - * @param[in] name the name of the threads queue variable - */ -#define threads_queue_t_DECL(name) \ - threads_queue_t name = _threads_queue_t_DATA(name) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - msg_t chQueueGoSleepTimeoutS(threads_queue_t *tqp, systime_t timeout); - void chQueueWakeupOneI(threads_queue_t *tqp, msg_t msg); - void chQueueWakeupAllI(threads_queue_t *tqp, msg_t msg); -#ifdef __cplusplus -} -#endif - -/*===========================================================================*/ -/* Module inline functions. */ -/*===========================================================================*/ - -/** - * @brief Threads list initialization. - * - * @notapi - */ -static inline void list_init(threads_list_t *tlp) { - - tlp->p_next = (thread_t *)tlp; -} - -/** - * @brief Evaluates to @p true if the specified threads list is empty. - * - * @notapi - */ -static inline bool list_isempty(threads_list_t *tlp) { - - return (bool)(tlp->p_next == (thread_t *)tlp); -} - -/** - * @brief Evaluates to @p true if the specified threads list is not empty. - * - * @notapi - */ -static inline bool list_notempty(threads_list_t *tlp) { - - return (bool)(tlp->p_next != (thread_t *)tlp); -} - -/** - * @brief Threads queue initialization. - * - * @notapi - */ -static inline void queue_init(threads_queue_t *tqp) { - - tqp->p_next = tqp->p_prev = (thread_t *)tqp; -} - -/** - * @brief Evaluates to @p true if the specified threads queue is empty. - * - * @notapi - */ -static inline bool queue_isempty(threads_queue_t *tqp) { - - return (bool)(tqp->p_next == (thread_t *)tqp); -} - -/** - * @brief Evaluates to @p true if the specified threads queue is not empty. - * - * @notapi - */ -static inline bool queue_notempty(threads_queue_t *tqp) { - - return (bool)(tqp->p_next != (thread_t *)tqp); -} - -/* If the performance code path has been chosen then all the following - functions are inlined into the various kernel modules.*/ -#if CH_CFG_OPTIMIZE_SPEED -static inline void list_insert(thread_t *tp, threads_list_t *tlp) { - - tp->p_next = tlp->p_next; - tlp->p_next = tp; -} - -static inline thread_t *list_remove(threads_list_t *tlp) { - - thread_t *tp = tlp->p_next; - tlp->p_next = tp->p_next; - return tp; -} - -static inline void queue_prio_insert(thread_t *tp, threads_queue_t *tqp) { - - thread_t *cp = (thread_t *)tqp; - do { - cp = cp->p_next; - } while ((cp != (thread_t *)tqp) && (cp->p_prio >= tp->p_prio)); - tp->p_next = cp; - tp->p_prev = cp->p_prev; - tp->p_prev->p_next = cp->p_prev = tp; -} - -static inline void queue_insert(thread_t *tp, threads_queue_t *tqp) { - - tp->p_next = (thread_t *)tqp; - tp->p_prev = tqp->p_prev; - tp->p_prev->p_next = tqp->p_prev = tp; -} - -static inline thread_t *queue_fifo_remove(threads_queue_t *tqp) { - thread_t *tp = tqp->p_next; - - (tqp->p_next = tp->p_next)->p_prev = (thread_t *)tqp; - return tp; -} - -static inline thread_t *queue_lifo_remove(threads_queue_t *tqp) { - thread_t *tp = tqp->p_prev; - - (tqp->p_prev = tp->p_prev)->p_next = (thread_t *)tqp; - return tp; -} - -static inline thread_t *queue_dequeue(thread_t *tp) { - - tp->p_prev->p_next = tp->p_next; - tp->p_next->p_prev = tp->p_prev; - return tp; -} -#endif /* CH_CFG_OPTIMIZE_SPEED */ - -/** - * @brief Initializes a threads queue object. - * - * @param[out] tqp pointer to the threads queue object - * - * @init - */ -static inline void chQueueObjectInit(threads_queue_t *tqp) { - - queue_init(tqp); -} - -#endif /* _CHLISTS_H_ */ diff --git a/os/rt/include/chschd.h b/os/rt/include/chschd.h index b4160acc6..718cedd58 100644 --- a/os/rt/include/chschd.h +++ b/os/rt/include/chschd.h @@ -87,6 +87,262 @@ /* Module data structures and types. */ /*===========================================================================*/ +/** + * @brief Generic threads single link list, it works like a stack. + */ +typedef struct { + thread_t *p_next; /**< @brief Next in the list/queue. */ +} threads_list_t; + +/** + * @extends threads_list_t + * + * @brief Generic threads bidirectional linked list header and element. + */ +typedef struct { + thread_t *p_next; /**< @brief Next in the list/queue. */ + thread_t *p_prev; /**< @brief Previous in the queue. */ +} threads_queue_t; + +/** + * @extends threads_queue_t + * + * @brief Ready list header. + */ +typedef struct { + threads_queue_t r_queue; /**< @brief Threads queue. */ + tprio_t r_prio; /**< @brief This field must be + initialized to zero. */ + struct context r_ctx; /**< @brief Not used, present because + offsets. */ +#if CH_CFG_USE_REGISTRY || defined(__DOXYGEN__) + thread_t *r_newer; /**< @brief Newer registry element. */ + thread_t *r_older; /**< @brief Older registry element. */ +#endif + /* End of the fields shared with the thread_t structure.*/ + thread_t *r_current; /**< @brief The currently running + thread. */ +} ready_list_t; + +/** + * @extends threads_queue_t + * + * @brief Structure representing a thread. + * @note Not all the listed fields are always needed, by switching off some + * not needed ChibiOS/RT subsystems it is possible to save RAM space + * by shrinking the @p thread_t structure. + */ +typedef struct thread { + thread_t *p_next; /**< @brief Next in the list/queue. */ + /* End of the fields shared with the threads_list_t structure.*/ + thread_t *p_prev; /**< @brief Previous in the queue. */ + /* End of the fields shared with the threads_queue_t structure.*/ + tprio_t p_prio; /**< @brief Thread priority. */ + struct context p_ctx; /**< @brief Processor context. */ +#if CH_CFG_USE_REGISTRY || defined(__DOXYGEN__) + thread_t *p_newer; /**< @brief Newer registry element. */ + thread_t *p_older; /**< @brief Older registry element. */ +#endif + /* End of the fields shared with the ReadyList structure. */ +#if CH_CFG_USE_REGISTRY || defined(__DOXYGEN__) + /** + * @brief Thread name or @p NULL. + */ + const char *p_name; +#endif +#if CH_DBG_ENABLE_STACK_CHECK || defined(__DOXYGEN__) + /** + * @brief Thread stack boundary. + */ + stkalign_t *p_stklimit; +#endif + /** + * @brief Current thread state. + */ + tstate_t p_state; + /** + * @brief Various thread flags. + */ + tmode_t p_flags; +#if CH_CFG_USE_DYNAMIC || defined(__DOXYGEN__) + /** + * @brief References to this thread. + */ + trefs_t p_refs; +#endif + /** + * @brief Number of ticks remaining to this thread. + */ +#if (CH_CFG_TIME_QUANTUM > 0) || defined(__DOXYGEN__) + tslices_t p_preempt; +#endif +#if CH_DBG_THREADS_PROFILING || defined(__DOXYGEN__) + /** + * @brief Thread consumed time in ticks. + * @note This field can overflow. + */ + volatile systime_t p_time; +#endif + /** + * @brief State-specific fields. + * @note All the fields declared in this union are only valid in the + * specified state or condition and are thus volatile. + */ + union { + /** + * @brief Thread wakeup code. + * @note This field contains the low level message sent to the thread + * by the waking thread or interrupt handler. The value is valid + * after exiting the @p chSchWakeupS() function. + */ + msg_t rdymsg; + /** + * @brief Thread exit code. + * @note The thread termination code is stored in this field in order + * to be retrieved by the thread performing a @p chThdWait() on + * this thread. + */ + msg_t exitcode; + /** + * @brief Pointer to a generic "wait" object. + * @note This field is used to get a generic pointer to a synchronization + * object and is valid when the thread is in one of the wait + * states. + */ + void *wtobjp; +#if CH_CFG_USE_EVENTS || defined(__DOXYGEN__) + /** + * @brief Enabled events mask. + * @note This field is only valid while the thread is in the + * @p CH_STATE_WTOREVT or @p CH_STATE_WTANDEVT states. + */ + eventmask_t ewmask; +#endif + } p_u; +#if CH_CFG_USE_WAITEXIT || defined(__DOXYGEN__) + /** + * @brief Termination waiting list. + */ + threads_list_t p_waiting; +#endif +#if CH_CFG_USE_MESSAGES || defined(__DOXYGEN__) + /** + * @brief Messages queue. + */ + threads_queue_t p_msgqueue; + /** + * @brief Thread message. + */ + msg_t p_msg; +#endif +#if CH_CFG_USE_EVENTS || defined(__DOXYGEN__) + /** + * @brief Pending events mask. + */ + eventmask_t p_epending; +#endif +#if CH_CFG_USE_MUTEXES || defined(__DOXYGEN__) + /** + * @brief List of the mutexes owned by this thread. + * @note The list is terminated by a @p NULL in this field. + */ + struct mutex *p_mtxlist; + /** + * @brief Thread's own, non-inherited, priority. + */ + tprio_t p_realprio; +#endif +#if (CH_CFG_USE_DYNAMIC && CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__) + /** + * @brief Memory Pool where the thread workspace is returned. + */ + void *p_mpool; +#endif +#if CH_DBG_STATISTICS || defined(__DOXYGEN__) + time_measurement_t p_stats; +#endif +#if defined(CH_CFG_THREAD_EXTRA_FIELDS) + /* Extra fields defined in chconf.h.*/ + CH_CFG_THREAD_EXTRA_FIELDS +#endif +} thread_t; + +/** + * @brief Virtual timers list header. + * @note The timers list is implemented as a double link bidirectional list + * in order to make the unlink time constant, the reset of a virtual + * timer is often used in the code. + */ +typedef struct { + virtual_timer_t *vt_next; /**< @brief Next timer in the delta + list. */ + virtual_timer_t *vt_prev; /**< @brief Last timer in the delta + list. */ + systime_t vt_delta; /**< @brief Must be initialized to -1. */ +#if CH_CFG_ST_TIMEDELTA == 0 || defined(__DOXYGEN__) + volatile systime_t vt_systime; /**< @brief System Time counter. */ +#endif +#if CH_CFG_ST_TIMEDELTA > 0 || defined(__DOXYGEN__) + /** + * @brief System time of the last tick event. + */ + systime_t vt_lasttime;/**< @brief System time of the last + tick event. */ +#endif +} virtual_timers_list_t; + +/** + * @brief System data structure. + * @note This structure contain all the data areas used by the OS except + * stacks. + */ +typedef struct ch_system { + /** + * @brief Ready list header. + */ + ready_list_t rlist; + /** + * @brief Virtual timers delta list header. + */ + virtual_timers_list_t vtlist; +#if CH_CFG_USE_TM || defined(__DOXYGEN__) + /** + * @brief Measurement calibration value. + */ + rtcnt_t measurement_offset; +#endif +#if CH_DBG_STATISTICS || defined(__DOXYGEN__) + /** + * @brief Global kernel statistics. + */ + kernel_stats_t kernel_stats; +#endif +#if CH_DBG_ENABLED || defined(__DOXYGEN__) + /** + * @brief Pointer to the panic message. + * @details This pointer is meant to be accessed through the debugger, it is + * written once and then the system is halted. + */ + const char *dbg_panic_msg; +#endif +#if CH_DBG_SYSTEM_STATE_CHECK || defined(__DOXYGEN__) + /** + * @brief ISR nesting level. + */ + cnt_t dbg_isr_cnt; + /** + * @brief Lock nesting level. + */ + cnt_t dbg_lock_cnt; +#endif +#if CH_DBG_ENABLE_TRACE || defined(__DOXYGEN__) + /** + * @brief Public trace buffer. + */ + ch_trace_buffer_t dbg_trace_buffer; +#endif +} ch_system_t; + /*===========================================================================*/ /* Module macros. */ /*===========================================================================*/ @@ -120,6 +376,10 @@ /* External declarations. */ /*===========================================================================*/ +#if !defined(__DOXYGEN__) +extern ch_system_t ch; +#endif + /* * Scheduler APIs. */ @@ -144,6 +404,122 @@ extern "C" { /* Module inline functions. */ /*===========================================================================*/ + /** + * @brief Threads list initialization. + * + * @notapi + */ + static inline void list_init(threads_list_t *tlp) { + + tlp->p_next = (thread_t *)tlp; + } + + /** + * @brief Evaluates to @p true if the specified threads list is empty. + * + * @notapi + */ + static inline bool list_isempty(threads_list_t *tlp) { + + return (bool)(tlp->p_next == (thread_t *)tlp); + } + + /** + * @brief Evaluates to @p true if the specified threads list is not empty. + * + * @notapi + */ + static inline bool list_notempty(threads_list_t *tlp) { + + return (bool)(tlp->p_next != (thread_t *)tlp); + } + + /** + * @brief Threads queue initialization. + * + * @notapi + */ + static inline void queue_init(threads_queue_t *tqp) { + + tqp->p_next = tqp->p_prev = (thread_t *)tqp; + } + + /** + * @brief Evaluates to @p true if the specified threads queue is empty. + * + * @notapi + */ + static inline bool queue_isempty(threads_queue_t *tqp) { + + return (bool)(tqp->p_next == (thread_t *)tqp); + } + + /** + * @brief Evaluates to @p true if the specified threads queue is not empty. + * + * @notapi + */ + static inline bool queue_notempty(threads_queue_t *tqp) { + + return (bool)(tqp->p_next != (thread_t *)tqp); + } + + /* If the performance code path has been chosen then all the following + functions are inlined into the various kernel modules.*/ + #if CH_CFG_OPTIMIZE_SPEED + static inline void list_insert(thread_t *tp, threads_list_t *tlp) { + + tp->p_next = tlp->p_next; + tlp->p_next = tp; + } + + static inline thread_t *list_remove(threads_list_t *tlp) { + + thread_t *tp = tlp->p_next; + tlp->p_next = tp->p_next; + return tp; + } + + static inline void queue_prio_insert(thread_t *tp, threads_queue_t *tqp) { + + thread_t *cp = (thread_t *)tqp; + do { + cp = cp->p_next; + } while ((cp != (thread_t *)tqp) && (cp->p_prio >= tp->p_prio)); + tp->p_next = cp; + tp->p_prev = cp->p_prev; + tp->p_prev->p_next = cp->p_prev = tp; + } + + static inline void queue_insert(thread_t *tp, threads_queue_t *tqp) { + + tp->p_next = (thread_t *)tqp; + tp->p_prev = tqp->p_prev; + tp->p_prev->p_next = tqp->p_prev = tp; + } + + static inline thread_t *queue_fifo_remove(threads_queue_t *tqp) { + thread_t *tp = tqp->p_next; + + (tqp->p_next = tp->p_next)->p_prev = (thread_t *)tqp; + return tp; + } + + static inline thread_t *queue_lifo_remove(threads_queue_t *tqp) { + thread_t *tp = tqp->p_prev; + + (tqp->p_prev = tp->p_prev)->p_next = (thread_t *)tqp; + return tp; + } + + static inline thread_t *queue_dequeue(thread_t *tp) { + + tp->p_prev->p_next = tp->p_next; + tp->p_next->p_prev = tp->p_prev; + return tp; + } +#endif /* CH_CFG_OPTIMIZE_SPEED */ + /** * @brief Determines if the current thread must reschedule. * @details This function returns @p true if there is a ready thread with diff --git a/os/rt/include/chthreads.h b/os/rt/include/chthreads.h index 1dcad9b48..e1a8b496d 100644 --- a/os/rt/include/chthreads.h +++ b/os/rt/include/chthreads.h @@ -158,6 +158,29 @@ typedef msg_t (*tfunc_t)(void *); #define THD_FUNCTION(tname, arg) PORT_THD_FUNCTION(tname, arg) /** @} */ +/** + * @name Threads queues + */ +/** + * @brief Data part of a static threads queue object initializer. + * @details This macro should be used when statically initializing a threads + * queue that is part of a bigger structure. + * + * @param[in] name the name of the threads queue variable + */ +#define _threads_queue_t_DATA(name) {(thread_t *)&name, (thread_t *)&name} + +/** + * @brief Static threads queue object initializer. + * @details Statically initialized threads queues require no explicit + * initialization using @p queue_init(). + * + * @param[in] name the name of the threads queue variable + */ +#define threads_queue_t_DECL(name) \ + threads_queue_t name = _threads_queue_t_DATA(name) +/** @} */ + /** * @name Macro Functions * @{ @@ -218,11 +241,14 @@ extern "C" { tprio_t prio, tfunc_t pf, void *arg); thread_t *chThdStart(thread_t *tp); tprio_t chThdSetPriority(tprio_t newprio); - msg_t chThreadSuspendS(thread_reference_t *trp); - msg_t chThreadSuspendTimeoutS(thread_reference_t *trp, systime_t timeout); - void chThreadResumeI(thread_reference_t *trp, msg_t msg); - void chThreadResumeS(thread_reference_t *trp, msg_t msg); - void chThreadResume(thread_reference_t *trp, msg_t msg); + msg_t chThdSuspendS(thread_reference_t *trp); + msg_t chThdSuspendTimeoutS(thread_reference_t *trp, systime_t timeout); + void chThdResumeI(thread_reference_t *trp, msg_t msg); + void chThdResumeS(thread_reference_t *trp, msg_t msg); + void chThdResume(thread_reference_t *trp, msg_t msg); + msg_t chThdEnqueueTimeoutS(threads_queue_t *tqp, systime_t timeout); + void chThdDequeueNextI(threads_queue_t *tqp, msg_t msg); + void chThdDequeueAllI(threads_queue_t *tqp, msg_t msg); void chThdTerminate(thread_t *tp); void chThdSleep(systime_t time); void chThdSleepUntil(systime_t time); @@ -337,6 +363,18 @@ static inline void chThdSleepS(systime_t time) { chSchGoSleepTimeoutS(CH_STATE_SLEEPING, time); } +/** + * @brief Initializes a threads queue object. + * + * @param[out] tqp pointer to the threads queue object + * + * @init + */ +static inline void chThdQueueObjectInit(threads_queue_t *tqp) { + + queue_init(tqp); +} + #endif /* _CHTHREADS_H_ */ /** @} */ diff --git a/os/rt/osal/osal.h b/os/rt/osal/osal.h index d5322cc96..b3335ccfd 100644 --- a/os/rt/osal/osal.h +++ b/os/rt/osal/osal.h @@ -570,7 +570,7 @@ static inline void osalThreadSleep(systime_t time) { */ static inline msg_t osalThreadSuspendS(thread_reference_t *trp) { - return chThreadSuspendS(trp); + return chThdSuspendS(trp); } /** @@ -595,7 +595,7 @@ static inline msg_t osalThreadSuspendS(thread_reference_t *trp) { static inline msg_t osalThreadSuspendTimeoutS(thread_reference_t *trp, systime_t timeout) { - return chThreadSuspendTimeoutS(trp, timeout); + return chThdSuspendTimeoutS(trp, timeout); } /** @@ -610,7 +610,7 @@ static inline msg_t osalThreadSuspendTimeoutS(thread_reference_t *trp, */ static inline void osalThreadResumeI(thread_reference_t *trp, msg_t msg) { - chThreadResumeI(trp, msg); + chThdResumeI(trp, msg); } /** @@ -625,7 +625,7 @@ static inline void osalThreadResumeI(thread_reference_t *trp, msg_t msg) { */ static inline void osalThreadResumeS(thread_reference_t *trp, msg_t msg) { - chThreadResumeS(trp, msg); + chThdResumeS(trp, msg); } /** @@ -635,9 +635,9 @@ static inline void osalThreadResumeS(thread_reference_t *trp, msg_t msg) { * * @init */ -static inline void osalQueueObjectInit(threads_queue_t *tqp) { +static inline void osalThreadQueueObjectInit(threads_queue_t *tqp) { - queue_init(tqp); + chThdQueueObjectInit(tqp); } /** @@ -663,10 +663,10 @@ static inline void osalQueueObjectInit(threads_queue_t *tqp) { * * @sclass */ -static inline msg_t osalQueueGoSleepTimeoutS(threads_queue_t *tqp, - systime_t time) { +static inline msg_t osalThreadEnqueueTimeoutS(threads_queue_t *tqp, + systime_t time) { - return chQueueGoSleepTimeoutS(tqp, time); + return chThdEnqueueTimeoutS(tqp, time); } /** @@ -677,9 +677,9 @@ static inline msg_t osalQueueGoSleepTimeoutS(threads_queue_t *tqp, * * @iclass */ -static inline void osalQueueWakeupOneI(threads_queue_t *tqp, msg_t msg) { +static inline void osalThreadDequeueNextI(threads_queue_t *tqp, msg_t msg) { - chQueueWakeupOneI(tqp, msg); + chThdDequeueNextI(tqp, msg); } /** @@ -690,9 +690,9 @@ static inline void osalQueueWakeupOneI(threads_queue_t *tqp, msg_t msg) { * * @iclass */ -static inline void osalQueueWakeupAllI(threads_queue_t *tqp, msg_t msg) { +static inline void osalThreadDequeueAllI(threads_queue_t *tqp, msg_t msg) { - chQueueWakeupAllI(tqp, msg); + chThdDequeueAllI(tqp, msg); } /** diff --git a/os/rt/rt.mk b/os/rt/rt.mk index b6dc526ec..55a189f75 100644 --- a/os/rt/rt.mk +++ b/os/rt/rt.mk @@ -2,11 +2,10 @@ # from this list, you can disable parts of the kernel by editing chconf.h. KERNSRC = ${CHIBIOS}/os/rt/src/chsys.c \ ${CHIBIOS}/os/rt/src/chdebug.c \ - ${CHIBIOS}/os/rt/src/chlists.c \ - ${CHIBIOS}/os/rt/src/chvt.c \ ${CHIBIOS}/os/rt/src/chtm.c \ ${CHIBIOS}/os/rt/src/chstats.c \ ${CHIBIOS}/os/rt/src/chschd.c \ + ${CHIBIOS}/os/rt/src/chvt.c \ ${CHIBIOS}/os/rt/src/chthreads.c \ ${CHIBIOS}/os/rt/src/chdynamic.c \ ${CHIBIOS}/os/rt/src/chregistry.c \ diff --git a/os/rt/src/chlists.c b/os/rt/src/chlists.c deleted file mode 100644 index 4dd141b9c..000000000 --- a/os/rt/src/chlists.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - 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 . -*/ - -/** - * @file chlists.c - * @brief Thread queues and lists code. - * - * @addtogroup queues_list - * @{ - */ -#include "ch.h" - -/*===========================================================================*/ -/* Module local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module exported functions. */ -/*===========================================================================*/ - -/** - * @brief Enqueues the caller thread. - * @details The caller thread is enqueued and put to sleep until it is - * dequeued or the specified timeouts expires. - * - * @param[in] tqp pointer to the threads queue object - * @param[in] timeout the timeout in system ticks, the special values are - * handled as follow: - * - @a TIME_INFINITE the thread enters an infinite sleep - * state. - * - @a TIME_IMMEDIATE the thread is not enqueued and - * the function returns @p MSG_TIMEOUT as if a timeout - * occurred. - * . - * @return The message from @p osalQueueWakeupOneI() or - * @p osalQueueWakeupAllI() functions. - * @retval MSG_TIMEOUT if the thread has not been dequeued within the - * specified timeout or if the function has been - * invoked with @p TIME_IMMEDIATE as timeout - * specification. - * - * @sclass - */ -msg_t chQueueGoSleepTimeoutS(threads_queue_t *tqp, systime_t timeout) { - - if (TIME_IMMEDIATE == timeout) - return MSG_TIMEOUT; - - queue_insert(currp, tqp); - return chSchGoSleepTimeoutS(CH_STATE_QUEUED, timeout); -} - -/** - * @brief Dequeues and wakes up one thread from the queue, if any. - * - * @param[in] tqp pointer to the threads queue object - * @param[in] msg the message code - * - * @iclass - */ -void chQueueWakeupOneI(threads_queue_t *tqp, msg_t msg) { - - if (queue_notempty(tqp)) { - thread_t *tp = queue_fifo_remove(tqp); - - chDbgAssert(tp->p_state == CH_STATE_QUEUED, - "not CH_STATE_QUEUED"); - - tp->p_u.rdymsg = msg; - chSchReadyI(tp); - } -} - -/** - * @brief Dequeues and wakes up all threads from the queue. - * - * @param[in] tqp pointer to the threads queue object - * @param[in] msg the message code - * - * @iclass - */ -void chQueueWakeupAllI(threads_queue_t *tqp, msg_t msg) { - - while (queue_notempty(tqp)) { - thread_t *tp = queue_fifo_remove(tqp); - - chDbgAssert(tp->p_state == CH_STATE_QUEUED, - "not CH_STATE_QUEUED"); - - tp->p_u.rdymsg = msg; - chSchReadyI(tp); - } -} - -#if !CH_CFG_OPTIMIZE_SPEED || defined(__DOXYGEN__) -/** - * @brief Inserts a thread into a priority ordered queue. - * @note The insertion is done by scanning the list from the highest - * priority toward the lowest. - * - * @param[in] tp the pointer to the thread to be inserted in the list - * @param[in] tqp the pointer to the threads list header - * - * @notapi - */ -void queue_prio_insert(thread_t *tp, threads_queue_t *tqp) { - - /* cp iterates over the queue.*/ - thread_t *cp = (thread_t *)tqp; - do { - /* Iterate to next thread in queue.*/ - cp = cp->p_next; - /* Not end of queue? and cp has equal or higher priority than tp?.*/ - } while ((cp != (thread_t *)tqp) && (cp->p_prio >= tp->p_prio)); - /* Insertion on p_prev.*/ - tp->p_next = cp; - tp->p_prev = cp->p_prev; - tp->p_prev->p_next = cp->p_prev = tp; -} - -/** - * @brief Inserts a thread into a queue. - * - * @param[in] tp the pointer to the thread to be inserted in the list - * @param[in] tqp the pointer to the threads list header - * - * @notapi - */ -void queue_insert(thread_t *tp, threads_queue_t *tqp) { - - tp->p_next = (thread_t *)tqp; - tp->p_prev = tqp->p_prev; - tp->p_prev->p_next = tqp->p_prev = tp; -} - -/** - * @brief Removes the first-out thread from a queue and returns it. - * @note If the queue is priority ordered then this function returns the - * thread with the highest priority. - * - * @param[in] tqp the pointer to the threads list header - * @return The removed thread pointer. - * - * @notapi - */ -thread_t *queue_fifo_remove(threads_queue_t *tqp) { - thread_t *tp = tqp->p_next; - - (tqp->p_next = tp->p_next)->p_prev = (thread_t *)tqp; - return tp; -} - -/** - * @brief Removes the last-out thread from a queue and returns it. - * @note If the queue is priority ordered then this function returns the - * thread with the lowest priority. - * - * @param[in] tqp the pointer to the threads list header - * @return The removed thread pointer. - * - * @notapi - */ -thread_t *queue_lifo_remove(threads_queue_t *tqp) { - thread_t *tp = tqp->p_prev; - - (tqp->p_prev = tp->p_prev)->p_next = (thread_t *)tqp; - return tp; -} - -/** - * @brief Removes a thread from a queue and returns it. - * @details The thread is removed from the queue regardless of its relative - * position and regardless the used insertion method. - * - * @param[in] tp the pointer to the thread to be removed from the queue - * @return The removed thread pointer. - * - * @notapi - */ -thread_t *queue_dequeue(thread_t *tp) { - - tp->p_prev->p_next = tp->p_next; - tp->p_next->p_prev = tp->p_prev; - return tp; -} - -/** - * @brief Pushes a thread_t on top of a stack list. - * - * @param[in] tp the pointer to the thread to be inserted in the list - * @param[in] tlp the pointer to the threads list header - * - * @notapi - */ -void list_insert(thread_t *tp, threads_list_t *tlp) { - - tp->p_next = tlp->p_next; - tlp->p_next = tp; -} - -/** - * @brief Pops a thread from the top of a stack list and returns it. - * @pre The list must be non-empty before calling this function. - * - * @param[in] tlp the pointer to the threads list header - * @return The removed thread pointer. - * - * @notapi - */ -thread_t *list_remove(threads_list_t *tlp) { - - thread_t *tp = tlp->p_next; - tlp->p_next = tp->p_next; - return tp; -} -#endif /* CH_CFG_OPTIMIZE_SPEED */ - -/** @} */ diff --git a/os/rt/src/chqueues.c b/os/rt/src/chqueues.c index c65eb06c6..c0b0f8256 100644 --- a/os/rt/src/chqueues.c +++ b/os/rt/src/chqueues.c @@ -88,7 +88,7 @@ void chIQObjectInit(input_queue_t *iqp, uint8_t *bp, size_t size, qnotify_t infy, void *link) { - chQueueObjectInit(&iqp->q_waiting); + chThdQueueObjectInit(&iqp->q_waiting); iqp->q_counter = 0; iqp->q_buffer = iqp->q_rdptr = iqp->q_wrptr = bp; iqp->q_top = bp + size; @@ -113,7 +113,7 @@ void chIQResetI(input_queue_t *iqp) { iqp->q_rdptr = iqp->q_wrptr = iqp->q_buffer; iqp->q_counter = 0; - chQueueWakeupAllI(&iqp->q_waiting, Q_RESET); + chThdDequeueAllI(&iqp->q_waiting, Q_RESET); } /** @@ -141,7 +141,7 @@ msg_t chIQPutI(input_queue_t *iqp, uint8_t b) { if (iqp->q_wrptr >= iqp->q_top) iqp->q_wrptr = iqp->q_buffer; - chQueueWakeupOneI(&iqp->q_waiting, Q_OK); + chThdDequeueNextI(&iqp->q_waiting, Q_OK); return Q_OK; } @@ -175,7 +175,7 @@ msg_t chIQGetTimeout(input_queue_t *iqp, systime_t time) { while (chIQIsEmptyI(iqp)) { msg_t msg; - if ((msg = chQueueGoSleepTimeoutS(&iqp->q_waiting, time)) < Q_OK) { + if ((msg = chThdEnqueueTimeoutS(&iqp->q_waiting, time)) < Q_OK) { chSysUnlock(); return msg; } @@ -227,7 +227,7 @@ size_t chIQReadTimeout(input_queue_t *iqp, uint8_t *bp, nfy(iqp); while (chIQIsEmptyI(iqp)) { - if (chQueueGoSleepTimeoutS(&iqp->q_waiting, time) != Q_OK) { + if (chThdEnqueueTimeoutS(&iqp->q_waiting, time) != Q_OK) { chSysUnlock(); return r; } @@ -266,7 +266,7 @@ size_t chIQReadTimeout(input_queue_t *iqp, uint8_t *bp, void chOQObjectInit(output_queue_t *oqp, uint8_t *bp, size_t size, qnotify_t onfy, void *link) { - chQueueObjectInit(&oqp->q_waiting); + chThdQueueObjectInit(&oqp->q_waiting); oqp->q_counter = size; oqp->q_buffer = oqp->q_rdptr = oqp->q_wrptr = bp; oqp->q_top = bp + size; @@ -291,7 +291,7 @@ void chOQResetI(output_queue_t *oqp) { oqp->q_rdptr = oqp->q_wrptr = oqp->q_buffer; oqp->q_counter = chQSizeI(oqp); - chQueueWakeupAllI(&oqp->q_waiting, Q_RESET); + chThdDequeueAllI(&oqp->q_waiting, Q_RESET); } /** @@ -322,7 +322,7 @@ msg_t chOQPutTimeout(output_queue_t *oqp, uint8_t b, systime_t time) { while (chOQIsFullI(oqp)) { msg_t msg; - if ((msg = chQueueGoSleepTimeoutS(&oqp->q_waiting, time)) < Q_OK) { + if ((msg = chThdEnqueueTimeoutS(&oqp->q_waiting, time)) < Q_OK) { chSysUnlock(); return msg; } @@ -363,7 +363,7 @@ msg_t chOQGetI(output_queue_t *oqp) { if (oqp->q_rdptr >= oqp->q_top) oqp->q_rdptr = oqp->q_buffer; - chQueueWakeupOneI(&oqp->q_waiting, Q_OK); + chThdDequeueNextI(&oqp->q_waiting, Q_OK); return b; } @@ -402,7 +402,7 @@ size_t chOQWriteTimeout(output_queue_t *oqp, const uint8_t *bp, chSysLock(); while (true) { while (chOQIsFullI(oqp)) { - if (chQueueGoSleepTimeoutS(&oqp->q_waiting, time) != Q_OK) { + if (chThdEnqueueTimeoutS(&oqp->q_waiting, time) != Q_OK) { chSysUnlock(); return w; } diff --git a/os/rt/src/chschd.c b/os/rt/src/chschd.c index 1e844b7b0..acf65fb85 100644 --- a/os/rt/src/chschd.c +++ b/os/rt/src/chschd.c @@ -37,6 +37,11 @@ /* Module exported variables. */ /*===========================================================================*/ +/** + * @brief System data structures. + */ +ch_system_t ch; + /*===========================================================================*/ /* Module local types. */ /*===========================================================================*/ @@ -67,6 +72,129 @@ void _scheduler_init(void) { #endif } +#if !CH_CFG_OPTIMIZE_SPEED || defined(__DOXYGEN__) +/** + * @brief Inserts a thread into a priority ordered queue. + * @note The insertion is done by scanning the list from the highest + * priority toward the lowest. + * + * @param[in] tp the pointer to the thread to be inserted in the list + * @param[in] tqp the pointer to the threads list header + * + * @notapi + */ +void queue_prio_insert(thread_t *tp, threads_queue_t *tqp) { + + /* cp iterates over the queue.*/ + thread_t *cp = (thread_t *)tqp; + do { + /* Iterate to next thread in queue.*/ + cp = cp->p_next; + /* Not end of queue? and cp has equal or higher priority than tp?.*/ + } while ((cp != (thread_t *)tqp) && (cp->p_prio >= tp->p_prio)); + /* Insertion on p_prev.*/ + tp->p_next = cp; + tp->p_prev = cp->p_prev; + tp->p_prev->p_next = cp->p_prev = tp; +} + +/** + * @brief Inserts a thread into a queue. + * + * @param[in] tp the pointer to the thread to be inserted in the list + * @param[in] tqp the pointer to the threads list header + * + * @notapi + */ +void queue_insert(thread_t *tp, threads_queue_t *tqp) { + + tp->p_next = (thread_t *)tqp; + tp->p_prev = tqp->p_prev; + tp->p_prev->p_next = tqp->p_prev = tp; +} + +/** + * @brief Removes the first-out thread from a queue and returns it. + * @note If the queue is priority ordered then this function returns the + * thread with the highest priority. + * + * @param[in] tqp the pointer to the threads list header + * @return The removed thread pointer. + * + * @notapi + */ +thread_t *queue_fifo_remove(threads_queue_t *tqp) { + thread_t *tp = tqp->p_next; + + (tqp->p_next = tp->p_next)->p_prev = (thread_t *)tqp; + return tp; +} + +/** + * @brief Removes the last-out thread from a queue and returns it. + * @note If the queue is priority ordered then this function returns the + * thread with the lowest priority. + * + * @param[in] tqp the pointer to the threads list header + * @return The removed thread pointer. + * + * @notapi + */ +thread_t *queue_lifo_remove(threads_queue_t *tqp) { + thread_t *tp = tqp->p_prev; + + (tqp->p_prev = tp->p_prev)->p_next = (thread_t *)tqp; + return tp; +} + +/** + * @brief Removes a thread from a queue and returns it. + * @details The thread is removed from the queue regardless of its relative + * position and regardless the used insertion method. + * + * @param[in] tp the pointer to the thread to be removed from the queue + * @return The removed thread pointer. + * + * @notapi + */ +thread_t *queue_dequeue(thread_t *tp) { + + tp->p_prev->p_next = tp->p_next; + tp->p_next->p_prev = tp->p_prev; + return tp; +} + +/** + * @brief Pushes a thread_t on top of a stack list. + * + * @param[in] tp the pointer to the thread to be inserted in the list + * @param[in] tlp the pointer to the threads list header + * + * @notapi + */ +void list_insert(thread_t *tp, threads_list_t *tlp) { + + tp->p_next = tlp->p_next; + tlp->p_next = tp; +} + +/** + * @brief Pops a thread from the top of a stack list and returns it. + * @pre The list must be non-empty before calling this function. + * + * @param[in] tlp the pointer to the threads list header + * @return The removed thread pointer. + * + * @notapi + */ +thread_t *list_remove(threads_list_t *tlp) { + + thread_t *tp = tlp->p_next; + tlp->p_next = tp->p_next; + return tp; +} +#endif /* CH_CFG_OPTIMIZE_SPEED */ + /** * @brief Inserts a thread in the Ready List. * @details The thread is positioned behind all threads with higher or equal diff --git a/os/rt/src/chsys.c b/os/rt/src/chsys.c index 94f1afd51..f7fd6766b 100644 --- a/os/rt/src/chsys.c +++ b/os/rt/src/chsys.c @@ -48,11 +48,6 @@ /* Module local variables. */ /*===========================================================================*/ -/** - * @brief System data structures. - */ -ch_system_t ch; - #if !CH_CFG_NO_IDLE_THREAD || defined(__DOXYGEN__) /** * @brief Idle thread working area. diff --git a/os/rt/src/chthreads.c b/os/rt/src/chthreads.c index 613810954..a8f3492e6 100644 --- a/os/rt/src/chthreads.c +++ b/os/rt/src/chthreads.c @@ -269,123 +269,6 @@ tprio_t chThdSetPriority(tprio_t newprio) { return oldprio; } -/** - * @brief Sends the current thread sleeping and sets a reference variable. - * @note This function must reschedule, it can only be called from thread - * context. - * - * @param[in] trp a pointer to a thread reference object - * @return The wake up message. - * - * @sclass - */ -msg_t chThreadSuspendS(thread_reference_t *trp) { - thread_t *tp = chThdGetSelfX(); - - chDbgAssert(*trp == NULL, "not NULL"); - - *trp = tp; - tp->p_u.wtobjp = &trp; - chSchGoSleepS(CH_STATE_SUSPENDED); - return chThdGetSelfX()->p_msg; -} - -/** - * @brief Sends the current thread sleeping and sets a reference variable. - * @note This function must reschedule, it can only be called from thread - * context. - * - * @param[in] trp a pointer to a thread reference object - * @param[in] timeout the timeout in system ticks, the special values are - * handled as follow: - * - @a TIME_INFINITE the thread enters an infinite sleep - * state. - * - @a TIME_IMMEDIATE the thread is not enqueued and - * the function returns @p MSG_TIMEOUT as if a timeout - * occurred. - * . - * @return The wake up message. - * @retval MSG_TIMEOUT if the operation timed out. - * - * @sclass - */ -msg_t chThreadSuspendTimeoutS(thread_reference_t *trp, systime_t timeout) { - thread_t *tp = chThdGetSelfX(); - - chDbgAssert(*trp == NULL, "not NULL"); - - if (TIME_IMMEDIATE == timeout) - return MSG_TIMEOUT; - - *trp = tp; - tp->p_u.wtobjp = &trp; - return chSchGoSleepTimeoutS(CH_STATE_SUSPENDED, timeout); -} - -/** - * @brief Wakes up a thread waiting on a thread reference object. - * @note This function must not reschedule because it can be called from - * ISR context. - * - * @param[in] trp a pointer to a thread reference object - * @param[in] msg the message code - * - * @iclass - */ -void chThreadResumeI(thread_reference_t *trp, msg_t msg) { - - if (*trp != NULL) { - thread_t *tp = *trp; - - chDbgAssert(tp->p_state == CH_STATE_SUSPENDED, - "not THD_STATE_SUSPENDED"); - - *trp = NULL; - tp->p_u.rdymsg = msg; - chSchReadyI(tp); - } -} - -/** - * @brief Wakes up a thread waiting on a thread reference object. - * @note This function must reschedule, it can only be called from thread - * context. - * - * @param[in] trp a pointer to a thread reference object - * @param[in] msg the message code - * - * @iclass - */ -void chThreadResumeS(thread_reference_t *trp, msg_t msg) { - - if (*trp != NULL) { - thread_t *tp = *trp; - - chDbgAssert(tp->p_state == CH_STATE_SUSPENDED, - "not THD_STATE_SUSPENDED"); - - *trp = NULL; - chSchWakeupS(tp, msg); - } -} - -/** - * @brief Wakes up a thread waiting on a thread reference object. - * @note This function must reschedule, it can only be called from thread - * context. - * - * @param[in] trp a pointer to a thread reference object - * @param[in] msg the message code - * - * @api - */ -void chThreadResume(thread_reference_t *trp, msg_t msg) { - - chSysLock(); - chThreadResumeS(trp, msg); - chSysUnlock(); -} - /** * @brief Requests a thread termination. * @pre The target thread must be written to invoke periodically @@ -566,4 +449,196 @@ msg_t chThdWait(thread_t *tp) { } #endif /* CH_CFG_USE_WAITEXIT */ +/** + * @brief Sends the current thread sleeping and sets a reference variable. + * @note This function must reschedule, it can only be called from thread + * context. + * + * @param[in] trp a pointer to a thread reference object + * @return The wake up message. + * + * @sclass + */ +msg_t chThdSuspendS(thread_reference_t *trp) { + thread_t *tp = chThdGetSelfX(); + + chDbgAssert(*trp == NULL, "not NULL"); + + *trp = tp; + tp->p_u.wtobjp = &trp; + chSchGoSleepS(CH_STATE_SUSPENDED); + return chThdGetSelfX()->p_msg; +} + +/** + * @brief Sends the current thread sleeping and sets a reference variable. + * @note This function must reschedule, it can only be called from thread + * context. + * + * @param[in] trp a pointer to a thread reference object + * @param[in] timeout the timeout in system ticks, the special values are + * handled as follow: + * - @a TIME_INFINITE the thread enters an infinite sleep + * state. + * - @a TIME_IMMEDIATE the thread is not enqueued and + * the function returns @p MSG_TIMEOUT as if a timeout + * occurred. + * . + * @return The wake up message. + * @retval MSG_TIMEOUT if the operation timed out. + * + * @sclass + */ +msg_t chThdSuspendTimeoutS(thread_reference_t *trp, systime_t timeout) { + thread_t *tp = chThdGetSelfX(); + + chDbgAssert(*trp == NULL, "not NULL"); + + if (TIME_IMMEDIATE == timeout) + return MSG_TIMEOUT; + + *trp = tp; + tp->p_u.wtobjp = &trp; + return chSchGoSleepTimeoutS(CH_STATE_SUSPENDED, timeout); +} + +/** + * @brief Wakes up a thread waiting on a thread reference object. + * @note This function must not reschedule because it can be called from + * ISR context. + * + * @param[in] trp a pointer to a thread reference object + * @param[in] msg the message code + * + * @iclass + */ +void chThdResumeI(thread_reference_t *trp, msg_t msg) { + + if (*trp != NULL) { + thread_t *tp = *trp; + + chDbgAssert(tp->p_state == CH_STATE_SUSPENDED, + "not THD_STATE_SUSPENDED"); + + *trp = NULL; + tp->p_u.rdymsg = msg; + chSchReadyI(tp); + } +} + +/** + * @brief Wakes up a thread waiting on a thread reference object. + * @note This function must reschedule, it can only be called from thread + * context. + * + * @param[in] trp a pointer to a thread reference object + * @param[in] msg the message code + * + * @iclass + */ +void chThdResumeS(thread_reference_t *trp, msg_t msg) { + + if (*trp != NULL) { + thread_t *tp = *trp; + + chDbgAssert(tp->p_state == CH_STATE_SUSPENDED, + "not THD_STATE_SUSPENDED"); + + *trp = NULL; + chSchWakeupS(tp, msg); + } +} + +/** + * @brief Wakes up a thread waiting on a thread reference object. + * @note This function must reschedule, it can only be called from thread + * context. + * + * @param[in] trp a pointer to a thread reference object + * @param[in] msg the message code + * + * @api + */ +void chThdResume(thread_reference_t *trp, msg_t msg) { + + chSysLock(); + chThdResumeS(trp, msg); + chSysUnlock(); +} + +/** + * @brief Enqueues the caller thread on a threads queue object. + * @details The caller thread is enqueued and put to sleep until it is + * dequeued or the specified timeouts expires. + * + * @param[in] tqp pointer to the threads queue object + * @param[in] timeout the timeout in system ticks, the special values are + * handled as follow: + * - @a TIME_INFINITE the thread enters an infinite sleep + * state. + * - @a TIME_IMMEDIATE the thread is not enqueued and + * the function returns @p MSG_TIMEOUT as if a timeout + * occurred. + * . + * @return The message from @p osalQueueWakeupOneI() or + * @p osalQueueWakeupAllI() functions. + * @retval MSG_TIMEOUT if the thread has not been dequeued within the + * specified timeout or if the function has been + * invoked with @p TIME_IMMEDIATE as timeout + * specification. + * + * @sclass + */ +msg_t chThdEnqueueTimeoutS(threads_queue_t *tqp, systime_t timeout) { + + if (TIME_IMMEDIATE == timeout) + return MSG_TIMEOUT; + + queue_insert(currp, tqp); + return chSchGoSleepTimeoutS(CH_STATE_QUEUED, timeout); +} + +/** + * @brief Dequeues and wakes up one thread from the threads queue object, + * if any. + * + * @param[in] tqp pointer to the threads queue object + * @param[in] msg the message code + * + * @iclass + */ +void chThdDequeueNextI(threads_queue_t *tqp, msg_t msg) { + + if (queue_notempty(tqp)) { + thread_t *tp = queue_fifo_remove(tqp); + + chDbgAssert(tp->p_state == CH_STATE_QUEUED, + "not CH_STATE_QUEUED"); + + tp->p_u.rdymsg = msg; + chSchReadyI(tp); + } +} + +/** + * @brief Dequeues and wakes up all threads from the threads queue object. + * + * @param[in] tqp pointer to the threads queue object + * @param[in] msg the message code + * + * @iclass + */ +void chThdDequeueAllI(threads_queue_t *tqp, msg_t msg) { + + while (queue_notempty(tqp)) { + thread_t *tp = queue_fifo_remove(tqp); + + chDbgAssert(tp->p_state == CH_STATE_QUEUED, + "not CH_STATE_QUEUED"); + + tp->p_u.rdymsg = msg; + chSchReadyI(tp); + } +} + /** @} */