kalloc and kfree interface and abstraction
[cortex-from-scratch] / lib / 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 * memory-pool
9  * (i.e. 4kB * 12 blocks) can be initialized. Note: this allocator
10  * is for use on processors without an MMU (memory management 
11  * unit). A MPU (memory protection unit), if available can be used
12  * to protect certain zones.
13  *
14  * This work is based on an article of Ben Kenwright.
15  *
16  * Blocks are fixed size. In some situations ideal, in some situation
17  * may be not. It's fast.
18  * 
19  * Preconditions: programmer should make sure the SRAM entry point
20  * + (blocks * blocksize) is free. 
21  *
22  * $SAMPLE USAGE$
23  * KERNEL: initialize one (or multiple!) fixed memory-sized 
24  * kernal heaps
25  *
26  * USER TASKS/PROCESS: can use this to dynamically allocate their
27  * own memory (i.e. heap). You might argue that a fixed size memory
28  * pool is not ideal, but you would be amazed that many programs
29  * use structs of more or less similar size.
30  * 
31  * 
32  * * */
33
34 #include <stdbool.h>
35 #include <stddef.h>
36 #include <stdint.h>
37
38 #include <lib/pool.h>
39 #include <lib/tinyprintf.h>
40 #include <lib/string.h>
41
42  
43 void pool_init(mem_pool_t * pool, size_t size_arg, unsigned int blocks_arg, unsigned char* entry_SRAM) {
44
45          pool->blocks = blocks_arg;
46          pool->block_size = size_arg;
47          pool->blocks_init = 0;
48          pool->SRAM_entry = entry_SRAM;
49          memset(entry_SRAM, 0x00, (sizeof(char) * (size_arg * blocks_arg)));
50          pool->free_blocks = blocks_arg;
51          pool->m_next = pool->SRAM_entry;
52  }
53
54  /* void deletepool()  {
55          pool->SRAM_entry = NULL;
56  } */
57
58 /* Helper functions */
59 unsigned char* AddrFromIndex(mem_pool_t * pool, unsigned int i)  {
60         return pool->SRAM_entry + ( i * pool->block_size );
61
62  }
63  
64 unsigned int IndexFromAddr(mem_pool_t * pool, const unsigned char* p) {
65         return (((unsigned int)(p - pool->SRAM_entry)) / pool->block_size);
66
67 }
68
69 /* alloc and free */ 
70 void * alloc(void * s) {
71         mem_pool_t * pool = (mem_pool_t *) s;
72         if (pool->blocks_init < pool->blocks ) {
73                  unsigned int * p = (unsigned int *)AddrFromIndex(pool, pool->blocks_init );
74                 *p = pool->blocks_init + 1;
75                  pool->blocks_init++;
76          }
77
78          void* ret = NULL;
79          if ( pool->free_blocks > 0 ) {
80                  ret = (void*)pool->m_next;
81                  --pool->free_blocks;
82          if (pool->free_blocks!=0) {
83                 pool->m_next = AddrFromIndex(pool, *((unsigned int*)pool->m_next) );
84          }
85          else {
86                  pool->m_next = NULL;
87          }
88         }
89          
90          return ret;
91  }
92
93 void free(void * s, void* p)  {
94
95         mem_pool_t * pool = (mem_pool_t *) s;
96         if (pool->m_next != NULL) {
97                 (*(unsigned int *)p) = IndexFromAddr(pool, pool->m_next );
98                 pool->m_next = (unsigned char*)p;
99         }
100         else {
101                  *((unsigned int*)p) = pool->blocks;
102                  pool->m_next = (unsigned char*) p;
103         }
104                 
105         ++pool->free_blocks;
106 }
107
108 /* Heap info helper functions */
109
110 void heap_info(void * s) {
111
112         mem_pool_t * pool = (mem_pool_t *) s;
113
114         printf("HEAP INFO:\n");
115         printf("BLOCKS FREE: %d\n", pool->free_blocks);
116
117         unsigned char* curr_addr = pool->SRAM_entry;
118
119         // Loop over heap blocks
120         for (int i = 0; i < pool->blocks; i++) {
121                 printf("\nBLOCK %d", i+1);
122                 for (int j = 0; j < (pool->block_size-1); j++) {
123
124                         if (j % 10 == 0)
125                                 printf("\n%x ", curr_addr);
126                         printf("%#x ", *curr_addr);
127                         curr_addr++;
128                 }
129                 printf("\n");
130                 curr_addr++;
131                 
132         }
133         printf("\n");
134
135 }
136
137
138