qpcpp/ports/win32/qp_port.hpp

185 lines
6.6 KiB
C++
Raw Normal View History

//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
2022-08-11 15:36:19 -04:00
// Copyright (C) 2005 Quantum Leaps, LLC <state-machine.com>.
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open source GNU
// General Public License version 3 (or any later version), or alternatively,
// under the terms of one of the closed source Quantum Leaps commercial
// licenses.
//
// The terms of the open source GNU General Public License version 3
// can be found at: <www.gnu.org/licenses/gpl-3.0>
//
// The terms of the closed source Quantum Leaps commercial licenses
// can be found at: <www.state-machine.com/licensing>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
2024-02-08 21:09:29 -05:00
//! @date Last updated on: 2024-02-16
//! @version Last updated for: @ref qpc_7_3_3
//!
2022-08-11 15:36:19 -04:00
//! @file
//! @brief QP/C++ port to Win32 (multithreaded), generic C++11
2022-08-11 15:36:19 -04:00
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_
2012-08-14 18:00:48 -04:00
#include <cstdint> // Exact-width types. C++11 Standard
2014-04-13 21:35:34 -04:00
#ifdef QP_CONFIG
#include "qp_config.hpp" // external QP configuration
#endif
2014-04-13 21:35:34 -04:00
// no-return function specifier (C++11 Standard)
#define Q_NORETURN [[ noreturn ]] void
2013-10-10 20:01:51 -04:00
2020-07-18 17:58:58 -04:00
// QActive event queue, os-type, and thread types
#define QACTIVE_EQUEUE_TYPE QEQueue
#define QACTIVE_OS_OBJ_TYPE void*
#define QACTIVE_THREAD_TYPE void*
2015-05-14 16:05:04 -04:00
// QF critical section for Win32, see NOTE1
#define QF_CRIT_STAT
#define QF_CRIT_ENTRY() QP::QF::enterCriticalSection_()
#define QF_CRIT_EXIT() QP::QF::leaveCriticalSection_()
2012-08-14 18:00:48 -04:00
2017-02-07 19:55:33 -05:00
// QF_LOG2 not defined -- use the internal LOG2() implementation
2016-09-29 19:54:50 -04:00
2013-10-10 20:01:51 -04:00
namespace QP {
2022-08-11 15:36:19 -04:00
namespace QF {
2012-08-14 18:00:48 -04:00
// internal functions for critical section management
void enterCriticalSection_();
void leaveCriticalSection_();
2015-05-14 16:05:04 -04:00
2018-10-25 11:13:01 -04:00
// set clock tick rate and priority
void setTickRate(uint32_t ticksPerSec, int tickPrio);
2015-05-14 16:05:04 -04:00
2024-02-08 21:09:29 -05:00
// clock tick callback
void onClockTick();
2012-08-14 18:00:48 -04:00
2024-02-08 21:09:29 -05:00
#ifdef QF_CONSOLE
// abstractions for console access...
void consoleSetup();
void consoleCleanup();
int consoleGetKey();
int consoleWaitForKey();
#endif
2018-10-25 11:13:01 -04:00
2022-08-11 15:36:19 -04:00
} // namespace QF
2014-04-13 21:35:34 -04:00
} // namespace QP
2012-08-14 18:00:48 -04:00
2016-05-05 12:22:15 -04:00
// special adaptations for QWIN GUI applications
#ifdef QWIN_GUI
2015-06-06 18:30:55 -04:00
// replace main() with main_gui() as the entry point to a GUI app.
#define main() main_gui()
int main_gui(); // prototype of the GUI application entry point
2015-06-06 18:30:55 -04:00
#endif
// include files -------------------------------------------------------------
#include "qequeue.hpp" // Win32-QV needs the native event-queue
#include "qmpool.hpp" // Win32-QV needs the native memory-pool
#include "qp.hpp" // QP platform-independent public interface
//============================================================================
// interface used only inside QF implementation, but not in applications
2012-08-14 18:00:48 -04:00
2014-04-13 21:35:34 -04:00
#ifdef QP_IMPL
2016-04-01 13:55:34 -04:00
// QF scheduler locking for Win32, see NOTE2
2016-09-29 19:54:50 -04:00
#define QF_SCHED_STAT_
#define QF_SCHED_LOCK_(dummy) static_cast<void>(0)
#define QF_SCHED_UNLOCK_() static_cast<void>(0)
2016-04-01 13:55:34 -04:00
// QF event queue customization for Win32...
2012-08-14 18:00:48 -04:00
#define QACTIVE_EQUEUE_WAIT_(me_) \
2020-03-17 21:33:58 -04:00
while ((me_)->m_eQueue.m_frontEvt == nullptr) { \
QF_CRIT_EXIT(); \
static_cast<void>(WaitForSingleObject((me_)->m_osObject, INFINITE)); \
QF_CRIT_ENTRY(); \
2012-08-14 18:00:48 -04:00
}
#define QACTIVE_EQUEUE_SIGNAL_(me_) \
static_cast<void>(SetEvent((me_)->m_osObject))
2012-08-14 18:00:48 -04:00
2022-08-11 15:36:19 -04:00
// native QF event pool operations
2015-05-14 16:05:04 -04:00
#define QF_EPOOL_TYPE_ QMPool
2016-11-08 12:48:44 -05:00
#define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \
(p_).init((poolSto_), (poolSize_), (evtSize_))
2012-08-14 18:00:48 -04:00
#define QF_EPOOL_EVENT_SIZE_(p_) ((p_).getBlockSize())
2024-01-17 07:50:09 -05:00
#define QF_EPOOL_GET_(p_, e_, m_, qsId_) \
((e_) = static_cast<QEvt *>((p_).get((m_), (qsId_))))
#define QF_EPOOL_PUT_(p_, e_, qsId_) ((p_).put((e_), (qsId_)))
2012-08-14 18:00:48 -04:00
2018-11-22 11:34:13 -05:00
// Minimum required Windows version is Windows-XP or newer (0x0501)
#ifdef WINVER
#undef WINVER
#endif
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define WINVER _WIN32_WINNT_WINXP
#define _WIN32_WINNT _WIN32_WINNT_WINXP
2012-08-14 18:00:48 -04:00
#define WIN32_LEAN_AND_MEAN
2018-10-25 11:13:01 -04:00
#include <windows.h> // Win32 API
2015-05-14 16:05:04 -04:00
#endif // QP_IMPL
2012-08-14 18:00:48 -04:00
//============================================================================
2015-05-14 16:05:04 -04:00
// NOTE1:
// QP, like all real-time frameworks, needs to execute certain sections of
2018-11-22 11:34:13 -05:00
// code exclusively, meaning that only one thread can execute the code at
// the time. Such sections of code are called "critical sections".
2012-08-14 18:00:48 -04:00
//
2022-08-11 15:36:19 -04:00
// This port uses a pair of functions QF::enterCriticalSection_() /
// QF::leaveCriticalSection_() to enter/leave the cirtical section,
2018-11-22 11:34:13 -05:00
// respectively.
2012-08-14 18:00:48 -04:00
//
2022-08-11 15:36:19 -04:00
// These functions are implemented in the qf_port.cpp module, where they
2018-11-22 11:34:13 -05:00
// manipulate the file-scope Win32 critical section object l_win32CritSect
// to protect all critical sections. Using the single critical section
// object for all critical section guarantees that only one thread at a time
2018-11-22 11:34:13 -05:00
// can execute inside a critical section. This prevents race conditions and
// data corruption.
2012-08-14 18:00:48 -04:00
//
// Please note, however, that the Win32 critical section implementation
2018-11-22 11:34:13 -05:00
// behaves differently than interrupt disabling. A common Win32 critical
// section 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 conditions.
2012-08-14 18:00:48 -04:00
//
// Unlike simply disabling and enabling interrupts, the critical section
2012-08-14 18:00:48 -04:00
// approach is also subject to priority inversions. Various versions of
// Windows handle priority inversions differently, but it seems that most of
// them recognize priority inversions and dynamically adjust the priorities of
// threads to prevent it. Please refer to the MSN articles for more
// information.
//
2015-05-14 16:05:04 -04:00
// NOTE2:
// Scheduler locking (used inside QActive_publish_()) is NOT implemented
// in this port. This means that event multicasting is NOT atomic, so thread
// preemption CAN happen during that time, especially when a low-priority
// thread publishes events to higher-priority threads. This can lead to
// (occasionally) unexpected event sequences.
2016-04-01 13:55:34 -04:00
//
2012-08-14 18:00:48 -04:00
#endif // QP_PORT_HPP_
2022-08-11 15:36:19 -04:00