diff options
Diffstat (limited to 'src/glibext/umemslice.c')
-rw-r--r-- | src/glibext/umemslice.c | 423 |
1 files changed, 423 insertions, 0 deletions
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; + +} |