/* ================================================================================ RPL/2 (R) version 4.1.20 Copyright (C) 1989-2015 Dr. BERTRAND Joël This file is part of RPL/2. RPL/2 is free software; you can redistribute it and/or modify it under the terms of the CeCILL V2 License as published by the french CEA, CNRS and INRIA. RPL/2 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 CeCILL V2 License for more details. You should have received a copy of the CeCILL License along with RPL/2. If not, write to info@cecill.info. ================================================================================ */ #include "rpl-conv.h" static size_t tailles[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576, 32768, 49152, 65536, 0 }; static int longueur_tailles = 0; /* ================================================================================ Recherche de la longueur optimale du buffer ================================================================================ Entrée : longueur du buffer à allouer -------------------------------------------------------------------------------- Sortie : indice de la liste candidate, -1 si aucune liste -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ static int recherche_longueur_buffer_optimale(integer8 longueur) { int a; int b; int m; a = 0; b = longueur_tailles - 1; if (longueur > ((integer8) tailles[b])) { return(-1); } while((b - a) > 1) { m = (a + b) / 2; if (longueur <= ((integer8) tailles[m])) { b = m; } else { a = m; } } return(b); } /* ================================================================================ Allocateur de mémoire fonctionnant avec un cache ================================================================================ Entrée : longueur du buffer à allouer -------------------------------------------------------------------------------- Sortie : pointeur sur une structure struct_buffer (ou NULL) -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ void initialisation_allocateur_buffer(struct_processus *s_etat_processus) { int i; if (longueur_tailles == 0) { while(tailles[longueur_tailles] != 0) { longueur_tailles++; } if (((*s_etat_processus).cache_buffer = malloc(((size_t) longueur_tailles) * sizeof(unsigned char **))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } if (((*s_etat_processus).pointeur_cache_buffer = malloc(((size_t) longueur_tailles) * sizeof(int))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } for(i = 0; i < longueur_tailles; i++) { if (((*s_etat_processus).cache_buffer[i] = malloc(TAILLE_CACHE * sizeof(unsigned char *))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } (*s_etat_processus).pointeur_cache_buffer[i] = 0; } } return; } void liberation_allocateur_buffer(struct_processus *s_etat_processus) { int i; int j; for(i = 0; i < longueur_tailles; i++) { for(j = 0; j < (*s_etat_processus).pointeur_cache_buffer[i]; j++) { free((*s_etat_processus).cache_buffer[i][j]); } free((*s_etat_processus).cache_buffer[i]); } free((*s_etat_processus).cache_buffer); return; } static inline struct_buffer * allocation_enveloppe_buffer(struct_processus *s_etat_processus) { struct_buffer *s_buffer; if ((*s_etat_processus).pointeur_enveloppes_buffers > 0) { s_buffer = (*s_etat_processus).enveloppes_buffers [--(*s_etat_processus).pointeur_enveloppes_buffers]; } else { if ((s_buffer = malloc(sizeof(struct_buffer))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } } return(NULL); } static inline void liberation_enveloppe_buffer(struct_processus *s_etat_processus, struct_buffer *s_buffer) { if ((*s_etat_processus).pointeur_enveloppes_buffers < TAILLE_CACHE) { (*s_etat_processus).enveloppes_buffers [(*s_etat_processus).pointeur_enveloppes_buffers++] = s_buffer; } else { free(s_buffer); } return; } struct_buffer * allocation_buffer(struct_processus *s_etat_processus, integer8 longueur) { int classe; struct_buffer *s_buffer; if (allocation_enveloppe_buffer(s_etat_processus) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } classe = recherche_longueur_buffer_optimale(longueur); if (classe >= 0) { if ((*s_etat_processus).pointeur_cache_buffer[classe] > 0) { (*s_buffer).buffer = (*s_etat_processus).cache_buffer[classe] [--(*s_etat_processus).pointeur_cache_buffer[classe]]; } else { if (((*s_buffer).buffer = malloc(tailles[classe] * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } } } else { if (((*s_buffer).buffer = malloc(((size_t) longueur) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } } (*s_buffer).classe = classe; (*s_buffer).longueur_requise = longueur; return(NULL); } void liberation_buffer(struct_processus *s_etat_processus, struct_buffer *s_buffer) { if ((*s_buffer).classe < 0) { free((*s_buffer).buffer); } else { if ((*s_etat_processus).pointeur_cache_buffer[(*s_buffer).classe] < TAILLE_CACHE) { (*s_etat_processus).cache_buffer[(*s_buffer).classe] [(*s_etat_processus).pointeur_cache_buffer [(*s_buffer).classe]++] = (*s_buffer).buffer; } else { free((*s_buffer).buffer); } } liberation_enveloppe_buffer(s_etat_processus, s_buffer); return; } // vim: ts=4