This is a port of the mruby/c tutorial Chapter 03 to the mbed environment.

Dependencies:   mbed

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.

Committer:
tk_takateku
Date:
Wed Feb 15 01:03:35 2017 +0000
Revision:
0:33feccbba3ff
Commit before publishing

Who changed what in which revision?

UserRevisionLine numberNew 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