fixed-sized memory pool allocator
[cortex-from-scratch] / pool.c
1 /* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
2  * 
3  * $LOG$
4  * 2019/7/20 - ROBIN KRENS      
5  * Initial version 
6  * 
7  * $DESCRIPTION$
8  * Fixed-sized memory pool allocation. A so called
9  * memory-pool (i.e. 4kB * 12 blocks) can be 
10  * initialized. Note: this allocator is for use on
11  * processors without an MMU (memory management 
12  * unit). A MPU (memory protection unit), if 
13  * available can be used to protect certain zones.
14  *
15  * This work is based on an article of Ben Kenwright
16  * 
17  * Preconditions: programmer should make sure the 
18  * SRAM entry point + (blocks * blocksize) is free. 
19  *
20  * $SAMPLE USAGE$
21  * KERNEL: can use initialize a big pool for all
22  * user tasks
23  *
24  * USER TASKS/PROCESS: can use this to dynamically
25  * allocate their own memory (i.e. heap)
26  * 
27  * 
28  * * */
29
30 #include <stdbool.h>
31 #include <stddef.h>
32 #include <stdint.h>
33 #include <stm32.h>
34 #include <mmap.h>
35
36
37 struct MEMPOOL {
38
39         unsigned short blocks; 
40         unsigned short block_size; 
41         unsigned short free_blocks;
42         unsigned short blocks_alloc; 
43         uint32_t * SRAM_entry;
44         uint32_t * m_next; 
45
46 };
47
48 struct MEMPOOL mem;
49
50  
51 void pool_init(size_t size_arg, unsigned int blocks_arg, uint32_t * entry_SRAM) {
52
53          mem.blocks = blocks_arg;
54          mem.block_size = size_arg;
55          mem.SRAM_entry = entry_SRAM;
56          memset(entry_SRAM, 0x00, (sizeof(char) * (size_arg * blocks_arg)));
57          mem.free_blocks = blocks_arg;
58          mem.m_next = mem.SRAM_entry;
59
60
61 /*       uint32_t * a =  alloc();
62          uint32_t * b = alloc();
63          uint32_t * c = alloc();
64          free(c);
65          uint32_t * d = alloc();
66
67          addrtohex(a);
68          addrtohex(b);
69          addrtohex(c);
70          addrtohex(d); */
71
72  }
73
74
75  /* void deletepool()  {
76          mem.SRAM_entry = NULL;
77  } */
78
79 uint32_t * AddrFromIndex(unsigned int i)  {
80         return mem.SRAM_entry + ( i * mem.block_size );
81
82  }
83  
84 unsigned int IndexFromAddr(const uint32_t * p) {
85         return (((unsigned int)(p - mem.SRAM_entry)) / mem.block_size);
86
87 }
88
89 void * alloc() {
90         if (mem.blocks_alloc < mem.blocks ) {
91                  unsigned int * p = (unsigned int *)AddrFromIndex( mem.blocks_alloc );
92                 *p = mem.blocks_alloc + 1;
93                  mem.blocks_alloc++;
94          }
95
96          void* ret = NULL;
97          if ( mem.free_blocks > 0 ) {
98                  ret = (void*)mem.m_next;
99                  --mem.free_blocks;
100          if (mem.free_blocks!=0) {
101                 mem.m_next = AddrFromIndex( *((unsigned int*)mem.m_next) );
102          }
103          else {
104                  mem.m_next = NULL;
105          }
106         }
107          
108          return ret;
109  }
110
111 void free(void* p)  {
112          if (mem.m_next != NULL) {
113                  (*(unsigned int *)p) = IndexFromAddr( mem.m_next );
114                  mem.m_next = (uint32_t *)p;
115         }
116          else {
117                  *((unsigned int*)p) = mem.blocks;
118                  mem.m_next = (uint32_t *) p;
119          }
120                 
121          ++mem.free_blocks;
122  }