/***************************************************************************** * Product: QP/C * Last Updated for Version: 5.2.0 * Date of the Last Update: Dec 02, 2013 * * Q u a n t u m L e a P s * --------------------------- * innovating embedded systems * * Copyright (C) 2002-2013 Quantum Leaps, LLC. 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 . * * Contact information: * Quantum Leaps Web sites: http://www.quantum-leaps.com * http://www.state-machine.com * e-mail: info@quantum-leaps.com *****************************************************************************/ #ifndef qmpool_h #define qmpool_h /** * \file * \ingroup qf * \brief platform-independent memory pool interface. * * This header file must be included in all QF ports that use native QF * memory pool implementation. */ /****************************************************************************/ #ifndef QF_MPOOL_SIZ_SIZE /** \brief macro to override the default ::QMPoolSize size. * Valid values 1, 2, or 4; default 2 */ #define QF_MPOOL_SIZ_SIZE 2 #endif #if (QF_MPOOL_SIZ_SIZE == 1) /** \brief The data type to store the block-size based on the macro * #QF_MPOOL_SIZ_SIZE. * * 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 == 2) typedef uint16_t QMPoolSize; #elif (QF_MPOOL_SIZ_SIZE == 4) typedef uint32_t QMPoolSize; #else #error "QF_MPOOL_SIZ_SIZE defined incorrectly, expected 1, 2, or 4" #endif /****************************************************************************/ #ifndef QF_MPOOL_CTR_SIZE /** \brief macro to override the default ::QMPoolCtr size. * Valid values 1, 2, or 4; default 2 */ #define QF_MPOOL_CTR_SIZE 2 #endif #if (QF_MPOOL_CTR_SIZE == 1) /** \brief The data type to store the block-counter based on the macro * #QF_MPOOL_CTR_SIZE. * * 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 == 2) typedef uint16_t QMPoolCtr; #elif (QF_MPOOL_CTR_SIZE == 4) typedef uint32_t QMPoolCtr; #else #error "QF_MPOOL_CTR_SIZE defined incorrectly, expected 1, 2, or 4" #endif /****************************************************************************/ /** \brief Native QF Memory Pool * * This structure 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. * * The ::QMPool structure 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. * * 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 QMPoolTag { /** The head of the linked list of free blocks */ void * volatile free_head; /** the original start this pool */ void *start; /** the last memory block managed by this memory pool */ void *end; /** maximum block size (in bytes) */ QMPoolSize blockSize; /** total number of blocks */ QMPoolCtr nTot; /** number of free blocks remaining */ QMPoolCtr volatile nFree; /** minimum number of free blocks ever present in this pool * * \note 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 functions: */ /** \brief Initializes the native QF event pool * * The parameters are as follows: \a me points to the ::QMPool struct to be * initialized, \a poolSto is the pool storage, \a poolSize is the size * of the pool storage in bytes, and \a blockSize is the block size of this * pool. * * The caller of this method must make sure that the \a poolSto pointer * is properly aligned. In particular, it must be possible to efficiently * store a pointer at the location pointed to by \a poolSto. * Internally, the QMPool_init() function rounds up the block size * \a 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 (\a poolSize / \a blockSize). You can check the capacity * of the pool by calling the QF_getPoolMin() function. */ void QMPool_init(QMPool * const me, void * const poolSto, uint_t poolSize, uint_t blockSize); /** \brief Obtains a memory block from a memory pool. * * The only parameter \a me is a pointer to the ::QMPool from which the * block is requested. The function returns a pointer to the allocated * memory block or NULL if no free blocks are available. * * A allocated block must be returned to the same pool from which it has * been allocated. * * This function can be called from any task level or ISR level. * * \note The memory pool \a 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. * * \sa QMPool_put() */ void *QMPool_get(QMPool * const me, uint_t const margin); /** \brief Returns a memory block back to a memory pool. * * The first parameter \a me is a pointer to the ::QMPool to which the * block is returned. The second parameter is the pointer to the returned * memory block. * * This function can be called from any task level or ISR level. * * \note The block must be allocated from the same memory pool to which it * is returned. The QMPool_put() function raises an assertion if the returned * pointer to the block points outside of the original memory buffer managed * by the memory pool. Also, the QMPool_put() 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. * * \sa QMPool_get() */ void QMPool_put(QMPool * const me, void *b); /* friend class QF; */ /** \brief Memory pool element to allocate correctly aligned storage * for QMPool class. */ #define QF_MPOOL_EL(type_) \ struct { void *sto_[((sizeof(type_) - 1U)/sizeof(void*)) + 1U]; } #endif /* qmpool_h */