basic heap implementation
[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  * Preconditions: programmer should make sure the SRAM entry point
17  * + (blocks * blocksize) is free. 
18  *
19  * $SAMPLE USAGE$
20  * KERNEL: can initialize a big pool for all user tasks
21  *
22  * USER TASKS/PROCESS: can use this to dynamically allocate their
23  * own memory (i.e. heap)
24  * 
25  * 
26  * * */
27
28 #include <stdbool.h>
29 #include <stddef.h>
30 #include <stdint.h>
31
32 #include <lib/pool.h>
33 #include <lib/string.h>
34
35  
36 void kpool_init(mem_pool_t * pool, size_t size_arg, unsigned int blocks_arg, uint32_t * entry_SRAM) {
37
38          pool->blocks = blocks_arg;
39          pool->block_size = size_arg;
40          pool->blocks_init = 0;
41          pool->SRAM_entry = entry_SRAM;
42          memset(entry_SRAM, 0x00, (sizeof(char) * (size_arg * blocks_arg)));
43          pool->free_blocks = blocks_arg;
44          pool->m_next = pool->SRAM_entry;
45  }
46
47  /* void deletepool()  {
48          pool->SRAM_entry = NULL;
49  } */
50
51 /* Helper functions */
52 uint32_t * AddrFromIndex(mem_pool_t * pool, unsigned int i)  {
53         return pool->SRAM_entry + ( i * pool->block_size );
54
55  }
56  
57 unsigned int IndexFromAddr(mem_pool_t * pool, const uint32_t * p) {
58         return (((unsigned int)(p - pool->SRAM_entry)) / pool->block_size);
59
60 }
61
62 /* alloc and free */ 
63 void * kalloc(mem_pool_t * pool) {
64         if (pool->blocks_init < pool->blocks ) {
65                  unsigned int * p = (unsigned int *)AddrFromIndex(pool, pool->blocks_init );
66                 *p = pool->blocks_init + 1;
67                  pool->blocks_init++;
68          }
69
70          void* ret = NULL;
71          if ( pool->free_blocks > 0 ) {
72                  ret = (void*)pool->m_next;
73                  --pool->free_blocks;
74          if (pool->free_blocks!=0) {
75                 pool->m_next = AddrFromIndex(pool, *((unsigned int*)pool->m_next) );
76          }
77          else {
78                  pool->m_next = NULL;
79          }
80         }
81          
82          return ret;
83  }
84
85 void kfree(mem_pool_t * pool, void* p)  {
86          if (pool->m_next != NULL) {
87                  (*(unsigned int *)p) = IndexFromAddr(pool, pool->m_next );
88                  pool->m_next = (uint32_t *)p;
89         }
90          else {
91                  *((unsigned int*)p) = pool->blocks;
92                  pool->m_next = (uint32_t *) p;
93          }
94                 
95          ++pool->free_blocks;
96  }