1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
   | /* rgn.c --- Routines d'allocation mémoire par régions.  */
 
#include "rgn.h"
#include <sys/mman.h>
#include <unistd.h>
#include <stdio.h>
 
/* L'allocation de bas niveau se fait avec "mmap":
 
   ptr = mmap (NULL, nbytes,
               PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)
 
   où nbytes doit être un multiple de la taille d'une page, i.e. un multiple
   de sysconf(_SC_PAGESIZE).  Cette mémoire peut être libérée plus tard
   avec "munmap".
   Voir "man mmap", "man munmap", et "man sysconf" pour de plus amples
   informations.  */
 
 
/* Type d'un descripteur de région.  */
struct rgn {
   int unlimited;
   int size;
   void *start;
   void *next;
   rgn *linked;
};
 
rgn *lastpage = NULL;
 
void new_page()
{
   lastpage = mmap(NULL, 4096, PROT_READ | PROT_WRITE , MAP_ANONYMOUS |
              MAP_PRIVATE , -1 , 0);
   (*lastpage).unlimited = 0;
   (*lastpage).size = 4096 - sizeof(rgn);
   (*lastpage).start = lastpage;
   (*lastpage).next = lastpage + sizeof(rgn);
   (*lastpage).linked = NULL;
}
 
/* Crée une nouvelle région dont la taille maximale est "maxbytes", ou
   qui peut grandir sans limite si "maxbytes" est égal à  0.  */
rgn  *rgn_new (size_t maxbytes)
{
   rgn *r;
   /*Cas ou nous creons une region de taille illimitee :
     On va commencer par allouer une region a une nouvelle page. Si la region 
     atteint sa taille limite, alors on recreera une nouvelle region dans 
     rgn_alloc que l'on reliera a la premiere region via le pointeur "linked"*/
   if(maxbytes == 0) {  
      r = mmap(NULL, 4096, PROT_READ | PROT_WRITE , MAP_ANONYMOUS |
               MAP_PRIVATE , -1 , 0);
      //On test si l'appel a mmap a reussi...
      if( r == MAP_FAILED) {
          //Si l'allocation a echoue, on imprime un message d'erreur
          perror(" Erreur mmap");
          }
 
      else  {
          //Sinon, on cree une region r dans l'espace alloue
          (*r).unlimited = 1;
          (*r).start = r;
          (*r).next = r + sizeof(rgn);
          (*r).linked = NULL; 
            }
   }          
 
   //Cas ou la taille de la region a allouer est inferieure a la taille d'une 
   //page : 
   if(maxbytes <= 4096 && maxbytes != 0) {
      // Si la derniere page allouee est egale a NULL :
      if(lastpage == NULL) {
         // On alloue une nouvelle page entiere:
         new_page();
         // Et on alloue un espace pour la region a l'interieur de cette page
         r = rgn_alloc(lastpage, maxbytes);
         // Si l'allocation a echoue
         if(r == NULL) {
            perror("Allocation failed");
         }
         //Sinon
         else {
            (*r).unlimited = 0;  
            (*r).size = maxbytes;
            (*r).start = r;
            (*r).next = r + sizeof(rgn);
            (*r).linked = NULL;
         } 
 
      }
 
      //Si la derniere page allouee n'est pas NULL :
      else {
         //S'il reste assez de place dans la derniere page allouee :
         if((*lastpage).size >= maxbytes + sizeof(rgn)) {
            r = rgn_alloc(lastpage, maxbytes);
            if(r == NULL) { perror("Allocation failed");}
            else { 
               (*lastpage).size = (*lastpage).size - maxbytes - sizeof(rgn);
               (*lastpage).next = (*lastpage).next + sizeof(rgn) + maxbytes;
 
               (*r).unlimited = 0;  
               (*r).size = maxbytes;
               (*r).start = r;
               (*r).next = r + sizeof(rgn);
               (*r).linked = NULL; 
 
            }}
         //Sinon, on cree une autre page :
         else {
            // On alloue une nouvelle page entiere:
            new_page();
            // Et on alloue un espace pour la region a l'interieur de cette page
            r = rgn_alloc(lastpage, maxbytes);
            // Si l'allocation a echoue
            if(r != NULL) { perror("Allocation failed");}
            //Sinon
            else {
               (*r).unlimited = 0;  
               (*r).size = maxbytes;
               (*r).start = r;
               (*r).next = r + sizeof(rgn);
               (*r).linked = NULL;
            } 
         }
      }
   }
 
   return r;    
}
 
 
/* Alloue un espace de "nbytes" dans la région "r" et renvoie son adresse,
   ou NULL si l'allocation échoue.  */
void *rgn_alloc (rgn *r, size_t nbytes)
{
   rgn *r2 = NULL;
 
 
   r2 = mmap((*r).next, nbytes, PROT_READ | PROT_WRITE , MAP_ANONYMOUS |
             MAP_PRIVATE , -1 , 0);
 
   if(r2 != NULL) {
      (*r).size = (*r).size - nbytes - sizeof(rgn);
      (*r).next = (*r).size + nbytes + sizeof(rgn);      
 
   }
   return r2;
}
 
 
/* Libère l'espace occupé par la région "r".  */
void  rgn_free (rgn *r)
{
      munmap(r, (*r).size + sizeof(rgn));
}
 
#if 0
/* On put implanter "malloc" au-dessus de nos régions.  */
 
void *malloc (size_t nbytes)
{
   rgn *r = rgn_new (nbytes + sizeof (rgn*));
   rgn **x = rgn_alloc (r, nbytes + sizeof (rgn*));
   *x = r;
   return x+1;
}
 
void free (void *ptr)
{
   rgn **x = ptr;
   rgn_free (x[-1]);
}
 
#endif
 
int main()
{    
      new_page();
      rgn *r;
      r = rgn_new(45);
      printf("%i %i %p %p %p \n", (*r).unlimited, (*r).size, (*r).start , (*r).next ,
            (*r).linked);
      return 0;      
      }
 
/* arch-tag: 64fdb756-d391-4f17-98b7-a5ecff6b652f */ | 
Partager