summaryrefslogtreecommitdiff
path: root/src/glibext
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2024-01-20 23:04:22 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2024-01-20 23:04:22 (GMT)
commit0fac40d5a5752e8d7b92f57ea3cfa089f13a2d1f (patch)
tree568009609e58402f44eca0ebb77f6b3e00071a69 /src/glibext
parent6c6e6b5ec27e2c236bd339a317e5bbf049eccefa (diff)
Define a memory allocator for large sets.
Diffstat (limited to 'src/glibext')
-rw-r--r--src/glibext/Makefile.am4
-rw-r--r--src/glibext/umemslice-int.h71
-rw-r--r--src/glibext/umemslice.c423
-rw-r--r--src/glibext/umemslice.h80
4 files changed, 577 insertions, 1 deletions
diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am
index ad98809..986bbd1 100644
--- a/src/glibext/Makefile.am
+++ b/src/glibext/Makefile.am
@@ -30,7 +30,9 @@ libglibext_la_SOURCES = \
seq.h seq.c \
signal.h signal.c \
singleton.h singleton.c \
- linesegment.h linesegment.c
+ linesegment.h linesegment.c \
+ umemslice-int.h \
+ umemslice.h umemslice.c
if BUILD_GTK_SUPPORT
diff --git a/src/glibext/umemslice-int.h b/src/glibext/umemslice-int.h
new file mode 100644
index 0000000..36cc2d4
--- /dev/null
+++ b/src/glibext/umemslice-int.h
@@ -0,0 +1,71 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * umemslice-int.h - prototypes internes pour les allocations en série d'un même type d'objets
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_UMEMSLICE_INT_H
+#define _GLIBEXT_UMEMSLICE_INT_H
+
+
+#include <stdbool.h>
+
+
+#include "umemslice.h"
+
+
+
+/* Informations portant sur un bloc */
+typedef struct _slice_slab_info_t
+{
+ void *data_max; /* Zone de débordement */
+ umem_slice_iter_t iter; /* Données pour l'utilisateur */
+
+} slice_slab_info_t;
+
+#define SLICE_INFO_SIZE (sizeof(void *) + sizeof(umem_slice_iter_t))
+
+
+/* Allocateur s'appuyant sur des séries d'objets de même type (instance) */
+struct _GUMemSlice
+{
+ GObject parent; /* A laisser en premier */
+
+ size_t obj_size; /* Taille des objects */
+
+ slice_slab_info_t *slabs; /* Ensembles complets */
+ slice_slab_info_t *last; /* Accès à l'ultime tranche */
+
+};
+
+/* Allocateur s'appuyant sur des séries d'objets de même type (classe) */
+struct _GUMemSliceClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un allocateur de zones identiques. */
+bool g_umem_slice_create(GUMemSlice *, size_t);
+
+
+
+#endif /* _GLIBEXT_UMEMSLICE_INT_H */
diff --git a/src/glibext/umemslice.c b/src/glibext/umemslice.c
new file mode 100644
index 0000000..1bdb4fe
--- /dev/null
+++ b/src/glibext/umemslice.c
@@ -0,0 +1,423 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * umemslice.c - allocations en série d'un même type d'objets
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "umemslice.h"
+
+
+#include <assert.h>
+#include <stdint.h>
+#include <sys/mman.h>
+
+
+#include "umemslice-int.h"
+#include "../core/logs.h"
+
+
+
+/* --------------------------- GESTION D'UN BLOC D'OBJETS --------------------------- */
+
+
+#define SLAB_SIZE (8 * 1024 * 1024)
+//#define SLAB_SIZE (32 * 1024)
+
+/* Alloue un espace pour un nouveau slab en mémoire. */
+static slice_slab_info_t *create_slice_slab(size_t, size_t);
+
+/* Supprime l'espace correspondant à un slab en mémoire. */
+static void destroy_slice_slab(slice_slab_info_t *, size_t);
+
+
+
+/* --------------------------- ALLOCATIONS ET LIBERATIONS --------------------------- */
+
+
+/* Initialise la classe des allocateurs d'objets similaires. */
+static void g_umem_slice_class_init(GUMemSliceClass *);
+
+/* Initialise une instance d'allocateur d'objets similaires. */
+static void g_umem_slice_init(GUMemSlice *);
+
+/* Supprime toutes les références externes. */
+static void g_umem_slice_dispose(GUMemSlice *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_umem_slice_finalize(GUMemSlice *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* GESTION D'UN BLOC D'OBJETS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : slab_size = taille totale du slab à allouer. *
+* obj_size = taille des futurs objets contenus. *
+* *
+* Description : Alloue un espace pour un nouveau slab en mémoire. *
+* *
+* Retour : Adresse du gestionnaire du slab mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static slice_slab_info_t *create_slice_slab(size_t slab_size, size_t obj_size)
+{
+ slice_slab_info_t *result; /* Structure à retourner */
+ void *data; /* Zone de mémoire allouée */
+ int ret; /* Bilan d'une précision */
+ size_t quantity; /* Quantité d'objets allouable */
+
+ assert(obj_size % sizeof(unsigned long) == 0);
+
+ data = mmap(NULL, slab_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS/* | MAP_POPULATE*/, -1, 0);
+
+ if (data == MAP_FAILED)
+ {
+ LOG_ERROR_N("mmap");
+ result = NULL;
+ goto exit;
+ }
+
+ ret = madvise(data, slab_size, MADV_SEQUENTIAL);
+ if (ret == -1)
+ LOG_ERROR_N("madvise");
+
+ /* Initialisation du gestionnaire */
+
+ result = data;
+
+ quantity = (slab_size - SLICE_INFO_SIZE) / obj_size;
+
+ //result->data_max = ((uint8_t *)data) + (quantity * obj_size);
+
+ result->iter.data_end = ((uint8_t *)data) + SLICE_INFO_SIZE;
+ result->iter.next = NULL;
+
+ result->data_max = result->iter.data_end + (quantity * obj_size);
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : slab = gestionnaire d'une zone mémoire à manipuler. *
+* slab_size = taille totale du slab à allouer. *
+* *
+* Description : Supprime l'espace correspondant à un slab en mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void destroy_slice_slab(slice_slab_info_t *slab, size_t slab_size)
+{
+ void *data; /* Zone de mémoire allouée */
+ int ret; /* Bilan de l'opération */
+
+ data = slab;
+
+ ret = munmap(data, slab_size);
+
+ if (ret == -1)
+ LOG_ERROR_N("munmap");
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* ALLOCATIONS ET LIBERATIONS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un allocateur en série d'objets depuis une même zone mémoire. */
+G_DEFINE_TYPE(GUMemSlice, g_umem_slice, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des allocateurs d'objets similaires. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_umem_slice_class_init(GUMemSliceClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_umem_slice_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_umem_slice_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : slice = instance à initialiser. *
+* *
+* Description : Initialise une instance d'allocateur d'objets similaires. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_umem_slice_init(GUMemSlice *slice)
+{
+ slice->obj_size = 0;
+
+ slice->slabs = NULL;
+ slice->last = NULL;
+
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : slice = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_umem_slice_dispose(GUMemSlice *slice)
+{
+ G_OBJECT_CLASS(g_umem_slice_parent_class)->dispose(G_OBJECT(slice));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : slice = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_umem_slice_finalize(GUMemSlice *slice)
+{
+ slice_slab_info_t *slab; /* Slab à libérer entièrement */
+ slice_slab_info_t *next; /* Slab suivant à traiter */
+
+ for (slab = slice->slabs; slab != NULL; slab = next)
+ {
+ if (slab->iter.next == NULL)
+ next = NULL;
+ else
+ next = (slice_slab_info_t *)(((uint8_t *)slab->iter.next) - sizeof(void *));
+
+ destroy_slice_slab(slab, SLAB_SIZE);
+
+ }
+
+ G_OBJECT_CLASS(g_umem_slice_parent_class)->finalize(G_OBJECT(slice));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : size = taille des objets à allouer en mémoire. *
+* *
+* Description : Crée un allocateur dédié à la création de zones identiques. *
+* *
+* Retour : Allocateur mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GUMemSlice *g_umem_slice_new(size_t size)
+{
+ GUMemSlice *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_UMEM_SLICE, NULL);
+
+ if (!g_umem_slice_create(result, size))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : slice = instance à initialiser pleinement. *
+* size = taille des objets à allouer en mémoire. *
+* *
+* Description : Met en place un allocateur de zones identiques. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_umem_slice_create(GUMemSlice *slice, size_t size)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ slice->obj_size = size;
+
+ slice->slabs = create_slice_slab(SLAB_SIZE, size);
+ slice->last = slice->slabs;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : slice = allocateur à manipuler. *
+* *
+* Description : Alloue une nouvelle zone de la taille attendue en mémoire. *
+* *
+* Retour : Adresse de la zone nouvellement disponible ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void *g_umem_slice_alloc(GUMemSlice *slice)
+{
+ void *result; /* Allocation à retourner */
+ slice_slab_info_t *slab; /* Slab concerné par l'opérat° */
+ umem_slice_iter_t *iter; /* Tête d'écriture courante */
+
+ slab = slice->last;
+
+ assert(slab != NULL);
+
+ if (slab->iter.data_end == slab->data_max)
+ {
+ slice->last = create_slice_slab(SLAB_SIZE, slice->obj_size);
+
+ slab->iter.next = &slice->last->iter;
+
+ slab = slice->last;
+
+ }
+
+ iter = &slab->iter;
+
+ result = iter->data_end;
+
+ *((unsigned long *)&iter->data_end) += slice->obj_size;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : slice = allocateur à manipuler. *
+* val = valeur de 64 bits à intégrer. *
+* *
+* Description : Mémorise un mot de 64 bits dans une nouvelle zone en mémoire.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_umem_slice_put_uint64(GUMemSlice *slice, uint64_t val)
+{
+ slice_slab_info_t *slab; /* Slab concerné par l'opérat° */
+
+ assert(slice->obj_size == sizeof(uint64_t));
+
+ slab = slice->last;
+
+ assert(slab != NULL);
+
+ if (slab->iter.data_end == slab->data_max)
+ {
+ slice->last = create_slice_slab(SLAB_SIZE, slice->obj_size);
+
+ slab->iter.next = &slice->last->iter;
+
+ slab = slice->last;
+
+ }
+
+ *slab->iter.data_end_uint64 = val;
+
+ slab->iter.data_end_ul += slice->obj_size;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : slice = allocateur à consulter. *
+* *
+* Description : Fournit un itérateur pour les données allouées. *
+* *
+* Retour : Premier descripteur des données allouées. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const umem_slice_iter_t *g_umem_slice_get_iter(const GUMemSlice *slice)
+{
+ const umem_slice_iter_t *result; /* Pointeur à retourner */
+
+ result = &slice->slabs->iter;
+
+ return result;
+
+}
diff --git a/src/glibext/umemslice.h b/src/glibext/umemslice.h
new file mode 100644
index 0000000..54b8433
--- /dev/null
+++ b/src/glibext/umemslice.h
@@ -0,0 +1,80 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * umemslice.h - prototypes pour les allocations en série d'un même type d'objets
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_UMEMSLICE_H
+#define _GLIBEXT_UMEMSLICE_H
+
+
+#include <glib-object.h>
+#include <stdint.h>
+
+
+
+#define G_TYPE_UMEM_SLICE g_umem_slice_get_type()
+#define G_UMEM_SLICE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_UMEM_SLICE, GUMemSlice))
+#define G_IS_UMEM_SLICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_UMEM_SLICE))
+#define G_UMEM_SLICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_UMEM_SLICE, GUMemSliceClass))
+#define G_IS_UMEM_SLICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_UMEM_SLICE))
+#define G_UMEM_SLICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_UMEM_SLICE, GUMemSliceClass))
+
+
+/* Allocateur s'appuyant sur des séries d'objets de même type (instance) */
+typedef struct _GUMemSlice GUMemSlice;
+
+/* Allocateur s'appuyant sur des séries d'objets de même type (classe) */
+typedef struct _GUMemSliceClass GUMemSliceClass;
+
+
+/* Indique le type défini pour un allocateur en série d'objets depuis une même zone mémoire. */
+GType g_umem_slice_get_type(void);
+
+/* Crée un allocateur dédié à la création de zones identiques. */
+GUMemSlice *g_umem_slice_new(size_t);
+
+/* Alloue une nouvelle zone de la taille attendue en mémoire. */
+void *g_umem_slice_alloc(GUMemSlice *);
+
+/* Mémorise un mot de 64 bits dans une nouvelle zone en mémoire. */
+void g_umem_slice_put_uint64(GUMemSlice *, uint64_t);
+
+/* Itérateur pour tranches de mémoire */
+typedef struct _umem_slice_iter_t
+{
+ union
+ {
+ void *data_end; /* Première zone libre */
+ uint64_t *data_end_uint64;
+ unsigned long data_end_ul;
+ };
+ struct _umem_slice_iter_t *next; /* Lien vers tranche suivante */
+
+ void *data[0]; /* Accès au premier élément */
+
+} umem_slice_iter_t;
+
+/* Fournit un itérateur pour les données allouées. */
+const umem_slice_iter_t *g_umem_slice_get_iter(const GUMemSlice *);
+
+
+
+#endif /* _GLIBEXT_UMEMSLICE_H */