ISIX-RTOS - small operating system for ARM microcontrollers 1.2

memory.c

Go to the documentation of this file.
00001 /*------------------------------------------------------*/
00002 /*
00003  * memory.c
00004  *  New heap allocator for the ISIX
00005  *  Created on: 2009-11-11
00006  *      Author: lucck
00007  */
00008 /*------------------------------------------------------*/
00009 //TODO: memory should not block interrupts
00010 #include <isix/memory.h>
00011 #include <isix/types.h>
00012 #include <isix/semaphore.h>
00013 #include <prv/semaphore.h>
00014 #include <prv/scheduler.h>
00015 
00016 #ifndef ISIX_DEBUG_MEMORY
00017 #define ISIX_DEBUG_MEMORY ISIX_DBG_OFF
00018 #endif
00019 
00020 
00021 #if ISIX_DEBUG_MEMORY == ISIX_DBG_ON
00022 #include <isix/printk.h>
00023 #else
00024 #define isix_printk(...)
00025 #endif
00026 
00027 /*------------------------------------------------------*/
00028 
00029 #define MAGIC 0x19790822
00030 #define ALIGN_TYPE      void *
00031 #define ALIGN_MASK      (sizeof(ALIGN_TYPE) - 1)
00032 #define ALIGN_SIZE(p)   (((size_t)(p) + ALIGN_MASK) & ~ALIGN_MASK)
00033 
00034 struct header
00035 {
00036   union
00037   {
00038     struct header       *h_next;
00039     size_t              h_magic;
00040   } h;
00041   size_t                h_size;
00042 };
00043 /*------------------------------------------------------*/
00044 static struct
00045 {
00046   struct header         free;   /* Guaranteed to be not adjacent to the heap */
00047 
00048 } heap;
00049 
00050 /*------------------------------------------------------*/
00052 static sem_t mem_sem;
00053 
00054 
00055 /*------------------------------------------------------*/
00057 static void mem_lock_init(void)
00058 {
00059         //Create unlocked semaphore
00060         isix_sem_create( &mem_sem, 1 );
00061 }
00062 /*------------------------------------------------------*/
00064 static void mem_lock(void)
00065 {
00066         if(isix_scheduler_running)
00067                 isix_sem_wait( &mem_sem, ISIX_TIME_INFINITE );
00068 }
00069 
00070 /*------------------------------------------------------*/
00072 static void mem_unlock(void)
00073 {
00074         if(isix_scheduler_running)
00075                 isix_sem_signal( &mem_sem );
00076 }
00077 
00078 /*------------------------------------------------------*/
00080 void isix_alloc_init(void)
00081 {
00082   struct header *hp;
00083 
00084   extern char __heap_start;
00085   extern char __heap_end;
00086 
00087   mem_lock_init();
00088 
00089   hp = (void *)&__heap_start;
00090   hp->h_size = &__heap_end - &__heap_start - sizeof(struct header);
00091 
00092   hp->h.h_next = NULL;
00093   heap.free.h.h_next = hp;
00094   heap.free.h_size = 0;
00095 
00096 }
00097 
00098 /*------------------------------------------------------*/
00099 void *isix_alloc(size_t size)
00100 {
00101   struct header *qp, *hp, *fp;
00102 
00103   size = ALIGN_SIZE(size);
00104   qp = &heap.free;
00105   mem_lock();
00106 
00107   while (qp->h.h_next != NULL) {
00108     hp = qp->h.h_next;
00109     if (hp->h_size >= size) {
00110       if (hp->h_size < size + sizeof(struct header)) {
00111         /* Gets the whole block even if it is slightly bigger than the
00112            requested size because the fragment would be too small to be
00113            useful */
00114         qp->h.h_next = hp->h.h_next;
00115       }
00116       else {
00117         /* Block bigger enough, must split it */
00118         fp = (void *)((char *)(hp) + sizeof(struct header) + size);
00119         fp->h.h_next = hp->h.h_next;
00120         fp->h_size = hp->h_size - sizeof(struct header) - size;
00121         qp->h.h_next = fp;
00122         hp->h_size = size;
00123       }
00124       hp->h.h_magic = MAGIC;
00125 
00126       mem_unlock();
00127       return (void *)(hp + 1);
00128     }
00129     qp = hp;
00130   }
00131 
00132   mem_unlock();
00133   return NULL;
00134 }
00135 
00136 /*------------------------------------------------------*/
00137 #define LIMIT(p) (struct header *)((char *)(p) + \
00138                                    sizeof(struct header) + \
00139                                    (p)->h_size)
00140 
00141 /*------------------------------------------------------*/
00142 void isix_free(void *p)
00143 {
00144   struct header *qp, *hp;
00145 
00146 
00147   hp = (struct header *)p - 1;
00148   /*chDbgAssert(hp->h_magic == MAGIC,
00149               "chHeapFree(), #1",
00150               "it is not magic"); */
00151   qp = &heap.free;
00152   mem_lock();
00153 
00154   while (1) {
00155 
00156 /*    chDbgAssert((hp < qp) || (hp >= LIMIT(qp)),
00157                 "chHeapFree(), #2",
00158                 "within free block"); */
00159 
00160     if (((qp == &heap.free) || (hp > qp)) &&
00161         ((qp->h.h_next == NULL) || (hp < qp->h.h_next))) {
00162       /* Insertion after qp */
00163       hp->h.h_next = qp->h.h_next;
00164       qp->h.h_next = hp;
00165       /* Verifies if the newly inserted block should be merged */
00166       if (LIMIT(hp) == hp->h.h_next) {
00167         /* Merge with the next block */
00168         hp->h_size += hp->h.h_next->h_size + sizeof(struct header);
00169         hp->h.h_next = hp->h.h_next->h.h_next;
00170       }
00171       if ((LIMIT(qp) == hp)) {  /* Cannot happen when qp == &heap.free */
00172         /* Merge with the previous block */
00173         qp->h_size += hp->h_size + sizeof(struct header);
00174         qp->h.h_next = hp->h.h_next;
00175       }
00176 
00177       mem_unlock();
00178       return;
00179     }
00180     qp = qp->h.h_next;
00181   }
00182   mem_unlock();
00183 }
00184 /*------------------------------------------------------*/
00185 size_t isix_heap_free(int *fragments)
00186 {
00187         int frags = 0; size_t mem = 0;
00188         mem_lock();
00189         for(struct header *qp=&heap.free; qp;  qp=qp->h.h_next)
00190         {
00191                 mem += qp->h_size;
00192                 frags++;
00193         }
00194         mem_unlock();
00195         if(fragments)
00196                 *fragments = frags;
00197         return mem;
00198 }
00199 /*------------------------------------------------------*/
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines