Newer
Older
libkc / modules / src / kc_memory_entry.c
/**
 * @file  kc_memory_entry.c
 * @brief  KC メモリ管理 Entry サブモジュール
 * @copyright  2003 - 2023  Nomura Kei
 */
#include <stdlib.h>

#include <kc_memory.h>
#include <kc_memory_entry.h>
#include "kc_memory_entry_inner.h"

#ifdef KC_MEMORY_ENABLED
#undef KC_MEMORY_ENABLED
#endif

////////////////////////////////////////////////////////////////////////////////
//
//  定数定義
//

////////////////////////////////////////////////////////////////////////////////
//
//  変数定義
//

// For UNITTEST
#ifdef UNITTEST
bool (*_UT_KcMemory_can_alloc)(
    KcMemoryEntry *entry, size_t alignment, size_t size,
    KcMemoryMark mark, const char *file, const char *func, int line) = NULL;
#endif // UNITTEST

/**
 * KcMemoryEntry を構築します。
 * entry が NULL の場合、新規に KeMemoryEntry を構築します。
 * entry が NULL でない場合、entry の管理するメモリサイズを変更し、各種値を更新します。
 * 構築に失敗した場合、NULL を返します。
 *
 * @param entry  メモリエントリ
 * @param alignment アライメント
 * @param size   メモリサイズ
 * @param mark   メモリ状態
 * @param file   メモリ確保ファイル名
 * @param func   メモリ確保関数名
 * @param line   メモリ確保行番号
 * @return 構築した KcMemoryEntry
 */
KcMemoryEntry *KcMemoryEntry_new(KcMemoryEntry *entry, size_t alignment, size_t size,
                                 KcMemoryMark mark, const char *file, const char *func, int line)
{
#ifdef UNITTEST
    if (_UT_KcMemory_can_alloc &&
        !_UT_KcMemory_can_alloc(entry, alignment, size, mark, file, func, line))
    {
        return NULL;
    }
#endif
    KcMemoryEntry *new_entry;
    if ((entry == NULL) && (alignment > 0) && (mark == KC_MEMORY_ALLOCATED_ALIGNED))
    { // アライメント指定でメモリを確保する。
        new_entry = (KcMemoryEntry *)raw_aligned_alloc(
            alignment, (size_t)(sizeof(KcMemoryEntry) + size));
    }
    else
    {
        new_entry = (KcMemoryEntry *)raw_realloc(
            entry, (size_t)(sizeof(KcMemoryEntry) + size));
    }
    KcMemoryEntry_set(new_entry, size, mark, file, func, line);

    return new_entry;
}

/**
 * KcMemoryEntry を破棄します。
 *
 * @param entry 破棄するメモリエントリ
 */
void KcMemoryEntry_delete(KcMemoryEntry *entry)
{
    if (KC_IS_WINDOWS && (entry->mark == KC_MEMORY_ALLOCATED_ALIGNED))
    {
        entry->mark = KC_MEMORY_DELETED;
        entry->size = 0;
        _aligned_free(entry);
    }
    else
    {
        entry->mark = KC_MEMORY_DELETED;
        entry->size = 0;
        raw_free(entry);
    }
}

/**
 * 指定された entry に、指定された値を設定します。
 * entry が NULL の場合、何もしません。
 *
 * @param entry  メモリエントリ
 * @param size   メモリサイズ
 * @param mark   メモリ状態
 * @param file   メモリ確保ファイル名
 * @param func   メモリ確保関数名
 * @param line   メモリ確保行番号
 */
void KcMemoryEntry_set(KcMemoryEntry *entry,
                       size_t size, KcMemoryMark mark, const char *file, const char *func, int line)
{
    if (entry != NULL)
    {
        entry->size = size;
        entry->mark = mark;
        entry->file = file;
        entry->func = func;
        entry->line = line;
        entry->_prev = NULL;
        entry->_next = NULL;
        entry->data = (entry + 1);
    }
}