git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6472 35acf78f-673a-0410-8e92-d51de3d6d3f4
parent
b6146e1fe4
commit
e86fc6ad21
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @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_ */
|
||||
|
||||
/** @} */
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @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_ */
|
|
@ -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
|
||||
|
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -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,
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @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 */
|
||||
|
||||
/** @} */
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
|
Loading…
Reference in New Issue