mirror of
https://github.com/QuantumLeaps/qpc.git
synced 2025-01-28 07:03:10 +08:00
282 lines
8.9 KiB
C
282 lines
8.9 KiB
C
/*$file${include::qmpool.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
|
|
/*
|
|
* Model: qpc.qm
|
|
* File: ${include::qmpool.h}
|
|
*
|
|
* This code has been generated by QM 5.2.4 <www.state-machine.com/qm>.
|
|
* DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
|
|
*
|
|
* This code is covered by the following QP license:
|
|
* License # : LicenseRef-QL-dual
|
|
* Issued to : Any user of the QP/C real-time embedded framework
|
|
* Framework(s) : qpc
|
|
* Support ends : 2023-12-31
|
|
* License scope:
|
|
*
|
|
* 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>
|
|
*/
|
|
/*$endhead${include::qmpool.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
|
|
/*! @file
|
|
* @brief QP native, platform-independent memory pool ::QMPool interface.
|
|
*/
|
|
#ifndef QP_INC_QMPOOL_H_
|
|
#define QP_INC_QMPOOL_H_
|
|
|
|
/*==========================================================================*/
|
|
#ifndef QF_MPOOL_SIZ_SIZE
|
|
/*! macro to override the default ::QMPoolSize size [bytes].
|
|
* Valid values 1U, 2U, or 4U; default 2U
|
|
*/
|
|
#define QF_MPOOL_SIZ_SIZE 2U
|
|
#endif
|
|
#if (QF_MPOOL_SIZ_SIZE == 1U)
|
|
|
|
/*! The data type to store the block-size based on the macro
|
|
* #QF_MPOOL_SIZ_SIZE.
|
|
* @details
|
|
* The dynamic range of this data type determines the maximum size
|
|
* of blocks that can be managed by the native QF event pool.
|
|
*/
|
|
typedef uint8_t QMPoolSize;
|
|
#elif (QF_MPOOL_SIZ_SIZE == 2U)
|
|
|
|
typedef uint16_t QMPoolSize;
|
|
#elif (QF_MPOOL_SIZ_SIZE == 4U)
|
|
typedef uint32_t QMPoolSize;
|
|
#else
|
|
#error "QF_MPOOL_SIZ_SIZE defined incorrectly, expected 1U, 2U, or 4U"
|
|
#endif
|
|
|
|
/*==========================================================================*/
|
|
#ifndef QF_MPOOL_CTR_SIZE
|
|
/*! macro to override the default ::QMPoolCtr size [bytes].
|
|
* Valid values 1U, 2U, or 4U; default 2U
|
|
*/
|
|
#define QF_MPOOL_CTR_SIZE 2U
|
|
#endif
|
|
#if (QF_MPOOL_CTR_SIZE == 1U)
|
|
|
|
/*! The data type to store the block-counter based on the macro
|
|
* #QF_MPOOL_CTR_SIZE.
|
|
* @details
|
|
* The dynamic range of this data type determines the maximum number
|
|
* of blocks that can be stored in the pool.
|
|
*/
|
|
typedef uint8_t QMPoolCtr;
|
|
#elif (QF_MPOOL_CTR_SIZE == 2U)
|
|
typedef uint16_t QMPoolCtr;
|
|
#elif (QF_MPOOL_CTR_SIZE == 4U)
|
|
typedef uint32_t QMPoolCtr;
|
|
#else
|
|
#error "QF_MPOOL_CTR_SIZE defined incorrectly, expected 1U, 2U, or 4U"
|
|
#endif
|
|
|
|
/*! Memory pool element to allocate correctly aligned storage
|
|
* for QMPool class.
|
|
* @param[in] evType_ event type (name of the subclass of QEvt)
|
|
*/
|
|
#define QF_MPOOL_EL(evType_) \
|
|
struct { void *sto_[((sizeof(evType_) - 1U)/sizeof(void*)) + 1U]; }
|
|
|
|
/*==========================================================================*/
|
|
/*$declare${QF::QMPool} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
|
|
|
|
/*${QF::QMPool} ............................................................*/
|
|
/*! @brief Native QF Memory Pool
|
|
* @class QMPool
|
|
*
|
|
* @details
|
|
* A fixed block-size memory pool is a very fast and efficient data
|
|
* structure for dynamic allocation of fixed block-size chunks of memory.
|
|
* A memory pool offers fast and deterministic allocation and recycling of
|
|
* memory blocks and is not subject to fragmenation.<br>
|
|
*
|
|
* The ::QMPool class describes the native QF memory pool, which can be used as
|
|
* the event pool for dynamic event allocation, or as a fast, deterministic
|
|
* fixed block-size heap for any other objects in your application.
|
|
*
|
|
* @note
|
|
* ::QMPool contains only data members for managing a memory pool, but
|
|
* does not contain the pool storage, which must be provided externally
|
|
* during the pool initialization.
|
|
*
|
|
* @note
|
|
* The native QF event pool is configured by defining the macro
|
|
* #QF_EPOOL_TYPE_ as ::QMPool in the specific QF port header file.
|
|
*/
|
|
typedef struct {
|
|
/* private: */
|
|
|
|
/*! start of the memory managed by this memory pool
|
|
* @private @memberof QMPool
|
|
*/
|
|
void * start;
|
|
|
|
/*! end of the memory managed by this memory pool
|
|
* @private @memberof QMPool
|
|
*/
|
|
void * end;
|
|
|
|
/*! head of linked list of free blocks
|
|
* @private @memberof QMPool
|
|
*/
|
|
void * volatile free_head;
|
|
|
|
/*! maximum block size (in bytes)
|
|
* @private @memberof QMPool
|
|
*/
|
|
QMPoolSize blockSize;
|
|
|
|
/*! total number of blocks
|
|
* @private @memberof QMPool
|
|
*/
|
|
QMPoolCtr nTot;
|
|
|
|
/*! number of free blocks remaining
|
|
* @private @memberof QMPool
|
|
*/
|
|
QMPoolCtr volatile nFree;
|
|
|
|
/*! minimum number of free blocks ever present in this pool
|
|
* @private @memberof QMPool
|
|
*
|
|
* @details
|
|
* this attribute remembers the low watermark of the pool, which
|
|
* provides a valuable information for sizing event pools.
|
|
* @sa QF_getPoolMin().
|
|
*/
|
|
QMPoolCtr nMin;
|
|
} QMPool;
|
|
|
|
/* public: */
|
|
|
|
/*! Initializes the native QF memory pool
|
|
* @public @memberof QMPool
|
|
*
|
|
* @details
|
|
* Initialize a fixed block-size memory pool by providing it with the pool
|
|
* memory to manage, size of this memory, and the block size.
|
|
*
|
|
* @param[in,out] me current instance pointer (see @ref oop)
|
|
* @param[in] poolSto pointer to the memory buffer for pool storage
|
|
* @param[in] poolSize size of the storage buffer in bytes
|
|
* @param[in] blockSize fixed-size of the memory blocks in bytes
|
|
*
|
|
* @attention
|
|
* The caller of QMPool::init() must make sure that the `poolSto`
|
|
* pointer is properly **aligned**. In particular, it must be possible to
|
|
* efficiently store a pointer at the location pointed to by `poolSto`.
|
|
* Internally, the QMPool_init() function rounds up the block size
|
|
* `blockSize` so that it can fit an integer number of pointers.
|
|
* This is done to achieve proper alignment of the blocks within the pool.
|
|
*
|
|
* @note
|
|
* Due to the rounding of block size the actual capacity of the pool might
|
|
* be less than (`poolSize` / `blockSize`). You can check the capacity
|
|
* of the pool by calling the QF_getPoolMin() function.
|
|
*
|
|
* @note
|
|
* This function is **not** protected by a critical section, because
|
|
* it is intended to be called only during the initialization of the system,
|
|
* when interrupts are not allowed yet.
|
|
*
|
|
* @note
|
|
* Many QF ports use memory pools to implement the event pools.
|
|
*
|
|
* @usage
|
|
* The following example illustrates how to invoke QMPool_init():
|
|
* @include qmp_init.c
|
|
*/
|
|
void QMPool_init(QMPool * const me,
|
|
void * const poolSto,
|
|
uint_fast32_t poolSize,
|
|
uint_fast16_t blockSize);
|
|
|
|
/*! Obtains a memory block from a memory pool.
|
|
* @public @memberof QMPool
|
|
*
|
|
* @details
|
|
* The function allocates a memory block from the pool and returns a pointer
|
|
* to the block back to the caller.
|
|
*
|
|
* @param[in,out] me current instance pointer (see @ref oop)
|
|
* @param[in] margin the minimum number of unused blocks still available
|
|
* in the pool after the allocation.
|
|
*
|
|
* @returns
|
|
* A pointer to a memory block or NULL if no more blocks are available in
|
|
* the memory pool.
|
|
*
|
|
* @note
|
|
* This function can be called from any task level or ISR level.
|
|
*
|
|
* @note
|
|
* The memory pool `me` must be initialized before any events can
|
|
* be requested from it. Also, the QMPool_get() function uses internally a
|
|
* QF critical section, so you should be careful not to call it from within
|
|
* a critical section when nesting of critical section is not supported.
|
|
*
|
|
* @attention
|
|
* An allocated block must be later returned back to the **same** pool
|
|
* from which it has been allocated.
|
|
*
|
|
* @sa QMPool_put()
|
|
*
|
|
* @usage
|
|
* The following example illustrates how to use QMPool_get():
|
|
* @include qmp_use.c
|
|
*/
|
|
void * QMPool_get(QMPool * const me,
|
|
uint_fast16_t const margin,
|
|
uint_fast8_t const qs_id);
|
|
|
|
/*! Recycles a memory block back to a memory pool.
|
|
* @public @memberof QMPool
|
|
*
|
|
* @details
|
|
* Recycle a memory block to the fixed block-size memory pool.
|
|
*
|
|
* @param[in,out] me current instance pointer (see @ref oop)
|
|
* @param[in] b pointer to the memory block that is being recycled
|
|
*
|
|
* @attention
|
|
* The recycled block must be allocated from the **same** memory pool
|
|
* to which it is returned.
|
|
*
|
|
* @note
|
|
* This function can be called from any task level or ISR level.
|
|
*
|
|
* @sa
|
|
* QMPool_get()
|
|
*
|
|
* @usage
|
|
* The following example illustrates how to use QMPool_put():
|
|
* @include qmp_use.c
|
|
*/
|
|
void QMPool_put(QMPool * const me,
|
|
void * const b,
|
|
uint_fast8_t const qs_id);
|
|
/*$enddecl${QF::QMPool} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
|
|
|
|
#endif /* QP_INC_QMPOOL_H_ */
|