]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
2009-02-08 Vesa Jääskeläinen <chaac@nic.fi>
authorchaac <chaac@localhost>
Sun, 8 Feb 2009 10:52:03 +0000 (10:52 +0000)
committerchaac <chaac@localhost>
Sun, 8 Feb 2009 10:52:03 +0000 (10:52 +0000)
* kern/mm.c: Add more comments.

ChangeLog
kern/mm.c

index 827679b22d99d603aeda1c702a419465bf82dcbb..34f5f66a9cf3c90ceaa3d65946549983ded8035c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2009-02-08  Vesa Jääskeläinen  <chaac@nic.fi>
+
+       * kern/mm.c: Add more comments.
+
 2009-02-08  Robert Millan  <rmh@aybabtu.com>
 
        Patch from Javier Martín.
index e0cb9cd3cd526edf1318454e5cce0b49df974125..a31dc2efd490e7202316031315a1ff6f840eb28e 100644 (file)
--- a/kern/mm.c
+++ b/kern/mm.c
@@ -129,7 +129,7 @@ get_header_from_pointer (void *ptr, grub_mm_header_t *p, grub_mm_region_t *r)
 
   if (! *r)
     grub_fatal ("out of range pointer %p", ptr);
-  
+
   *p = (grub_mm_header_t) ptr - 1;
   if ((*p)->magic != GRUB_MM_ALLOC_MAGIC)
     grub_fatal ("alloc magic is broken at %p", *p);
@@ -155,7 +155,7 @@ grub_mm_init_region (void *addr, grub_size_t size)
   r = (grub_mm_region_t) (((grub_addr_t) addr + GRUB_MM_ALIGN - 1)
                          & (~(GRUB_MM_ALIGN - 1)));
   size -= (char *) r - (char *) addr + sizeof (*r);
-  
+
   h = (grub_mm_header_t) ((char *) r + GRUB_MM_ALIGN);
   h->next = h;
   h->magic = GRUB_MM_FREE_MAGIC;
@@ -170,22 +170,26 @@ grub_mm_init_region (void *addr, grub_size_t size)
   for (p = &base, q = *p; q; p = &(q->next), q = *p)
     if (q->size > r->size)
       break;
-  
+
   *p = r;
   r->next = q;
 }
 
 /* Allocate the number of units N with the alignment ALIGN from the ring
-   buffer starting from *FIRST. ALIGN must be a power of two. Return a
-   non-NULL if successful, otherwise return NULL.  */
+   buffer starting from *FIRST.  ALIGN must be a power of two. Both N and
+   ALIGN are in units of GRUB_MM_ALIGN.  Return a non-NULL if successful,
+   otherwise return NULL.  */
 static void *
 grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align)
 {
   grub_mm_header_t p, q;
 
+  /* When everything is allocated side effect is that *first will have alloc
+     magic marked, meaning that there is no room in this region.  */
   if ((*first)->magic == GRUB_MM_ALLOC_MAGIC)
     return 0;
 
+  /* Try to search free slot for allocation in this memory region.  */
   for (q = *first, p = q->next; ; q = p, p = p->next)
     {
       grub_off_t extra;
@@ -204,11 +208,37 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align)
        {
          if (extra == 0 && p->size == n)
            {
+             /* There is no special alignment requirement and memory block
+                is complete match.
+
+                1. Just mark memory block as allocated and remove it from
+                   free list.
+
+                Result:
+                +---------------+ previous block's next
+                | alloc, size=n |          |
+                +---------------+          v
+              */
              q->next = p->next;
              p->magic = GRUB_MM_ALLOC_MAGIC;
            }
          else if (extra == 0 || p->size == n + extra)
            {
+             /* There might be alignment requirement, when taking it into
+                account memory block fits in.
+
+                1. Allocate new area at end of memory block.
+                2. Reduce size of available blocks from original node.
+                3. Mark new area as allocated and "remove" it from free
+                   list.
+
+                Result:
+                +---------------+
+                | free, size-=n | next --+
+                +---------------+        |
+                | alloc, size=n |        |
+                +---------------+        v
+              */
              p->size -= n;
              p += p->size;
              p->size = n;
@@ -216,13 +246,32 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align)
            }
          else
            {
+             /* There is alignment requirement and there is room in memory
+                block.  Split memory block to three pieces.
+
+                1. Create new memory block right after section being
+                   allocated.  Mark it as free.
+                2. Add new memory block to free chain.
+                3. Mark current memory block having only extra blocks.
+                4. Advance to aligned block and mark that as allocated and
+                   "remove" it from free list.
+
+                Result:
+                +------------------------------+
+                | free, size=extra             | next --+
+                +------------------------------+        |
+                | alloc, size=n                |        |
+                +------------------------------+        |
+                | free, size=orig.size-extra-n | <------+, next --+
+                +------------------------------+                  v
+              */
              grub_mm_header_t r;
 
              r = p + extra + n;
              r->magic = GRUB_MM_FREE_MAGIC;
              r->size = p->size - extra - n;
              r->next = p->next;
-             
+
              p->size = extra;
              p->next = r;
              p += extra;
@@ -230,11 +279,15 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align)
              p->magic = GRUB_MM_ALLOC_MAGIC;
            }
 
