summaryrefslogtreecommitdiffstats
path: root/pceplib/pcep_utils_memory.c
diff options
context:
space:
mode:
Diffstat (limited to 'pceplib/pcep_utils_memory.c')
-rw-r--r--pceplib/pcep_utils_memory.c224
1 files changed, 224 insertions, 0 deletions
diff --git a/pceplib/pcep_utils_memory.c b/pceplib/pcep_utils_memory.c
new file mode 100644
index 0000000..c564705
--- /dev/null
+++ b/pceplib/pcep_utils_memory.c
@@ -0,0 +1,224 @@
+/*
+ * This file is part of the PCEPlib, a PCEP protocol library.
+ *
+ * Copyright (C) 2020 Volta Networks https://voltanet.io/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * Author : Brady Johnson <brady@voltanet.io>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "pcep_utils_logging.h"
+#include "pcep_utils_memory.h"
+
+/* Set default values for memory function pointers */
+static pceplib_malloc_func mfunc = NULL;
+static pceplib_calloc_func cfunc = NULL;
+static pceplib_realloc_func rfunc = NULL;
+static pceplib_strdup_func sfunc = NULL;
+static pceplib_free_func ffunc = NULL;
+
+/* Internal memory types */
+struct pceplib_memory_type pceplib_infra_mt = {
+ .memory_type_name = "PCEPlib Infrastructure memory",
+ .total_bytes_allocated = 0,
+ .num_allocates = 0,
+ .total_bytes_freed = 0,
+ .num_frees = 0};
+struct pceplib_memory_type pceplib_messages_mt = {
+ .memory_type_name = "PCEPlib Messages memory",
+ .total_bytes_allocated = 0,
+ .num_allocates = 0,
+ .total_bytes_freed = 0,
+ .num_frees = 0};
+
+/* The memory type pointers default to the internal memory types */
+void *PCEPLIB_INFRA = &pceplib_infra_mt;
+void *PCEPLIB_MESSAGES = &pceplib_messages_mt;
+
+/* Initialize memory function pointers and memory type pointers */
+bool pceplib_memory_initialize(void *pceplib_infra_mt,
+ void *pceplib_messages_mt,
+ pceplib_malloc_func mf, pceplib_calloc_func cf,
+ pceplib_realloc_func rf, pceplib_strdup_func sf,
+ pceplib_free_func ff)
+{
+ PCEPLIB_INFRA = (pceplib_infra_mt ? pceplib_infra_mt : PCEPLIB_INFRA);
+ PCEPLIB_MESSAGES =
+ (pceplib_messages_mt ? pceplib_messages_mt : PCEPLIB_MESSAGES);
+
+ mfunc = (mf ? mf : mfunc);
+ cfunc = (cf ? cf : cfunc);
+ rfunc = (rf ? rf : rfunc);
+ sfunc = (sf ? sf : sfunc);
+ ffunc = (ff ? ff : ffunc);
+
+ return true;
+}
+
+void pceplib_memory_reset()
+{
+ pceplib_infra_mt.total_bytes_allocated = 0;
+ pceplib_infra_mt.num_allocates = 0;
+ pceplib_infra_mt.total_bytes_freed = 0;
+ pceplib_infra_mt.num_frees = 0;
+
+ pceplib_messages_mt.total_bytes_allocated = 0;
+ pceplib_messages_mt.num_allocates = 0;
+ pceplib_messages_mt.total_bytes_freed = 0;
+ pceplib_messages_mt.num_frees = 0;
+}
+
+void pceplib_memory_dump()
+{
+ if (PCEPLIB_INFRA) {
+ pcep_log(
+ LOG_INFO,
+ "%s: Memory Type [%s] Total [allocs, alloc bytes, frees] [%d, %d, %d]",
+ __func__,
+ ((struct pceplib_memory_type *)PCEPLIB_INFRA)
+ ->memory_type_name,
+ ((struct pceplib_memory_type *)PCEPLIB_INFRA)
+ ->num_allocates,
+ ((struct pceplib_memory_type *)PCEPLIB_INFRA)
+ ->total_bytes_allocated,
+ ((struct pceplib_memory_type *)PCEPLIB_INFRA)
+ ->num_frees);
+ }
+
+ if (PCEPLIB_MESSAGES) {
+ pcep_log(
+ LOG_INFO,
+ "%s: Memory Type [%s] Total [allocs, alloc bytes, frees] [%d, %d, %d]",
+ __func__,
+ ((struct pceplib_memory_type *)PCEPLIB_MESSAGES)
+ ->memory_type_name,
+ ((struct pceplib_memory_type *)PCEPLIB_MESSAGES)
+ ->num_allocates,
+ ((struct pceplib_memory_type *)PCEPLIB_MESSAGES)
+ ->total_bytes_allocated,
+ ((struct pceplib_memory_type *)PCEPLIB_MESSAGES)
+ ->num_frees);
+ }
+}
+
+/* PCEPlib memory functions:
+ * They either call the supplied function pointers, or use the internal
+ * implementations, which just increment simple counters and call the
+ * C stdlib memory implementations. */
+
+void *pceplib_malloc(void *mem_type, size_t size)
+{
+ if (mfunc == NULL) {
+ if (mem_type != NULL) {
+ ((struct pceplib_memory_type *)mem_type)
+ ->total_bytes_allocated += size;
+ ((struct pceplib_memory_type *)mem_type)
+ ->num_allocates++;
+ }
+
+ return malloc(size);
+ } else {
+ return mfunc(mem_type, size);
+ }
+}
+
+void *pceplib_calloc(void *mem_type, size_t size)
+{
+ if (cfunc == NULL) {
+ if (mem_type != NULL) {
+ ((struct pceplib_memory_type *)mem_type)
+ ->total_bytes_allocated += size;
+ ((struct pceplib_memory_type *)mem_type)
+ ->num_allocates++;
+ }
+
+ return calloc(1, size);
+ } else {
+ return cfunc(mem_type, size);
+ }
+}
+
+void *pceplib_realloc(void *mem_type, void *ptr, size_t size)
+{
+ if (rfunc == NULL) {
+ if (mem_type != NULL) {
+ /* TODO should add previous allocated bytes to
+ * total_bytes_freed */
+ ((struct pceplib_memory_type *)mem_type)
+ ->total_bytes_allocated += size;
+ ((struct pceplib_memory_type *)mem_type)
+ ->num_allocates++;
+ }
+
+ return realloc(ptr, size);
+ } else {
+ return rfunc(mem_type, ptr, size);
+ }
+}
+
+void *pceplib_strdup(void *mem_type, const char *str)
+{
+ if (sfunc == NULL) {
+ if (mem_type != NULL) {
+ ((struct pceplib_memory_type *)mem_type)
+ ->total_bytes_allocated += strlen(str);
+ ((struct pceplib_memory_type *)mem_type)
+ ->num_allocates++;
+ }
+
+ return strdup(str);
+ } else {
+ return sfunc(mem_type, str);
+ }
+}
+
+void pceplib_free(void *mem_type, void *ptr)
+{
+ if (ffunc == NULL) {
+ if (mem_type != NULL) {
+ /* TODO in order to increment total_bytes_freed, we need
+ * to keep track of the bytes allocated per pointer.
+ * Currently not implemented. */
+ ((struct pceplib_memory_type *)mem_type)->num_frees++;
+ if (((struct pceplib_memory_type *)mem_type)
+ ->num_allocates
+ < ((struct pceplib_memory_type *)mem_type)
+ ->num_frees) {
+ pcep_log(
+ LOG_ERR,
+ "%s: pceplib_free MT N_Alloc < N_Free: MemType [%s] NumAllocates [%d] NumFrees [%d]",
+ __func__,
+ ((struct pceplib_memory_type *)mem_type)
+ ->memory_type_name,
+ ((struct pceplib_memory_type *)mem_type)
+ ->num_allocates,
+ ((struct pceplib_memory_type *)mem_type)
+ ->num_frees);
+ }
+ }
+
+ return free(ptr);
+ } else {
+ return ffunc(mem_type, ptr);
+ }
+}