Newer
Older
stm32 / common / molelord / MoleMalloc.c
/**
 * @file MoleMalloc.c
 * @brief FreeRTOS環境下で安全にヒープを使用できるよう、mallocファミリを乗っ取る
 * @details
 * GNU ldに--wrapオプションを与えることで、malloc, calloc, realloc, freeを
 * 乗っ取ります。
 * 使用許諾は The MIT License です。
 * 参照 https://opensource.org/licenses/mit-license.php
 * @copyright
 * Copyright (c) 2020 molelord
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:

 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "main.h"     // assert_param()
#include <stddef.h>   // NULL
#include <string.h>   // memset()
#include "FreeRTOS.h"

void *
__wrap_malloc(size_t size)
{
    return pvPortMalloc(size);
}

void *
__wrap_calloc(size_t size)
{
    void *ptr = pvPortMalloc(size);
    if (ptr)
    {
        memset(ptr, 0, size);
    }
    return ptr;
}

void *
__wrap_realloc(void *oldptr, size_t size)
{
    if (oldptr == NULL)
    {
        return pvPortMalloc(size);
    }

    if (size == 0)
    {
        vPortFree(oldptr);
        return NULL;
    }

    /*!
     * FreeRTOSのheap_x.cの内部で管理しているデータ構造に依存せずに
     * realloc()を実装しているため元々のsizeが分からず、
     * 後ろに空き領域がある場合でも領域の連結が行えず非効率である。
     * しかし、realloc()自体がそれほど使用頻度の高い関数ではないの
     * でよしとする。
     * また、旧領域から新領域へコピーするときに、旧領域の大きさを
     * 超えて読み出しを行うが、それもよしとする。
     */
    void *newptr = pvPortMalloc(size);
    if (newptr == NULL)
    {
        return NULL;
    }

    memcpy(oldptr, newptr, size);
    vPortFree(oldptr);
    return newptr;
}

void
__wrap_free(void *ptr)
{
    vPortFree(ptr);
}

// vim: tabstop=4 shiftwidth=4 expandtab