diff --git a/modules/libkc/Makefile b/modules/libkc/Makefile new file mode 100644 index 0000000..efd29fb --- /dev/null +++ b/modules/libkc/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libkc +TARGET = $(NAME).so +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/modules/libkc/Makefile b/modules/libkc/Makefile new file mode 100644 index 0000000..efd29fb --- /dev/null +++ b/modules/libkc/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libkc +TARGET = $(NAME).so +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/modules/libkc/include/kc.h b/modules/libkc/include/kc.h new file mode 100644 index 0000000..5f628ed --- /dev/null +++ b/modules/libkc/include/kc.h @@ -0,0 +1,38 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// KC Header File +// +#ifndef KC_H +#define KC_H + +#if defined(__cplusplus) && (__cplusplus >= 201103L) +// ============================================================================= +// C++11 +// ============================================================================= +#include + +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) +// ============================================================================= +// C11 +// ============================================================================= +#include +#include +#include +#define thread_local _Thread_local +#define nullptr NULL + +#else +// ============================================================================= +// ERROR +// ============================================================================= +#error "suuports C11/C++1 or later" + + +// ============================================================================= +// 共通定義 +// ============================================================================= +#define UNUSED_VARIABLE(val) (void)(val) + + +#endif // C11 +#endif // KC_H diff --git a/modules/libkc/Makefile b/modules/libkc/Makefile new file mode 100644 index 0000000..efd29fb --- /dev/null +++ b/modules/libkc/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libkc +TARGET = $(NAME).so +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/modules/libkc/include/kc.h b/modules/libkc/include/kc.h new file mode 100644 index 0000000..5f628ed --- /dev/null +++ b/modules/libkc/include/kc.h @@ -0,0 +1,38 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// KC Header File +// +#ifndef KC_H +#define KC_H + +#if defined(__cplusplus) && (__cplusplus >= 201103L) +// ============================================================================= +// C++11 +// ============================================================================= +#include + +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) +// ============================================================================= +// C11 +// ============================================================================= +#include +#include +#include +#define thread_local _Thread_local +#define nullptr NULL + +#else +// ============================================================================= +// ERROR +// ============================================================================= +#error "suuports C11/C++1 or later" + + +// ============================================================================= +// 共通定義 +// ============================================================================= +#define UNUSED_VARIABLE(val) (void)(val) + + +#endif // C11 +#endif // KC_H diff --git a/modules/libkc/include/kc_memory.h b/modules/libkc/include/kc_memory.h new file mode 100644 index 0000000..e54c14f --- /dev/null +++ b/modules/libkc/include/kc_memory.h @@ -0,0 +1,88 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// メモリ管理モジュール ヘッダファイル +// @copyright 2003 - 2023 Nomura Kei +// +#ifndef KC_MEMORY_H +#define KC_MEMORY_H + +#include + +#ifdef __cplusplus +extern "C" { +namespace kc { +using namespace std; +#endif + + +#ifdef KC_MEMORY_ENABLED +// メモリ管理有効 +#define malloc(size) kc_memory_malloc ( size, __FILE__, __func__, __LINE__) +#define calloc(nmemb, size) kc_memory_calloc (nmemb, size, __FILE__, __func__, __LINE__) +#define realloc(ptr, size) kc_memory_realloc(ptr , size, __FILE__, __func__, __LINE__) +#define free(ptr) kc_memory_free (ptr) + +#else +#include + +#endif // !KC_MEMORY_ENABLED + + + +// 管理メモリ種別を表すための識別マーク +#define KC_MEMORY_MARK_HEAD (0x55AA5A00) +#define KC_MEMORY_MARK_MASK (0xFFFFFF00) +typedef enum +{ + KC_MEMORY_DELETED = KC_MEMORY_MARK_HEAD | 0x00, //!< メモリが解放されている + KC_MEMORY_ALLOCATED = KC_MEMORY_MARK_HEAD | 0x01, //!< メモリが確保されている + KC_MEMORY_ALLOCATED_NEW = KC_MEMORY_MARK_HEAD | 0x02, //!< new により確保されたメモリ + KC_MEMORY_ALLOCATED_NEW_ARRAY = KC_MEMORY_MARK_HEAD | 0x03 //!< new[] により確保されたメモリ +} KcMemoryMark; + + +/** + * 指定されたメモリ管理用種別マークが正しいか判定します。 + * + * @param mark 種別マーク + * @return true/false (管理されているメモリ/管理されていないメモリ) + */ +#define kc_memory_is_valid_mark(mark) ((mark & KC_MEMORY_MARK_MASK) == SC_MEMORY_MARK_HEAD) + + +/** + * メモリエントリ。 + */ +typedef struct KcMemoryEntry_ +{ + const char* file; /*!< メモリ確保ファイル名 */ + const char* func; /*!< メモリ確保関数名 */ + int line; /*!< メモリ確保行番号 */ + int size; /*!< 確保サイズ */ + int _mark; /*!< 確保メモリ状態 */ + struct KcMemoryEntry_* _prev; /*!< 前の管理メモリポインタ */ + struct KcMemoryEntry_* _next; /*!< 次の管理メモリポインタ */ + void* data; /*!< データ */ + // 構造体末尾の配列に限りサイズ省略可能 (C99 : incomplete array) +} KcMemoryEntry; + + +// ハンドラ関数ポインタ +typedef bool (*KcMemoryHandler)(KcMemoryEntry* entry, const char* msg); + + +// プロトタイプ宣言 +void kc_memory_set_handlers(KcMemoryHandler allocate, KcMemoryHandler free, KcMemoryHandler error); +void kc_memory_dump(int mode); + +void* kc_memory_malloc ( size_t size, const char* file, const char* func, int line); +void* kc_memory_calloc (size_t nmemb, size_t size, const char* file, const char* func, int line); +void* kc_memory_realloc(void* ptr , size_t size, const char* file, const char* func, int line); +void kc_memory_free (void* ptr); + + +#ifdef __cplusplus +} // namespace kc +} // extern "C" +#endif +#endif // KC_MEMORY_H diff --git a/modules/libkc/Makefile b/modules/libkc/Makefile new file mode 100644 index 0000000..efd29fb --- /dev/null +++ b/modules/libkc/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libkc +TARGET = $(NAME).so +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/modules/libkc/include/kc.h b/modules/libkc/include/kc.h new file mode 100644 index 0000000..5f628ed --- /dev/null +++ b/modules/libkc/include/kc.h @@ -0,0 +1,38 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// KC Header File +// +#ifndef KC_H +#define KC_H + +#if defined(__cplusplus) && (__cplusplus >= 201103L) +// ============================================================================= +// C++11 +// ============================================================================= +#include + +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) +// ============================================================================= +// C11 +// ============================================================================= +#include +#include +#include +#define thread_local _Thread_local +#define nullptr NULL + +#else +// ============================================================================= +// ERROR +// ============================================================================= +#error "suuports C11/C++1 or later" + + +// ============================================================================= +// 共通定義 +// ============================================================================= +#define UNUSED_VARIABLE(val) (void)(val) + + +#endif // C11 +#endif // KC_H diff --git a/modules/libkc/include/kc_memory.h b/modules/libkc/include/kc_memory.h new file mode 100644 index 0000000..e54c14f --- /dev/null +++ b/modules/libkc/include/kc_memory.h @@ -0,0 +1,88 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// メモリ管理モジュール ヘッダファイル +// @copyright 2003 - 2023 Nomura Kei +// +#ifndef KC_MEMORY_H +#define KC_MEMORY_H + +#include + +#ifdef __cplusplus +extern "C" { +namespace kc { +using namespace std; +#endif + + +#ifdef KC_MEMORY_ENABLED +// メモリ管理有効 +#define malloc(size) kc_memory_malloc ( size, __FILE__, __func__, __LINE__) +#define calloc(nmemb, size) kc_memory_calloc (nmemb, size, __FILE__, __func__, __LINE__) +#define realloc(ptr, size) kc_memory_realloc(ptr , size, __FILE__, __func__, __LINE__) +#define free(ptr) kc_memory_free (ptr) + +#else +#include + +#endif // !KC_MEMORY_ENABLED + + + +// 管理メモリ種別を表すための識別マーク +#define KC_MEMORY_MARK_HEAD (0x55AA5A00) +#define KC_MEMORY_MARK_MASK (0xFFFFFF00) +typedef enum +{ + KC_MEMORY_DELETED = KC_MEMORY_MARK_HEAD | 0x00, //!< メモリが解放されている + KC_MEMORY_ALLOCATED = KC_MEMORY_MARK_HEAD | 0x01, //!< メモリが確保されている + KC_MEMORY_ALLOCATED_NEW = KC_MEMORY_MARK_HEAD | 0x02, //!< new により確保されたメモリ + KC_MEMORY_ALLOCATED_NEW_ARRAY = KC_MEMORY_MARK_HEAD | 0x03 //!< new[] により確保されたメモリ +} KcMemoryMark; + + +/** + * 指定されたメモリ管理用種別マークが正しいか判定します。 + * + * @param mark 種別マーク + * @return true/false (管理されているメモリ/管理されていないメモリ) + */ +#define kc_memory_is_valid_mark(mark) ((mark & KC_MEMORY_MARK_MASK) == SC_MEMORY_MARK_HEAD) + + +/** + * メモリエントリ。 + */ +typedef struct KcMemoryEntry_ +{ + const char* file; /*!< メモリ確保ファイル名 */ + const char* func; /*!< メモリ確保関数名 */ + int line; /*!< メモリ確保行番号 */ + int size; /*!< 確保サイズ */ + int _mark; /*!< 確保メモリ状態 */ + struct KcMemoryEntry_* _prev; /*!< 前の管理メモリポインタ */ + struct KcMemoryEntry_* _next; /*!< 次の管理メモリポインタ */ + void* data; /*!< データ */ + // 構造体末尾の配列に限りサイズ省略可能 (C99 : incomplete array) +} KcMemoryEntry; + + +// ハンドラ関数ポインタ +typedef bool (*KcMemoryHandler)(KcMemoryEntry* entry, const char* msg); + + +// プロトタイプ宣言 +void kc_memory_set_handlers(KcMemoryHandler allocate, KcMemoryHandler free, KcMemoryHandler error); +void kc_memory_dump(int mode); + +void* kc_memory_malloc ( size_t size, const char* file, const char* func, int line); +void* kc_memory_calloc (size_t nmemb, size_t size, const char* file, const char* func, int line); +void* kc_memory_realloc(void* ptr , size_t size, const char* file, const char* func, int line); +void kc_memory_free (void* ptr); + + +#ifdef __cplusplus +} // namespace kc +} // extern "C" +#endif +#endif // KC_MEMORY_H diff --git a/modules/libkc/include/kc_memory.hpp b/modules/libkc/include/kc_memory.hpp new file mode 100644 index 0000000..0602b74 --- /dev/null +++ b/modules/libkc/include/kc_memory.hpp @@ -0,0 +1,56 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// メモリ管理モジュール ヘッダファイル +// @copyright 2003 - 2023 Nomura Kei +// +#ifndef KC_MEMORY_HPP +#define KC_MEMORY_HPP + +#include + + +//////////////////////////////////////////////////////////////////////////////// +// +// KC_MEMORY_ENABLED が定義されている場合、メモリ管理が有効となります。 +// +#ifdef KC_MEMORY_ENABLED +namespace kc { + +#if (__cplusplus > 201703L) +// C++20 (C++2a) [C++20 は、202002L] +[[nodiscard]] void* operator new(std::size_t size); +[[nodiscard]] void* operator new(std::size_t size, std::align_val_t alignment); +[[nodiscard]] void* operator new(std::size_t size, const std::nothrow_t&) noexcept; +[[nodiscard]] void* operator new(std::size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept; +[[nodiscard]] void* operator new(std::size_t size, void* ptr) noexcept; + +#elif (__cplusplus >= 201703L) +// C++17 (C++1z) +void* operator new(std::size size); +void* operator new(std::size size, std::align_val_t alignment); +void* operator new(std::size_t size, const std::nothrow_t&) noexcept; +void* operator new(std::size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept; +void* operator new(std::size_t size, void* ptr) noexcept; + +#else +// C++14 (C++1y), C++11 (C++0x) +void* operator new(std::size_t size); +void* operator new(std::size_t size, void* ptr) noexcept; + +#endif + + +extern thread_local const char* memory_file; +extern thread_local const char* memory_func; +extern thread_local int memory_line; + +#define new \ + ((kc::memory_file = __FILE__, \ + kc::memory_func = __func__, \ + kc::memory_line = __LINE__, \ + 0) && 0) ? 0 : new + +} + +#ifdef // KC_MEMORY_ENABLED +#endif // KC_MEMORY_HPP diff --git a/modules/libkc/Makefile b/modules/libkc/Makefile new file mode 100644 index 0000000..efd29fb --- /dev/null +++ b/modules/libkc/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libkc +TARGET = $(NAME).so +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/modules/libkc/include/kc.h b/modules/libkc/include/kc.h new file mode 100644 index 0000000..5f628ed --- /dev/null +++ b/modules/libkc/include/kc.h @@ -0,0 +1,38 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// KC Header File +// +#ifndef KC_H +#define KC_H + +#if defined(__cplusplus) && (__cplusplus >= 201103L) +// ============================================================================= +// C++11 +// ============================================================================= +#include + +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) +// ============================================================================= +// C11 +// ============================================================================= +#include +#include +#include +#define thread_local _Thread_local +#define nullptr NULL + +#else +// ============================================================================= +// ERROR +// ============================================================================= +#error "suuports C11/C++1 or later" + + +// ============================================================================= +// 共通定義 +// ============================================================================= +#define UNUSED_VARIABLE(val) (void)(val) + + +#endif // C11 +#endif // KC_H diff --git a/modules/libkc/include/kc_memory.h b/modules/libkc/include/kc_memory.h new file mode 100644 index 0000000..e54c14f --- /dev/null +++ b/modules/libkc/include/kc_memory.h @@ -0,0 +1,88 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// メモリ管理モジュール ヘッダファイル +// @copyright 2003 - 2023 Nomura Kei +// +#ifndef KC_MEMORY_H +#define KC_MEMORY_H + +#include + +#ifdef __cplusplus +extern "C" { +namespace kc { +using namespace std; +#endif + + +#ifdef KC_MEMORY_ENABLED +// メモリ管理有効 +#define malloc(size) kc_memory_malloc ( size, __FILE__, __func__, __LINE__) +#define calloc(nmemb, size) kc_memory_calloc (nmemb, size, __FILE__, __func__, __LINE__) +#define realloc(ptr, size) kc_memory_realloc(ptr , size, __FILE__, __func__, __LINE__) +#define free(ptr) kc_memory_free (ptr) + +#else +#include + +#endif // !KC_MEMORY_ENABLED + + + +// 管理メモリ種別を表すための識別マーク +#define KC_MEMORY_MARK_HEAD (0x55AA5A00) +#define KC_MEMORY_MARK_MASK (0xFFFFFF00) +typedef enum +{ + KC_MEMORY_DELETED = KC_MEMORY_MARK_HEAD | 0x00, //!< メモリが解放されている + KC_MEMORY_ALLOCATED = KC_MEMORY_MARK_HEAD | 0x01, //!< メモリが確保されている + KC_MEMORY_ALLOCATED_NEW = KC_MEMORY_MARK_HEAD | 0x02, //!< new により確保されたメモリ + KC_MEMORY_ALLOCATED_NEW_ARRAY = KC_MEMORY_MARK_HEAD | 0x03 //!< new[] により確保されたメモリ +} KcMemoryMark; + + +/** + * 指定されたメモリ管理用種別マークが正しいか判定します。 + * + * @param mark 種別マーク + * @return true/false (管理されているメモリ/管理されていないメモリ) + */ +#define kc_memory_is_valid_mark(mark) ((mark & KC_MEMORY_MARK_MASK) == SC_MEMORY_MARK_HEAD) + + +/** + * メモリエントリ。 + */ +typedef struct KcMemoryEntry_ +{ + const char* file; /*!< メモリ確保ファイル名 */ + const char* func; /*!< メモリ確保関数名 */ + int line; /*!< メモリ確保行番号 */ + int size; /*!< 確保サイズ */ + int _mark; /*!< 確保メモリ状態 */ + struct KcMemoryEntry_* _prev; /*!< 前の管理メモリポインタ */ + struct KcMemoryEntry_* _next; /*!< 次の管理メモリポインタ */ + void* data; /*!< データ */ + // 構造体末尾の配列に限りサイズ省略可能 (C99 : incomplete array) +} KcMemoryEntry; + + +// ハンドラ関数ポインタ +typedef bool (*KcMemoryHandler)(KcMemoryEntry* entry, const char* msg); + + +// プロトタイプ宣言 +void kc_memory_set_handlers(KcMemoryHandler allocate, KcMemoryHandler free, KcMemoryHandler error); +void kc_memory_dump(int mode); + +void* kc_memory_malloc ( size_t size, const char* file, const char* func, int line); +void* kc_memory_calloc (size_t nmemb, size_t size, const char* file, const char* func, int line); +void* kc_memory_realloc(void* ptr , size_t size, const char* file, const char* func, int line); +void kc_memory_free (void* ptr); + + +#ifdef __cplusplus +} // namespace kc +} // extern "C" +#endif +#endif // KC_MEMORY_H diff --git a/modules/libkc/include/kc_memory.hpp b/modules/libkc/include/kc_memory.hpp new file mode 100644 index 0000000..0602b74 --- /dev/null +++ b/modules/libkc/include/kc_memory.hpp @@ -0,0 +1,56 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// メモリ管理モジュール ヘッダファイル +// @copyright 2003 - 2023 Nomura Kei +// +#ifndef KC_MEMORY_HPP +#define KC_MEMORY_HPP + +#include + + +//////////////////////////////////////////////////////////////////////////////// +// +// KC_MEMORY_ENABLED が定義されている場合、メモリ管理が有効となります。 +// +#ifdef KC_MEMORY_ENABLED +namespace kc { + +#if (__cplusplus > 201703L) +// C++20 (C++2a) [C++20 は、202002L] +[[nodiscard]] void* operator new(std::size_t size); +[[nodiscard]] void* operator new(std::size_t size, std::align_val_t alignment); +[[nodiscard]] void* operator new(std::size_t size, const std::nothrow_t&) noexcept; +[[nodiscard]] void* operator new(std::size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept; +[[nodiscard]] void* operator new(std::size_t size, void* ptr) noexcept; + +#elif (__cplusplus >= 201703L) +// C++17 (C++1z) +void* operator new(std::size size); +void* operator new(std::size size, std::align_val_t alignment); +void* operator new(std::size_t size, const std::nothrow_t&) noexcept; +void* operator new(std::size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept; +void* operator new(std::size_t size, void* ptr) noexcept; + +#else +// C++14 (C++1y), C++11 (C++0x) +void* operator new(std::size_t size); +void* operator new(std::size_t size, void* ptr) noexcept; + +#endif + + +extern thread_local const char* memory_file; +extern thread_local const char* memory_func; +extern thread_local int memory_line; + +#define new \ + ((kc::memory_file = __FILE__, \ + kc::memory_func = __func__, \ + kc::memory_line = __LINE__, \ + 0) && 0) ? 0 : new + +} + +#ifdef // KC_MEMORY_ENABLED +#endif // KC_MEMORY_HPP diff --git a/modules/libkc/src/kc_memory.c b/modules/libkc/src/kc_memory.c new file mode 100644 index 0000000..351a4c1 --- /dev/null +++ b/modules/libkc/src/kc_memory.c @@ -0,0 +1,550 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// メモリ管理モジュール +// @copyright 2003 - 2023 Nomura Kei +// + +#include +#include +#include +#include +#include + + +// 常に本来の malloc, free を利用するため、KC_MEMORY_ENABLED を無効化する。 +#ifdef KC_MEMORY_ENABLED +#undef KC_MEMORY_ENABLED +#endif + +// KC_MEMORY_DUMP_LEAK が未定義の場合 0:無効 を定義する。 +#ifndef KC_MEMORY_DUMP_LEAK +#define KC_MEMORY_DUMP_LEAK (0) +#endif + +#include + + + +//////////////////////////////////////////////////////////////////////////////// +// +// 定数定義 +// +/** パディング */ +#define KC_MEMORY_PADDING (sizeof(void*) * 2) + + + +//////////////////////////////////////////////////////////////////////////////// +// +// 内部変数 +// +static KcMemoryHandler kc_memory_ahandler = NULL; //file = file; + entry->func = func; + entry->line = line; + entry->size = size; + entry->_mark = mark; + entry->data = (entry + 1); + entry->_prev = NULL; + entry->_next = NULL; +} + + +/** + * 指定されたエントリをメモリ管理のリストに追加します。 + * メモリがリストに追加された際、予め登録されたメモリ確保のハンドラが実行されます。 + * + * @param entry 追加するエントリ + */ +static +void kc_memory_add_entry(KcMemoryEntry* entry) +{ + kc_memory_init_entry(); + bool is_executed = kc_memory_locked_execute(kc_memory_add_entry_handler, entry, NULL); + if (is_executed) + { + } +} + + +/** + * 指定されたエントリをメモリ管理のリストに追加します。 + * + * @param entry 追加するエントリ + * @param msg メッセージ (使用されません) + * @return true (固定) + */ +static +bool kc_memory_add_entry_handler(KcMemoryEntry* entry, msg) +{ + // [tail] の一つ前に挿入する。 + entry->_next = &kc_memory_tail; + entry->_prev = kc_memory_tail._prev; + kc_memory_tail._prev->_next = entry; + kc_memory_tail._prev = entry; + return true; +} + + + +// ============================================================================ +// 同期化 +// ============================================================================= + +/** 同期化のための mutex */ +static mtx_t kc_memory_mutex; +static bool kc_memory_mutex_init(void); +static bool kc_memory_locked_execute(KcMemoryHandler handler, KcMemoryEntry* entry, const char* msg); + +/** + * 同期化実現のための mutex を初期化します。 + * + * @return true/false (初期化成功/失敗) + */ +static +bool kc_memory_mutex_init(void) +{ + static bool kc_memory_mutex_initialized = false; + if (!kc_memory_mutex_initialized) + { // 未初期化の場合のみ実施する。 + int result = mtx_init(&kc_memory_mutex, mtx_plain); + if (result == thrd_success) + { + kc_memory_mutex_initialized = true; + } + else + { + perror("kc memory : can't init mutex"); + } + } + return kc_memory_mutex_initilized; +} + + +/** + * 指定された handler の実行を同期化します。 + * mutex によるロック失敗により、handler を実行できなかった場合、false を返します。 + * + * @param handler 同期化して実行する関数 + * @param entry handler へ渡される第一引数 (操作するメモリエントリ) + * @param msg handler へ渡される第二引数 + * @return true/false (handler を実行した/handler を実行できなかった) + */ +static +bool kc_memory_locked_execute(KcMemoryHandler handler, KcMemoryEntry* entry, const char* msg) +{ + (void) kc_memory_mutex_init(); + + int is_locked = mtx_lock(&kc_memory_mutex); + if (is_locked == thrd_success) + { + // ハンドラの戻り値は Don't Care + (void) handler(entry, msg); + + bool is_unlocked = mtx_unlock(&kc_memory_mutex); + if (is_unlocked != thrd_success) + { + perror("memory : can't unlock"); + } + // アンロックに失敗しても handler 自体は実行しているため true を返す。 + return true; + } + return false; +} + + +// ============================================================================= +// 登録ハンドラの実行 +// ============================================================================= + + +/** + * メモリ確保時のハンドラを実行します。 + * ハンドラが未登録の場合何もしません。 + * + * @param entry 確保したメモリエントリ + * @param msg メッセージ + */ +static +void kc_memory_execute_ahandler(KcMemoryEntry* entry, const char* msg) +{ + if (kc_memory_ahandler != NULL) + { + kc_memory_ahandler(entry, msg); + } +} + + +/** + * メモリ解放時のハンドラを実行します。 + * ハンドラが未登録の場合何もしません。 + * + * @param entry 解放するメモリエントリ + * @param msg メッセージ + */ +static +void kc_memory_execute_fhandler(KcMemoryEntry* entry, const char* msg) +{ + if (kc_memory_fhandler != NULL) + { + kc_memory_fhandler(entry, msg); + } +} + + +/** + * エラー発生時のハンドラを実行します。 + * ハンドラが未登録の場合何もしません。 + * + * @param entry 関連するメモリエントリ + * @param msg メッセージ + */ +static +void kc_memory_execute_ehandler(KcMemoryEntry* entry, const char* msg) +{ + if (kc_memory_ehandler != NULL) + { + kc_memory_ehandler(entry, msg); + } +} + + +// ============================================================================= +// 内部関数 プロトタイプ宣言 +// ============================================================================= +static void* kc_memory_allocate(void* ptr, size_t size, + KcMemoryMark mark, const char* file, const char* func, int line); +static void kc_memory_set_entry(KcMemoryEntry* entry, size_t size, + KcMemoryMark mark, const char* file, const char* func, int line); +static void kc_memory_do_init(void); +static void kc_memory_init(void); +static void kc_memory_add(KcMemoryEntry* entry); +static void kc_memory_remove(KcMemoryEntry* entry); +static void kc_memory_exec_handler(void (*handler)(const KcMemoryEntry* entry), KcMemoryEntry* entry); + +static bool kc_memory_mtx_lock(KcMemoryEntry* entry); +static bool kc_memory_mtx_unlock(KcMemoryEntry* entry); + + +/** + * メモリ確保、解放、エラー発生時に呼び出されるハンドラを設定します。 + * + * @param allocate_handler メモリ確保時に呼び出されるハンドラ + * @param free_handler メモリ解放時に呼び出されるハンドラ + * @param error_handler メモリ確保/解放エラー発生時に呼び出されるハンドラ + */ +void kc_memory_set_memory_handler( void (*allocate_handler)(const KcMemoryEntry* entry), + void (*free_handler )(const KcMemoryEntry* entry), + void (*error_handler )(const KcMemoryEntry* entry)) +{ + kc_memory_allocate_handler = allocate_handler; + kc_memory_free_handler = free_handler; + kc_memory_error_handler = error_handler; +} + + +void kc_memory_entries( void (*handler )(const KcMemoryEntry* entry)) +{ +} + +void* kc_memory_malloc(size_t size) +{ +} + +void* kc_memory_calloc(size_t nmemb, size_t size) +{ +} + +void* kc_memory_realloc(void* ptr, size_t size) +{ +} +void kc_memory_free(void* ptr) +{ +} + + +//////////////////////////////////////////////////////////////////////////////// +// +// メモリ管理実装 +// + + +// ここでは、常に本来の malloc, free を利用するため、KC_MEMORY_ENABLED を無効化する +#ifdef KC_MEMORY_ENABLED +#undef KC_MEMORY_ENABLED +#endif + +#ifndef KC_MEMORY_DUMP_LEAK +#define KC_MEMORY_DUMP_LEAK (0) +#endif + + + +/** + * realloc(ptr, size) と同様の方法でメモリを確保します。 + * + * @param ptr メモリサイズを変更するメモリへのポインタ + * @param size 確保するメモリサイズ + * @param mark メモリ確保情報を示すマーク + * @param file 呼び出し元ソースファイル + * @param func 呼び出し元関数 + * @param line 呼び出し元ソース行番号 + * @return 確保したメモリへのポインタ + */ +static void* kc_memory_allocate(void* ptr, size_t size, + KcMemoryMark mark, const char* file, const char* func, int line) +{ + if (size == 0) + { // size == 0 の場合は、free と等価 + kc_memory_free(ptr); + return NULL; + } + + KcMemoryEntry* entry = (KcMemoryEntry*) malloc(size + sizeof(KcMemoryEntry) + KC_MEMORY_PADDING); + if (entry == NULL) + { // メモリ確保失敗 + errno = ENOMEM; + kc_memory_set_entry(&kc_memory_error, mark, size, file, func, line); + kc_exec_handler(kc_memory_error_handler, kc_memory_error); + return NULL; + } + + if (ptr != NULL) + { + KcMemoryEntry* old_entry = (KcMemoryEntry*) ptr; + switch (old_entry->_mark) + { + case KC_MEMORY_DELETE: // 削除済みメモリ + case KC_MEMORY_ALLOCATE_NEW: // new で確保したメモリ + case KC_MEMORY_ALLOCATE_NEW_ARRAY: // new[] で確保したメモリ + // 管理メモリ(エラー) + errno = EINVAL; + kc_memory_exec_handler(kc_memory_error_handler, old_entry); + return NULL; + case KC_MEMORY_ALLOCATED: + default: + // ptr 領域のデータを移動し、解放する。 + memmove((entry + 1), ptr, size); + kc_memory_free(ptr); + break; + } + } + + // 基本設定 + kc_memory_set_entry(entry, mark, file, func, line); + (void) kc_memory_add(entry); + return (entry->data); +} + + + + +/** + * 指定された entry に各値を設定します。 + * + * @param entry エントリ + * @param mark 種別マーク + * @param size メモリサイズ + * @param file 呼び出し元ソースファイル + * @param func 呼び出し元関数 + * @param line 呼び出し元関数 + */ +static void kc_memory_set_entry(KcMemoryEntry* entry, size_t size, + KcMemoryMark mark, const char* file, const char* func, int line) +{ + entry->size = size; + entry->file = file; + entry->func = func; + entry->line = line; + entry->_mark = mark; + entry->data = (entry + 1); + entry->_prev = NULL; + entry->_next = NULL; +} + + +static void kc_memory_do_init(void); +static void kc_memory_init(void); +static void kc_memory_add(KcMemoryEntry* entry); +static void kc_memory_remove(KcMemoryEntry* entry); + +static bool kc_memory_mtx_lock(KcMemoryEntry* entry); +static bool kc_memory_mtx_unlock(KcMemoryEntry* entry); + +static void (*kc_memory_allocate_handler)(const KcMemoryEntry* entry) = NULL; +static void (*kc_memory_free_handler) (const KcMemoryEntry* entry) = NULL; +static void (*kc_memory_error_handler) (const KcMemoryEntry* entry) = NULL; +static KcMemoryEntry kc_memory_head; +static KcMemoryEntry kc_memory_tail; +static KcMemoryEntry kc_memory_error; +static thread_local bool kc_memory_nolock = false; +static once_flag kc_memory_once_flag = ONCE_FLAG_INIT; +static mtx_t kc_memory_mutex; + + + +/** + * メモリエントリ。 + */ +//typedef struct KcMemoryEntry_ +//{ +// const char* file; /*!< メモリ確保ファイル名 */ +// const char* func; /*!< メモリ確保関数名 */ +// int line; /*!< メモリ確保行番号 */ +// int size; /*!< 確保サイズ */ +// int status; /*!< 確保メモリ状態 */ +// struct KcMemoryEntry_* _prev; /*!< 前の管理メモリポインタ */ +// struct KcMemoryEntry_* _next; /*!< 次の管理メモリポインタ */ +// uint8_t data[]; /*!< データ */ +//} KcMemoryEntry; + + diff --git a/modules/libkc/Makefile b/modules/libkc/Makefile new file mode 100644 index 0000000..efd29fb --- /dev/null +++ b/modules/libkc/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libkc +TARGET = $(NAME).so +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/modules/libkc/include/kc.h b/modules/libkc/include/kc.h new file mode 100644 index 0000000..5f628ed --- /dev/null +++ b/modules/libkc/include/kc.h @@ -0,0 +1,38 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// KC Header File +// +#ifndef KC_H +#define KC_H + +#if defined(__cplusplus) && (__cplusplus >= 201103L) +// ============================================================================= +// C++11 +// ============================================================================= +#include + +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) +// ============================================================================= +// C11 +// ============================================================================= +#include +#include +#include +#define thread_local _Thread_local +#define nullptr NULL + +#else +// ============================================================================= +// ERROR +// ============================================================================= +#error "suuports C11/C++1 or later" + + +// ============================================================================= +// 共通定義 +// ============================================================================= +#define UNUSED_VARIABLE(val) (void)(val) + + +#endif // C11 +#endif // KC_H diff --git a/modules/libkc/include/kc_memory.h b/modules/libkc/include/kc_memory.h new file mode 100644 index 0000000..e54c14f --- /dev/null +++ b/modules/libkc/include/kc_memory.h @@ -0,0 +1,88 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// メモリ管理モジュール ヘッダファイル +// @copyright 2003 - 2023 Nomura Kei +// +#ifndef KC_MEMORY_H +#define KC_MEMORY_H + +#include + +#ifdef __cplusplus +extern "C" { +namespace kc { +using namespace std; +#endif + + +#ifdef KC_MEMORY_ENABLED +// メモリ管理有効 +#define malloc(size) kc_memory_malloc ( size, __FILE__, __func__, __LINE__) +#define calloc(nmemb, size) kc_memory_calloc (nmemb, size, __FILE__, __func__, __LINE__) +#define realloc(ptr, size) kc_memory_realloc(ptr , size, __FILE__, __func__, __LINE__) +#define free(ptr) kc_memory_free (ptr) + +#else +#include + +#endif // !KC_MEMORY_ENABLED + + + +// 管理メモリ種別を表すための識別マーク +#define KC_MEMORY_MARK_HEAD (0x55AA5A00) +#define KC_MEMORY_MARK_MASK (0xFFFFFF00) +typedef enum +{ + KC_MEMORY_DELETED = KC_MEMORY_MARK_HEAD | 0x00, //!< メモリが解放されている + KC_MEMORY_ALLOCATED = KC_MEMORY_MARK_HEAD | 0x01, //!< メモリが確保されている + KC_MEMORY_ALLOCATED_NEW = KC_MEMORY_MARK_HEAD | 0x02, //!< new により確保されたメモリ + KC_MEMORY_ALLOCATED_NEW_ARRAY = KC_MEMORY_MARK_HEAD | 0x03 //!< new[] により確保されたメモリ +} KcMemoryMark; + + +/** + * 指定されたメモリ管理用種別マークが正しいか判定します。 + * + * @param mark 種別マーク + * @return true/false (管理されているメモリ/管理されていないメモリ) + */ +#define kc_memory_is_valid_mark(mark) ((mark & KC_MEMORY_MARK_MASK) == SC_MEMORY_MARK_HEAD) + + +/** + * メモリエントリ。 + */ +typedef struct KcMemoryEntry_ +{ + const char* file; /*!< メモリ確保ファイル名 */ + const char* func; /*!< メモリ確保関数名 */ + int line; /*!< メモリ確保行番号 */ + int size; /*!< 確保サイズ */ + int _mark; /*!< 確保メモリ状態 */ + struct KcMemoryEntry_* _prev; /*!< 前の管理メモリポインタ */ + struct KcMemoryEntry_* _next; /*!< 次の管理メモリポインタ */ + void* data; /*!< データ */ + // 構造体末尾の配列に限りサイズ省略可能 (C99 : incomplete array) +} KcMemoryEntry; + + +// ハンドラ関数ポインタ +typedef bool (*KcMemoryHandler)(KcMemoryEntry* entry, const char* msg); + + +// プロトタイプ宣言 +void kc_memory_set_handlers(KcMemoryHandler allocate, KcMemoryHandler free, KcMemoryHandler error); +void kc_memory_dump(int mode); + +void* kc_memory_malloc ( size_t size, const char* file, const char* func, int line); +void* kc_memory_calloc (size_t nmemb, size_t size, const char* file, const char* func, int line); +void* kc_memory_realloc(void* ptr , size_t size, const char* file, const char* func, int line); +void kc_memory_free (void* ptr); + + +#ifdef __cplusplus +} // namespace kc +} // extern "C" +#endif +#endif // KC_MEMORY_H diff --git a/modules/libkc/include/kc_memory.hpp b/modules/libkc/include/kc_memory.hpp new file mode 100644 index 0000000..0602b74 --- /dev/null +++ b/modules/libkc/include/kc_memory.hpp @@ -0,0 +1,56 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// メモリ管理モジュール ヘッダファイル +// @copyright 2003 - 2023 Nomura Kei +// +#ifndef KC_MEMORY_HPP +#define KC_MEMORY_HPP + +#include + + +//////////////////////////////////////////////////////////////////////////////// +// +// KC_MEMORY_ENABLED が定義されている場合、メモリ管理が有効となります。 +// +#ifdef KC_MEMORY_ENABLED +namespace kc { + +#if (__cplusplus > 201703L) +// C++20 (C++2a) [C++20 は、202002L] +[[nodiscard]] void* operator new(std::size_t size); +[[nodiscard]] void* operator new(std::size_t size, std::align_val_t alignment); +[[nodiscard]] void* operator new(std::size_t size, const std::nothrow_t&) noexcept; +[[nodiscard]] void* operator new(std::size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept; +[[nodiscard]] void* operator new(std::size_t size, void* ptr) noexcept; + +#elif (__cplusplus >= 201703L) +// C++17 (C++1z) +void* operator new(std::size size); +void* operator new(std::size size, std::align_val_t alignment); +void* operator new(std::size_t size, const std::nothrow_t&) noexcept; +void* operator new(std::size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept; +void* operator new(std::size_t size, void* ptr) noexcept; + +#else +// C++14 (C++1y), C++11 (C++0x) +void* operator new(std::size_t size); +void* operator new(std::size_t size, void* ptr) noexcept; + +#endif + + +extern thread_local const char* memory_file; +extern thread_local const char* memory_func; +extern thread_local int memory_line; + +#define new \ + ((kc::memory_file = __FILE__, \ + kc::memory_func = __func__, \ + kc::memory_line = __LINE__, \ + 0) && 0) ? 0 : new + +} + +#ifdef // KC_MEMORY_ENABLED +#endif // KC_MEMORY_HPP diff --git a/modules/libkc/src/kc_memory.c b/modules/libkc/src/kc_memory.c new file mode 100644 index 0000000..351a4c1 --- /dev/null +++ b/modules/libkc/src/kc_memory.c @@ -0,0 +1,550 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// メモリ管理モジュール +// @copyright 2003 - 2023 Nomura Kei +// + +#include +#include +#include +#include +#include + + +// 常に本来の malloc, free を利用するため、KC_MEMORY_ENABLED を無効化する。 +#ifdef KC_MEMORY_ENABLED +#undef KC_MEMORY_ENABLED +#endif + +// KC_MEMORY_DUMP_LEAK が未定義の場合 0:無効 を定義する。 +#ifndef KC_MEMORY_DUMP_LEAK +#define KC_MEMORY_DUMP_LEAK (0) +#endif + +#include + + + +//////////////////////////////////////////////////////////////////////////////// +// +// 定数定義 +// +/** パディング */ +#define KC_MEMORY_PADDING (sizeof(void*) * 2) + + + +//////////////////////////////////////////////////////////////////////////////// +// +// 内部変数 +// +static KcMemoryHandler kc_memory_ahandler = NULL; //file = file; + entry->func = func; + entry->line = line; + entry->size = size; + entry->_mark = mark; + entry->data = (entry + 1); + entry->_prev = NULL; + entry->_next = NULL; +} + + +/** + * 指定されたエントリをメモリ管理のリストに追加します。 + * メモリがリストに追加された際、予め登録されたメモリ確保のハンドラが実行されます。 + * + * @param entry 追加するエントリ + */ +static +void kc_memory_add_entry(KcMemoryEntry* entry) +{ + kc_memory_init_entry(); + bool is_executed = kc_memory_locked_execute(kc_memory_add_entry_handler, entry, NULL); + if (is_executed) + { + } +} + + +/** + * 指定されたエントリをメモリ管理のリストに追加します。 + * + * @param entry 追加するエントリ + * @param msg メッセージ (使用されません) + * @return true (固定) + */ +static +bool kc_memory_add_entry_handler(KcMemoryEntry* entry, msg) +{ + // [tail] の一つ前に挿入する。 + entry->_next = &kc_memory_tail; + entry->_prev = kc_memory_tail._prev; + kc_memory_tail._prev->_next = entry; + kc_memory_tail._prev = entry; + return true; +} + + + +// ============================================================================ +// 同期化 +// ============================================================================= + +/** 同期化のための mutex */ +static mtx_t kc_memory_mutex; +static bool kc_memory_mutex_init(void); +static bool kc_memory_locked_execute(KcMemoryHandler handler, KcMemoryEntry* entry, const char* msg); + +/** + * 同期化実現のための mutex を初期化します。 + * + * @return true/false (初期化成功/失敗) + */ +static +bool kc_memory_mutex_init(void) +{ + static bool kc_memory_mutex_initialized = false; + if (!kc_memory_mutex_initialized) + { // 未初期化の場合のみ実施する。 + int result = mtx_init(&kc_memory_mutex, mtx_plain); + if (result == thrd_success) + { + kc_memory_mutex_initialized = true; + } + else + { + perror("kc memory : can't init mutex"); + } + } + return kc_memory_mutex_initilized; +} + + +/** + * 指定された handler の実行を同期化します。 + * mutex によるロック失敗により、handler を実行できなかった場合、false を返します。 + * + * @param handler 同期化して実行する関数 + * @param entry handler へ渡される第一引数 (操作するメモリエントリ) + * @param msg handler へ渡される第二引数 + * @return true/false (handler を実行した/handler を実行できなかった) + */ +static +bool kc_memory_locked_execute(KcMemoryHandler handler, KcMemoryEntry* entry, const char* msg) +{ + (void) kc_memory_mutex_init(); + + int is_locked = mtx_lock(&kc_memory_mutex); + if (is_locked == thrd_success) + { + // ハンドラの戻り値は Don't Care + (void) handler(entry, msg); + + bool is_unlocked = mtx_unlock(&kc_memory_mutex); + if (is_unlocked != thrd_success) + { + perror("memory : can't unlock"); + } + // アンロックに失敗しても handler 自体は実行しているため true を返す。 + return true; + } + return false; +} + + +// ============================================================================= +// 登録ハンドラの実行 +// ============================================================================= + + +/** + * メモリ確保時のハンドラを実行します。 + * ハンドラが未登録の場合何もしません。 + * + * @param entry 確保したメモリエントリ + * @param msg メッセージ + */ +static +void kc_memory_execute_ahandler(KcMemoryEntry* entry, const char* msg) +{ + if (kc_memory_ahandler != NULL) + { + kc_memory_ahandler(entry, msg); + } +} + + +/** + * メモリ解放時のハンドラを実行します。 + * ハンドラが未登録の場合何もしません。 + * + * @param entry 解放するメモリエントリ + * @param msg メッセージ + */ +static +void kc_memory_execute_fhandler(KcMemoryEntry* entry, const char* msg) +{ + if (kc_memory_fhandler != NULL) + { + kc_memory_fhandler(entry, msg); + } +} + + +/** + * エラー発生時のハンドラを実行します。 + * ハンドラが未登録の場合何もしません。 + * + * @param entry 関連するメモリエントリ + * @param msg メッセージ + */ +static +void kc_memory_execute_ehandler(KcMemoryEntry* entry, const char* msg) +{ + if (kc_memory_ehandler != NULL) + { + kc_memory_ehandler(entry, msg); + } +} + + +// ============================================================================= +// 内部関数 プロトタイプ宣言 +// ============================================================================= +static void* kc_memory_allocate(void* ptr, size_t size, + KcMemoryMark mark, const char* file, const char* func, int line); +static void kc_memory_set_entry(KcMemoryEntry* entry, size_t size, + KcMemoryMark mark, const char* file, const char* func, int line); +static void kc_memory_do_init(void); +static void kc_memory_init(void); +static void kc_memory_add(KcMemoryEntry* entry); +static void kc_memory_remove(KcMemoryEntry* entry); +static void kc_memory_exec_handler(void (*handler)(const KcMemoryEntry* entry), KcMemoryEntry* entry); + +static bool kc_memory_mtx_lock(KcMemoryEntry* entry); +static bool kc_memory_mtx_unlock(KcMemoryEntry* entry); + + +/** + * メモリ確保、解放、エラー発生時に呼び出されるハンドラを設定します。 + * + * @param allocate_handler メモリ確保時に呼び出されるハンドラ + * @param free_handler メモリ解放時に呼び出されるハンドラ + * @param error_handler メモリ確保/解放エラー発生時に呼び出されるハンドラ + */ +void kc_memory_set_memory_handler( void (*allocate_handler)(const KcMemoryEntry* entry), + void (*free_handler )(const KcMemoryEntry* entry), + void (*error_handler )(const KcMemoryEntry* entry)) +{ + kc_memory_allocate_handler = allocate_handler; + kc_memory_free_handler = free_handler; + kc_memory_error_handler = error_handler; +} + + +void kc_memory_entries( void (*handler )(const KcMemoryEntry* entry)) +{ +} + +void* kc_memory_malloc(size_t size) +{ +} + +void* kc_memory_calloc(size_t nmemb, size_t size) +{ +} + +void* kc_memory_realloc(void* ptr, size_t size) +{ +} +void kc_memory_free(void* ptr) +{ +} + + +//////////////////////////////////////////////////////////////////////////////// +// +// メモリ管理実装 +// + + +// ここでは、常に本来の malloc, free を利用するため、KC_MEMORY_ENABLED を無効化する +#ifdef KC_MEMORY_ENABLED +#undef KC_MEMORY_ENABLED +#endif + +#ifndef KC_MEMORY_DUMP_LEAK +#define KC_MEMORY_DUMP_LEAK (0) +#endif + + + +/** + * realloc(ptr, size) と同様の方法でメモリを確保します。 + * + * @param ptr メモリサイズを変更するメモリへのポインタ + * @param size 確保するメモリサイズ + * @param mark メモリ確保情報を示すマーク + * @param file 呼び出し元ソースファイル + * @param func 呼び出し元関数 + * @param line 呼び出し元ソース行番号 + * @return 確保したメモリへのポインタ + */ +static void* kc_memory_allocate(void* ptr, size_t size, + KcMemoryMark mark, const char* file, const char* func, int line) +{ + if (size == 0) + { // size == 0 の場合は、free と等価 + kc_memory_free(ptr); + return NULL; + } + + KcMemoryEntry* entry = (KcMemoryEntry*) malloc(size + sizeof(KcMemoryEntry) + KC_MEMORY_PADDING); + if (entry == NULL) + { // メモリ確保失敗 + errno = ENOMEM; + kc_memory_set_entry(&kc_memory_error, mark, size, file, func, line); + kc_exec_handler(kc_memory_error_handler, kc_memory_error); + return NULL; + } + + if (ptr != NULL) + { + KcMemoryEntry* old_entry = (KcMemoryEntry*) ptr; + switch (old_entry->_mark) + { + case KC_MEMORY_DELETE: // 削除済みメモリ + case KC_MEMORY_ALLOCATE_NEW: // new で確保したメモリ + case KC_MEMORY_ALLOCATE_NEW_ARRAY: // new[] で確保したメモリ + // 管理メモリ(エラー) + errno = EINVAL; + kc_memory_exec_handler(kc_memory_error_handler, old_entry); + return NULL; + case KC_MEMORY_ALLOCATED: + default: + // ptr 領域のデータを移動し、解放する。 + memmove((entry + 1), ptr, size); + kc_memory_free(ptr); + break; + } + } + + // 基本設定 + kc_memory_set_entry(entry, mark, file, func, line); + (void) kc_memory_add(entry); + return (entry->data); +} + + + + +/** + * 指定された entry に各値を設定します。 + * + * @param entry エントリ + * @param mark 種別マーク + * @param size メモリサイズ + * @param file 呼び出し元ソースファイル + * @param func 呼び出し元関数 + * @param line 呼び出し元関数 + */ +static void kc_memory_set_entry(KcMemoryEntry* entry, size_t size, + KcMemoryMark mark, const char* file, const char* func, int line) +{ + entry->size = size; + entry->file = file; + entry->func = func; + entry->line = line; + entry->_mark = mark; + entry->data = (entry + 1); + entry->_prev = NULL; + entry->_next = NULL; +} + + +static void kc_memory_do_init(void); +static void kc_memory_init(void); +static void kc_memory_add(KcMemoryEntry* entry); +static void kc_memory_remove(KcMemoryEntry* entry); + +static bool kc_memory_mtx_lock(KcMemoryEntry* entry); +static bool kc_memory_mtx_unlock(KcMemoryEntry* entry); + +static void (*kc_memory_allocate_handler)(const KcMemoryEntry* entry) = NULL; +static void (*kc_memory_free_handler) (const KcMemoryEntry* entry) = NULL; +static void (*kc_memory_error_handler) (const KcMemoryEntry* entry) = NULL; +static KcMemoryEntry kc_memory_head; +static KcMemoryEntry kc_memory_tail; +static KcMemoryEntry kc_memory_error; +static thread_local bool kc_memory_nolock = false; +static once_flag kc_memory_once_flag = ONCE_FLAG_INIT; +static mtx_t kc_memory_mutex; + + + +/** + * メモリエントリ。 + */ +//typedef struct KcMemoryEntry_ +//{ +// const char* file; /*!< メモリ確保ファイル名 */ +// const char* func; /*!< メモリ確保関数名 */ +// int line; /*!< メモリ確保行番号 */ +// int size; /*!< 確保サイズ */ +// int status; /*!< 確保メモリ状態 */ +// struct KcMemoryEntry_* _prev; /*!< 前の管理メモリポインタ */ +// struct KcMemoryEntry_* _next; /*!< 次の管理メモリポインタ */ +// uint8_t data[]; /*!< データ */ +//} KcMemoryEntry; + + diff --git a/modules/main/src/main.c b/modules/main/src/main.c index 897d709..bdf609e 100644 --- a/modules/main/src/main.c +++ b/modules/main/src/main.c @@ -1,10 +1,26 @@ #include + +void compile(void); +void execute(void); + +void compile(void) +{ + printf("compile\n"); +} + +void execute(void) +{ + printf("execute\n"); +} + + int main(int argc, char* argv[]) { (void) argc; (void) argv; - printf("Test\n"); + compile(); + execute(); return 0; }