+         /* Mark find as a start marker for next allocation to fasten it.
+            This will have side effect of fragmenting memory as small
+            pieces before this will be un-used.  */
          *first = q;
-         
+
          return p + 1;
        }
 
+      /* Search was completed without result.  */
       if (p == *first)
        break;
     }
@@ -249,17 +302,17 @@ grub_memalign (grub_size_t align, grub_size_t size)
   grub_mm_region_t r;
   grub_size_t n = ((size + GRUB_MM_ALIGN - 1) >> GRUB_MM_ALIGN_LOG2) + 1;
   int count = 0;
-  
+
   align = (align >> GRUB_MM_ALIGN_LOG2);
   if (align == 0)
     align = 1;
 
  again:
-  
+
   for (r = base; r; r = r->next)
     {
       void *p;
-      
+
       p = grub_real_malloc (&(r->first), n, align);
       if (p)
        return p;
@@ -273,7 +326,7 @@ grub_memalign (grub_size_t align, grub_size_t size)
       grub_disk_cache_invalidate_all ();
       count++;
       goto again;
-      
+
     case 1:
       /* Unload unneeded modules.  */
       grub_dl_unload_unneeded ();
@@ -283,7 +336,7 @@ grub_memalign (grub_size_t align, grub_size_t size)
     default:
       break;
     }
-  
+
   grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
   return 0;
 }
@@ -326,12 +379,12 @@ grub_free (void *ptr)
        }
       while (q != r->first);
 #endif
-      
+
       for (q = r->first; q >= p || q->next <= p; q = q->next)
        {
          if (q->magic != GRUB_MM_FREE_MAGIC)
            grub_fatal ("free magic is broken at %p: 0x%x", q, q->magic);
-         
+
          if (q >= q->next && (q < p || q->next > p))
            break;
        }
@@ -339,7 +392,7 @@ grub_free (void *ptr)
       p->magic = GRUB_MM_FREE_MAGIC;
       p->next = q->next;
       q->next = p;
-      
+
       if (p + p->size == p->next)
        {
          if (p->next == q)
@@ -349,7 +402,7 @@ grub_free (void *ptr)
          p->size += p->next->size;
          p->next = p->next->next;
        }
-      
+
       if (q + q->size == p)
        {
          p->magic = 0;
@@ -370,7 +423,7 @@ grub_realloc (void *ptr, grub_size_t size)
   grub_mm_region_t r;
   void *q;
   grub_size_t n;
-  
+
   if (! ptr)
     return grub_malloc (size);
 
@@ -383,14 +436,14 @@ grub_realloc (void *ptr, grub_size_t size)
   /* FIXME: Not optimal.  */
   n = ((size + GRUB_MM_ALIGN - 1) >> GRUB_MM_ALIGN_LOG2) + 1;
   get_header_from_pointer (ptr, &p, &r);
-  
+
   if (p->size >= n)
     return ptr;
-  
+
   q = grub_malloc (size);
   if (! q)
     return q;
-  
+
   grub_memcpy (q, ptr, size);
   grub_free (ptr);
   return q;
@@ -434,7 +487,7 @@ grub_mm_dump (unsigned lineno)
   for (r = base; r; r = r->next)
     {
       grub_mm_header_t p;
-      
+
       for (p = (grub_mm_header_t) ((r->addr + GRUB_MM_ALIGN - 1)
                                   & (~(GRUB_MM_ALIGN - 1)));
           (grub_addr_t) p < r->addr + r->size;
@@ -493,7 +546,7 @@ grub_debug_memalign (const char *file, int line, grub_size_t align,
                    grub_size_t size)
 {
   void *ptr;
-  
+
   if (grub_mm_debug)
     grub_printf ("%s:%d: memalign (0x%x, 0x%x) = ",
                 file, line, align, size);