Пример #1
0
/**
* \description
* The function allocates a memory block from the pool and returns a pointer
* to the block back to the caller.
*
* \arguments
* \arg[in,out] \c me      pointer (see \ref derivation)
* \arg[in]     \c margin  the minimum number of unused blocks still available
*                         in the pool after the allocation.
*
* \note 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.
*
* \attention
* An allocated block must be later returned back to the same pool
* from which it has been allocated.
*
* \sa QMPool_put()
*/
void *QMPool_get(QMPool * const me, uint_fast16_t const margin) {
    QFreeBlock *fb;
    QF_CRIT_STAT_

    QF_CRIT_ENTRY_();

    /* have more free blocks than the requested margin? */
    if (me->nFree > (QMPoolCtr)margin) {
        void *fb_next;
        fb = (QFreeBlock *)me->free_head; /* get a free block */

        /* the pool has some free blocks, so a free block must be available */
        Q_ASSERT_ID(110, fb != (QFreeBlock *)0);

        fb_next = fb->next; /* put volatile to a temporary to avoid UB */

        /* is the pool becoming empty? */
        --me->nFree; /* one less free block */
        if (me->nFree == (QMPoolCtr)0) {
            /* pool is becoming empty, so the next free block must be NULL */
            Q_ASSERT_ID(120, fb_next == (QFreeBlock *)0);

            me->nMin = (QMPoolCtr)0; /* remember that the pool got empty */
        }
        else {
            /* pool is not empty, so the next free block must be in range
            *
            * NOTE: the next free block pointer can fall out of range
            * when the client code writes past the memory block, thus
            * corrupting the next block.
            */
            Q_ASSERT_ID(130, QF_PTR_RANGE_(fb_next, me->start, me->end));

            /* is the number of free blocks the new minimum so far? */
            if (me->nMin > me->nFree) {
                me->nMin = me->nFree; /* remember the new minimum */
            }
        }

        me->free_head = fb_next; /* set the head to the next free block */

        QS_BEGIN_NOCRIT_(QS_QF_MPOOL_GET, QS_priv_.mpObjFilter, me->start)
            QS_TIME_();         /* timestamp */
            QS_OBJ_(me->start); /* the memory managed by this pool */
            QS_MPC_(me->nFree); /* # of free blocks in the pool */
            QS_MPC_(me->nMin);  /* min # free blocks ever in the pool */
        QS_END_NOCRIT_()

    }
Пример #2
0
/*..........................................................................*/
void QMPool_put(QMPool *me, void *b) {
    QF_CRIT_STAT_

    Q_REQUIRE(me->nFree <= me->nTot);      /* # free blocks must be < total */
    Q_REQUIRE(QF_PTR_RANGE_(b, me->start, me->end));  /* b must be in range */

    QF_CRIT_ENTRY_();
    ((QFreeBlock *)b)->next = (QFreeBlock *)me->free_head;/* link into list */
    me->free_head = b;                  /* set as new head of the free list */
    ++me->nFree;                        /* one more free block in this pool */

    QS_BEGIN_NOCRIT_(QS_QF_MPOOL_PUT, QS_mpObj_, me->start)
        QS_TIME_();                                            /* timestamp */
        QS_OBJ_(me->start);              /* the memory managed by this pool */
        QS_MPC_(me->nFree);        /* the number of free blocks in the pool */
    QS_END_NOCRIT_()

    QF_CRIT_EXIT_();
}