2015-05-14 16:05:04 -04:00
|
|
|
/// @file
|
|
|
|
/// @brief platform-independent priority sets of 8 or 64 elements.
|
|
|
|
/// @ingroup qf
|
|
|
|
/// @cond
|
2014-04-13 21:35:34 -04:00
|
|
|
///***************************************************************************
|
2016-09-29 19:54:50 -04:00
|
|
|
/// Last updated for version 5.7.2
|
|
|
|
/// Last updated on 2016-09-26
|
2014-04-13 21:35:34 -04:00
|
|
|
///
|
|
|
|
/// Q u a n t u m L e a P s
|
|
|
|
/// ---------------------------
|
|
|
|
/// innovating embedded systems
|
|
|
|
///
|
2015-12-31 14:56:37 -05:00
|
|
|
/// Copyright (C) Quantum Leaps. All rights reserved.
|
2012-08-14 18:00:48 -04:00
|
|
|
///
|
2014-04-13 21:35:34 -04:00
|
|
|
/// This program is open source 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.
|
|
|
|
///
|
|
|
|
/// Alternatively, this program may be distributed and modified under the
|
|
|
|
/// terms of Quantum Leaps commercial licenses, which expressly supersede
|
|
|
|
/// the GNU General Public License and are specifically designed for
|
|
|
|
/// licensees interested in retaining the proprietary status of their code.
|
|
|
|
///
|
|
|
|
/// This program 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/>.
|
|
|
|
///
|
|
|
|
/// Contact information:
|
2015-12-31 14:56:37 -05:00
|
|
|
/// http://www.state-machine.com
|
|
|
|
/// mailto:info@state-machine.com
|
2014-04-13 21:35:34 -04:00
|
|
|
///***************************************************************************
|
2015-05-14 16:05:04 -04:00
|
|
|
/// @endcond
|
2014-04-13 21:35:34 -04:00
|
|
|
|
|
|
|
#ifndef qpset_h
|
|
|
|
#define qpset_h
|
2012-08-14 18:00:48 -04:00
|
|
|
|
2016-09-29 19:54:50 -04:00
|
|
|
#if (QF_MAX_ACTIVE < 1) || (64 < QF_MAX_ACTIVE)
|
|
|
|
#error "QF_MAX_ACTIVE not defined or out of range. Valid range is 1..64"
|
|
|
|
#endif
|
2012-08-14 18:00:48 -04:00
|
|
|
|
2016-09-29 19:54:50 -04:00
|
|
|
namespace QP {
|
2012-08-14 18:00:48 -04:00
|
|
|
|
2016-09-29 19:54:50 -04:00
|
|
|
/****************************************************************************/
|
|
|
|
/* Log-base-2 calculations ...*/
|
2013-02-12 10:02:51 -05:00
|
|
|
#ifndef QF_LOG2
|
|
|
|
|
2016-09-29 19:54:50 -04:00
|
|
|
//! Lookup table for (log2(n) + 1), where n = 0..255 */
|
|
|
|
///
|
2015-05-14 16:05:04 -04:00
|
|
|
/// @description
|
2013-02-12 10:02:51 -05:00
|
|
|
/// This lookup delivers the 1-based number of the most significant 1-bit
|
|
|
|
/// of a byte.
|
2015-12-31 14:56:37 -05:00
|
|
|
extern uint8_t const QF_log2Lkup[256];
|
2013-02-12 10:02:51 -05:00
|
|
|
|
2016-09-29 19:54:50 -04:00
|
|
|
//! function that returns (log2(x) + 1), where @p x is uint32_t */
|
|
|
|
///
|
|
|
|
/// @description
|
|
|
|
/// This function returns the 1-based number of the most significant 1-bit
|
|
|
|
/// of a 32-bit number. This function can be replaced in the QP ports, if
|
|
|
|
/// the CPU supports special instructions, such as CLZ
|
|
|
|
/// (count leading zeros).
|
|
|
|
///
|
|
|
|
inline uint_fast8_t QF_LOG2(uint32_t const x) {
|
|
|
|
uint_fast8_t n;
|
|
|
|
uint_fast8_t i;
|
|
|
|
|
|
|
|
if ((x >> 16) != static_cast<uint32_t>(0)) {
|
|
|
|
if ((x >> 24) != static_cast<uint32_t>(0)) {
|
|
|
|
i = static_cast<uint_fast8_t>(x >> 24);
|
|
|
|
n = static_cast<uint_fast8_t>(24);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
i = static_cast<uint_fast8_t>(x >> 16);
|
|
|
|
n = static_cast<uint_fast8_t>(16);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if ((x >> 8) != static_cast<uint32_t>(0)) {
|
|
|
|
i = static_cast<uint_fast8_t>(x >> 8);
|
|
|
|
n = static_cast<uint_fast8_t>(8);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
i = static_cast<uint_fast8_t>(x);
|
|
|
|
n = static_cast<uint_fast8_t>(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return static_cast<uint_fast8_t>(QF_log2Lkup[i]) + n;
|
|
|
|
}
|
2012-08-14 18:00:48 -04:00
|
|
|
|
2016-09-29 19:54:50 -04:00
|
|
|
#endif // QF_LOG2
|
2012-08-14 18:00:48 -04:00
|
|
|
|
2013-10-10 20:01:51 -04:00
|
|
|
//****************************************************************************
|
2016-09-29 19:54:50 -04:00
|
|
|
#if (QF_MAX_ACTIVE <= 32)
|
|
|
|
//! Priority Set of up to 32 elements */
|
|
|
|
///
|
2012-08-14 18:00:48 -04:00
|
|
|
/// The priority set represents the set of active objects that are ready to
|
2016-09-29 19:54:50 -04:00
|
|
|
/// run and need to be considered by the scheduling algorithm. The set is
|
|
|
|
/// capable of storing up to 32 priority levels.
|
|
|
|
///
|
|
|
|
class QPSet {
|
2012-08-14 18:00:48 -04:00
|
|
|
|
2016-09-29 19:54:50 -04:00
|
|
|
uint32_t volatile m_bits; //!< bitmask with a bit for each element
|
2012-08-14 18:00:48 -04:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
2016-09-29 19:54:50 -04:00
|
|
|
//! Makes the priority set @p me_ empty.
|
|
|
|
void setEmpty(void) {
|
|
|
|
m_bits = static_cast<uint32_t>(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Evaluates to true if the priority set is empty
|
2012-08-14 18:00:48 -04:00
|
|
|
bool isEmpty(void) const {
|
2016-09-29 19:54:50 -04:00
|
|
|
return (m_bits == static_cast<uint32_t>(0));
|
2012-08-14 18:00:48 -04:00
|
|
|
}
|
|
|
|
|
2016-09-29 19:54:50 -04:00
|
|
|
//! Evaluates to true if the priority set is not empty
|
2012-08-14 18:00:48 -04:00
|
|
|
bool notEmpty(void) const {
|
2016-09-29 19:54:50 -04:00
|
|
|
return (m_bits != static_cast<uint32_t>(0));
|
2012-08-14 18:00:48 -04:00
|
|
|
}
|
|
|
|
|
2014-04-13 21:35:34 -04:00
|
|
|
//! the function evaluates to TRUE if the priority set has the element n.
|
|
|
|
bool hasElement(uint_fast8_t const n) const {
|
2016-09-29 19:54:50 -04:00
|
|
|
return (m_bits & (static_cast<uint32_t>(1)
|
|
|
|
<< (n - static_cast<uint_fast8_t>(1))))
|
|
|
|
!= static_cast<uint32_t>(0);
|
2012-08-14 18:00:48 -04:00
|
|
|
}
|
|
|
|
|
2015-05-14 16:05:04 -04:00
|
|
|
//! insert element @p n into the set, n = 1..8
|
2014-04-13 21:35:34 -04:00
|
|
|
void insert(uint_fast8_t const n) {
|
2016-09-29 19:54:50 -04:00
|
|
|
m_bits |= static_cast<uint32_t>(
|
|
|
|
static_cast<uint32_t>(1) << (n - static_cast<uint_fast8_t>(1)));
|
2012-08-14 18:00:48 -04:00
|
|
|
}
|
|
|
|
|
2015-05-14 16:05:04 -04:00
|
|
|
//! remove element @p n from the set, n = 1..8
|
2014-04-13 21:35:34 -04:00
|
|
|
void remove(uint_fast8_t const n) {
|
2016-09-29 19:54:50 -04:00
|
|
|
m_bits &= static_cast<uint32_t>(
|
|
|
|
~(static_cast<uint32_t>(1) << (n - static_cast<uint_fast8_t>(1))));
|
2012-08-14 18:00:48 -04:00
|
|
|
}
|
|
|
|
|
2014-04-13 21:35:34 -04:00
|
|
|
//! find the maximum element in the set, returns zero if the set is empty
|
|
|
|
uint_fast8_t findMax(void) const {
|
2016-09-29 19:54:50 -04:00
|
|
|
return QF_LOG2(m_bits);
|
2012-08-14 18:00:48 -04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-09-29 19:54:50 -04:00
|
|
|
#else // QF_MAX_ACTIVE > 32
|
|
|
|
|
|
|
|
//! Priority Set of up to 64 elements
|
|
|
|
///
|
2012-08-14 18:00:48 -04:00
|
|
|
/// The priority set represents the set of active objects that are ready to
|
2016-09-29 19:54:50 -04:00
|
|
|
/// run and need to be considered by the scheduling algorithm. The set is
|
|
|
|
/// capable of storing up to 64 priority levels.
|
|
|
|
///
|
|
|
|
class QPSet {
|
|
|
|
|
|
|
|
uint32_t volatile m_bits[2]; //!< two bitmasks with a bit for each element
|
2012-08-14 18:00:48 -04:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
2016-09-29 19:54:50 -04:00
|
|
|
//! Makes the priority set @p me_ empty.
|
|
|
|
void setEmpty(void) {
|
|
|
|
m_bits[0] = static_cast<uint32_t>(0);
|
|
|
|
m_bits[1] = static_cast<uint32_t>(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Evaluates to true if the priority set is empty
|
|
|
|
// the following logic avoids UB in volatile access for MISRA compliantce
|
2012-08-14 18:00:48 -04:00
|
|
|
bool isEmpty(void) const {
|
2016-09-29 19:54:50 -04:00
|
|
|
return (m_bits[0] == static_cast<uint32_t>(0))
|
|
|
|
? (m_bits[1] == static_cast<uint32_t>(0))
|
|
|
|
: false;
|
2012-08-14 18:00:48 -04:00
|
|
|
}
|
|
|
|
|
2016-09-29 19:54:50 -04:00
|
|
|
//! Evaluates to true if the priority set is not empty
|
|
|
|
// the following logic avoids UB in volatile access for MISRA compliantce
|
2012-08-14 18:00:48 -04:00
|
|
|
bool notEmpty(void) const {
|
2016-09-29 19:54:50 -04:00
|
|
|
return (m_bits[0] != static_cast<uint32_t>(0))
|
|
|
|
? true
|
|
|
|
: (m_bits[1] != static_cast<uint32_t>(0));
|
2012-08-14 18:00:48 -04:00
|
|
|
}
|
|
|
|
|
2014-04-13 21:35:34 -04:00
|
|
|
//! the function evaluates to TRUE if the priority set has the element n.
|
|
|
|
bool hasElement(uint_fast8_t const n) const {
|
2016-09-29 19:54:50 -04:00
|
|
|
return (n <= static_cast<uint_fast8_t>(32))
|
|
|
|
? ((m_bits[0] & (static_cast<uint32_t>(1)
|
|
|
|
<< (n - static_cast<uint_fast8_t>(1))))
|
|
|
|
!= static_cast<uint32_t>(0))
|
|
|
|
: ((m_bits[1] & (static_cast<uint32_t>(1)
|
|
|
|
<< (n - static_cast<uint_fast8_t>(33))))
|
|
|
|
!= static_cast<uint32_t>(0));
|
2012-08-14 18:00:48 -04:00
|
|
|
}
|
|
|
|
|
2015-05-14 16:05:04 -04:00
|
|
|
//! insert element @p n into the set, n = 1..64
|
2014-04-13 21:35:34 -04:00
|
|
|
void insert(uint_fast8_t const n) {
|
2016-09-29 19:54:50 -04:00
|
|
|
if (n <= static_cast<uint_fast8_t>(32)) {
|
|
|
|
m_bits[0] |= (static_cast<uint32_t>(1)
|
|
|
|
<< (n - static_cast<uint_fast8_t>(1)));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m_bits[1] |= (static_cast<uint32_t>(1)
|
|
|
|
<< (n - static_cast<uint_fast8_t>(33)));
|
|
|
|
}
|
2012-08-14 18:00:48 -04:00
|
|
|
}
|
|
|
|
|
2015-05-14 16:05:04 -04:00
|
|
|
//! remove element @p n from the set, n = 1..64
|
2014-04-13 21:35:34 -04:00
|
|
|
void remove(uint_fast8_t const n) {
|
2016-09-29 19:54:50 -04:00
|
|
|
if (n <= static_cast<uint_fast8_t>(32)) {
|
|
|
|
(m_bits[0] &= ~(static_cast<uint32_t>(1)
|
|
|
|
<< (n - static_cast<uint_fast8_t>(1))));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
(m_bits[1] &= ~(static_cast<uint32_t>(1)
|
|
|
|
<< (n - static_cast<uint_fast8_t>(33))));
|
2012-08-14 18:00:48 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-13 21:35:34 -04:00
|
|
|
//! find the maximum element in the set, returns zero if the set is empty
|
|
|
|
uint_fast8_t findMax(void) const {
|
2016-09-29 19:54:50 -04:00
|
|
|
return (m_bits[1] != static_cast<uint32_t>(0))
|
|
|
|
? (QF_LOG2(m_bits[1]) + static_cast<uint_fast8_t>(32)) \
|
|
|
|
: (QF_LOG2(m_bits[0]));
|
2012-08-14 18:00:48 -04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-09-29 19:54:50 -04:00
|
|
|
#endif // QF_MAX_ACTIVE
|
|
|
|
|
2014-04-13 21:35:34 -04:00
|
|
|
} // namespace QP
|
2012-08-14 18:00:48 -04:00
|
|
|
|
2014-04-13 21:35:34 -04:00
|
|
|
#endif // qpset_h
|
2012-08-14 18:00:48 -04:00
|
|
|
|