-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathqf_port.hpp
151 lines (126 loc) · 5.41 KB
/
qf_port.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/// @file
/// @brief QF/C++ port to cpputest host based testing environment
/// @cond
///***************************************************************************
/// Last updated for version 6.9.1
/// Last updated on 2020-09-21
///
/// Q u a n t u m L e a P s
/// ------------------------
/// Modern Embedded Software
///
/// Copyright (C) 2005-2020 Quantum Leaps. All rights reserved.
///
/// 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 <www.gnu.org/licenses>.
///
/// Contact information:
/// <www.state-machine.com/licensing>
/// <[email protected]>
///***************************************************************************
/// @endcond
#ifndef QF_PORT_HPP
#define QF_PORT_HPP
// provide QP::QHsm virtual destructor
#define Q_HSM_XTOR 1
// event queue and thread types
#define QF_EQUEUE_TYPE QEQueue
// QF_OS_OBJECT_TYPE not used
// QF_THREAD_TYPE not used
#define QF_EPOOL_TYPE_ QMPool
// The maximum number of active objects in the application
#define QF_MAX_ACTIVE 64U
// The number of system clock tick rates
#define QF_MAX_TICK_RATE 2U
// Activate the QF QActive::stop() API
#define QF_ACTIVE_STOP 1
// various QF object sizes configuration for this port
#define QF_EVENT_SIZ_SIZE 4U
#define QF_EQUEUE_CTR_SIZE 4U
#define QF_MPOOL_SIZ_SIZE 4U
#define QF_MPOOL_CTR_SIZE 4U
#define QF_TIMEEVT_CTR_SIZE 4U
// QF critical section entry/exit for POSIX, see NOTE1
// QF_CRIT_STAT_TYPE not defined
#define QF_CRIT_ENTRY(dummy)
#define QF_CRIT_EXIT(dummy)
// QF_LOG2 not defined -- use the internal LOG2() implementation
#include "qep_port.hpp" // QEP port
#include "qequeue.hpp" // POSIX-QV needs event-queue
#include "qmpool.hpp" // POSIX-QV needs memory-pool
#include "qf.hpp" // QF platform-independent public interface
namespace QP {
void QF_runUntilNoReadyActiveObjects();
} // namespace QP
//****************************************************************************
// interface used only inside QF implementation, but not in applications
//
#ifdef QP_IMPL
// scheduler locking (not needed in single-thread port)
#define QF_SCHED_STAT_
#define QF_SCHED_LOCK_(dummy) ((void)0)
#define QF_SCHED_UNLOCK_() ((void)0)
// event queue operations...
#define QACTIVE_EQUEUE_WAIT_(me_) \
Q_ASSERT((me_)->m_eQueue.m_frontEvt != nullptr)
#define QACTIVE_EQUEUE_SIGNAL_(me_) do { \
cpputest_readySet_.insert((me_)->m_prio); \
} while (false)
// event pool operations...
#define QF_EPOOL_TYPE_ QMPool
#define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \
(p_).init((poolSto_), (poolSize_), (evtSize_))
#define QF_EPOOL_EVENT_SIZE_(p_) ((p_).getBlockSize())
#define QF_EPOOL_GET_(p_, e_, m_, qs_id_) \
((e_) = static_cast<QEvt *>((p_).get((m_), (qs_id_))))
#define QF_EPOOL_PUT_(p_, e_, qs_id_) ((p_).put((e_), (qs_id_)))
namespace QP {
extern QPSet cpputest_readySet_; // ready set of active objects
} // namespace QP
#endif // QP_IMPL
// NOTES: ====================================================================
//
// NOTE1:
// QF, like all real-time frameworks, needs to execute certain sections of
// code exclusively, meaning that only one thread can execute the code at
// the time. Such sections of code are called "critical sections"
//
// This port uses a pair of functions QF_enterCriticalSection_() /
// QF_leaveCriticalSection_() to enter/leave the cirtical section,
// respectively.
//
// These functions are implemented in the qf_port.c module, where they
// manipulate the file-scope POSIX mutex object l_pThreadMutex_
// to protect all critical sections. Using the single mutex for all crtical
// section guarantees that only one thread at a time can execute inside a
// critical section. This prevents race conditions and data corruption.
//
// Please note, however, that the POSIX mutex implementation behaves
// differently than interrupt disabling. A common POSIX mutex ensures
// that only one thread at a time can execute a critical section, but it
// does not guarantee that a context switch cannot occur within the
// critical section. In fact, such context switches probably will happen,
// but they should not cause concurrency hazards because the critical
// section eliminates all race conditionis.
//
// Unlinke simply disabling and enabling interrupts, the mutex approach is
// also subject to priority inversions. However, the p-thread mutex
// implementation, such as POSIX threads, should support the priority-
// inheritance protocol.
//
#endif // QF_PORT_HPP