This is a port of the mruby/c tutorial Chapter 03 to the mbed environment.
For details, refer to the following.
http://www.s-itoc.jp/activity/research/mrubyc/mrubyc_tutorial/436
Note:There is a change in rtt0.h from the original source in the mruby/c. It was necessary for inclusion in C ++ source.
mrubyc/alloc.c@0:33feccbba3ff, 2017-02-15 (annotated)
- Committer:
- tk_takateku
- Date:
- Wed Feb 15 01:03:35 2017 +0000
- Revision:
- 0:33feccbba3ff
Commit before publishing
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
tk_takateku | 0:33feccbba3ff | 1 | /*! @file |
tk_takateku | 0:33feccbba3ff | 2 | @brief |
tk_takateku | 0:33feccbba3ff | 3 | mrubyc memory management. |
tk_takateku | 0:33feccbba3ff | 4 | |
tk_takateku | 0:33feccbba3ff | 5 | <pre> |
tk_takateku | 0:33feccbba3ff | 6 | Copyright (C) 2015 Kyushu Institute of Technology. |
tk_takateku | 0:33feccbba3ff | 7 | Copyright (C) 2015 Shimane IT Open-Innovation Center. |
tk_takateku | 0:33feccbba3ff | 8 | |
tk_takateku | 0:33feccbba3ff | 9 | This file is distributed under BSD 3-Clause License. |
tk_takateku | 0:33feccbba3ff | 10 | |
tk_takateku | 0:33feccbba3ff | 11 | Memory management for objects in mruby/c. |
tk_takateku | 0:33feccbba3ff | 12 | |
tk_takateku | 0:33feccbba3ff | 13 | </pre> |
tk_takateku | 0:33feccbba3ff | 14 | */ |
tk_takateku | 0:33feccbba3ff | 15 | |
tk_takateku | 0:33feccbba3ff | 16 | #include <stddef.h> |
tk_takateku | 0:33feccbba3ff | 17 | #include <string.h> |
tk_takateku | 0:33feccbba3ff | 18 | #include "alloc.h" |
tk_takateku | 0:33feccbba3ff | 19 | #include "console.h" |
tk_takateku | 0:33feccbba3ff | 20 | |
tk_takateku | 0:33feccbba3ff | 21 | // |
tk_takateku | 0:33feccbba3ff | 22 | #define ALLOC_TOTAL_MEMORY_SIZE 0x2800 |
tk_takateku | 0:33feccbba3ff | 23 | |
tk_takateku | 0:33feccbba3ff | 24 | // address space 16bit, 64KB |
tk_takateku | 0:33feccbba3ff | 25 | #define ALLOC_MAX_BIT 16 |
tk_takateku | 0:33feccbba3ff | 26 | |
tk_takateku | 0:33feccbba3ff | 27 | // Layer 1st(f) and 2nd(s) model |
tk_takateku | 0:33feccbba3ff | 28 | // last 4bit is ignored |
tk_takateku | 0:33feccbba3ff | 29 | // f : size |
tk_takateku | 0:33feccbba3ff | 30 | // 0 : 0000-007f |
tk_takateku | 0:33feccbba3ff | 31 | // 1 : 0080-00ff |
tk_takateku | 0:33feccbba3ff | 32 | // 2 : 0100-01ff |
tk_takateku | 0:33feccbba3ff | 33 | // 3 : 0200-03ff |
tk_takateku | 0:33feccbba3ff | 34 | // 4 : 0400-07ff |
tk_takateku | 0:33feccbba3ff | 35 | // 5 : 0800-0fff |
tk_takateku | 0:33feccbba3ff | 36 | // 6 : 1000-1fff |
tk_takateku | 0:33feccbba3ff | 37 | // 7 : 2000-3fff |
tk_takateku | 0:33feccbba3ff | 38 | // 8 : 4000-7fff |
tk_takateku | 0:33feccbba3ff | 39 | // 9 : 8000-ffff |
tk_takateku | 0:33feccbba3ff | 40 | |
tk_takateku | 0:33feccbba3ff | 41 | #define ALLOC_1ST_LAYER 8 |
tk_takateku | 0:33feccbba3ff | 42 | #define ALLOC_1ST_LAYER_BIT ALLOC_1ST_LAYER |
tk_takateku | 0:33feccbba3ff | 43 | #define ALLOC_1ST_LAYER_MASK 0xff80 |
tk_takateku | 0:33feccbba3ff | 44 | |
tk_takateku | 0:33feccbba3ff | 45 | // 2nd layer size |
tk_takateku | 0:33feccbba3ff | 46 | #define ALLOC_2ND_LAYER 8 |
tk_takateku | 0:33feccbba3ff | 47 | #define ALLOC_2ND_LAYER_BIT 3 |
tk_takateku | 0:33feccbba3ff | 48 | #define ALLOC_2ND_LAYER_MASK 0x0070 |
tk_takateku | 0:33feccbba3ff | 49 | |
tk_takateku | 0:33feccbba3ff | 50 | // memory |
tk_takateku | 0:33feccbba3ff | 51 | static uint8_t memory_pool[ALLOC_TOTAL_MEMORY_SIZE]; |
tk_takateku | 0:33feccbba3ff | 52 | |
tk_takateku | 0:33feccbba3ff | 53 | // define flags |
tk_takateku | 0:33feccbba3ff | 54 | #define FLAG_TAIL_BLOCK 1 |
tk_takateku | 0:33feccbba3ff | 55 | #define FLAG_NOT_TAIL_BLOCK 0 |
tk_takateku | 0:33feccbba3ff | 56 | #define FLAG_FREE_BLOCK 1 |
tk_takateku | 0:33feccbba3ff | 57 | #define FLAG_USED_BLOCK 0 |
tk_takateku | 0:33feccbba3ff | 58 | |
tk_takateku | 0:33feccbba3ff | 59 | // memory block header |
tk_takateku | 0:33feccbba3ff | 60 | struct USED_BLOCK { |
tk_takateku | 0:33feccbba3ff | 61 | unsigned int t: 1; /* FLAG_TAIL_BLOCK or FLAG_NOT_TAIL_BLOCK */ |
tk_takateku | 0:33feccbba3ff | 62 | unsigned int f: 1; /* FLAG_FREE_BLOCK or BLOCK_IS_NOT_FREE */ |
tk_takateku | 0:33feccbba3ff | 63 | unsigned int size: 14; /* block size, header included */ |
tk_takateku | 0:33feccbba3ff | 64 | struct USED_BLOCK *prev; /* link to previous block */ |
tk_takateku | 0:33feccbba3ff | 65 | uint8_t data[]; |
tk_takateku | 0:33feccbba3ff | 66 | }; |
tk_takateku | 0:33feccbba3ff | 67 | |
tk_takateku | 0:33feccbba3ff | 68 | struct FREE_BLOCK { |
tk_takateku | 0:33feccbba3ff | 69 | unsigned int t: 1; /* 0: not tail, 1: tail */ |
tk_takateku | 0:33feccbba3ff | 70 | unsigned int f: 1; /* 0: not free, 1: free */ |
tk_takateku | 0:33feccbba3ff | 71 | unsigned int size: 14; /* block size, header included */ |
tk_takateku | 0:33feccbba3ff | 72 | struct FREE_BLOCK *prev; /* link to previous block */ |
tk_takateku | 0:33feccbba3ff | 73 | struct FREE_BLOCK *next_free; |
tk_takateku | 0:33feccbba3ff | 74 | struct FREE_BLOCK *prev_free; |
tk_takateku | 0:33feccbba3ff | 75 | }; |
tk_takateku | 0:33feccbba3ff | 76 | |
tk_takateku | 0:33feccbba3ff | 77 | // free memory bitmap |
tk_takateku | 0:33feccbba3ff | 78 | static struct FREE_BLOCK *free_blocks[ALLOC_1ST_LAYER * ALLOC_2ND_LAYER]; |
tk_takateku | 0:33feccbba3ff | 79 | |
tk_takateku | 0:33feccbba3ff | 80 | |
tk_takateku | 0:33feccbba3ff | 81 | // calc f and s, and returns index of free_blocks |
tk_takateku | 0:33feccbba3ff | 82 | static int calc_index(uint32_t alloc_size) |
tk_takateku | 0:33feccbba3ff | 83 | { |
tk_takateku | 0:33feccbba3ff | 84 | if( alloc_size < 16 ) alloc_size = 16; |
tk_takateku | 0:33feccbba3ff | 85 | |
tk_takateku | 0:33feccbba3ff | 86 | // 1st layer |
tk_takateku | 0:33feccbba3ff | 87 | int f = 0; |
tk_takateku | 0:33feccbba3ff | 88 | uint32_t f_bit = ALLOC_1ST_LAYER_MASK; |
tk_takateku | 0:33feccbba3ff | 89 | uint32_t s_bit = ALLOC_2ND_LAYER_MASK; |
tk_takateku | 0:33feccbba3ff | 90 | while( (alloc_size & f_bit) != 0 ){ |
tk_takateku | 0:33feccbba3ff | 91 | f++; |
tk_takateku | 0:33feccbba3ff | 92 | f_bit <<= 1; |
tk_takateku | 0:33feccbba3ff | 93 | s_bit <<= 1; |
tk_takateku | 0:33feccbba3ff | 94 | } |
tk_takateku | 0:33feccbba3ff | 95 | |
tk_takateku | 0:33feccbba3ff | 96 | // 2nd layer |
tk_takateku | 0:33feccbba3ff | 97 | int s = (alloc_size & s_bit) >> (f + 4); |
tk_takateku | 0:33feccbba3ff | 98 | |
tk_takateku | 0:33feccbba3ff | 99 | return f * ALLOC_2ND_LAYER + s; |
tk_takateku | 0:33feccbba3ff | 100 | } |
tk_takateku | 0:33feccbba3ff | 101 | |
tk_takateku | 0:33feccbba3ff | 102 | |
tk_takateku | 0:33feccbba3ff | 103 | // |
tk_takateku | 0:33feccbba3ff | 104 | static void add_free_block(struct FREE_BLOCK *block) |
tk_takateku | 0:33feccbba3ff | 105 | { |
tk_takateku | 0:33feccbba3ff | 106 | block->f = FLAG_FREE_BLOCK; |
tk_takateku | 0:33feccbba3ff | 107 | int index = calc_index(block->size); |
tk_takateku | 0:33feccbba3ff | 108 | |
tk_takateku | 0:33feccbba3ff | 109 | block->prev_free = NULL; |
tk_takateku | 0:33feccbba3ff | 110 | block->next_free = free_blocks[index]; |
tk_takateku | 0:33feccbba3ff | 111 | if( free_blocks[index] != NULL ){ |
tk_takateku | 0:33feccbba3ff | 112 | free_blocks[index]->prev_free = block; |
tk_takateku | 0:33feccbba3ff | 113 | } |
tk_takateku | 0:33feccbba3ff | 114 | free_blocks[index] = block; |
tk_takateku | 0:33feccbba3ff | 115 | } |
tk_takateku | 0:33feccbba3ff | 116 | |
tk_takateku | 0:33feccbba3ff | 117 | |
tk_takateku | 0:33feccbba3ff | 118 | // initialize free block |
tk_takateku | 0:33feccbba3ff | 119 | void mrbc_init_alloc(void) |
tk_takateku | 0:33feccbba3ff | 120 | { |
tk_takateku | 0:33feccbba3ff | 121 | // clear links to free block |
tk_takateku | 0:33feccbba3ff | 122 | int i; |
tk_takateku | 0:33feccbba3ff | 123 | for( i=0 ; i<ALLOC_1ST_LAYER*ALLOC_2ND_LAYER ; i++ ){ |
tk_takateku | 0:33feccbba3ff | 124 | free_blocks[i] = NULL; |
tk_takateku | 0:33feccbba3ff | 125 | } |
tk_takateku | 0:33feccbba3ff | 126 | |
tk_takateku | 0:33feccbba3ff | 127 | // memory pool |
tk_takateku | 0:33feccbba3ff | 128 | struct FREE_BLOCK *block = (struct FREE_BLOCK *)memory_pool; |
tk_takateku | 0:33feccbba3ff | 129 | block->t = FLAG_TAIL_BLOCK; |
tk_takateku | 0:33feccbba3ff | 130 | block->size = ALLOC_TOTAL_MEMORY_SIZE; |
tk_takateku | 0:33feccbba3ff | 131 | add_free_block(block); |
tk_takateku | 0:33feccbba3ff | 132 | } |
tk_takateku | 0:33feccbba3ff | 133 | |
tk_takateku | 0:33feccbba3ff | 134 | // split block *alloc by size |
tk_takateku | 0:33feccbba3ff | 135 | static struct FREE_BLOCK *split_block(struct FREE_BLOCK *alloc, int size) |
tk_takateku | 0:33feccbba3ff | 136 | { |
tk_takateku | 0:33feccbba3ff | 137 | if( alloc->size < size + 24 ) return NULL; |
tk_takateku | 0:33feccbba3ff | 138 | |
tk_takateku | 0:33feccbba3ff | 139 | // split block, free |
tk_takateku | 0:33feccbba3ff | 140 | uint8_t *p = (uint8_t *)alloc; |
tk_takateku | 0:33feccbba3ff | 141 | struct FREE_BLOCK *split = (struct FREE_BLOCK *)(p + size); |
tk_takateku | 0:33feccbba3ff | 142 | struct FREE_BLOCK *next = (struct FREE_BLOCK *)(p + alloc->size); |
tk_takateku | 0:33feccbba3ff | 143 | split->size = alloc->size - size; |
tk_takateku | 0:33feccbba3ff | 144 | split->prev = alloc; |
tk_takateku | 0:33feccbba3ff | 145 | split->f = FLAG_FREE_BLOCK; |
tk_takateku | 0:33feccbba3ff | 146 | split->t = alloc->t; |
tk_takateku | 0:33feccbba3ff | 147 | alloc->size = size; |
tk_takateku | 0:33feccbba3ff | 148 | alloc->f = FLAG_USED_BLOCK; |
tk_takateku | 0:33feccbba3ff | 149 | alloc->t = FLAG_NOT_TAIL_BLOCK; |
tk_takateku | 0:33feccbba3ff | 150 | if( split->t == FLAG_NOT_TAIL_BLOCK ){ |
tk_takateku | 0:33feccbba3ff | 151 | next->prev = split; |
tk_takateku | 0:33feccbba3ff | 152 | } |
tk_takateku | 0:33feccbba3ff | 153 | |
tk_takateku | 0:33feccbba3ff | 154 | return split; |
tk_takateku | 0:33feccbba3ff | 155 | } |
tk_takateku | 0:33feccbba3ff | 156 | |
tk_takateku | 0:33feccbba3ff | 157 | |
tk_takateku | 0:33feccbba3ff | 158 | // just remove the free_block *remove from index |
tk_takateku | 0:33feccbba3ff | 159 | static void remove_index(struct FREE_BLOCK *remove) |
tk_takateku | 0:33feccbba3ff | 160 | { |
tk_takateku | 0:33feccbba3ff | 161 | // remove is top of linked list? |
tk_takateku | 0:33feccbba3ff | 162 | if( remove->prev_free == NULL ){ |
tk_takateku | 0:33feccbba3ff | 163 | int index = calc_index(remove->size); |
tk_takateku | 0:33feccbba3ff | 164 | free_blocks[index] = remove->next_free; |
tk_takateku | 0:33feccbba3ff | 165 | if( free_blocks[index] != NULL ){ |
tk_takateku | 0:33feccbba3ff | 166 | free_blocks[index]->prev = NULL; |
tk_takateku | 0:33feccbba3ff | 167 | } |
tk_takateku | 0:33feccbba3ff | 168 | } else { |
tk_takateku | 0:33feccbba3ff | 169 | remove->prev_free->next_free = remove->next_free; |
tk_takateku | 0:33feccbba3ff | 170 | if( remove->next_free != NULL ){ |
tk_takateku | 0:33feccbba3ff | 171 | remove->next_free->prev_free = remove->prev_free; |
tk_takateku | 0:33feccbba3ff | 172 | } |
tk_takateku | 0:33feccbba3ff | 173 | } |
tk_takateku | 0:33feccbba3ff | 174 | } |
tk_takateku | 0:33feccbba3ff | 175 | |
tk_takateku | 0:33feccbba3ff | 176 | // memory allocation |
tk_takateku | 0:33feccbba3ff | 177 | uint8_t *mrbc_raw_alloc(uint32_t size) |
tk_takateku | 0:33feccbba3ff | 178 | { |
tk_takateku | 0:33feccbba3ff | 179 | uint32_t alloc_size = size + sizeof(struct USED_BLOCK); |
tk_takateku | 0:33feccbba3ff | 180 | |
tk_takateku | 0:33feccbba3ff | 181 | int index = calc_index(alloc_size); |
tk_takateku | 0:33feccbba3ff | 182 | while( index < ALLOC_1ST_LAYER*ALLOC_2ND_LAYER && free_blocks[index] == NULL ){ |
tk_takateku | 0:33feccbba3ff | 183 | index++; |
tk_takateku | 0:33feccbba3ff | 184 | } |
tk_takateku | 0:33feccbba3ff | 185 | if( index >= ALLOC_1ST_LAYER*ALLOC_2ND_LAYER ){ |
tk_takateku | 0:33feccbba3ff | 186 | // out of memory |
tk_takateku | 0:33feccbba3ff | 187 | console_print("Fatal error: Out of memory.\n"); |
tk_takateku | 0:33feccbba3ff | 188 | return NULL; |
tk_takateku | 0:33feccbba3ff | 189 | } |
tk_takateku | 0:33feccbba3ff | 190 | |
tk_takateku | 0:33feccbba3ff | 191 | // alloc a free block |
tk_takateku | 0:33feccbba3ff | 192 | struct FREE_BLOCK *alloc = free_blocks[index]; |
tk_takateku | 0:33feccbba3ff | 193 | alloc->f = FLAG_USED_BLOCK; |
tk_takateku | 0:33feccbba3ff | 194 | remove_index(alloc); |
tk_takateku | 0:33feccbba3ff | 195 | |
tk_takateku | 0:33feccbba3ff | 196 | // split a block |
tk_takateku | 0:33feccbba3ff | 197 | struct FREE_BLOCK *release = split_block(alloc, alloc_size); |
tk_takateku | 0:33feccbba3ff | 198 | if( release != NULL ){ |
tk_takateku | 0:33feccbba3ff | 199 | // split alloc -> alloc + release |
tk_takateku | 0:33feccbba3ff | 200 | int index = calc_index(release->size); |
tk_takateku | 0:33feccbba3ff | 201 | release->next_free = free_blocks[index]; |
tk_takateku | 0:33feccbba3ff | 202 | release->prev_free = NULL; |
tk_takateku | 0:33feccbba3ff | 203 | free_blocks[index] = release; |
tk_takateku | 0:33feccbba3ff | 204 | if( release->next_free != NULL ){ |
tk_takateku | 0:33feccbba3ff | 205 | release->next_free->prev_free = release; |
tk_takateku | 0:33feccbba3ff | 206 | } |
tk_takateku | 0:33feccbba3ff | 207 | } |
tk_takateku | 0:33feccbba3ff | 208 | |
tk_takateku | 0:33feccbba3ff | 209 | return ((struct USED_BLOCK *)alloc)->data; |
tk_takateku | 0:33feccbba3ff | 210 | } |
tk_takateku | 0:33feccbba3ff | 211 | |
tk_takateku | 0:33feccbba3ff | 212 | |
tk_takateku | 0:33feccbba3ff | 213 | // merge ptr1 and ptr2 |
tk_takateku | 0:33feccbba3ff | 214 | // ptr2 will disappear |
tk_takateku | 0:33feccbba3ff | 215 | static void merge(struct FREE_BLOCK *ptr1, struct FREE_BLOCK *ptr2) |
tk_takateku | 0:33feccbba3ff | 216 | { |
tk_takateku | 0:33feccbba3ff | 217 | // merge ptr1 and ptr2 |
tk_takateku | 0:33feccbba3ff | 218 | ptr1->t = ptr2->t; |
tk_takateku | 0:33feccbba3ff | 219 | ptr1->size += ptr2->size; |
tk_takateku | 0:33feccbba3ff | 220 | |
tk_takateku | 0:33feccbba3ff | 221 | // update block info |
tk_takateku | 0:33feccbba3ff | 222 | if( ptr1->t == FLAG_NOT_TAIL_BLOCK ){ |
tk_takateku | 0:33feccbba3ff | 223 | uint8_t *p = (uint8_t *)ptr1; |
tk_takateku | 0:33feccbba3ff | 224 | struct FREE_BLOCK *next = (struct FREE_BLOCK *)(p + ptr1->size); |
tk_takateku | 0:33feccbba3ff | 225 | next->prev = ptr1; |
tk_takateku | 0:33feccbba3ff | 226 | } |
tk_takateku | 0:33feccbba3ff | 227 | } |
tk_takateku | 0:33feccbba3ff | 228 | |
tk_takateku | 0:33feccbba3ff | 229 | // memory release |
tk_takateku | 0:33feccbba3ff | 230 | void mrbc_raw_free(void *ptr) |
tk_takateku | 0:33feccbba3ff | 231 | { |
tk_takateku | 0:33feccbba3ff | 232 | // get free block |
tk_takateku | 0:33feccbba3ff | 233 | uint8_t *p = ptr; |
tk_takateku | 0:33feccbba3ff | 234 | struct FREE_BLOCK *free_ptr = (struct FREE_BLOCK *)(p - sizeof(struct USED_BLOCK)); |
tk_takateku | 0:33feccbba3ff | 235 | free_ptr->f = FLAG_FREE_BLOCK; |
tk_takateku | 0:33feccbba3ff | 236 | |
tk_takateku | 0:33feccbba3ff | 237 | // check next block, merge? |
tk_takateku | 0:33feccbba3ff | 238 | p = (uint8_t *)free_ptr; |
tk_takateku | 0:33feccbba3ff | 239 | struct FREE_BLOCK *next_ptr = (struct FREE_BLOCK *)(p + free_ptr->size); |
tk_takateku | 0:33feccbba3ff | 240 | if( free_ptr->t == FLAG_NOT_TAIL_BLOCK && next_ptr->f == FLAG_FREE_BLOCK ){ |
tk_takateku | 0:33feccbba3ff | 241 | remove_index(next_ptr); |
tk_takateku | 0:33feccbba3ff | 242 | merge(free_ptr, next_ptr); |
tk_takateku | 0:33feccbba3ff | 243 | } |
tk_takateku | 0:33feccbba3ff | 244 | |
tk_takateku | 0:33feccbba3ff | 245 | // check prev block, merge? |
tk_takateku | 0:33feccbba3ff | 246 | struct FREE_BLOCK *prev_ptr = free_ptr->prev; |
tk_takateku | 0:33feccbba3ff | 247 | if( prev_ptr != NULL && prev_ptr->f == FLAG_FREE_BLOCK ){ |
tk_takateku | 0:33feccbba3ff | 248 | remove_index(prev_ptr); |
tk_takateku | 0:33feccbba3ff | 249 | merge(prev_ptr, free_ptr); |
tk_takateku | 0:33feccbba3ff | 250 | free_ptr = prev_ptr; |
tk_takateku | 0:33feccbba3ff | 251 | } |
tk_takateku | 0:33feccbba3ff | 252 | |
tk_takateku | 0:33feccbba3ff | 253 | // free, add to index |
tk_takateku | 0:33feccbba3ff | 254 | add_free_block(free_ptr); |
tk_takateku | 0:33feccbba3ff | 255 | } |
tk_takateku | 0:33feccbba3ff | 256 | |
tk_takateku | 0:33feccbba3ff | 257 | |
tk_takateku | 0:33feccbba3ff | 258 | // simple realloc |
tk_takateku | 0:33feccbba3ff | 259 | uint8_t *mrbc_raw_realloc(uint8_t *ptr, uint32_t size) |
tk_takateku | 0:33feccbba3ff | 260 | { |
tk_takateku | 0:33feccbba3ff | 261 | uint8_t *new_ptr = mrbc_raw_alloc(size); |
tk_takateku | 0:33feccbba3ff | 262 | if( new_ptr == NULL ) return NULL; // ENOMEM |
tk_takateku | 0:33feccbba3ff | 263 | |
tk_takateku | 0:33feccbba3ff | 264 | // get block info |
tk_takateku | 0:33feccbba3ff | 265 | uint8_t *src_ptr = ptr; |
tk_takateku | 0:33feccbba3ff | 266 | struct USED_BLOCK *src_block = (struct USED_BLOCK *)(src_ptr - sizeof(struct USED_BLOCK)); |
tk_takateku | 0:33feccbba3ff | 267 | |
tk_takateku | 0:33feccbba3ff | 268 | // copy size |
tk_takateku | 0:33feccbba3ff | 269 | int copy_size; |
tk_takateku | 0:33feccbba3ff | 270 | if( size > src_block->size-sizeof(struct USED_BLOCK) ){ |
tk_takateku | 0:33feccbba3ff | 271 | copy_size = src_block->size - sizeof(struct USED_BLOCK); |
tk_takateku | 0:33feccbba3ff | 272 | } else { |
tk_takateku | 0:33feccbba3ff | 273 | copy_size = size; |
tk_takateku | 0:33feccbba3ff | 274 | } |
tk_takateku | 0:33feccbba3ff | 275 | |
tk_takateku | 0:33feccbba3ff | 276 | // copy and free |
tk_takateku | 0:33feccbba3ff | 277 | memcpy(new_ptr, src_ptr, copy_size); |
tk_takateku | 0:33feccbba3ff | 278 | mrbc_raw_free(ptr); |
tk_takateku | 0:33feccbba3ff | 279 | |
tk_takateku | 0:33feccbba3ff | 280 | return new_ptr; |
tk_takateku | 0:33feccbba3ff | 281 | } |
tk_takateku | 0:33feccbba3ff | 282 | |
tk_takateku | 0:33feccbba3ff | 283 | // for debug |
tk_takateku | 0:33feccbba3ff | 284 | #ifdef MRBC_DEBUG |
tk_takateku | 0:33feccbba3ff | 285 | #include <stdio.h> |
tk_takateku | 0:33feccbba3ff | 286 | void mrbc_alloc_debug(void) |
tk_takateku | 0:33feccbba3ff | 287 | { |
tk_takateku | 0:33feccbba3ff | 288 | struct FREE_BLOCK *ptr = (struct FREE_BLOCK *)memory_pool; |
tk_takateku | 0:33feccbba3ff | 289 | printf("-----\naddress f size\n"); |
tk_takateku | 0:33feccbba3ff | 290 | do { |
tk_takateku | 0:33feccbba3ff | 291 | uint8_t *p = (uint8_t *)ptr; |
tk_takateku | 0:33feccbba3ff | 292 | printf("%p: %d %x\n", p, ptr->f, ptr->size); |
tk_takateku | 0:33feccbba3ff | 293 | if( ptr->t == FLAG_TAIL_BLOCK ) break; |
tk_takateku | 0:33feccbba3ff | 294 | p += ptr->size; |
tk_takateku | 0:33feccbba3ff | 295 | ptr = (struct FREE_BLOCK *)p; |
tk_takateku | 0:33feccbba3ff | 296 | } while(1); |
tk_takateku | 0:33feccbba3ff | 297 | |
tk_takateku | 0:33feccbba3ff | 298 | printf("-----\n"); |
tk_takateku | 0:33feccbba3ff | 299 | int i; |
tk_takateku | 0:33feccbba3ff | 300 | for( i=0 ; i<ALLOC_1ST_LAYER * ALLOC_2ND_LAYER ; i++ ){ |
tk_takateku | 0:33feccbba3ff | 301 | if( free_blocks[i] == NULL ) continue; |
tk_takateku | 0:33feccbba3ff | 302 | printf("free[%d]\n", i); |
tk_takateku | 0:33feccbba3ff | 303 | struct FREE_BLOCK *ptr = free_blocks[i]; |
tk_takateku | 0:33feccbba3ff | 304 | while( ptr != NULL ){ |
tk_takateku | 0:33feccbba3ff | 305 | printf(" %p: size=%d\n", ptr, ptr->size); |
tk_takateku | 0:33feccbba3ff | 306 | ptr = ptr->next_free; |
tk_takateku | 0:33feccbba3ff | 307 | } |
tk_takateku | 0:33feccbba3ff | 308 | } |
tk_takateku | 0:33feccbba3ff | 309 | } |
tk_takateku | 0:33feccbba3ff | 310 | #endif |
tk_takateku | 0:33feccbba3ff | 311 | |
tk_takateku | 0:33feccbba3ff | 312 | //// for mruby/c |
tk_takateku | 0:33feccbba3ff | 313 | |
tk_takateku | 0:33feccbba3ff | 314 | struct MEM_WITH_VM { |
tk_takateku | 0:33feccbba3ff | 315 | uint8_t vm_id; |
tk_takateku | 0:33feccbba3ff | 316 | uint8_t data[]; |
tk_takateku | 0:33feccbba3ff | 317 | }; |
tk_takateku | 0:33feccbba3ff | 318 | |
tk_takateku | 0:33feccbba3ff | 319 | uint8_t *mrbc_alloc(mrb_vm *vm, int size) |
tk_takateku | 0:33feccbba3ff | 320 | { |
tk_takateku | 0:33feccbba3ff | 321 | int alloc_size = size + sizeof(struct MEM_WITH_VM); |
tk_takateku | 0:33feccbba3ff | 322 | struct MEM_WITH_VM *alloc_block = |
tk_takateku | 0:33feccbba3ff | 323 | (struct MEM_WITH_VM *)mrbc_raw_alloc(alloc_size); |
tk_takateku | 0:33feccbba3ff | 324 | if( alloc_block == NULL ) return NULL; // ENOMEM |
tk_takateku | 0:33feccbba3ff | 325 | |
tk_takateku | 0:33feccbba3ff | 326 | alloc_block->vm_id = (vm != NULL) ? vm->vm_id : 0; |
tk_takateku | 0:33feccbba3ff | 327 | return alloc_block->data; |
tk_takateku | 0:33feccbba3ff | 328 | } |
tk_takateku | 0:33feccbba3ff | 329 | |
tk_takateku | 0:33feccbba3ff | 330 | |
tk_takateku | 0:33feccbba3ff | 331 | uint8_t *mrbc_realloc(mrb_vm *vm, void *ptr, int size) |
tk_takateku | 0:33feccbba3ff | 332 | { |
tk_takateku | 0:33feccbba3ff | 333 | int alloc_size = size + sizeof(struct MEM_WITH_VM); |
tk_takateku | 0:33feccbba3ff | 334 | struct MEM_WITH_VM *alloc_block = |
tk_takateku | 0:33feccbba3ff | 335 | (struct MEM_WITH_VM *)mrbc_raw_realloc(ptr, alloc_size); |
tk_takateku | 0:33feccbba3ff | 336 | if( alloc_block == NULL ) return NULL; // ENOMEM |
tk_takateku | 0:33feccbba3ff | 337 | |
tk_takateku | 0:33feccbba3ff | 338 | alloc_block->vm_id = (vm != NULL) ? vm->vm_id : 0; |
tk_takateku | 0:33feccbba3ff | 339 | return alloc_block->data; |
tk_takateku | 0:33feccbba3ff | 340 | } |
tk_takateku | 0:33feccbba3ff | 341 | |
tk_takateku | 0:33feccbba3ff | 342 | |
tk_takateku | 0:33feccbba3ff | 343 | void mrbc_free(mrb_vm *vm, void *ptr) |
tk_takateku | 0:33feccbba3ff | 344 | { |
tk_takateku | 0:33feccbba3ff | 345 | if( ptr == NULL ) return; |
tk_takateku | 0:33feccbba3ff | 346 | |
tk_takateku | 0:33feccbba3ff | 347 | uint8_t *p = (uint8_t *)ptr; |
tk_takateku | 0:33feccbba3ff | 348 | struct MEM_WITH_VM *free_block = (struct MEM_WITH_VM *)(p - sizeof(struct MEM_WITH_VM)); |
tk_takateku | 0:33feccbba3ff | 349 | mrbc_raw_free(free_block); |
tk_takateku | 0:33feccbba3ff | 350 | } |
tk_takateku | 0:33feccbba3ff | 351 | |
tk_takateku | 0:33feccbba3ff | 352 | |
tk_takateku | 0:33feccbba3ff | 353 | void mrbc_free_all(mrb_vm *vm) |
tk_takateku | 0:33feccbba3ff | 354 | { |
tk_takateku | 0:33feccbba3ff | 355 | int vm_id = vm->vm_id; |
tk_takateku | 0:33feccbba3ff | 356 | |
tk_takateku | 0:33feccbba3ff | 357 | struct USED_BLOCK *ptr = (struct USED_BLOCK *)memory_pool; |
tk_takateku | 0:33feccbba3ff | 358 | while( ptr->t != FLAG_TAIL_BLOCK ){ |
tk_takateku | 0:33feccbba3ff | 359 | struct MEM_WITH_VM *vm_ptr = (struct MEM_WITH_VM *)(ptr->data); |
tk_takateku | 0:33feccbba3ff | 360 | if( ptr->f == FLAG_FREE_BLOCK || vm_ptr->vm_id != vm_id ){ |
tk_takateku | 0:33feccbba3ff | 361 | uint8_t *p = (uint8_t *)ptr; |
tk_takateku | 0:33feccbba3ff | 362 | ptr = (struct USED_BLOCK *)(p + ptr->size); |
tk_takateku | 0:33feccbba3ff | 363 | continue; |
tk_takateku | 0:33feccbba3ff | 364 | } |
tk_takateku | 0:33feccbba3ff | 365 | if( vm_ptr->vm_id != vm_id ) continue; |
tk_takateku | 0:33feccbba3ff | 366 | // free a block |
tk_takateku | 0:33feccbba3ff | 367 | struct USED_BLOCK *next_ptr = ptr->prev; |
tk_takateku | 0:33feccbba3ff | 368 | if( next_ptr == NULL ) next_ptr = ptr; |
tk_takateku | 0:33feccbba3ff | 369 | mrbc_raw_free(ptr->data); |
tk_takateku | 0:33feccbba3ff | 370 | ptr = next_ptr; |
tk_takateku | 0:33feccbba3ff | 371 | } |
tk_takateku | 0:33feccbba3ff | 372 | } |
tk_takateku | 0:33feccbba3ff | 373 |