Fixed bug #1138.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/stable_20.3.x@13979 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
parent
7ab26d58b5
commit
73db4eb94a
|
@ -104,6 +104,7 @@ extern "C" {
|
|||
/* Base kernel headers.*/
|
||||
#include "chtypes.h" /* CHTODO: Rename and rework.*/
|
||||
#include "chsystypes.h"
|
||||
#include "chlists.h"
|
||||
#include "chdebug.h"
|
||||
#include "chtime.h"
|
||||
#include "chalign.h"
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
* @brief condition_variable_t structure.
|
||||
*/
|
||||
typedef struct condition_variable {
|
||||
threads_queue_t queue; /**< @brief Condition variable
|
||||
ch_queue_t queue; /**< @brief Condition variable
|
||||
threads queue. */
|
||||
} condition_variable_t;
|
||||
|
||||
|
@ -72,7 +72,7 @@ typedef struct condition_variable {
|
|||
*
|
||||
* @param[in] name the name of the condition variable
|
||||
*/
|
||||
#define _CONDVAR_DATA(name) {_THREADS_QUEUE_DATA(name.queue)}
|
||||
#define _CONDVAR_DATA(name) {_CH_QUEUE_DATA(name.queue)}
|
||||
|
||||
/**
|
||||
* @brief Static condition variable initializer.
|
||||
|
|
|
@ -0,0 +1,406 @@
|
|||
/*
|
||||
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS.
|
||||
|
||||
ChibiOS 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 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 Lists and Queues header.
|
||||
*
|
||||
* @addtogroup os_lists
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef CHLISTS_H
|
||||
#define CHLISTS_H
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Type of a generic single link list header and element.
|
||||
*/
|
||||
typedef struct ch_list ch_list_t;
|
||||
|
||||
/**
|
||||
* @brief Structure representing a generic single link list header
|
||||
* and element.
|
||||
*/
|
||||
struct ch_list {
|
||||
ch_list_t *next; /**< @brief Next in the list/queue. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Type of a generic bidirectional linked list header and element.
|
||||
*/
|
||||
typedef struct ch_queue ch_queue_t;
|
||||
|
||||
/**
|
||||
* @brief Structure representing a generic bidirectional linked list header
|
||||
* and element.
|
||||
*/
|
||||
struct ch_queue {
|
||||
ch_queue_t *next; /**< @brief Next in the list/queue. */
|
||||
ch_queue_t *prev; /**< @brief Previous in the queue. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Type of a generic priority-ordered bidirectional linked list
|
||||
* header and element.
|
||||
*/
|
||||
typedef struct ch_priority_queue ch_priority_queue_t;
|
||||
|
||||
/**
|
||||
* @brief Structure representing a generic priority-ordered bidirectional
|
||||
* linked list header and element.
|
||||
* @note Link fields are void pointers in order to avoid aliasing issues.
|
||||
*/
|
||||
struct ch_priority_queue {
|
||||
ch_priority_queue_t *next; /**< @brief Next in the list/queue. */
|
||||
ch_priority_queue_t *prev; /**< @brief Previous in the queue. */
|
||||
tprio_t prio;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Data part of a static queue object initializer.
|
||||
* @details This macro should be used when statically initializing a
|
||||
* queue that is part of a bigger structure.
|
||||
*
|
||||
* @param[in] name the name of the queue variable
|
||||
*/
|
||||
#define _CH_QUEUE_DATA(name) {(ch_queue_t *)&name, (ch_queue_t *)&name}
|
||||
|
||||
/**
|
||||
* @brief Static queue object initializer.
|
||||
* @details Statically initialized queues require no explicit
|
||||
* initialization using @p queue_init().
|
||||
*
|
||||
* @param[in] name the name of the queue variable
|
||||
*/
|
||||
#define CH_QUEUE_DECL(name) \
|
||||
ch_queue_t name = _CH_QUEUE_DATA(name)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/* Early function prototypes required by the following headers.*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module inline functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief List initialization.
|
||||
*
|
||||
* @param[out] lp pointer to the list header
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline void ch_list_init(ch_list_t *lp) {
|
||||
|
||||
lp->next = lp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Evaluates to @p true if the specified list is empty.
|
||||
*
|
||||
* @param[in] lp pointer to the list header
|
||||
* @return The status of the list.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline bool ch_list_isempty(ch_list_t *lp) {
|
||||
|
||||
return (bool)(lp->next == lp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Evaluates to @p true if the specified list is not empty.
|
||||
*
|
||||
* @param[in] lp pointer to the list header
|
||||
* @return The status of the list.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline bool ch_list_notempty(ch_list_t *lp) {
|
||||
|
||||
return (bool)(lp->next != lp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pushes an element on top of a stack list.
|
||||
*
|
||||
* @param[in] p the pointer to the element to be inserted in the list
|
||||
* @param[in] lp the pointer to the list header
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline void ch_list_push(ch_list_t *p, ch_list_t *lp) {
|
||||
|
||||
p->next = lp->next;
|
||||
lp->next = p;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pops an element from the top of a stack list and returns it.
|
||||
* @pre The list must be non-empty before calling this function.
|
||||
*
|
||||
* @param[in] lp the pointer to the list header
|
||||
* @return The removed element pointer.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline ch_list_t *ch_list_pop(ch_list_t *lp) {
|
||||
|
||||
ch_list_t *p = lp->next;
|
||||
lp->next = p->next;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Queue initialization.
|
||||
*
|
||||
* @param[out] qp pointer to the queue header
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline void ch_queue_init(ch_queue_t *qp) {
|
||||
|
||||
qp->next = qp;
|
||||
qp->prev = qp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Evaluates to @p true if the specified queue is empty.
|
||||
*
|
||||
* @param[in] qp pointer to the queue header
|
||||
* @return The status of the queue.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline bool ch_queue_isempty(const ch_queue_t *qp) {
|
||||
|
||||
return (bool)(qp->next == qp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Evaluates to @p true if the specified queue is not empty.
|
||||
*
|
||||
* @param[in] qp pointer to the queue header
|
||||
* @return The status of the queue.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline bool ch_queue_notempty(const ch_queue_t *qp) {
|
||||
|
||||
return (bool)(qp->next != qp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inserts an element into a queue.
|
||||
*
|
||||
* @param[in] p the pointer to the element to be inserted in the queue
|
||||
* @param[in] qp the pointer to the queue header
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline void ch_queue_insert(ch_queue_t *p, ch_queue_t *qp) {
|
||||
|
||||
p->next = qp;
|
||||
p->prev = qp->prev;
|
||||
p->prev->next = p;
|
||||
qp->prev = p;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes the first-out element from a queue and returns it.
|
||||
* @note If the queue is priority ordered then this function returns the
|
||||
* element with the highest priority.
|
||||
*
|
||||
* @param[in] qp the pointer to the queue list header
|
||||
* @return The removed element pointer.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline ch_queue_t *ch_queue_fifo_remove(ch_queue_t *qp) {
|
||||
ch_queue_t *p = qp->next;
|
||||
|
||||
qp->next = p->next;
|
||||
qp->next->prev = qp;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes the last-out element from a queue and returns it.
|
||||
* @note If the queue is priority ordered then this function returns the
|
||||
* element with the lowest priority.
|
||||
*
|
||||
* @param[in] qp the pointer to the queue list header
|
||||
* @return The removed element pointer.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline ch_queue_t *ch_queue_lifo_remove(ch_queue_t *qp) {
|
||||
ch_queue_t *p = qp->prev;
|
||||
|
||||
qp->prev = p->prev;
|
||||
qp->prev->next = qp;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes an element from a queue and returns it.
|
||||
* @details The element is removed from the queue regardless of its relative
|
||||
* position and regardless the used insertion method.
|
||||
*
|
||||
* @param[in] p the pointer to the element to be removed from the queue
|
||||
* @return The removed element pointer.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline ch_queue_t *ch_queue_dequeue(ch_queue_t *p) {
|
||||
|
||||
p->prev->next = p->next;
|
||||
p->next->prev = p->prev;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Priority queue initialization.
|
||||
* @note The queue header priority is initialized to zero, all other
|
||||
* elements in the queue are assumed to have priority greater
|
||||
* than zero.
|
||||
*
|
||||
* @param[out] pqp pointer to the priority queue header
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline void ch_pqueue_init(ch_priority_queue_t *pqp) {
|
||||
|
||||
pqp->next = pqp;
|
||||
pqp->prev = pqp;
|
||||
pqp->prio = (tprio_t)0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes the highest priority element from a priority queue and
|
||||
* returns it.
|
||||
*
|
||||
* @param[in] pqp the pointer to the priority queue list header
|
||||
* @return The removed element pointer.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline ch_priority_queue_t *ch_pqueue_remove_highest(ch_priority_queue_t *pqp) {
|
||||
ch_priority_queue_t *p = pqp->next;
|
||||
|
||||
pqp->next = p->next;
|
||||
pqp->next->prev = pqp;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inserts an element in the priority queue placing it behind
|
||||
* its peers.
|
||||
* @details The element is positioned behind all elements with higher or
|
||||
* equal priority.
|
||||
*
|
||||
* @param[in] pqp the pointer to the priority queue list header
|
||||
* @param[in] p the pointer to the element to be inserted in the queue
|
||||
* @return The inserted element pointer.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline ch_priority_queue_t *ch_pqueue_insert_behind(ch_priority_queue_t *pqp,
|
||||
ch_priority_queue_t *p) {
|
||||
|
||||
/* Scanning priority queue.*/
|
||||
do {
|
||||
pqp = pqp->next;
|
||||
} while (pqp->prio >= p->prio);
|
||||
|
||||
/* Insertion on prev.*/
|
||||
p->next = pqp;
|
||||
p->prev = pqp->prev;
|
||||
p->prev->next = p;
|
||||
pqp->prev = p;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inserts an element in the priority queue placing it ahead of
|
||||
* its peers.
|
||||
* @details The element is positioned ahead of all elements with higher or
|
||||
* equal priority.
|
||||
*
|
||||
* @param[in] pqp the pointer to the priority queue list header
|
||||
* @param[in] p the pointer to the element to be inserted in the queue
|
||||
* @return The inserted element pointer.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline ch_priority_queue_t *ch_pqueue_insert_ahead(ch_priority_queue_t *pqp,
|
||||
ch_priority_queue_t *p) {
|
||||
|
||||
/* Scanning priority queue.*/
|
||||
do {
|
||||
pqp = pqp->next;
|
||||
} while (pqp->prio > p->prio);
|
||||
|
||||
/* Insertion on prev.*/
|
||||
p->next = pqp;
|
||||
p->prev = pqp->prev;
|
||||
p->prev->next = p;
|
||||
pqp->prev = p;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
#endif /* CHLISTS_H */
|
||||
|
||||
/** @} */
|
|
@ -168,7 +168,7 @@ static inline bool chMsgIsPendingI(thread_t *tp) {
|
|||
|
||||
chDbgCheckClassI();
|
||||
|
||||
return (bool)(tp->msgqueue.next != (thread_t *)&tp->msgqueue);
|
||||
return (bool)(tp->msgqueue.next != &tp->msgqueue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -55,7 +55,7 @@ typedef struct ch_mutex mutex_t;
|
|||
* @brief Mutex structure.
|
||||
*/
|
||||
struct ch_mutex {
|
||||
threads_queue_t queue; /**< @brief Queue of the threads sleeping
|
||||
ch_queue_t queue; /**< @brief Queue of the threads sleeping
|
||||
on this mutex. */
|
||||
thread_t *owner; /**< @brief Owner @p thread_t pointer or
|
||||
@p NULL. */
|
||||
|
@ -78,9 +78,9 @@ struct ch_mutex {
|
|||
* @param[in] name the name of the mutex variable
|
||||
*/
|
||||
#if (CH_CFG_USE_MUTEXES_RECURSIVE == TRUE) || defined(__DOXYGEN__)
|
||||
#define _MUTEX_DATA(name) {_THREADS_QUEUE_DATA(name.queue), NULL, NULL, 0}
|
||||
#define _MUTEX_DATA(name) {_CH_QUEUE_DATA(name.queue), NULL, NULL, 0}
|
||||
#else
|
||||
#define _MUTEX_DATA(name) {_THREADS_QUEUE_DATA(name.queue), NULL, NULL}
|
||||
#define _MUTEX_DATA(name) {_CH_QUEUE_DATA(name.queue), NULL, NULL}
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -129,7 +129,7 @@ static inline bool chMtxQueueNotEmptyS(mutex_t *mp) {
|
|||
|
||||
chDbgCheckClassS();
|
||||
|
||||
return queue_notempty(&mp->queue);
|
||||
return ch_queue_notempty(&mp->queue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -119,19 +119,11 @@
|
|||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Generic threads single link list, it works like a stack.
|
||||
* @brief Type of a threads queue.
|
||||
*/
|
||||
struct ch_threads_list {
|
||||
thread_t *next; /**< @brief Next in the list/queue. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Generic threads bidirectional linked list header and element.
|
||||
*/
|
||||
struct ch_threads_queue {
|
||||
thread_t *next; /**< @brief Next in the list/queue. */
|
||||
thread_t *prev; /**< @brief Previous in the queue. */
|
||||
};
|
||||
typedef struct ch_threads_queue {
|
||||
ch_queue_t queue; /**< @brief Threads queue header. */
|
||||
} threads_queue_t;
|
||||
|
||||
/**
|
||||
* @brief Structure representing a thread.
|
||||
|
@ -140,8 +132,12 @@ struct ch_threads_queue {
|
|||
* by shrinking this structure.
|
||||
*/
|
||||
struct ch_thread {
|
||||
threads_queue_t queue; /**< @brief Threads queue header. */
|
||||
tprio_t prio; /**< @brief Thread priority. */
|
||||
union {
|
||||
ch_list_t list; /**< @brief Threads lists element. */
|
||||
ch_queue_t queue; /**< @brief Threads queues element. */
|
||||
ch_priority_queue_t pqueue; /**< @brief Threads ordered queues
|
||||
element. */
|
||||
} hdr;
|
||||
struct port_context ctx; /**< @brief Processor context. */
|
||||
#if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
|
||||
thread_t *newer; /**< @brief Newer registry element. */
|
||||
|
@ -261,13 +257,13 @@ struct ch_thread {
|
|||
/**
|
||||
* @brief Termination waiting list.
|
||||
*/
|
||||
threads_list_t waiting;
|
||||
ch_list_t waiting;
|
||||
#endif
|
||||
#if (CH_CFG_USE_MESSAGES == TRUE) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Messages queue.
|
||||
*/
|
||||
threads_queue_t msgqueue;
|
||||
ch_queue_t msgqueue;
|
||||
#endif
|
||||
#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
|
||||
/**
|
||||
|
@ -306,32 +302,43 @@ struct ch_thread {
|
|||
};
|
||||
|
||||
/**
|
||||
* @extends virtual_timers_list_t
|
||||
*
|
||||
* @brief Virtual Timer descriptor structure.
|
||||
* @brief Type of a Virtual Timer callback function.
|
||||
*/
|
||||
struct ch_virtual_timer {
|
||||
virtual_timer_t *next; /**< @brief Next timer in the list. */
|
||||
virtual_timer_t *prev; /**< @brief Previous timer in the list. */
|
||||
typedef void (*vtfunc_t)(void *p);
|
||||
|
||||
/**
|
||||
* @brief Type of a Virtual Timer structure.
|
||||
*/
|
||||
typedef struct ch_delta_list delta_list_t;
|
||||
|
||||
/**
|
||||
* @brief Virtual Timer delta list element and header structure.
|
||||
*/
|
||||
struct ch_delta_list {
|
||||
delta_list_t *next; /**< @brief Next timer in the list. */
|
||||
delta_list_t *prev; /**< @brief Previous timer in the list. */
|
||||
sysinterval_t delta; /**< @brief Time delta before timeout. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Type of a Virtual Timer.
|
||||
*/
|
||||
typedef struct ch_virtual_timer {
|
||||
delta_list_t dlist; /**< @brief Delta list element. */
|
||||
vtfunc_t func; /**< @brief Timer callback function
|
||||
pointer. */
|
||||
void *par; /**< @brief Timer callback function
|
||||
parameter. */
|
||||
};
|
||||
} virtual_timer_t;
|
||||
|
||||
/**
|
||||
* @brief Virtual timers list header.
|
||||
* @brief Type of 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.
|
||||
*/
|
||||
struct ch_virtual_timers_list {
|
||||
virtual_timer_t *next; /**< @brief Next timer in the delta
|
||||
list. */
|
||||
virtual_timer_t *prev; /**< @brief Last timer in the delta
|
||||
list. */
|
||||
sysinterval_t delta; /**< @brief Must be initialized to -1. */
|
||||
typedef struct ch_virtual_timers_list {
|
||||
delta_list_t dlist; /**< @brief Delta list header. */
|
||||
#if (CH_CFG_ST_TIMEDELTA == 0) || defined(__DOXYGEN__)
|
||||
volatile systime_t systime; /**< @brief System Time counter. */
|
||||
#endif
|
||||
|
@ -342,24 +349,36 @@ struct ch_virtual_timers_list {
|
|||
systime_t lasttime; /**< @brief System time of the last
|
||||
tick event. */
|
||||
#endif
|
||||
};
|
||||
} virtual_timers_list_t;
|
||||
|
||||
/**
|
||||
* @extends threads_queue_t
|
||||
*/
|
||||
struct ch_ready_list {
|
||||
threads_queue_t queue; /**< @brief Threads queue. */
|
||||
tprio_t prio; /**< @brief This field must be
|
||||
initialized to zero. */
|
||||
struct port_context ctx; /**< @brief Not used, present because
|
||||
offsets. */
|
||||
/**
|
||||
* @brief Threads ordered queues header.
|
||||
* @note The priority field must be initialized to zero.
|
||||
*/
|
||||
ch_priority_queue_t pqueue;
|
||||
/**
|
||||
* @brief Not used, present because offsets.
|
||||
*/
|
||||
struct port_context ctx;
|
||||
#if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
|
||||
thread_t *newer; /**< @brief Newer registry element. */
|
||||
thread_t *older; /**< @brief Older registry element. */
|
||||
/**
|
||||
* @brief Newer registry element.
|
||||
*/
|
||||
thread_t *newer;
|
||||
/**
|
||||
* @brief Older registry element.
|
||||
*/
|
||||
thread_t *older;
|
||||
#endif
|
||||
/* End of the fields shared with the thread_t structure.*/
|
||||
thread_t *current; /**< @brief The currently running
|
||||
thread. */
|
||||
/**
|
||||
* @brief The currently running thread.
|
||||
*/
|
||||
thread_t *current;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -473,13 +492,7 @@ extern "C" {
|
|||
void chSchDoRescheduleAhead(void);
|
||||
void chSchDoReschedule(void);
|
||||
#if CH_CFG_OPTIMIZE_SPEED == FALSE
|
||||
void queue_prio_insert(thread_t *tp, threads_queue_t *tqp);
|
||||
void queue_insert(thread_t *tp, threads_queue_t *tqp);
|
||||
thread_t *queue_fifo_remove(threads_queue_t *tqp);
|
||||
thread_t *queue_lifo_remove(threads_queue_t *tqp);
|
||||
thread_t *queue_dequeue(thread_t *tp);
|
||||
void list_insert(thread_t *tp, threads_list_t *tlp);
|
||||
thread_t *list_remove(threads_list_t *tlp);
|
||||
void ch_sch_prio_insert(ch_queue_t *tp, ch_queue_t *qp);
|
||||
#endif /* CH_CFG_OPTIMIZE_SPEED == FALSE */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -489,144 +502,20 @@ extern "C" {
|
|||
/* Module inline functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Threads list initialization.
|
||||
*
|
||||
* @param[in] tlp pointer to the threads list object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline void list_init(threads_list_t *tlp) {
|
||||
|
||||
tlp->next = (thread_t *)tlp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Evaluates to @p true if the specified threads list is empty.
|
||||
*
|
||||
* @param[in] tlp pointer to the threads list object
|
||||
* @return The status of the list.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline bool list_isempty(threads_list_t *tlp) {
|
||||
|
||||
return (bool)(tlp->next == (thread_t *)tlp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Evaluates to @p true if the specified threads list is not empty.
|
||||
*
|
||||
* @param[in] tlp pointer to the threads list object
|
||||
* @return The status of the list.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline bool list_notempty(threads_list_t *tlp) {
|
||||
|
||||
return (bool)(tlp->next != (thread_t *)tlp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Threads queue initialization.
|
||||
*
|
||||
* @param[in] tqp pointer to the threads queue object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline void queue_init(threads_queue_t *tqp) {
|
||||
|
||||
tqp->next = (thread_t *)tqp;
|
||||
tqp->prev = (thread_t *)tqp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Evaluates to @p true if the specified threads queue is empty.
|
||||
*
|
||||
* @param[in] tqp pointer to the threads queue object
|
||||
* @return The status of the queue.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline bool queue_isempty(const threads_queue_t *tqp) {
|
||||
|
||||
return (bool)(tqp->next == (const thread_t *)tqp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Evaluates to @p true if the specified threads queue is not empty.
|
||||
*
|
||||
* @param[in] tqp pointer to the threads queue object
|
||||
* @return The status of the queue.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline bool queue_notempty(const threads_queue_t *tqp) {
|
||||
|
||||
return (bool)(tqp->next != (const 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 == TRUE
|
||||
static inline void list_insert(thread_t *tp, threads_list_t *tlp) {
|
||||
static inline void ch_sch_prio_insert(ch_queue_t *tp, ch_queue_t *qp) {
|
||||
|
||||
tp->queue.next = tlp->next;
|
||||
tlp->next = tp;
|
||||
}
|
||||
|
||||
static inline thread_t *list_remove(threads_list_t *tlp) {
|
||||
|
||||
thread_t *tp = tlp->next;
|
||||
tlp->next = tp->queue.next;
|
||||
|
||||
return tp;
|
||||
}
|
||||
|
||||
static inline void queue_prio_insert(thread_t *tp, threads_queue_t *tqp) {
|
||||
|
||||
thread_t *cp = (thread_t *)tqp;
|
||||
ch_queue_t *cp = qp;
|
||||
do {
|
||||
cp = cp->queue.next;
|
||||
} while ((cp != (thread_t *)tqp) && (cp->prio >= tp->prio));
|
||||
tp->queue.next = cp;
|
||||
tp->queue.prev = cp->queue.prev;
|
||||
tp->queue.prev->queue.next = tp;
|
||||
cp->queue.prev = tp;
|
||||
}
|
||||
|
||||
static inline void queue_insert(thread_t *tp, threads_queue_t *tqp) {
|
||||
|
||||
tp->queue.next = (thread_t *)tqp;
|
||||
tp->queue.prev = tqp->prev;
|
||||
tp->queue.prev->queue.next = tp;
|
||||
tqp->prev = tp;
|
||||
}
|
||||
|
||||
static inline thread_t *queue_fifo_remove(threads_queue_t *tqp) {
|
||||
thread_t *tp = tqp->next;
|
||||
|
||||
tqp->next = tp->queue.next;
|
||||
tqp->next->queue.prev = (thread_t *)tqp;
|
||||
|
||||
return tp;
|
||||
}
|
||||
|
||||
static inline thread_t *queue_lifo_remove(threads_queue_t *tqp) {
|
||||
thread_t *tp = tqp->prev;
|
||||
|
||||
tqp->prev = tp->queue.prev;
|
||||
tqp->prev->queue.next = (thread_t *)tqp;
|
||||
|
||||
return tp;
|
||||
}
|
||||
|
||||
static inline thread_t *queue_dequeue(thread_t *tp) {
|
||||
|
||||
tp->queue.prev->queue.next = tp->queue.next;
|
||||
tp->queue.next->queue.prev = tp->queue.prev;
|
||||
|
||||
return tp;
|
||||
cp = cp->next;
|
||||
} while ((cp != qp) &&
|
||||
(((thread_t *)cp)->hdr.pqueue.prio >= ((thread_t *)tp)->hdr.pqueue.prio));
|
||||
tp->next = cp;
|
||||
tp->prev = cp->prev;
|
||||
tp->prev->next = tp;
|
||||
cp->prev = tp;
|
||||
}
|
||||
#endif /* CH_CFG_OPTIMIZE_SPEED == TRUE */
|
||||
|
||||
|
@ -645,7 +534,7 @@ static inline bool chSchIsRescRequiredI(void) {
|
|||
|
||||
chDbgCheckClassI();
|
||||
|
||||
return firstprio(&ch.rlist.queue) > currp->prio;
|
||||
return firstprio(&ch.rlist.pqueue) > currp->hdr.pqueue.prio;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -663,7 +552,7 @@ static inline bool chSchCanYieldS(void) {
|
|||
|
||||
chDbgCheckClassS();
|
||||
|
||||
return firstprio(&ch.rlist.queue) >= currp->prio;
|
||||
return firstprio(&ch.rlist.pqueue) >= currp->hdr.pqueue.prio;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -690,8 +579,8 @@ static inline void chSchDoYieldS(void) {
|
|||
* @special
|
||||
*/
|
||||
static inline void chSchPreemption(void) {
|
||||
tprio_t p1 = firstprio(&ch.rlist.queue);
|
||||
tprio_t p2 = currp->prio;
|
||||
tprio_t p1 = firstprio(&ch.rlist.pqueue);
|
||||
tprio_t p2 = currp->hdr.pqueue.prio;
|
||||
|
||||
#if CH_CFG_TIME_QUANTUM > 0
|
||||
if (currp->ticks > (tslices_t)0) {
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
* @brief Semaphore structure.
|
||||
*/
|
||||
typedef struct ch_semaphore {
|
||||
threads_queue_t queue; /**< @brief Queue of the threads sleeping
|
||||
ch_queue_t queue; /**< @brief Queue of the threads sleeping
|
||||
on this semaphore. */
|
||||
cnt_t cnt; /**< @brief The semaphore counter. */
|
||||
} semaphore_t;
|
||||
|
@ -68,7 +68,7 @@ typedef struct ch_semaphore {
|
|||
* @param[in] n the counter initial value, this value must be
|
||||
* non-negative
|
||||
*/
|
||||
#define _SEMAPHORE_DATA(name, n) {_THREADS_QUEUE_DATA(name.queue), n}
|
||||
#define _SEMAPHORE_DATA(name, n) {_CH_QUEUE_DATA(name.queue), n}
|
||||
|
||||
/**
|
||||
* @brief Static semaphore initializer.
|
||||
|
|
|
@ -371,8 +371,8 @@ static inline void chSysUnlock(void) {
|
|||
in a critical section not followed by a chSchRescheduleS(), this means
|
||||
that the current thread has a lower priority than the next thread in
|
||||
the ready list.*/
|
||||
chDbgAssert((ch.rlist.queue.next == (thread_t *)&ch.rlist.queue) ||
|
||||
(ch.rlist.current->prio >= ch.rlist.queue.next->prio),
|
||||
chDbgAssert((ch.rlist.pqueue.next == &ch.rlist.pqueue) ||
|
||||
(ch.rlist.current->hdr.pqueue.prio >= ch.rlist.pqueue.next->prio),
|
||||
"priority order violation");
|
||||
|
||||
port_unlock();
|
||||
|
@ -460,7 +460,7 @@ static inline void chSysUnconditionalUnlock(void) {
|
|||
*/
|
||||
static inline thread_t *chSysGetIdleThreadX(void) {
|
||||
|
||||
return ch.rlist.queue.prev;
|
||||
return (thread_t *)ch.rlist.pqueue.prev;
|
||||
}
|
||||
#endif /* CH_CFG_NO_IDLE_THREAD == FALSE */
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ typedef struct {
|
|||
*
|
||||
* @param[in] name the name of the threads queue variable
|
||||
*/
|
||||
#define _THREADS_QUEUE_DATA(name) {(thread_t *)&name, (thread_t *)&name}
|
||||
#define _THREADS_QUEUE_DATA(name) {_CH_QUEUE_DATA(name)}
|
||||
|
||||
/**
|
||||
* @brief Static threads queue object initializer.
|
||||
|
@ -104,7 +104,7 @@ typedef struct {
|
|||
*
|
||||
* @param[in] name the name of the threads queue variable
|
||||
*/
|
||||
#define _THREADS_QUEUE_DECL(name) \
|
||||
#define THREADS_QUEUE_DECL(name) \
|
||||
threads_queue_t name = _THREADS_QUEUE_DATA(name)
|
||||
/** @} */
|
||||
|
||||
|
@ -284,7 +284,7 @@ static inline thread_t *chThdGetSelfX(void) {
|
|||
*/
|
||||
static inline tprio_t chThdGetPriorityX(void) {
|
||||
|
||||
return chThdGetSelfX()->prio;
|
||||
return chThdGetSelfX()->hdr.pqueue.prio;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -391,7 +391,7 @@ static inline void chThdSleepS(sysinterval_t ticks) {
|
|||
*/
|
||||
static inline void chThdQueueObjectInit(threads_queue_t *tqp) {
|
||||
|
||||
queue_init(tqp);
|
||||
ch_queue_init(&tqp->queue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -408,7 +408,7 @@ static inline bool chThdQueueIsEmptyI(threads_queue_t *tqp) {
|
|||
|
||||
chDbgCheckClassI();
|
||||
|
||||
return queue_isempty(tqp);
|
||||
return ch_queue_isempty(&tqp->queue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -425,9 +425,9 @@ static inline bool chThdQueueIsEmptyI(threads_queue_t *tqp) {
|
|||
static inline void chThdDoDequeueNextI(threads_queue_t *tqp, msg_t msg) {
|
||||
thread_t *tp;
|
||||
|
||||
chDbgAssert(queue_notempty(tqp), "empty queue");
|
||||
chDbgAssert(ch_queue_notempty(&tqp->queue), "empty queue");
|
||||
|
||||
tp = queue_fifo_remove(tqp);
|
||||
tp = (thread_t *)ch_queue_fifo_remove(&tqp->queue);
|
||||
|
||||
chDbgAssert(tp->state == CH_STATE_QUEUED, "invalid state");
|
||||
|
||||
|
|
|
@ -208,19 +208,21 @@ static inline bool chVTIsSystemTimeWithin(systime_t start, systime_t end) {
|
|||
* @iclass
|
||||
*/
|
||||
static inline bool chVTGetTimersStateI(sysinterval_t *timep) {
|
||||
virtual_timers_list_t *vtlp = &ch.vtlist;
|
||||
delta_list_t *dlp = &vtlp->dlist;
|
||||
|
||||
chDbgCheckClassI();
|
||||
|
||||
if (&ch.vtlist == (virtual_timers_list_t *)ch.vtlist.next) {
|
||||
if (dlp == dlp->next) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (timep != NULL) {
|
||||
#if CH_CFG_ST_TIMEDELTA == 0
|
||||
*timep = ch.vtlist.next->delta;
|
||||
*timep = dlp->next->delta;
|
||||
#else
|
||||
*timep = (ch.vtlist.next->delta + (sysinterval_t)CH_CFG_ST_TIMEDELTA) -
|
||||
chTimeDiffX(ch.vtlist.lasttime, chVTGetSystemTimeX());
|
||||
*timep = (dlp->next->delta + (sysinterval_t)CH_CFG_ST_TIMEDELTA) -
|
||||
chTimeDiffX(vtlp->lasttime, chVTGetSystemTimeX());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ void chCondObjectInit(condition_variable_t *cp) {
|
|||
|
||||
chDbgCheck(cp != NULL);
|
||||
|
||||
queue_init(&cp->queue);
|
||||
ch_queue_init(&cp->queue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -91,8 +91,8 @@ void chCondSignal(condition_variable_t *cp) {
|
|||
chDbgCheck(cp != NULL);
|
||||
|
||||
chSysLock();
|
||||
if (queue_notempty(&cp->queue)) {
|
||||
chSchWakeupS(queue_fifo_remove(&cp->queue), MSG_OK);
|
||||
if (ch_queue_notempty(&cp->queue)) {
|
||||
chSchWakeupS((thread_t *)ch_queue_fifo_remove(&cp->queue), MSG_OK);
|
||||
}
|
||||
chSysUnlock();
|
||||
}
|
||||
|
@ -113,8 +113,8 @@ void chCondSignalI(condition_variable_t *cp) {
|
|||
chDbgCheckClassI();
|
||||
chDbgCheck(cp != NULL);
|
||||
|
||||
if (queue_notempty(&cp->queue)) {
|
||||
thread_t *tp = queue_fifo_remove(&cp->queue);
|
||||
if (ch_queue_notempty(&cp->queue)) {
|
||||
thread_t *tp = (thread_t *)ch_queue_fifo_remove(&cp->queue);
|
||||
tp->u.rdymsg = MSG_OK;
|
||||
(void) chSchReadyI(tp);
|
||||
}
|
||||
|
@ -154,8 +154,8 @@ void chCondBroadcastI(condition_variable_t *cp) {
|
|||
/* Empties the condition variable queue and inserts all the threads into the
|
||||
ready list in FIFO order. The wakeup message is set to @p MSG_RESET in
|
||||
order to make a chCondBroadcast() detectable from a chCondSignal().*/
|
||||
while (queue_notempty(&cp->queue)) {
|
||||
chSchReadyI(queue_fifo_remove(&cp->queue))->u.rdymsg = MSG_RESET;
|
||||
while (ch_queue_notempty(&cp->queue)) {
|
||||
chSchReadyI((thread_t *)ch_queue_fifo_remove(&cp->queue))->u.rdymsg = MSG_RESET;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,7 +217,7 @@ msg_t chCondWaitS(condition_variable_t *cp) {
|
|||
/* Start waiting on the condition variable, on exit the mutex is taken
|
||||
again.*/
|
||||
ctp->u.wtobjp = cp;
|
||||
queue_prio_insert(ctp, &cp->queue);
|
||||
ch_sch_prio_insert(&ctp->hdr.queue, &cp->queue);
|
||||
chSchGoSleepS(CH_STATE_WTCOND);
|
||||
msg = ctp->u.rdymsg;
|
||||
chMtxLockS(mp);
|
||||
|
@ -306,7 +306,7 @@ msg_t chCondWaitTimeoutS(condition_variable_t *cp, sysinterval_t timeout) {
|
|||
/* Start waiting on the condition variable, on exit the mutex is taken
|
||||
again.*/
|
||||
currp->u.wtobjp = cp;
|
||||
queue_prio_insert(currp, &cp->queue);
|
||||
ch_sch_prio_insert(&currp->hdr.queue, &cp->queue);
|
||||
msg = chSchGoSleepTimeoutS(CH_STATE_WTCOND, timeout);
|
||||
if (msg != MSG_TIMEOUT) {
|
||||
chMtxLockS(mp);
|
||||
|
|
|
@ -64,9 +64,9 @@
|
|||
/*===========================================================================*/
|
||||
|
||||
#if CH_CFG_USE_MESSAGES_PRIORITY == TRUE
|
||||
#define msg_insert(tp, qp) queue_prio_insert(tp, qp)
|
||||
#define msg_insert(tp, qp) ch_sch_prio_insert(&tp->hdr.queue, qp)
|
||||
#else
|
||||
#define msg_insert(tp, qp) queue_insert(tp, qp)
|
||||
#define msg_insert(tp, qp) ch_queue_insert(&tp->hdr.queue, qp)
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
|
@ -126,7 +126,7 @@ thread_t *chMsgWaitS(void) {
|
|||
if (!chMsgIsPendingI(currp)) {
|
||||
chSchGoSleepS(CH_STATE_WTMSG);
|
||||
}
|
||||
tp = queue_fifo_remove(&currp->msgqueue);
|
||||
tp = (thread_t *)ch_queue_fifo_remove(&currp->msgqueue);
|
||||
tp->state = CH_STATE_SNDMSG;
|
||||
|
||||
return tp;
|
||||
|
@ -164,7 +164,7 @@ thread_t *chMsgWaitTimeoutS(sysinterval_t timeout) {
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
tp = queue_fifo_remove(&currp->msgqueue);
|
||||
tp = (thread_t *)ch_queue_fifo_remove(&currp->msgqueue);
|
||||
tp->state = CH_STATE_SNDMSG;
|
||||
|
||||
return tp;
|
||||
|
@ -191,7 +191,7 @@ thread_t *chMsgPollS(void) {
|
|||
thread_t *tp = NULL;
|
||||
|
||||
if (chMsgIsPendingI(currp)) {
|
||||
tp = queue_fifo_remove(&currp->msgqueue);
|
||||
tp = (thread_t *)ch_queue_fifo_remove(&currp->msgqueue);
|
||||
tp->state = CH_STATE_SNDMSG;
|
||||
}
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ void chMtxObjectInit(mutex_t *mp) {
|
|||
|
||||
chDbgCheck(mp != NULL);
|
||||
|
||||
queue_init(&mp->queue);
|
||||
ch_queue_init(&mp->queue);
|
||||
mp->owner = NULL;
|
||||
#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
|
||||
mp->cnt = (cnt_t)0;
|
||||
|
@ -137,7 +137,7 @@ void chMtxLock(mutex_t *mp) {
|
|||
* @sclass
|
||||
*/
|
||||
void chMtxLockS(mutex_t *mp) {
|
||||
thread_t *ctp = currp;
|
||||
thread_t *currtp = chThdGetSelfX();
|
||||
|
||||
chDbgCheckClassS();
|
||||
chDbgCheck(mp != NULL);
|
||||
|
@ -150,7 +150,7 @@ void chMtxLockS(mutex_t *mp) {
|
|||
|
||||
/* If the mutex is already owned by this thread, the counter is increased
|
||||
and there is no need of more actions.*/
|
||||
if (mp->owner == ctp) {
|
||||
if (mp->owner == currtp) {
|
||||
mp->cnt++;
|
||||
}
|
||||
else {
|
||||
|
@ -162,15 +162,16 @@ void chMtxLockS(mutex_t *mp) {
|
|||
|
||||
/* Does the running thread have higher priority than the mutex
|
||||
owning thread? */
|
||||
while (tp->prio < ctp->prio) {
|
||||
while (tp->hdr.pqueue.prio < currtp->hdr.pqueue.prio) {
|
||||
/* Make priority of thread tp match the running thread's priority.*/
|
||||
tp->prio = ctp->prio;
|
||||
tp->hdr.pqueue.prio = currtp->hdr.pqueue.prio;
|
||||
|
||||
/* The following states need priority queues reordering.*/
|
||||
switch (tp->state) {
|
||||
case CH_STATE_WTMTX:
|
||||
/* Re-enqueues the mutex owner with its new priority.*/
|
||||
queue_prio_insert(queue_dequeue(tp), &tp->u.wtmtxp->queue);
|
||||
ch_sch_prio_insert(ch_queue_dequeue(&tp->hdr.queue),
|
||||
&tp->u.wtmtxp->queue);
|
||||
tp = tp->u.wtmtxp->owner;
|
||||
/*lint -e{9042} [16.1] Continues the while.*/
|
||||
continue;
|
||||
|
@ -190,7 +191,8 @@ void chMtxLockS(mutex_t *mp) {
|
|||
case CH_STATE_SNDMSGQ:
|
||||
#endif
|
||||
/* Re-enqueues tp with its new priority on the queue.*/
|
||||
queue_prio_insert(queue_dequeue(tp), &tp->u.wtmtxp->queue);
|
||||
ch_sch_prio_insert(ch_queue_dequeue(&tp->hdr.queue),
|
||||
&tp->u.wtmtxp->queue);
|
||||
break;
|
||||
#endif
|
||||
case CH_STATE_READY:
|
||||
|
@ -199,7 +201,7 @@ void chMtxLockS(mutex_t *mp) {
|
|||
tp->state = CH_STATE_CURRENT;
|
||||
#endif
|
||||
/* Re-enqueues tp with its new priority on the ready list.*/
|
||||
(void) chSchReadyI(queue_dequeue(tp));
|
||||
(void) chSchReadyI((thread_t *)ch_queue_dequeue(&tp->hdr.queue));
|
||||
break;
|
||||
default:
|
||||
/* Nothing to do for other states.*/
|
||||
|
@ -209,14 +211,14 @@ void chMtxLockS(mutex_t *mp) {
|
|||
}
|
||||
|
||||
/* Sleep on the mutex.*/
|
||||
queue_prio_insert(ctp, &mp->queue);
|
||||
ctp->u.wtmtxp = mp;
|
||||
ch_sch_prio_insert(&currtp->hdr.queue, &mp->queue);
|
||||
currtp->u.wtmtxp = mp;
|
||||
chSchGoSleepS(CH_STATE_WTMTX);
|
||||
|
||||
/* It is assumed that the thread performing the unlock operation assigns
|
||||
the mutex to this thread.*/
|
||||
chDbgAssert(mp->owner == ctp, "not owner");
|
||||
chDbgAssert(ctp->mtxlist == mp, "not owned");
|
||||
chDbgAssert(mp->owner == currtp, "not owner");
|
||||
chDbgAssert(currtp->mtxlist == mp, "not owned");
|
||||
#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
|
||||
chDbgAssert(mp->cnt == (cnt_t)1, "counter is not one");
|
||||
}
|
||||
|
@ -229,9 +231,9 @@ void chMtxLockS(mutex_t *mp) {
|
|||
mp->cnt++;
|
||||
#endif
|
||||
/* It was not owned, inserted in the owned mutexes list.*/
|
||||
mp->owner = ctp;
|
||||
mp->next = ctp->mtxlist;
|
||||
ctp->mtxlist = mp;
|
||||
mp->owner = currtp;
|
||||
mp->next = currtp->mtxlist;
|
||||
currtp->mtxlist = mp;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -280,6 +282,7 @@ bool chMtxTryLock(mutex_t *mp) {
|
|||
* @sclass
|
||||
*/
|
||||
bool chMtxTryLockS(mutex_t *mp) {
|
||||
thread_t *currtp = chThdGetSelfX();
|
||||
|
||||
chDbgCheckClassS();
|
||||
chDbgCheck(mp != NULL);
|
||||
|
@ -289,7 +292,7 @@ bool chMtxTryLockS(mutex_t *mp) {
|
|||
|
||||
chDbgAssert(mp->cnt >= (cnt_t)1, "counter is not positive");
|
||||
|
||||
if (mp->owner == currp) {
|
||||
if (mp->owner == currtp) {
|
||||
mp->cnt++;
|
||||
return true;
|
||||
}
|
||||
|
@ -302,9 +305,9 @@ bool chMtxTryLockS(mutex_t *mp) {
|
|||
|
||||
mp->cnt++;
|
||||
#endif
|
||||
mp->owner = currp;
|
||||
mp->next = currp->mtxlist;
|
||||
currp->mtxlist = mp;
|
||||
mp->owner = currtp;
|
||||
mp->next = currtp->mtxlist;
|
||||
currtp->mtxlist = mp;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -321,27 +324,27 @@ bool chMtxTryLockS(mutex_t *mp) {
|
|||
* @api
|
||||
*/
|
||||
void chMtxUnlock(mutex_t *mp) {
|
||||
thread_t *ctp = currp;
|
||||
thread_t *currtp = chThdGetSelfX();
|
||||
mutex_t *lmp;
|
||||
|
||||
chDbgCheck(mp != NULL);
|
||||
|
||||
chSysLock();
|
||||
|
||||
chDbgAssert(ctp->mtxlist != NULL, "owned mutexes list empty");
|
||||
chDbgAssert(ctp->mtxlist->owner == ctp, "ownership failure");
|
||||
chDbgAssert(currtp->mtxlist != NULL, "owned mutexes list empty");
|
||||
chDbgAssert(currtp->mtxlist->owner == currtp, "ownership failure");
|
||||
#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
|
||||
chDbgAssert(mp->cnt >= (cnt_t)1, "counter is not positive");
|
||||
|
||||
if (--mp->cnt == (cnt_t)0) {
|
||||
#endif
|
||||
|
||||
chDbgAssert(ctp->mtxlist == mp, "not next in list");
|
||||
chDbgAssert(currtp->mtxlist == mp, "not next in list");
|
||||
|
||||
/* Removes the top mutex from the thread's owned mutexes list and marks
|
||||
it as not owned. Note, it is assumed to be the same mutex passed as
|
||||
parameter of this function.*/
|
||||
ctp->mtxlist = mp->next;
|
||||
currtp->mtxlist = mp->next;
|
||||
|
||||
/* If a thread is waiting on the mutex then the fun part begins.*/
|
||||
if (chMtxQueueNotEmptyS(mp)) {
|
||||
|
@ -349,29 +352,29 @@ void chMtxUnlock(mutex_t *mp) {
|
|||
|
||||
/* Recalculates the optimal thread priority by scanning the owned
|
||||
mutexes list.*/
|
||||
tprio_t newprio = ctp->realprio;
|
||||
lmp = ctp->mtxlist;
|
||||
tprio_t newprio = currtp->realprio;
|
||||
lmp = currtp->mtxlist;
|
||||
while (lmp != NULL) {
|
||||
/* If the highest priority thread waiting in the mutexes list has a
|
||||
greater priority than the current thread base priority then the
|
||||
final priority will have at least that priority.*/
|
||||
if (chMtxQueueNotEmptyS(lmp) &&
|
||||
(lmp->queue.next->prio > newprio)) {
|
||||
newprio = lmp->queue.next->prio;
|
||||
(((thread_t *)lmp->queue.next)->hdr.pqueue.prio > newprio)) {
|
||||
newprio = ((thread_t *)lmp->queue.next)->hdr.pqueue.prio;
|
||||
}
|
||||
lmp = lmp->next;
|
||||
}
|
||||
|
||||
/* Assigns to the current thread the highest priority among all the
|
||||
waiting threads.*/
|
||||
ctp->prio = newprio;
|
||||
currtp->hdr.pqueue.prio = newprio;
|
||||
|
||||
/* Awakens the highest priority thread waiting for the unlocked mutex and
|
||||
assigns the mutex to it.*/
|
||||
#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
|
||||
mp->cnt = (cnt_t)1;
|
||||
#endif
|
||||
tp = queue_fifo_remove(&mp->queue);
|
||||
tp = (thread_t *)ch_queue_fifo_remove(&mp->queue);
|
||||
mp->owner = tp;
|
||||
mp->next = tp->mtxlist;
|
||||
tp->mtxlist = mp;
|
||||
|
@ -408,26 +411,26 @@ void chMtxUnlock(mutex_t *mp) {
|
|||
* @sclass
|
||||
*/
|
||||
void chMtxUnlockS(mutex_t *mp) {
|
||||
thread_t *ctp = currp;
|
||||
thread_t *currtp = chThdGetSelfX();
|
||||
mutex_t *lmp;
|
||||
|
||||
chDbgCheckClassS();
|
||||
chDbgCheck(mp != NULL);
|
||||
|
||||
chDbgAssert(ctp->mtxlist != NULL, "owned mutexes list empty");
|
||||
chDbgAssert(ctp->mtxlist->owner == ctp, "ownership failure");
|
||||
chDbgAssert(currtp->mtxlist != NULL, "owned mutexes list empty");
|
||||
chDbgAssert(currtp->mtxlist->owner == currtp, "ownership failure");
|
||||
#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
|
||||
chDbgAssert(mp->cnt >= (cnt_t)1, "counter is not positive");
|
||||
|
||||
if (--mp->cnt == (cnt_t)0) {
|
||||
#endif
|
||||
|
||||
chDbgAssert(ctp->mtxlist == mp, "not next in list");
|
||||
chDbgAssert(currtp->mtxlist == mp, "not next in list");
|
||||
|
||||
/* Removes the top mutex from the thread's owned mutexes list and marks
|
||||
it as not owned. Note, it is assumed to be the same mutex passed as
|
||||
parameter of this function.*/
|
||||
ctp->mtxlist = mp->next;
|
||||
currtp->mtxlist = mp->next;
|
||||
|
||||
/* If a thread is waiting on the mutex then the fun part begins.*/
|
||||
if (chMtxQueueNotEmptyS(mp)) {
|
||||
|
@ -435,29 +438,29 @@ void chMtxUnlockS(mutex_t *mp) {
|
|||
|
||||
/* Recalculates the optimal thread priority by scanning the owned
|
||||
mutexes list.*/
|
||||
tprio_t newprio = ctp->realprio;
|
||||
lmp = ctp->mtxlist;
|
||||
tprio_t newprio = currtp->realprio;
|
||||
lmp = currtp->mtxlist;
|
||||
while (lmp != NULL) {
|
||||
/* If the highest priority thread waiting in the mutexes list has a
|
||||
greater priority than the current thread base priority then the
|
||||
final priority will have at least that priority.*/
|
||||
if (chMtxQueueNotEmptyS(lmp) &&
|
||||
(lmp->queue.next->prio > newprio)) {
|
||||
newprio = lmp->queue.next->prio;
|
||||
(((thread_t *)lmp->queue.next)->hdr.pqueue.prio > newprio)) {
|
||||
newprio = ((thread_t *)lmp->queue.next)->hdr.pqueue.prio;
|
||||
}
|
||||
lmp = lmp->next;
|
||||
}
|
||||
|
||||
/* Assigns to the current thread the highest priority among all the
|
||||
waiting threads.*/
|
||||
ctp->prio = newprio;
|
||||
currtp->hdr.pqueue.prio = newprio;
|
||||
|
||||
/* Awakens the highest priority thread waiting for the unlocked mutex and
|
||||
assigns the mutex to it.*/
|
||||
#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
|
||||
mp->cnt = (cnt_t)1;
|
||||
#endif
|
||||
tp = queue_fifo_remove(&mp->queue);
|
||||
tp = (thread_t *)ch_queue_fifo_remove(&mp->queue);
|
||||
mp->owner = tp;
|
||||
mp->next = tp->mtxlist;
|
||||
tp->mtxlist = mp;
|
||||
|
@ -485,18 +488,18 @@ void chMtxUnlockS(mutex_t *mp) {
|
|||
* @sclass
|
||||
*/
|
||||
void chMtxUnlockAllS(void) {
|
||||
thread_t *ctp = currp;
|
||||
thread_t *currtp = chThdGetSelfX();
|
||||
|
||||
if (ctp->mtxlist != NULL) {
|
||||
if (currtp->mtxlist != NULL) {
|
||||
do {
|
||||
mutex_t *mp = ctp->mtxlist;
|
||||
ctp->mtxlist = mp->next;
|
||||
mutex_t *mp = currtp->mtxlist;
|
||||
currtp->mtxlist = mp->next;
|
||||
if (chMtxQueueNotEmptyS(mp)) {
|
||||
thread_t *tp;
|
||||
#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
|
||||
mp->cnt = (cnt_t)1;
|
||||
#endif
|
||||
tp = queue_fifo_remove(&mp->queue);
|
||||
tp = (thread_t *)ch_queue_fifo_remove(&mp->queue);
|
||||
mp->owner = tp;
|
||||
mp->next = tp->mtxlist;
|
||||
tp->mtxlist = mp;
|
||||
|
@ -508,8 +511,8 @@ void chMtxUnlockAllS(void) {
|
|||
#endif
|
||||
mp->owner = NULL;
|
||||
}
|
||||
} while (ctp->mtxlist != NULL);
|
||||
ctp->prio = ctp->realprio;
|
||||
} while (currtp->mtxlist != NULL);
|
||||
currtp->hdr.pqueue.prio = currtp->realprio;
|
||||
chSchRescheduleS();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ ROMCONST chdebug_t ch_debug = {
|
|||
(uint8_t)sizeof (void *),
|
||||
(uint8_t)sizeof (systime_t),
|
||||
(uint8_t)sizeof (thread_t),
|
||||
(uint8_t)_offsetof(thread_t, prio),
|
||||
(uint8_t)_offsetof(thread_t, hdr.pqueue.prio),
|
||||
(uint8_t)_offsetof(thread_t, ctx),
|
||||
(uint8_t)_offsetof(thread_t, newer),
|
||||
(uint8_t)_offsetof(thread_t, older),
|
||||
|
|
|
@ -53,266 +53,6 @@ ch_system_t ch;
|
|||
/* Module local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Scheduler initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void _scheduler_init(void) {
|
||||
|
||||
queue_init(&ch.rlist.queue);
|
||||
ch.rlist.prio = NOPRIO;
|
||||
#if CH_CFG_USE_REGISTRY == TRUE
|
||||
ch.rlist.newer = (thread_t *)&ch.rlist;
|
||||
ch.rlist.older = (thread_t *)&ch.rlist;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if (CH_CFG_OPTIMIZE_SPEED == FALSE) || 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) {
|
||||
|
||||
thread_t *cp = (thread_t *)tqp;
|
||||
do {
|
||||
cp = cp->queue.next;
|
||||
} while ((cp != (thread_t *)tqp) && (cp->prio >= tp->prio));
|
||||
tp->queue.next = cp;
|
||||
tp->queue.prev = cp->queue.prev;
|
||||
tp->queue.prev->queue.next = tp;
|
||||
cp->queue.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->queue.next = (thread_t *)tqp;
|
||||
tp->queue.prev = tqp->prev;
|
||||
tp->queue.prev->queue.next = tp;
|
||||
tqp->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->next;
|
||||
|
||||
tqp->next = tp->queue.next;
|
||||
tqp->next->queue.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->prev;
|
||||
|
||||
tqp->prev = tp->queue.prev;
|
||||
tqp->prev->queue.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->queue.prev->queue.next = tp->queue.next;
|
||||
tp->queue.next->queue.prev = tp->queue.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->queue.next = tlp->next;
|
||||
tlp->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->next;
|
||||
tlp->next = tp->queue.next;
|
||||
|
||||
return tp;
|
||||
}
|
||||
#endif /* CH_CFG_OPTIMIZE_SPEED */
|
||||
|
||||
/**
|
||||
* @brief Inserts a thread in the Ready List placing it behind its peers.
|
||||
* @details The thread is positioned behind all threads with higher or equal
|
||||
* priority.
|
||||
* @pre The thread must not be already inserted in any list through its
|
||||
* @p next and @p prev or list corruption would occur.
|
||||
* @post This function does not reschedule so a call to a rescheduling
|
||||
* function must be performed before unlocking the kernel. Note that
|
||||
* interrupt handlers always reschedule on exit so an explicit
|
||||
* reschedule must not be performed in ISRs.
|
||||
*
|
||||
* @param[in] tp the thread to be made ready
|
||||
* @return The thread pointer.
|
||||
*
|
||||
* @iclass
|
||||
*/
|
||||
thread_t *chSchReadyI(thread_t *tp) {
|
||||
thread_t *cp;
|
||||
|
||||
chDbgCheckClassI();
|
||||
chDbgCheck(tp != NULL);
|
||||
chDbgAssert((tp->state != CH_STATE_READY) &&
|
||||
(tp->state != CH_STATE_FINAL),
|
||||
"invalid state");
|
||||
|
||||
tp->state = CH_STATE_READY;
|
||||
cp = (thread_t *)&ch.rlist.queue;
|
||||
do {
|
||||
cp = cp->queue.next;
|
||||
} while (cp->prio >= tp->prio);
|
||||
/* Insertion on prev.*/
|
||||
tp->queue.next = cp;
|
||||
tp->queue.prev = cp->queue.prev;
|
||||
tp->queue.prev->queue.next = tp;
|
||||
cp->queue.prev = tp;
|
||||
|
||||
return tp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inserts a thread in the Ready List placing it ahead its peers.
|
||||
* @details The thread is positioned ahead all threads with higher or equal
|
||||
* priority.
|
||||
* @pre The thread must not be already inserted in any list through its
|
||||
* @p next and @p prev or list corruption would occur.
|
||||
* @post This function does not reschedule so a call to a rescheduling
|
||||
* function must be performed before unlocking the kernel. Note that
|
||||
* interrupt handlers always reschedule on exit so an explicit
|
||||
* reschedule must not be performed in ISRs.
|
||||
*
|
||||
* @param[in] tp the thread to be made ready
|
||||
* @return The thread pointer.
|
||||
*
|
||||
* @iclass
|
||||
*/
|
||||
thread_t *chSchReadyAheadI(thread_t *tp) {
|
||||
thread_t *cp;
|
||||
|
||||
chDbgCheckClassI();
|
||||
chDbgCheck(tp != NULL);
|
||||
chDbgAssert((tp->state != CH_STATE_READY) &&
|
||||
(tp->state != CH_STATE_FINAL),
|
||||
"invalid state");
|
||||
|
||||
tp->state = CH_STATE_READY;
|
||||
cp = (thread_t *)&ch.rlist.queue;
|
||||
do {
|
||||
cp = cp->queue.next;
|
||||
} while (cp->prio > tp->prio);
|
||||
/* Insertion on prev.*/
|
||||
tp->queue.next = cp;
|
||||
tp->queue.prev = cp->queue.prev;
|
||||
tp->queue.prev->queue.next = tp;
|
||||
cp->queue.prev = tp;
|
||||
|
||||
return tp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Puts the current thread to sleep into the specified state.
|
||||
* @details The thread goes into a sleeping state. The possible
|
||||
* @ref thread_states are defined into @p threads.h.
|
||||
*
|
||||
* @param[in] newstate the new thread state
|
||||
*
|
||||
* @sclass
|
||||
*/
|
||||
void chSchGoSleepS(tstate_t newstate) {
|
||||
thread_t *otp = currp;
|
||||
|
||||
chDbgCheckClassS();
|
||||
|
||||
/* New state.*/
|
||||
otp->state = newstate;
|
||||
|
||||
#if CH_CFG_TIME_QUANTUM > 0
|
||||
/* The thread is renouncing its remaining time slices so it will have a new
|
||||
time quantum when it will wakeup.*/
|
||||
otp->ticks = (tslices_t)CH_CFG_TIME_QUANTUM;
|
||||
#endif
|
||||
|
||||
/* Next thread in ready list becomes current.*/
|
||||
currp = queue_fifo_remove(&ch.rlist.queue);
|
||||
currp->state = CH_STATE_CURRENT;
|
||||
|
||||
/* Handling idle-enter hook.*/
|
||||
if (currp->prio == IDLEPRIO) {
|
||||
CH_CFG_IDLE_ENTER_HOOK();
|
||||
}
|
||||
|
||||
/* Swap operation as tail call.*/
|
||||
chSysSwitch(currp, otp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Timeout wakeup callback.
|
||||
*/
|
||||
|
@ -340,7 +80,7 @@ static void wakeup(void *p) {
|
|||
case CH_STATE_WTCOND:
|
||||
#endif
|
||||
/* States requiring dequeuing.*/
|
||||
(void) queue_dequeue(tp);
|
||||
(void) ch_queue_dequeue(&tp->hdr.queue);
|
||||
break;
|
||||
default:
|
||||
/* Any other state, nothing to do.*/
|
||||
|
@ -351,6 +91,149 @@ static void wakeup(void *p) {
|
|||
chSysUnlockFromISR();
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if (CH_CFG_OPTIMIZE_SPEED == FALSE) || 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 ch_sch_prio_insert(ch_queue_t *tp, ch_queue_t *qp) {
|
||||
|
||||
ch_queue_t *cp = qp;
|
||||
do {
|
||||
cp = cp->next;
|
||||
} while ((cp != qp) &&
|
||||
(((thread_t *)cp)->hdr.pqueue.prio >= ((thread_t *)tp)->hdr.pqueue.prio));
|
||||
tp->next = cp;
|
||||
tp->prev = cp->prev;
|
||||
tp->prev->next = tp;
|
||||
cp->prev = tp;
|
||||
}
|
||||
#endif /* CH_CFG_OPTIMIZE_SPEED */
|
||||
|
||||
/**
|
||||
* @brief Scheduler initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void _scheduler_init(void) {
|
||||
|
||||
ch_pqueue_init(&ch.rlist.pqueue);
|
||||
#if CH_CFG_USE_REGISTRY == TRUE
|
||||
ch.rlist.newer = (thread_t *)&ch.rlist;
|
||||
ch.rlist.older = (thread_t *)&ch.rlist;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inserts a thread in the Ready List placing it behind its peers.
|
||||
* @details The thread is positioned behind all threads with higher or equal
|
||||
* priority.
|
||||
* @pre The thread must not be already inserted in any list through its
|
||||
* @p next and @p prev or list corruption would occur.
|
||||
* @post This function does not reschedule so a call to a rescheduling
|
||||
* function must be performed before unlocking the kernel. Note that
|
||||
* interrupt handlers always reschedule on exit so an explicit
|
||||
* reschedule must not be performed in ISRs.
|
||||
*
|
||||
* @param[in] tp the thread to be made ready
|
||||
* @return The thread pointer.
|
||||
*
|
||||
* @iclass
|
||||
*/
|
||||
thread_t *chSchReadyI(thread_t *tp) {
|
||||
|
||||
chDbgCheckClassI();
|
||||
chDbgCheck(tp != NULL);
|
||||
chDbgAssert((tp->state != CH_STATE_READY) &&
|
||||
(tp->state != CH_STATE_FINAL),
|
||||
"invalid state");
|
||||
|
||||
/* The thread is marked ready.*/
|
||||
tp->state = CH_STATE_READY;
|
||||
|
||||
/* Insertion in the priority queue.*/
|
||||
return (thread_t *)ch_pqueue_insert_behind(&ch.rlist.pqueue,
|
||||
&tp->hdr.pqueue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inserts a thread in the Ready List placing it ahead its peers.
|
||||
* @details The thread is positioned ahead all threads with higher or equal
|
||||
* priority.
|
||||
* @pre The thread must not be already inserted in any list through its
|
||||
* @p next and @p prev or list corruption would occur.
|
||||
* @post This function does not reschedule so a call to a rescheduling
|
||||
* function must be performed before unlocking the kernel. Note that
|
||||
* interrupt handlers always reschedule on exit so an explicit
|
||||
* reschedule must not be performed in ISRs.
|
||||
*
|
||||
* @param[in] tp the thread to be made ready
|
||||
* @return The thread pointer.
|
||||
*
|
||||
* @iclass
|
||||
*/
|
||||
thread_t *chSchReadyAheadI(thread_t *tp) {
|
||||
|
||||
chDbgCheckClassI();
|
||||
chDbgCheck(tp != NULL);
|
||||
chDbgAssert((tp->state != CH_STATE_READY) &&
|
||||
(tp->state != CH_STATE_FINAL),
|
||||
"invalid state");
|
||||
|
||||
/* The thread is marked ready.*/
|
||||
tp->state = CH_STATE_READY;
|
||||
|
||||
/* Insertion in the priority queue.*/
|
||||
return (thread_t *)ch_pqueue_insert_ahead(&ch.rlist.pqueue,
|
||||
&tp->hdr.pqueue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Puts the current thread to sleep into the specified state.
|
||||
* @details The thread goes into a sleeping state. The possible
|
||||
* @ref thread_states are defined into @p threads.h.
|
||||
*
|
||||
* @param[in] newstate the new thread state
|
||||
*
|
||||
* @sclass
|
||||
*/
|
||||
void chSchGoSleepS(tstate_t newstate) {
|
||||
thread_t *otp = currp;
|
||||
|
||||
chDbgCheckClassS();
|
||||
|
||||
/* New state.*/
|
||||
otp->state = newstate;
|
||||
|
||||
#if CH_CFG_TIME_QUANTUM > 0
|
||||
/* The thread is renouncing its remaining time slices so it will have a new
|
||||
time quantum when it will wakeup.*/
|
||||
otp->ticks = (tslices_t)CH_CFG_TIME_QUANTUM;
|
||||
#endif
|
||||
|
||||
/* Next thread in ready list becomes current.*/
|
||||
currp = (thread_t *)ch_pqueue_remove_highest(&ch.rlist.pqueue);
|
||||
currp->state = CH_STATE_CURRENT;
|
||||
|
||||
/* Handling idle-enter hook.*/
|
||||
if (currp->hdr.pqueue.prio == IDLEPRIO) {
|
||||
CH_CFG_IDLE_ENTER_HOOK();
|
||||
}
|
||||
|
||||
/* Swap operation as tail call.*/
|
||||
chSysSwitch(currp, otp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Puts the current thread to sleep into the specified state with
|
||||
* timeout specification.
|
||||
|
@ -414,8 +297,8 @@ void chSchWakeupS(thread_t *ntp, msg_t msg) {
|
|||
|
||||
chDbgCheckClassS();
|
||||
|
||||
chDbgAssert((ch.rlist.queue.next == (thread_t *)&ch.rlist.queue) ||
|
||||
(ch.rlist.current->prio >= ch.rlist.queue.next->prio),
|
||||
chDbgAssert((ch.rlist.pqueue.next == &ch.rlist.pqueue) ||
|
||||
(ch.rlist.current->hdr.pqueue.prio >= ch.rlist.pqueue.next->prio),
|
||||
"priority order violation");
|
||||
|
||||
/* Storing the message to be retrieved by the target thread when it will
|
||||
|
@ -426,14 +309,14 @@ void chSchWakeupS(thread_t *ntp, msg_t msg) {
|
|||
one then it is just inserted in the ready list else it made
|
||||
running immediately and the invoking thread goes in the ready
|
||||
list instead.*/
|
||||
if (ntp->prio <= otp->prio) {
|
||||
if (ntp->hdr.pqueue.prio <= otp->hdr.pqueue.prio) {
|
||||
(void) chSchReadyI(ntp);
|
||||
}
|
||||
else {
|
||||
otp = chSchReadyAheadI(otp);
|
||||
|
||||
/* Handling idle-leave hook.*/
|
||||
if (otp->prio == IDLEPRIO) {
|
||||
if (otp->hdr.pqueue.prio == IDLEPRIO) {
|
||||
CH_CFG_IDLE_LEAVE_HOOK();
|
||||
}
|
||||
|
||||
|
@ -477,8 +360,8 @@ void chSchRescheduleS(void) {
|
|||
* @special
|
||||
*/
|
||||
bool chSchIsPreemptionRequired(void) {
|
||||
tprio_t p1 = firstprio(&ch.rlist.queue);
|
||||
tprio_t p2 = currp->prio;
|
||||
tprio_t p1 = firstprio(&ch.rlist.pqueue);
|
||||
tprio_t p2 = currp->hdr.pqueue.prio;
|
||||
|
||||
#if CH_CFG_TIME_QUANTUM > 0
|
||||
/* If the running thread has not reached its time quantum, reschedule only
|
||||
|
@ -508,11 +391,11 @@ void chSchDoRescheduleBehind(void) {
|
|||
thread_t *otp = currp;
|
||||
|
||||
/* Picks the first thread from the ready queue and makes it current.*/
|
||||
currp = queue_fifo_remove(&ch.rlist.queue);
|
||||
currp = (thread_t *)ch_pqueue_remove_highest(&ch.rlist.pqueue);
|
||||
currp->state = CH_STATE_CURRENT;
|
||||
|
||||
/* Handling idle-leave hook.*/
|
||||
if (otp->prio == IDLEPRIO) {
|
||||
if (otp->hdr.pqueue.prio == IDLEPRIO) {
|
||||
CH_CFG_IDLE_LEAVE_HOOK();
|
||||
}
|
||||
|
||||
|
@ -541,11 +424,11 @@ void chSchDoRescheduleAhead(void) {
|
|||
thread_t *otp = currp;
|
||||
|
||||
/* Picks the first thread from the ready queue and makes it current.*/
|
||||
currp = queue_fifo_remove(&ch.rlist.queue);
|
||||
currp = (thread_t *)ch_pqueue_remove_highest(&ch.rlist.pqueue);
|
||||
currp->state = CH_STATE_CURRENT;
|
||||
|
||||
/* Handling idle-leave hook.*/
|
||||
if (otp->prio == IDLEPRIO) {
|
||||
if (otp->hdr.pqueue.prio == IDLEPRIO) {
|
||||
CH_CFG_IDLE_LEAVE_HOOK();
|
||||
}
|
||||
|
||||
|
@ -571,11 +454,11 @@ void chSchDoReschedule(void) {
|
|||
thread_t *otp = currp;
|
||||
|
||||
/* Picks the first thread from the ready queue and makes it current.*/
|
||||
currp = queue_fifo_remove(&ch.rlist.queue);
|
||||
currp = (thread_t *)ch_pqueue_remove_highest(&ch.rlist.pqueue);
|
||||
currp->state = CH_STATE_CURRENT;
|
||||
|
||||
/* Handling idle-leave hook.*/
|
||||
if (otp->prio == IDLEPRIO) {
|
||||
if (otp->hdr.pqueue.prio == IDLEPRIO) {
|
||||
CH_CFG_IDLE_LEAVE_HOOK();
|
||||
}
|
||||
|
||||
|
|
|
@ -76,9 +76,9 @@
|
|||
/*===========================================================================*/
|
||||
|
||||
#if CH_CFG_USE_SEMAPHORES_PRIORITY == TRUE
|
||||
#define sem_insert(tp, qp) queue_prio_insert(tp, qp)
|
||||
#define sem_insert(tp, qp) ch_sch_prio_insert(&tp->hdr.pqueue, qp)
|
||||
#else
|
||||
#define sem_insert(tp, qp) queue_insert(tp, qp)
|
||||
#define sem_insert(tp, qp) ch_queue_insert(&tp->hdr.queue, qp)
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
|
@ -98,7 +98,7 @@ void chSemObjectInit(semaphore_t *sp, cnt_t n) {
|
|||
|
||||
chDbgCheck((sp != NULL) && (n >= (cnt_t)0));
|
||||
|
||||
queue_init(&sp->queue);
|
||||
ch_queue_init(&sp->queue);
|
||||
sp->cnt = n;
|
||||
}
|
||||
|
||||
|
@ -144,13 +144,13 @@ void chSemResetWithMessageI(semaphore_t *sp, cnt_t n, msg_t msg) {
|
|||
|
||||
chDbgCheckClassI();
|
||||
chDbgCheck((sp != NULL) && (n >= (cnt_t)0));
|
||||
chDbgAssert(((sp->cnt >= (cnt_t)0) && queue_isempty(&sp->queue)) ||
|
||||
((sp->cnt < (cnt_t)0) && queue_notempty(&sp->queue)),
|
||||
chDbgAssert(((sp->cnt >= (cnt_t)0) && ch_queue_isempty(&sp->queue)) ||
|
||||
((sp->cnt < (cnt_t)0) && ch_queue_notempty(&sp->queue)),
|
||||
"inconsistent semaphore");
|
||||
|
||||
sp->cnt = n;
|
||||
while (queue_notempty(&sp->queue)) {
|
||||
chSchReadyI(queue_lifo_remove(&sp->queue))->u.rdymsg = msg;
|
||||
while (ch_queue_notempty(&sp->queue)) {
|
||||
chSchReadyI((thread_t *)ch_queue_lifo_remove(&sp->queue))->u.rdymsg = msg;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,8 +192,8 @@ msg_t chSemWaitS(semaphore_t *sp) {
|
|||
|
||||
chDbgCheckClassS();
|
||||
chDbgCheck(sp != NULL);
|
||||
chDbgAssert(((sp->cnt >= (cnt_t)0) && queue_isempty(&sp->queue)) ||
|
||||
((sp->cnt < (cnt_t)0) && queue_notempty(&sp->queue)),
|
||||
chDbgAssert(((sp->cnt >= (cnt_t)0) && ch_queue_isempty(&sp->queue)) ||
|
||||
((sp->cnt < (cnt_t)0) && ch_queue_notempty(&sp->queue)),
|
||||
"inconsistent semaphore");
|
||||
|
||||
if (--sp->cnt < (cnt_t)0) {
|
||||
|
@ -259,8 +259,8 @@ msg_t chSemWaitTimeoutS(semaphore_t *sp, sysinterval_t timeout) {
|
|||
|
||||
chDbgCheckClassS();
|
||||
chDbgCheck(sp != NULL);
|
||||
chDbgAssert(((sp->cnt >= (cnt_t)0) && queue_isempty(&sp->queue)) ||
|
||||
((sp->cnt < (cnt_t)0) && queue_notempty(&sp->queue)),
|
||||
chDbgAssert(((sp->cnt >= (cnt_t)0) && ch_queue_isempty(&sp->queue)) ||
|
||||
((sp->cnt < (cnt_t)0) && ch_queue_notempty(&sp->queue)),
|
||||
"inconsistent semaphore");
|
||||
|
||||
if (--sp->cnt < (cnt_t)0) {
|
||||
|
@ -290,11 +290,11 @@ void chSemSignal(semaphore_t *sp) {
|
|||
chDbgCheck(sp != NULL);
|
||||
|
||||
chSysLock();
|
||||
chDbgAssert(((sp->cnt >= (cnt_t)0) && queue_isempty(&sp->queue)) ||
|
||||
((sp->cnt < (cnt_t)0) && queue_notempty(&sp->queue)),
|
||||
chDbgAssert(((sp->cnt >= (cnt_t)0) && ch_queue_isempty(&sp->queue)) ||
|
||||
((sp->cnt < (cnt_t)0) && ch_queue_notempty(&sp->queue)),
|
||||
"inconsistent semaphore");
|
||||
if (++sp->cnt <= (cnt_t)0) {
|
||||
chSchWakeupS(queue_fifo_remove(&sp->queue), MSG_OK);
|
||||
chSchWakeupS((thread_t *)ch_queue_fifo_remove(&sp->queue), MSG_OK);
|
||||
}
|
||||
chSysUnlock();
|
||||
}
|
||||
|
@ -314,14 +314,14 @@ void chSemSignalI(semaphore_t *sp) {
|
|||
|
||||
chDbgCheckClassI();
|
||||
chDbgCheck(sp != NULL);
|
||||
chDbgAssert(((sp->cnt >= (cnt_t)0) && queue_isempty(&sp->queue)) ||
|
||||
((sp->cnt < (cnt_t)0) && queue_notempty(&sp->queue)),
|
||||
chDbgAssert(((sp->cnt >= (cnt_t)0) && ch_queue_isempty(&sp->queue)) ||
|
||||
((sp->cnt < (cnt_t)0) && ch_queue_notempty(&sp->queue)),
|
||||
"inconsistent semaphore");
|
||||
|
||||
if (++sp->cnt <= (cnt_t)0) {
|
||||
/* Note, it is done this way in order to allow a tail call on
|
||||
chSchReadyI().*/
|
||||
thread_t *tp = queue_fifo_remove(&sp->queue);
|
||||
thread_t *tp = (thread_t *)ch_queue_fifo_remove(&sp->queue);
|
||||
tp->u.rdymsg = MSG_OK;
|
||||
(void) chSchReadyI(tp);
|
||||
}
|
||||
|
@ -344,13 +344,13 @@ void chSemAddCounterI(semaphore_t *sp, cnt_t n) {
|
|||
|
||||
chDbgCheckClassI();
|
||||
chDbgCheck((sp != NULL) && (n > (cnt_t)0));
|
||||
chDbgAssert(((sp->cnt >= (cnt_t)0) && queue_isempty(&sp->queue)) ||
|
||||
((sp->cnt < (cnt_t)0) && queue_notempty(&sp->queue)),
|
||||
chDbgAssert(((sp->cnt >= (cnt_t)0) && ch_queue_isempty(&sp->queue)) ||
|
||||
((sp->cnt < (cnt_t)0) && ch_queue_notempty(&sp->queue)),
|
||||
"inconsistent semaphore");
|
||||
|
||||
while (n > (cnt_t)0) {
|
||||
if (++sp->cnt <= (cnt_t)0) {
|
||||
chSchReadyI(queue_fifo_remove(&sp->queue))->u.rdymsg = MSG_OK;
|
||||
chSchReadyI((thread_t *)ch_queue_fifo_remove(&sp->queue))->u.rdymsg = MSG_OK;
|
||||
}
|
||||
n--;
|
||||
}
|
||||
|
@ -375,14 +375,14 @@ msg_t chSemSignalWait(semaphore_t *sps, semaphore_t *spw) {
|
|||
chDbgCheck((sps != NULL) && (spw != NULL));
|
||||
|
||||
chSysLock();
|
||||
chDbgAssert(((sps->cnt >= (cnt_t)0) && queue_isempty(&sps->queue)) ||
|
||||
((sps->cnt < (cnt_t)0) && queue_notempty(&sps->queue)),
|
||||
chDbgAssert(((sps->cnt >= (cnt_t)0) && ch_queue_isempty(&sps->queue)) ||
|
||||
((sps->cnt < (cnt_t)0) && ch_queue_notempty(&sps->queue)),
|
||||
"inconsistent semaphore");
|
||||
chDbgAssert(((spw->cnt >= (cnt_t)0) && queue_isempty(&spw->queue)) ||
|
||||
((spw->cnt < (cnt_t)0) && queue_notempty(&spw->queue)),
|
||||
chDbgAssert(((spw->cnt >= (cnt_t)0) && ch_queue_isempty(&spw->queue)) ||
|
||||
((spw->cnt < (cnt_t)0) && ch_queue_notempty(&spw->queue)),
|
||||
"inconsistent semaphore");
|
||||
if (++sps->cnt <= (cnt_t)0) {
|
||||
chSchReadyI(queue_fifo_remove(&sps->queue))->u.rdymsg = MSG_OK;
|
||||
chSchReadyI((thread_t *)ch_queue_fifo_remove(&sps->queue))->u.rdymsg = MSG_OK;
|
||||
}
|
||||
if (--spw->cnt < (cnt_t)0) {
|
||||
thread_t *ctp = currp;
|
||||
|
|
|
@ -236,21 +236,21 @@ bool chSysIntegrityCheckI(unsigned testmask) {
|
|||
|
||||
/* Ready List integrity check.*/
|
||||
if ((testmask & CH_INTEGRITY_RLIST) != 0U) {
|
||||
thread_t *tp;
|
||||
ch_priority_queue_t *pqp;
|
||||
|
||||
/* Scanning the ready list forward.*/
|
||||
n = (cnt_t)0;
|
||||
tp = ch.rlist.queue.next;
|
||||
while (tp != (thread_t *)&ch.rlist.queue) {
|
||||
pqp = ch.rlist.pqueue.next;
|
||||
while (pqp != &ch.rlist.pqueue) {
|
||||
n++;
|
||||
tp = tp->queue.next;
|
||||
pqp = pqp->next;
|
||||
}
|
||||
|
||||
/* Scanning the ready list backward.*/
|
||||
tp = ch.rlist.queue.prev;
|
||||
while (tp != (thread_t *)&ch.rlist.queue) {
|
||||
pqp = ch.rlist.pqueue.prev;
|
||||
while (pqp != &ch.rlist.pqueue) {
|
||||
n--;
|
||||
tp = tp->queue.prev;
|
||||
pqp = pqp->prev;
|
||||
}
|
||||
|
||||
/* The number of elements must match.*/
|
||||
|
@ -261,21 +261,21 @@ bool chSysIntegrityCheckI(unsigned testmask) {
|
|||
|
||||
/* Timers list integrity check.*/
|
||||
if ((testmask & CH_INTEGRITY_VTLIST) != 0U) {
|
||||
virtual_timer_t * vtp;
|
||||
delta_list_t *dlp;
|
||||
|
||||
/* Scanning the timers list forward.*/
|
||||
n = (cnt_t)0;
|
||||
vtp = ch.vtlist.next;
|
||||
while (vtp != (virtual_timer_t *)&ch.vtlist) {
|
||||
dlp = ch.vtlist.dlist.next;
|
||||
while (dlp != &ch.vtlist.dlist) {
|
||||
n++;
|
||||
vtp = vtp->next;
|
||||
dlp = dlp->next;
|
||||
}
|
||||
|
||||
/* Scanning the timers list backward.*/
|
||||
vtp = ch.vtlist.prev;
|
||||
while (vtp != (virtual_timer_t *)&ch.vtlist) {
|
||||
dlp = ch.vtlist.dlist.prev;
|
||||
while (dlp != &ch.vtlist.dlist) {
|
||||
n--;
|
||||
vtp = vtp->prev;
|
||||
dlp = dlp->prev;
|
||||
}
|
||||
|
||||
/* The number of elements must match.*/
|
||||
|
|
|
@ -87,34 +87,34 @@
|
|||
*/
|
||||
thread_t *_thread_init(thread_t *tp, const char *name, tprio_t prio) {
|
||||
|
||||
tp->prio = prio;
|
||||
tp->state = CH_STATE_WTSTART;
|
||||
tp->flags = CH_FLAG_MODE_STATIC;
|
||||
tp->hdr.pqueue.prio = prio;
|
||||
tp->state = CH_STATE_WTSTART;
|
||||
tp->flags = CH_FLAG_MODE_STATIC;
|
||||
#if CH_CFG_TIME_QUANTUM > 0
|
||||
tp->ticks = (tslices_t)CH_CFG_TIME_QUANTUM;
|
||||
tp->ticks = (tslices_t)CH_CFG_TIME_QUANTUM;
|
||||
#endif
|
||||
#if CH_CFG_USE_MUTEXES == TRUE
|
||||
tp->realprio = prio;
|
||||
tp->mtxlist = NULL;
|
||||
tp->realprio = prio;
|
||||
tp->mtxlist = NULL;
|
||||
#endif
|
||||
#if CH_CFG_USE_EVENTS == TRUE
|
||||
tp->epending = (eventmask_t)0;
|
||||
tp->epending = (eventmask_t)0;
|
||||
#endif
|
||||
#if CH_DBG_THREADS_PROFILING == TRUE
|
||||
tp->time = (systime_t)0;
|
||||
tp->time = (systime_t)0;
|
||||
#endif
|
||||
#if CH_CFG_USE_REGISTRY == TRUE
|
||||
tp->refs = (trefs_t)1;
|
||||
tp->name = name;
|
||||
tp->refs = (trefs_t)1;
|
||||
tp->name = name;
|
||||
REG_INSERT(tp);
|
||||
#else
|
||||
(void)name;
|
||||
#endif
|
||||
#if CH_CFG_USE_WAITEXIT == TRUE
|
||||
list_init(&tp->waiting);
|
||||
ch_list_init(&tp->waiting);
|
||||
#endif
|
||||
#if CH_CFG_USE_MESSAGES == TRUE
|
||||
queue_init(&tp->msgqueue);
|
||||
ch_queue_init(&tp->msgqueue);
|
||||
#endif
|
||||
#if CH_DBG_STATISTICS == TRUE
|
||||
chTMObjectInit(&tp->stats);
|
||||
|
@ -509,8 +509,8 @@ void chThdExitS(msg_t msg) {
|
|||
|
||||
#if CH_CFG_USE_WAITEXIT == TRUE
|
||||
/* Waking up any waiting thread.*/
|
||||
while (list_notempty(&tp->waiting)) {
|
||||
(void) chSchReadyI(list_remove(&tp->waiting));
|
||||
while (ch_list_notempty(&tp->waiting)) {
|
||||
(void) chSchReadyI((thread_t *)ch_list_pop(&tp->waiting));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -568,7 +568,7 @@ msg_t chThdWait(thread_t *tp) {
|
|||
#endif
|
||||
|
||||
if (tp->state != CH_STATE_FINAL) {
|
||||
list_insert(currp, &tp->waiting);
|
||||
ch_list_push(&currp->hdr.list, &tp->waiting);
|
||||
chSchGoSleepS(CH_STATE_WTEXIT);
|
||||
}
|
||||
msg = tp->u.exitcode;
|
||||
|
@ -603,13 +603,14 @@ tprio_t chThdSetPriority(tprio_t newprio) {
|
|||
chSysLock();
|
||||
#if CH_CFG_USE_MUTEXES == TRUE
|
||||
oldprio = currp->realprio;
|
||||
if ((currp->prio == currp->realprio) || (newprio > currp->prio)) {
|
||||
currp->prio = newprio;
|
||||
if ((currp->hdr.pqueue.prio == currp->realprio) ||
|
||||
(newprio > currp->hdr.pqueue.prio)) {
|
||||
currp->hdr.pqueue.prio = newprio;
|
||||
}
|
||||
currp->realprio = newprio;
|
||||
#else
|
||||
oldprio = currp->prio;
|
||||
currp->prio = newprio;
|
||||
oldprio = currp->hdr.pqueue.prio;
|
||||
currp->hdr.pqueue.prio = newprio;
|
||||
#endif
|
||||
chSchRescheduleS();
|
||||
chSysUnlock();
|
||||
|
@ -867,7 +868,7 @@ msg_t chThdEnqueueTimeoutS(threads_queue_t *tqp, sysinterval_t timeout) {
|
|||
return MSG_TIMEOUT;
|
||||
}
|
||||
|
||||
queue_insert(currp, tqp);
|
||||
ch_queue_insert(&currp->hdr.queue, &tqp->queue);
|
||||
|
||||
return chSchGoSleepTimeoutS(CH_STATE_QUEUED, timeout);
|
||||
}
|
||||
|
@ -883,7 +884,7 @@ msg_t chThdEnqueueTimeoutS(threads_queue_t *tqp, sysinterval_t timeout) {
|
|||
*/
|
||||
void chThdDequeueNextI(threads_queue_t *tqp, msg_t msg) {
|
||||
|
||||
if (queue_notempty(tqp)) {
|
||||
if (ch_queue_notempty(&tqp->queue)) {
|
||||
chThdDoDequeueNextI(tqp, msg);
|
||||
}
|
||||
}
|
||||
|
@ -898,7 +899,7 @@ void chThdDequeueNextI(threads_queue_t *tqp, msg_t msg) {
|
|||
*/
|
||||
void chThdDequeueAllI(threads_queue_t *tqp, msg_t msg) {
|
||||
|
||||
while (queue_notempty(tqp)) {
|
||||
while (ch_queue_notempty(&tqp->queue)) {
|
||||
chThdDoDequeueNextI(tqp, msg);
|
||||
}
|
||||
}
|
||||
|
|
227
os/rt/src/chvt.c
227
os/rt/src/chvt.c
|
@ -32,45 +32,6 @@
|
|||
/* Module local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief List empty check.
|
||||
*
|
||||
* @param[in] vtlp pointer to the list header
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define is_vtlist_empty(vtlp) ((vtlp) == (virtual_timers_list_t *)(vtlp)->next)
|
||||
|
||||
/**
|
||||
* @brief Last timer in the list check.
|
||||
*
|
||||
* @param[in] vtlp pointer to the list header
|
||||
* @param[in] vtp pointer to the timer header
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define is_last_timer(vtlp, vtp) ((vtp)->next == (virtual_timer_t *)(vtlp))
|
||||
|
||||
/**
|
||||
* @brief Fist timer in the list check.
|
||||
*
|
||||
* @param[in] vtlp pointer to the list header
|
||||
* @param[in] vtp pointer to the timer header
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define is_first_timer(vtlp, vtp) ((vtlp)->next == (vtp))
|
||||
|
||||
/**
|
||||
* @brief Timer check.
|
||||
*
|
||||
* @param[in] vtlp pointer to the list header
|
||||
* @param[in] vtp pointer to the timer header
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define is_timer(vtlp, vtp) ((vtp) != (virtual_timer_t *)(vtlp))
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
@ -87,7 +48,58 @@
|
|||
/* Module local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief List empty check.
|
||||
*
|
||||
* @param[in] dlhp pointer to the delta list header
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline bool is_vtlist_empty(delta_list_t *dlhp) {
|
||||
|
||||
return (bool)(dlhp == dlhp->next);
|
||||
}
|
||||
|
||||
#if (CH_CFG_ST_TIMEDELTA > 0) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Last timer in the list check.
|
||||
*
|
||||
* @param[in] dlhp pointer to the delta list header
|
||||
* @param[in] dlp pointer to the delta list element
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline bool is_last_timer(delta_list_t *dlhp, delta_list_t *dlp) {
|
||||
|
||||
return (bool)(dlp->next == dlhp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Fist timer in the list check.
|
||||
*
|
||||
* @param[in] dlhp pointer to the delta list header
|
||||
* @param[in] dlp pointer to the delta list element
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline bool is_first_timer(delta_list_t *dlhp, delta_list_t *dlp) {
|
||||
|
||||
return (bool)(dlhp->next == dlp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Timer check.
|
||||
*
|
||||
* @param[in] dlhp pointer to the delta list header
|
||||
* @param[in] dlp pointer to the delta list element
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline bool is_timer(delta_list_t *dlhp, delta_list_t *dlp) {
|
||||
|
||||
return (bool)(dlp != dlhp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Delta list compression.
|
||||
*
|
||||
|
@ -98,21 +110,21 @@
|
|||
*/
|
||||
static void vt_list_compress(virtual_timers_list_t *vtlp,
|
||||
sysinterval_t deltanow) {
|
||||
virtual_timer_t *vtp = vtlp->next;
|
||||
delta_list_t *dlp = vtlp->dlist.next;
|
||||
|
||||
/* The loop is bounded because the delta list header has the delta field
|
||||
set to (sysinterval_t)-1 which is larger than all deltas.*/
|
||||
while (vtp->delta < deltanow) {
|
||||
deltanow -= vtp->delta;
|
||||
vtp->delta = (sysinterval_t)0;
|
||||
vtp = vtp->next;
|
||||
while (dlp->delta < deltanow) {
|
||||
deltanow -= dlp->delta;
|
||||
dlp->delta = (sysinterval_t)0;
|
||||
dlp = dlp->next;
|
||||
}
|
||||
|
||||
vtlp->lasttime = vtlp->lasttime + deltanow;
|
||||
|
||||
/* Adjusting next timer in the list, if any.*/
|
||||
if (is_timer(vtlp, vtp)) {
|
||||
vtp->delta -= deltanow;
|
||||
if (is_timer(&vtlp->dlist, dlp)) {
|
||||
dlp->delta -= deltanow;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -129,9 +141,9 @@ static void vt_list_compress(virtual_timers_list_t *vtlp,
|
|||
*/
|
||||
void _vt_init(void) {
|
||||
|
||||
ch.vtlist.next = (virtual_timer_t *)&ch.vtlist;
|
||||
ch.vtlist.prev = (virtual_timer_t *)&ch.vtlist;
|
||||
ch.vtlist.delta = (sysinterval_t)-1;
|
||||
ch.vtlist.dlist.next = &ch.vtlist.dlist;
|
||||
ch.vtlist.dlist.prev = &ch.vtlist.dlist;
|
||||
ch.vtlist.dlist.delta = (sysinterval_t)-1;
|
||||
#if CH_CFG_ST_TIMEDELTA == 0
|
||||
ch.vtlist.systime = (systime_t)0;
|
||||
#else /* CH_CFG_ST_TIMEDELTA > 0 */
|
||||
|
@ -164,7 +176,7 @@ void _vt_init(void) {
|
|||
void chVTDoSetI(virtual_timer_t *vtp, sysinterval_t delay,
|
||||
vtfunc_t vtfunc, void *par) {
|
||||
virtual_timers_list_t *vtlp = &ch.vtlist;
|
||||
virtual_timer_t *p;
|
||||
delta_list_t *dlp;
|
||||
sysinterval_t delta;
|
||||
|
||||
chDbgCheckClassI();
|
||||
|
@ -185,16 +197,16 @@ void chVTDoSetI(virtual_timer_t *vtp, sysinterval_t delay,
|
|||
}
|
||||
|
||||
/* Special case where the timers list is empty.*/
|
||||
if (is_vtlist_empty(vtlp)) {
|
||||
if (is_vtlist_empty(&vtlp->dlist)) {
|
||||
|
||||
/* The delta list is empty, the current time becomes the new
|
||||
delta list base time, the timer is inserted.*/
|
||||
vtlp->lasttime = now;
|
||||
vtlp->next = vtp;
|
||||
vtlp->prev = vtp;
|
||||
vtp->next = (virtual_timer_t *)vtlp;
|
||||
vtp->prev = (virtual_timer_t *)vtlp;
|
||||
vtp->delta = delay;
|
||||
vtlp->dlist.next = &vtp->dlist;
|
||||
vtlp->dlist.prev = &vtp->dlist;
|
||||
vtp->dlist.next = &vtlp->dlist;
|
||||
vtp->dlist.prev = &vtlp->dlist;
|
||||
vtp->dlist.delta = delay;
|
||||
|
||||
#if CH_CFG_INTERVALS_SIZE > CH_CFG_ST_RESOLUTION
|
||||
/* The delta could be too large for the physical timer to handle.*/
|
||||
|
@ -220,7 +232,7 @@ void chVTDoSetI(virtual_timer_t *vtp, sysinterval_t delay,
|
|||
vt_list_compress(vtlp, deltanow);
|
||||
delta -= deltanow;
|
||||
}
|
||||
else if (delta < vtlp->next->delta) {
|
||||
else if (delta < vtlp->dlist.next->delta) {
|
||||
sysinterval_t deadline_delta;
|
||||
|
||||
/* A small delay that will become the first element in the delta list
|
||||
|
@ -242,28 +254,28 @@ void chVTDoSetI(virtual_timer_t *vtp, sysinterval_t delay,
|
|||
|
||||
/* The delta list is scanned in order to find the correct position for
|
||||
this timer. */
|
||||
p = vtlp->next;
|
||||
while (p->delta < delta) {
|
||||
dlp = vtlp->dlist.next;
|
||||
while (dlp->delta < delta) {
|
||||
/* Debug assert if the timer is already in the list.*/
|
||||
chDbgAssert(p != vtp, "timer already armed");
|
||||
chDbgAssert(dlp != &vtp->dlist, "timer already armed");
|
||||
|
||||
delta -= p->delta;
|
||||
p = p->next;
|
||||
delta -= dlp->delta;
|
||||
dlp = dlp->next;
|
||||
}
|
||||
|
||||
/* The timer is inserted in the delta list.*/
|
||||
vtp->next = p;
|
||||
vtp->prev = vtp->next->prev;
|
||||
vtp->prev->next = vtp;
|
||||
p->prev = vtp;
|
||||
vtp->delta = delta;
|
||||
vtp->dlist.next = dlp;
|
||||
vtp->dlist.prev = vtp->dlist.next->prev;
|
||||
vtp->dlist.prev->next = &vtp->dlist;
|
||||
dlp->prev = &vtp->dlist;
|
||||
vtp->dlist.delta = delta;
|
||||
|
||||
/* Calculate new delta for the following entry.*/
|
||||
p->delta -= delta;
|
||||
dlp->delta -= delta;
|
||||
|
||||
/* Special case when the timer is in last position in the list, the
|
||||
value in the header must be restored.*/
|
||||
vtlp->delta = (sysinterval_t)-1;
|
||||
vtlp->dlist.delta = (sysinterval_t)-1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -284,52 +296,52 @@ void chVTDoResetI(virtual_timer_t *vtp) {
|
|||
#if CH_CFG_ST_TIMEDELTA == 0
|
||||
|
||||
/* The delta of the timer is added to the next timer.*/
|
||||
vtp->next->delta += vtp->delta;
|
||||
vtp->dlist.next->delta += vtp->dlist.delta;
|
||||
|
||||
/* Removing the element from the delta list.*/
|
||||
vtp->prev->next = vtp->next;
|
||||
vtp->next->prev = vtp->prev;
|
||||
vtp->dlist.prev->next = vtp->dlist.next;
|
||||
vtp->dlist.next->prev = vtp->dlist.prev;
|
||||
vtp->func = NULL;
|
||||
|
||||
/* The above code changes the value in the header when the removed element
|
||||
is the last of the list, restoring it.*/
|
||||
vtlp->delta = (sysinterval_t)-1;
|
||||
vtlp->dlist.delta = (sysinterval_t)-1;
|
||||
#else /* CH_CFG_ST_TIMEDELTA > 0 */
|
||||
sysinterval_t nowdelta, delta;
|
||||
|
||||
/* If the timer is not the first of the list then it is simply unlinked
|
||||
else the operation is more complex.*/
|
||||
if (!is_first_timer(vtlp, vtp)) {
|
||||
if (!is_first_timer(&vtlp->dlist, &vtp->dlist)) {
|
||||
/* Removing the element from the delta list.*/
|
||||
vtp->prev->next = vtp->next;
|
||||
vtp->next->prev = vtp->prev;
|
||||
vtp->dlist.prev->next = vtp->dlist.next;
|
||||
vtp->dlist.next->prev = vtp->dlist.prev;
|
||||
vtp->func = NULL;
|
||||
|
||||
/* Adding delta to the next element, if it is not the last one.*/
|
||||
if (is_timer(vtlp, vtp->next))
|
||||
vtp->next->delta += vtp->delta;
|
||||
if (is_timer(&vtlp->dlist, vtp->dlist.next))
|
||||
vtp->dlist.next->delta += vtp->dlist.delta;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Removing the first timer from the list.*/
|
||||
vtlp->next = vtp->next;
|
||||
vtlp->next->prev = (virtual_timer_t *)vtlp;
|
||||
vtlp->dlist.next = vtp->dlist.next;
|
||||
vtlp->dlist.next->prev = &vtlp->dlist;
|
||||
vtp->func = NULL;
|
||||
|
||||
/* If the list become empty then the alarm timer is stopped and done.*/
|
||||
if (is_vtlist_empty(vtlp)) {
|
||||
if (is_vtlist_empty(&vtlp->dlist)) {
|
||||
port_timer_stop_alarm();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* The delta of the removed timer is added to the new first timer.*/
|
||||
vtlp->next->delta += vtp->delta;
|
||||
vtlp->dlist.next->delta += vtp->dlist.delta;
|
||||
|
||||
/* If the new first timer has a delta of zero then the alarm is not
|
||||
modified, the already programmed alarm will serve it.*/
|
||||
/* if (vtlp->next->delta == 0) {
|
||||
/* if (vtlp->dlist.next->delta == 0) {
|
||||
return;
|
||||
}*/
|
||||
|
||||
|
@ -338,12 +350,12 @@ void chVTDoResetI(virtual_timer_t *vtp) {
|
|||
|
||||
/* If the current time surpassed the time of the next element in list
|
||||
then the event interrupt is already pending, just return.*/
|
||||
if (nowdelta >= vtlp->next->delta) {
|
||||
if (nowdelta >= vtlp->dlist.next->delta) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Distance from the next scheduled event and now.*/
|
||||
delta = vtlp->next->delta - nowdelta;
|
||||
delta = vtlp->dlist.next->delta - nowdelta;
|
||||
|
||||
/* Making sure to not schedule an event closer than CH_CFG_ST_TIMEDELTA
|
||||
ticks from now.*/
|
||||
|
@ -379,30 +391,30 @@ void chVTDoTickI(void) {
|
|||
|
||||
#if CH_CFG_ST_TIMEDELTA == 0
|
||||
vtlp->systime++;
|
||||
if (!is_vtlist_empty(vtlp)) {
|
||||
if (!is_vtlist_empty(&vtlp->dlist)) {
|
||||
/* The list is not empty, processing elements on top.*/
|
||||
--vtlp->next->delta;
|
||||
while (vtlp->next->delta == (sysinterval_t)0) {
|
||||
--vtlp->dlist.next->delta;
|
||||
while (vtlp->dlist.next->delta == (sysinterval_t)0) {
|
||||
virtual_timer_t *vtp;
|
||||
vtfunc_t fn;
|
||||
|
||||
vtp = vtlp->next;
|
||||
vtp = (virtual_timer_t *)vtlp->dlist.next;
|
||||
fn = vtp->func;
|
||||
vtp->func = NULL;
|
||||
vtp->next->prev = (virtual_timer_t *)vtlp;
|
||||
vtlp->next = vtp->next;
|
||||
vtp->dlist.next->prev = &vtlp->dlist;
|
||||
vtlp->dlist.next = vtp->dlist.next;
|
||||
chSysUnlockFromISR();
|
||||
fn(vtp->par);
|
||||
chSysLockFromISR();
|
||||
}
|
||||
}
|
||||
#else /* CH_CFG_ST_TIMEDELTA > 0 */
|
||||
virtual_timer_t *vtp;
|
||||
delta_list_t *dlp;
|
||||
systime_t now;
|
||||
sysinterval_t delta, nowdelta;
|
||||
|
||||
/* Looping through timers.*/
|
||||
vtp = vtlp->next;
|
||||
dlp = vtlp->dlist.next;
|
||||
while (true) {
|
||||
|
||||
/* Getting the system time as reference.*/
|
||||
|
@ -410,27 +422,32 @@ void chVTDoTickI(void) {
|
|||
nowdelta = chTimeDiffX(vtlp->lasttime, now);
|
||||
|
||||
/* The list scan is limited by the timers header having
|
||||
"vtlp->vt_delta == (sysinterval_t)-1" which is
|
||||
"vtlp->dlist.delta == (sysinterval_t)-1" which is
|
||||
greater than all deltas.*/
|
||||
if (nowdelta < vtp->delta) {
|
||||
if (nowdelta < dlp->delta) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Consuming all timers between "vtp->lasttime" and now.*/
|
||||
do {
|
||||
vtfunc_t fn;
|
||||
virtual_timer_t *vtp = (virtual_timer_t *)dlp;
|
||||
|
||||
/* The "last time" becomes this timer's expiration time.*/
|
||||
vtlp->lasttime += vtp->delta;
|
||||
nowdelta -= vtp->delta;
|
||||
vtlp->lasttime += dlp->delta;
|
||||
nowdelta -= dlp->delta;
|
||||
|
||||
vtp->next->prev = (virtual_timer_t *)vtlp;
|
||||
vtlp->next = vtp->next;
|
||||
/* Removing the timer from the list.*/
|
||||
dlp->next->prev = &vtlp->dlist;
|
||||
vtlp->dlist.next = dlp->next;
|
||||
|
||||
/* Calling the associated function and then marking the timer as
|
||||
non active.*/
|
||||
fn = vtp->func;
|
||||
vtp->func = NULL;
|
||||
|
||||
/* If the list becomes empty then the timer is stopped.*/
|
||||
if (is_vtlist_empty(vtlp)) {
|
||||
if (is_vtlist_empty(&vtlp->dlist)) {
|
||||
port_timer_stop_alarm();
|
||||
}
|
||||
|
||||
|
@ -440,23 +457,23 @@ void chVTDoTickI(void) {
|
|||
chSysLockFromISR();
|
||||
|
||||
/* Next element in the list.*/
|
||||
vtp = vtlp->next;
|
||||
dlp = vtlp->dlist.next;
|
||||
}
|
||||
while (vtp->delta <= nowdelta);
|
||||
while (dlp->delta <= nowdelta);
|
||||
}
|
||||
|
||||
/* If the list is empty, nothing else to do.*/
|
||||
if (is_vtlist_empty(vtlp)) {
|
||||
if (is_vtlist_empty(&vtlp->dlist)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* The "unprocessed nowdelta" time slice is added to "last time"
|
||||
and subtracted to next timer's delta.*/
|
||||
vtlp->lasttime += nowdelta;
|
||||
vtlp->next->delta -= nowdelta;
|
||||
vtlp->dlist.next->delta -= nowdelta;
|
||||
|
||||
/* Recalculating the next alarm time.*/
|
||||
delta = vtp->delta - chTimeDiffX(vtlp->lasttime, now);
|
||||
delta = dlp->delta - chTimeDiffX(vtlp->lasttime, now);
|
||||
if (delta < (sysinterval_t)CH_CFG_ST_TIMEDELTA) {
|
||||
delta = (sysinterval_t)CH_CFG_ST_TIMEDELTA;
|
||||
}
|
||||
|
|
|
@ -75,6 +75,8 @@
|
|||
|
||||
*** 20.3.3 ***
|
||||
- FIX: Fixed GCC 10 causes warning in factory module (bug #1139).
|
||||
- FIX: Fixed C strict aliasing rules violation causes test cases to fail
|
||||
(bug #1138).
|
||||
- FIX: Fixed STM32H7xx Missing CRC RCC macros (bug #1137).
|
||||
- FIX: Fixed STM32L0x wrong ISR names for USART 4 and 5 (bug #1136).
|
||||
- FIX: Fixed OTG_FS error on STM32H7 (bug #1135).
|
||||
|
|
|
@ -1064,7 +1064,7 @@ test_assert(chThdGetPriorityX() == prio, "unexpected priority level");]]></value
|
|||
</tags>
|
||||
<code>
|
||||
<value><![CDATA[prio = chThdGetPriorityX();
|
||||
chThdGetSelfX()->prio += 2;
|
||||
chThdGetSelfX()->hdr.pqueue.prio += 2;
|
||||
test_assert(chThdGetPriorityX() == prio + 2, "unexpected priority level");]]></value>
|
||||
</code>
|
||||
</step>
|
||||
|
@ -1078,7 +1078,7 @@ test_assert(chThdGetPriorityX() == prio + 2, "unexpected priority level");]]></v
|
|||
<code>
|
||||
<value><![CDATA[p1 = chThdSetPriority(prio + 1);
|
||||
test_assert(p1 == prio, "unexpected returned priority level");
|
||||
test_assert(chThdGetSelfX()->prio == prio + 2, "unexpected priority level");
|
||||
test_assert(chThdGetSelfX()->hdr.pqueue.prio == prio + 2, "unexpected priority level");
|
||||
test_assert(chThdGetSelfX()->realprio == prio + 1, "unexpected returned real priority level");]]></value>
|
||||
</code>
|
||||
</step>
|
||||
|
@ -1092,7 +1092,7 @@ test_assert(chThdGetSelfX()->realprio == prio + 1, "unexpected returned real pri
|
|||
<code>
|
||||
<value><![CDATA[p1 = chThdSetPriority(prio + 3);
|
||||
test_assert(p1 == prio + 1, "unexpected returned priority level");
|
||||
test_assert(chThdGetSelfX()->prio == prio + 3, "unexpected priority level");
|
||||
test_assert(chThdGetSelfX()->hdr.pqueue.prio == prio + 3, "unexpected priority level");
|
||||
test_assert(chThdGetSelfX()->realprio == prio + 3, "unexpected real priority level");]]></value>
|
||||
</code>
|
||||
</step>
|
||||
|
@ -1105,7 +1105,7 @@ test_assert(chThdGetSelfX()->realprio == prio + 3, "unexpected real priority lev
|
|||
</tags>
|
||||
<code>
|
||||
<value><![CDATA[chSysLock();
|
||||
chThdGetSelfX()->prio = prio;
|
||||
chThdGetSelfX()->hdr.pqueue.prio = prio;
|
||||
chThdGetSelfX()->realprio = prio;
|
||||
chSysUnlock();]]></value>
|
||||
</code>
|
||||
|
@ -1407,7 +1407,7 @@ msg_t msg;]]></value>
|
|||
<code>
|
||||
<value><![CDATA[msg = chSemWaitTimeout(&sem1, TIME_IMMEDIATE);
|
||||
test_assert(msg == MSG_TIMEOUT, "wrong wake-up message");
|
||||
test_assert(queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(ch_queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(sem1.cnt == 0, "counter not zero");]]></value>
|
||||
</code>
|
||||
</step>
|
||||
|
@ -1424,7 +1424,7 @@ test_assert(sem1.cnt == 0, "counter not zero");]]></value>
|
|||
msg = chSemWaitTimeout(&sem1, TIME_MS2I(500));
|
||||
test_wait_threads();
|
||||
test_assert(msg == MSG_OK, "wrong wake-up message");
|
||||
test_assert(queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(ch_queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(sem1.cnt == 0, "counter not zero");]]></value>
|
||||
</code>
|
||||
</step>
|
||||
|
@ -1441,7 +1441,7 @@ for (i = 0; i < 5; i++) {
|
|||
test_emit_token('A' + i);
|
||||
msg = chSemWaitTimeout(&sem1, TIME_MS2I(50));
|
||||
test_assert(msg == MSG_TIMEOUT, "wrong wake-up message");
|
||||
test_assert(queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(ch_queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(sem1.cnt == 0, "counter not zero");
|
||||
}
|
||||
test_assert_sequence("ABCDE", "invalid sequence");
|
||||
|
@ -1546,7 +1546,7 @@ test_assert_sequence("A", "invalid sequence");]]></value>
|
|||
</tags>
|
||||
<code>
|
||||
<value><![CDATA[chSemSignalWait(&sem1, &sem1);
|
||||
test_assert(queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(ch_queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(sem1.cnt == 0, "counter not zero");]]></value>
|
||||
</code>
|
||||
</step>
|
||||
|
@ -1559,7 +1559,7 @@ test_assert(sem1.cnt == 0, "counter not zero");]]></value>
|
|||
</tags>
|
||||
<code>
|
||||
<value><![CDATA[chSemSignalWait(&sem1, &sem1);
|
||||
test_assert(queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(ch_queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(sem1.cnt == 0, "counter not zero");]]></value>
|
||||
</code>
|
||||
</step>
|
||||
|
@ -2251,7 +2251,7 @@ test_assert(!b, "not locked");]]></value>
|
|||
<code>
|
||||
<value><![CDATA[chMtxUnlock(&m1);
|
||||
test_assert(m1.owner == NULL, "still owned");
|
||||
test_assert(queue_isempty(&m1.queue), "queue not empty");]]></value>
|
||||
test_assert(ch_queue_isempty(&m1.queue), "queue not empty");]]></value>
|
||||
</code>
|
||||
</step>
|
||||
<step>
|
||||
|
@ -2280,7 +2280,7 @@ test_assert(!b, "not locked");
|
|||
|
||||
chMtxUnlockAll();
|
||||
test_assert(m1.owner == NULL, "still owned");
|
||||
test_assert(queue_isempty(&m1.queue), "queue not empty");]]></value>
|
||||
test_assert(ch_queue_isempty(&m1.queue), "queue not empty");]]></value>
|
||||
</code>
|
||||
</step>
|
||||
<step>
|
||||
|
@ -2376,7 +2376,7 @@ test_assert(m1.owner != NULL, "not owned");]]></value>
|
|||
<code>
|
||||
<value><![CDATA[chMtxUnlock(&m1);
|
||||
test_assert(m1.owner == NULL, "still owned");
|
||||
test_assert(queue_isempty(&m1.queue), "queue not empty");]]></value>
|
||||
test_assert(ch_queue_isempty(&m1.queue), "queue not empty");]]></value>
|
||||
</code>
|
||||
</step>
|
||||
<step>
|
||||
|
@ -2409,7 +2409,7 @@ chSysLock();
|
|||
chMtxUnlockAllS();
|
||||
chSysUnlock();
|
||||
test_assert(m1.owner == NULL, "still owned");
|
||||
test_assert(queue_isempty(&m1.queue), "queue not empty");
|
||||
test_assert(ch_queue_isempty(&m1.queue), "queue not empty");
|
||||
test_assert(m1.cnt == 0, "invalid recursion counter");]]></value>
|
||||
</code>
|
||||
</step>
|
||||
|
@ -2430,7 +2430,7 @@ test_assert(m1.owner != NULL, "not owned");
|
|||
test_assert(m1.cnt == 2, "invalid recursion counter");
|
||||
chMtxUnlockAll();
|
||||
test_assert(m1.owner == NULL, "still owned");
|
||||
test_assert(queue_isempty(&m1.queue), "queue not empty");
|
||||
test_assert(ch_queue_isempty(&m1.queue), "queue not empty");
|
||||
test_assert(m1.cnt == 0, "invalid recursion counter");]]></value>
|
||||
</code>
|
||||
</step>
|
||||
|
|
|
@ -294,7 +294,7 @@ static void rt_test_004_004_execute(void) {
|
|||
test_set_step(1);
|
||||
{
|
||||
prio = chThdGetPriorityX();
|
||||
chThdGetSelfX()->prio += 2;
|
||||
chThdGetSelfX()->hdr.pqueue.prio += 2;
|
||||
test_assert(chThdGetPriorityX() == prio + 2, "unexpected priority level");
|
||||
}
|
||||
test_end_step(1);
|
||||
|
@ -305,7 +305,7 @@ static void rt_test_004_004_execute(void) {
|
|||
{
|
||||
p1 = chThdSetPriority(prio + 1);
|
||||
test_assert(p1 == prio, "unexpected returned priority level");
|
||||
test_assert(chThdGetSelfX()->prio == prio + 2, "unexpected priority level");
|
||||
test_assert(chThdGetSelfX()->hdr.pqueue.prio == prio + 2, "unexpected priority level");
|
||||
test_assert(chThdGetSelfX()->realprio == prio + 1, "unexpected returned real priority level");
|
||||
}
|
||||
test_end_step(2);
|
||||
|
@ -315,7 +315,7 @@ static void rt_test_004_004_execute(void) {
|
|||
{
|
||||
p1 = chThdSetPriority(prio + 3);
|
||||
test_assert(p1 == prio + 1, "unexpected returned priority level");
|
||||
test_assert(chThdGetSelfX()->prio == prio + 3, "unexpected priority level");
|
||||
test_assert(chThdGetSelfX()->hdr.pqueue.prio == prio + 3, "unexpected priority level");
|
||||
test_assert(chThdGetSelfX()->realprio == prio + 3, "unexpected real priority level");
|
||||
}
|
||||
test_end_step(3);
|
||||
|
@ -324,7 +324,7 @@ static void rt_test_004_004_execute(void) {
|
|||
test_set_step(4);
|
||||
{
|
||||
chSysLock();
|
||||
chThdGetSelfX()->prio = prio;
|
||||
chThdGetSelfX()->hdr.pqueue.prio = prio;
|
||||
chThdGetSelfX()->realprio = prio;
|
||||
chSysUnlock();
|
||||
}
|
||||
|
|
|
@ -246,7 +246,7 @@ static void rt_test_006_003_execute(void) {
|
|||
{
|
||||
msg = chSemWaitTimeout(&sem1, TIME_IMMEDIATE);
|
||||
test_assert(msg == MSG_TIMEOUT, "wrong wake-up message");
|
||||
test_assert(queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(ch_queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(sem1.cnt == 0, "counter not zero");
|
||||
}
|
||||
test_end_step(1);
|
||||
|
@ -259,7 +259,7 @@ static void rt_test_006_003_execute(void) {
|
|||
msg = chSemWaitTimeout(&sem1, TIME_MS2I(500));
|
||||
test_wait_threads();
|
||||
test_assert(msg == MSG_OK, "wrong wake-up message");
|
||||
test_assert(queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(ch_queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(sem1.cnt == 0, "counter not zero");
|
||||
}
|
||||
test_end_step(2);
|
||||
|
@ -272,7 +272,7 @@ static void rt_test_006_003_execute(void) {
|
|||
test_emit_token('A' + i);
|
||||
msg = chSemWaitTimeout(&sem1, TIME_MS2I(50));
|
||||
test_assert(msg == MSG_TIMEOUT, "wrong wake-up message");
|
||||
test_assert(queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(ch_queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(sem1.cnt == 0, "counter not zero");
|
||||
}
|
||||
test_assert_sequence("ABCDE", "invalid sequence");
|
||||
|
@ -386,7 +386,7 @@ static void rt_test_006_005_execute(void) {
|
|||
test_set_step(2);
|
||||
{
|
||||
chSemSignalWait(&sem1, &sem1);
|
||||
test_assert(queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(ch_queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(sem1.cnt == 0, "counter not zero");
|
||||
}
|
||||
test_end_step(2);
|
||||
|
@ -397,7 +397,7 @@ static void rt_test_006_005_execute(void) {
|
|||
test_set_step(3);
|
||||
{
|
||||
chSemSignalWait(&sem1, &sem1);
|
||||
test_assert(queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(ch_queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(sem1.cnt == 0, "counter not zero");
|
||||
}
|
||||
test_end_step(3);
|
||||
|
|
|
@ -648,7 +648,7 @@ static void rt_test_007_005_execute(void) {
|
|||
{
|
||||
chMtxUnlock(&m1);
|
||||
test_assert(m1.owner == NULL, "still owned");
|
||||
test_assert(queue_isempty(&m1.queue), "queue not empty");
|
||||
test_assert(ch_queue_isempty(&m1.queue), "queue not empty");
|
||||
}
|
||||
test_end_step(4);
|
||||
|
||||
|
@ -669,7 +669,7 @@ static void rt_test_007_005_execute(void) {
|
|||
|
||||
chMtxUnlockAll();
|
||||
test_assert(m1.owner == NULL, "still owned");
|
||||
test_assert(queue_isempty(&m1.queue), "queue not empty");
|
||||
test_assert(ch_queue_isempty(&m1.queue), "queue not empty");
|
||||
}
|
||||
test_end_step(6);
|
||||
|
||||
|
@ -770,7 +770,7 @@ static void rt_test_007_006_execute(void) {
|
|||
{
|
||||
chMtxUnlock(&m1);
|
||||
test_assert(m1.owner == NULL, "still owned");
|
||||
test_assert(queue_isempty(&m1.queue), "queue not empty");
|
||||
test_assert(ch_queue_isempty(&m1.queue), "queue not empty");
|
||||
}
|
||||
test_end_step(5);
|
||||
|
||||
|
@ -796,7 +796,7 @@ static void rt_test_007_006_execute(void) {
|
|||
chMtxUnlockAllS();
|
||||
chSysUnlock();
|
||||
test_assert(m1.owner == NULL, "still owned");
|
||||
test_assert(queue_isempty(&m1.queue), "queue not empty");
|
||||
test_assert(ch_queue_isempty(&m1.queue), "queue not empty");
|
||||
test_assert(m1.cnt == 0, "invalid recursion counter");
|
||||
}
|
||||
test_end_step(7);
|
||||
|
@ -814,7 +814,7 @@ static void rt_test_007_006_execute(void) {
|
|||
test_assert(m1.cnt == 2, "invalid recursion counter");
|
||||
chMtxUnlockAll();
|
||||
test_assert(m1.owner == NULL, "still owned");
|
||||
test_assert(queue_isempty(&m1.queue), "queue not empty");
|
||||
test_assert(ch_queue_isempty(&m1.queue), "queue not empty");
|
||||
test_assert(m1.cnt == 0, "invalid recursion counter");
|
||||
}
|
||||
test_end_step(8);
|
||||
|
|
Loading…
Reference in New Issue