Diff for /rpl/src/allocateur.c between versions 1.2 and 1.3

version 1.2, 2015/01/08 16:05:31 version 1.3, 2015/01/27 14:18:05
Line 22 Line 22
   
 #include "rpl-conv.h"  #include "rpl-conv.h"
   
   // Les fonctions malloc() et free() sont surchargées pour appeler
   // les fonctions rpl_malloc() et rpl_free(). Elles sont désactivées pour
   // éviter d'avoir un allocateur récursif.
   
   #undef malloc
   #undef realloc
   #undef free
   
   //  Classes :
   //  -1 : trop grand pour utiliser l'allocateur, on utilise l'allocateur par
   //  défaut du système. La classe -1 est aussi utilisée lorsque le buffer
   //  n'a pas encore été alloué. Dans ce cas, il est initialisé à NULL.
   
 static size_t                   tailles[] =  static size_t                   tailles[] =
         { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,          { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
Line 45  static int      longueur_tailles = 0; Line 57  static int      longueur_tailles = 0;
 */  */
   
 static int  static int
 recherche_longueur_buffer_optimale(integer8 longueur)  recherche_longueur_buffer_optimale(size_t longueur)
 {  {
     int         a;      int         a;
     int         b;      int         b;
Line 54  recherche_longueur_buffer_optimale(integ Line 66  recherche_longueur_buffer_optimale(integ
     a = 0;      a = 0;
     b = longueur_tailles - 1;      b = longueur_tailles - 1;
   
     if (longueur > ((integer8) tailles[b]))      if (longueur > tailles[b])
     {      {
         return(-1);          return(-1);
     }      }
Line 63  recherche_longueur_buffer_optimale(integ Line 75  recherche_longueur_buffer_optimale(integ
     {      {
         m = (a + b) / 2;          m = (a + b) / 2;
   
         if (longueur <= ((integer8) tailles[m]))          if (longueur <= tailles[m])
         {          {
             b = m;              b = m;
         }          }
Line 79  recherche_longueur_buffer_optimale(integ Line 91  recherche_longueur_buffer_optimale(integ
   
 /*  /*
 ================================================================================  ================================================================================
   Allocateur de mémoire fonctionnant avec un cache    Allocation d'une enveloppe de buffer
   
     Contrairement au malloc() de la libc, cet allocateur fournit une structure
     (l'enveloppe) contenant un pointeur sur la zone allouée ainsi que la longueur
     de la zone allouée et une information de classe pour gérer le cache.
     La zone allouée est comporte un pointeur sur l'enveloppe puis un
     buffer traditionnel.
 ================================================================================  ================================================================================
   Entrée : longueur du buffer à allouer    Entrée : état du processus courant
   --------------------------------------------------------------------------------
     Sortie : enveloppe de buffer
   --------------------------------------------------------------------------------
     Effets de bord : néant
   ================================================================================
   */
   
   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 = sys_malloc(sizeof(struct_buffer))) == NULL)
           {
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return(NULL);
           }
       }
   
       return(s_buffer);
   }
   
   
   /*
   ================================================================================
     Libération d'une enveloppe de buffer
   
     Ne libère pas le buffer qui doit être libéré à part.
   ================================================================================
     Entrée : état du processus courant, enveloppe
   --------------------------------------------------------------------------------
     Sortie : néant
   --------------------------------------------------------------------------------
     Effets de bord : néant
   ================================================================================
   */
   
   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
       {
           sys_free(s_buffer);
       }
   
       return;
   }
   
   
   /*
   ================================================================================
     Initialisation des structures de données de l'allocateur
   ================================================================================
     Entrée : état du processus courant (contient les données nécessaires
              au fonctionnement de l'allocateur par thread)
 --------------------------------------------------------------------------------  --------------------------------------------------------------------------------
   Sortie : pointeur sur une structure struct_buffer (ou NULL)    Sortie : néant
 --------------------------------------------------------------------------------  --------------------------------------------------------------------------------
   Effets de bord : néant    Effets de bord : néant
 ================================================================================  ================================================================================
Line 101  initialisation_allocateur_buffer(struct_ Line 187  initialisation_allocateur_buffer(struct_
             longueur_tailles++;              longueur_tailles++;
         }          }
   
         if (((*s_etat_processus).cache_buffer = malloc(((size_t)          if (((*s_etat_processus).cache_buffer = sys_malloc(((size_t)
                 longueur_tailles) * sizeof(unsigned char **))) == NULL)                  longueur_tailles) * sizeof(unsigned char **))) == NULL)
         {          {
             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;              (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
             return;              return;
         }          }
   
         if (((*s_etat_processus).pointeur_cache_buffer = malloc(((size_t)          if (((*s_etat_processus).pointeur_cache_buffer = sys_malloc(((size_t)
                 longueur_tailles) * sizeof(int))) == NULL)                  longueur_tailles) * sizeof(int))) == NULL)
         {          {
             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;              (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
             return;              return;
         }          }
       }
   
         for(i = 0; i < longueur_tailles; i++)      for(i = 0; i < longueur_tailles; i++)
       {
           if (((*s_etat_processus).cache_buffer[i] =
                   sys_malloc(TAILLE_CACHE * sizeof(unsigned char *))) == NULL)
         {          {
             if (((*s_etat_processus).cache_buffer[i] =              (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                     malloc(TAILLE_CACHE * sizeof(unsigned char *))) == NULL)              return;
             {  
                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;  
                 return;  
             }  
   
             (*s_etat_processus).pointeur_cache_buffer[i] = 0;  
         }          }
   
           (*s_etat_processus).pointeur_cache_buffer[i] = 0;
     }      }
   
       (*s_etat_processus).pointeur_enveloppes_buffers = 0;
     return;      return;
 }  }
   
   
   /*
   ================================================================================
     Libération des structures de données de l'allocateur
   ================================================================================
     Entrée : état du processus courant (contient les données nécessaires
              au fonctionnement de l'allocateur par thread)
   --------------------------------------------------------------------------------
     Sortie : néant
   --------------------------------------------------------------------------------
     Effets de bord : néant
   ================================================================================
   */
   
 void  void
 liberation_allocateur_buffer(struct_processus *s_etat_processus)  liberation_allocateur_buffer(struct_processus *s_etat_processus)
 {  {
Line 142  liberation_allocateur_buffer(struct_proc Line 242  liberation_allocateur_buffer(struct_proc
     {      {
         for(j = 0; j < (*s_etat_processus).pointeur_cache_buffer[i]; j++)          for(j = 0; j < (*s_etat_processus).pointeur_cache_buffer[i]; j++)
         {          {
             free((*s_etat_processus).cache_buffer[i][j]);              sys_free((*s_etat_processus).cache_buffer[i][j]);
         }          }
   
         free((*s_etat_processus).cache_buffer[i]);          sys_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);      sys_free((*s_etat_processus).cache_buffer);
 }      sys_free((*s_etat_processus).pointeur_cache_buffer);
   
   
 static inline void      for(i = 0; i < (*s_etat_processus).pointeur_enveloppes_buffers; i++)
 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);          sys_free((*s_etat_processus).enveloppes_buffers[i]);
     }      }
   
     return;      return;
 }  }
   
   
   /*
   ================================================================================
     Allocation d'un buffer et de son enveloppe
   ================================================================================
     Entrée : état du processus courant, longueur du buffer
   --------------------------------------------------------------------------------
     Sortie : néant
   --------------------------------------------------------------------------------
     Effets de bord : néant
   ================================================================================
   */
   
 struct_buffer *  struct_buffer *
 allocation_buffer(struct_processus *s_etat_processus, integer8 longueur)  allocation_buffer(struct_processus *s_etat_processus, size_t longueur)
 {  {
     int                     classe;      int                     classe;
   
     struct_buffer           *s_buffer;      struct_buffer           *s_buffer;
   
     if (allocation_enveloppe_buffer(s_etat_processus) == NULL)      if ((s_buffer = allocation_enveloppe_buffer(s_etat_processus)) == NULL)
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
         return(NULL);          return(NULL);
     }      }
   
     classe = recherche_longueur_buffer_optimale(longueur);      if (longueur == 0)
   
     if (classe >= 0)  
     {      {
         if ((*s_etat_processus).pointeur_cache_buffer[classe] > 0)          (*s_buffer).buffer = NULL;
           classe = -1;
       }
       else
       {
           classe = recherche_longueur_buffer_optimale(longueur);
   
           if (classe >= 0)
         {          {
             (*s_buffer).buffer = (*s_etat_processus).cache_buffer[classe]              // La classe correspond à la longueur effectivement disponible
                     [--(*s_etat_processus).pointeur_cache_buffer[classe]];              // dans le buffer alloué. Or il faut ajouter à ce buffer un
               // pointeur vers l'enveloppe (struct_buffer *).
   
               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 = sys_malloc((tailles[classe] *
                           sizeof(unsigned char)) + sizeof(struct_buffer *)))
                           == NULL)
                   {
                       (*s_etat_processus).erreur_systeme =
                               d_es_allocation_memoire;
                       return(NULL);
                   }
               }
         }          }
         else          else
         {          {
             if (((*s_buffer).buffer = malloc(tailles[classe] *              if (((*s_buffer).buffer = sys_malloc((((size_t) longueur) *
                     sizeof(unsigned char))) == NULL)                      sizeof(unsigned char)) + sizeof(struct_buffer *))) == NULL)
             {              {
                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;                  (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                 return(NULL);                  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);  
         }  
     }  
   
     BUG((longueur > ((integer8) tailles[classe])),  
             uprintf("Bad buffer class !\n"));  
   
     (*s_buffer).classe = classe;      (*s_buffer).classe = classe;
     (*s_buffer).longueur_requise = longueur;      (*s_buffer).longueur_requise = longueur;
   
     return(NULL);      // (*s_buffer).buffer est un pointeur sur un 'unsigned char *' et se
       // compose d'un pointeur vers s_buffer suivi d'une zone variable.
       // s_buffer est le pointeur sur l'enveloppe.
       // (*s_buffer).buffer est le pointeur sur le début de la zone allouée
       // aux données.
       (*(((struct_buffer **) (*s_buffer).buffer))) = s_buffer;
   
       return(s_buffer);
 }  }
   
   
   /*
   ================================================================================
     Libération d'un buffer et de son enveloppe
   ================================================================================
     Entrée : état du processus courant, longueur du buffer
   --------------------------------------------------------------------------------
     Sortie : néant
   --------------------------------------------------------------------------------
     Effets de bord : néant
   ================================================================================
   */
   
 void  void
 liberation_buffer(struct_processus *s_etat_processus, struct_buffer *s_buffer)  liberation_buffer(struct_processus *s_etat_processus, struct_buffer *s_buffer)
 {  {
     if ((*s_buffer).classe < 0)      if ((*s_buffer).classe < 0)
     {      {
         free((*s_buffer).buffer);          if ((*s_buffer).buffer != NULL)
           {
               sys_free((*s_buffer).buffer);
           }
     }      }
     else      else
     {      {
Line 264  liberation_buffer(struct_processus *s_et Line 375  liberation_buffer(struct_processus *s_et
         }          }
         else          else
         {          {
             free((*s_buffer).buffer);              sys_free((*s_buffer).buffer);
         }          }
     }      }
   
Line 272  liberation_buffer(struct_processus *s_et Line 383  liberation_buffer(struct_processus *s_et
     return;      return;
 }  }
   
   
   /*
   ================================================================================
     Allocation d'un buffer et de son enveloppe. Le pointeur retourné est
     le pointeur sur le début de la zone utilisable pour être conforme au
     malloc() de la libc.
   ================================================================================
     Entrée : état du processus courant, longueur du buffer
   --------------------------------------------------------------------------------
     Sortie : pointeur sur un void
   --------------------------------------------------------------------------------
     Effets de bord : néant
   ================================================================================
   */
   
   void *
   rpl_malloc(struct_processus *s_etat_processus, size_t s)
   {
       struct_buffer               *s_buffer;
   
       void                        *pointeur;
   
       if ((s_buffer = allocation_buffer(s_etat_processus, s)) == NULL)
       {
           (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return(NULL);
       }
   
       pointeur = (*s_buffer).buffer + sizeof(struct_buffer *);
       return(pointeur);
   }
   
   
   /*
   ================================================================================
     Réallocation d'un buffer et de son enveloppe. Le pointeur retourné est
     le pointeur sur le début de la zone utilisable pour être conforme au
     malloc() de la libc.
   ================================================================================
     Entrée : état du processus courant, longueur du buffer
   --------------------------------------------------------------------------------
     Sortie : pointeur sur un void
   --------------------------------------------------------------------------------
     Effets de bord : néant
   ================================================================================
   */
   
   void *
   rpl_realloc(struct_processus *s_etat_processus, void *ptr, size_t s)
   {
       struct_buffer               *s_ancien_buffer;
       struct_buffer               *s_nouveau_buffer;
   
       size_t                      longueur_copie;
   
       void                        *pointeur;
   
       if ((s_nouveau_buffer = allocation_buffer(s_etat_processus, s)) == NULL)
       {
           (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return(NULL);
       }
   
       s_ancien_buffer = (*((struct_buffer **) (ptr - sizeof(struct_buffer *))));
   
       longueur_copie = ((*s_ancien_buffer).longueur_requise > s)
               ? s : (*s_ancien_buffer).longueur_requise;
   
       memcpy((*s_nouveau_buffer).buffer + sizeof(struct_buffer *),
               (*s_ancien_buffer).buffer + sizeof(struct_buffer *),
               longueur_copie);
   
       liberation_buffer(s_etat_processus, s_ancien_buffer);
       pointeur = (*s_nouveau_buffer).buffer + sizeof(struct_buffer *);
   
       return(pointeur);
   }
   
   
   /*
   ================================================================================
     Libération d'un buffer et de son enveloppe.
   ================================================================================
     Entrée : état du processus courant, longueur du buffer
   --------------------------------------------------------------------------------
     Sortie : pointeur sur un void
   --------------------------------------------------------------------------------
     Effets de bord : néant
   ================================================================================
   */
   
   void
   rpl_free(struct_processus *s_etat_processus, void *ptr)
   {
       struct_buffer               *s_buffer;
   
       if (ptr == NULL)
       {
           return;
       }
   
       s_buffer = (*((struct_buffer **) (ptr - sizeof(struct_buffer *))));
       liberation_buffer(s_etat_processus, s_buffer);
       return;
   }
   
   
   // Réécriture des fonctions malloc() et free() de la libc
   
   void *
   sys_malloc(size_t s)
   {
       return(malloc(s));
   }
   
   void
   sys_free(void *ptr)
   {
       free(ptr);
   }
   
 // vim: ts=4  // vim: ts=4

Removed from v.1.2  
changed lines
  Added in v.1.3


CVSweb interface <joel.bertrand@systella.fr>