mbed I/F binding for mruby
Dependents: mruby_mbed_web mirb_mbed
pool.c
00001 /* 00002 ** pool.c - memory pool 00003 ** 00004 ** See Copyright Notice in mruby.h 00005 */ 00006 00007 #include <stddef.h> 00008 #include <stdint.h> 00009 #include <string.h> 00010 #include "mruby.h" 00011 00012 /* configuration section */ 00013 /* allocated memory address should be multiple of POOL_ALIGNMENT */ 00014 /* or undef it if alignment does not matter */ 00015 #ifndef POOL_ALIGNMENT 00016 #define POOL_ALIGNMENT 4 00017 #endif 00018 /* page size of memory pool */ 00019 #ifndef POOL_PAGE_SIZE 00020 #define POOL_PAGE_SIZE 16000 00021 #endif 00022 /* end of configuration section */ 00023 00024 struct mrb_pool_page { 00025 struct mrb_pool_page *next; 00026 size_t offset; 00027 size_t len; 00028 void *last; 00029 char page[]; 00030 }; 00031 00032 struct mrb_pool { 00033 mrb_state *mrb; 00034 struct mrb_pool_page *pages; 00035 }; 00036 00037 #undef TEST_POOL 00038 #ifdef TEST_POOL 00039 00040 #define mrb_malloc_simple(m,s) malloc(s) 00041 #define mrb_free(m,p) free(p) 00042 #endif 00043 00044 #ifdef POOL_ALIGNMENT 00045 # define ALIGN_PADDING(x) ((SIZE_MAX - (x) + 1) & (POOL_ALIGNMENT - 1)) 00046 #else 00047 # define ALIGN_PADDING(x) (0) 00048 #endif 00049 00050 MRB_API mrb_pool* 00051 mrb_pool_open(mrb_state *mrb) 00052 { 00053 mrb_pool *pool = (mrb_pool *)mrb_malloc_simple(mrb, sizeof(mrb_pool)); 00054 00055 if (pool) { 00056 pool->mrb = mrb; 00057 pool->pages = NULL; 00058 } 00059 00060 return pool; 00061 } 00062 00063 MRB_API void 00064 mrb_pool_close(mrb_pool *pool) 00065 { 00066 struct mrb_pool_page *page, *tmp; 00067 00068 if (!pool) return; 00069 page = pool->pages; 00070 while (page) { 00071 tmp = page; 00072 page = page->next; 00073 mrb_free(pool->mrb, tmp); 00074 } 00075 mrb_free(pool->mrb, pool); 00076 } 00077 00078 static struct mrb_pool_page* 00079 page_alloc(mrb_pool *pool, size_t len) 00080 { 00081 struct mrb_pool_page *page; 00082 00083 if (len < POOL_PAGE_SIZE) 00084 len = POOL_PAGE_SIZE; 00085 page = (struct mrb_pool_page *)mrb_malloc_simple(pool->mrb, sizeof(struct mrb_pool_page)+len); 00086 if (page) { 00087 page->offset = 0; 00088 page->len = len; 00089 } 00090 00091 return page; 00092 } 00093 00094 MRB_API void* 00095 mrb_pool_alloc(mrb_pool *pool, size_t len) 00096 { 00097 struct mrb_pool_page *page; 00098 size_t n; 00099 00100 if (!pool) return NULL; 00101 len += ALIGN_PADDING(len); 00102 page = pool->pages; 00103 while (page) { 00104 if (page->offset + len <= page->len) { 00105 n = page->offset; 00106 page->offset += len; 00107 page->last = (char*)page->page+n; 00108 return page->last; 00109 } 00110 page = page->next; 00111 } 00112 page = page_alloc(pool, len); 00113 if (!page) return NULL; 00114 page->offset = len; 00115 page->next = pool->pages; 00116 pool->pages = page; 00117 00118 page->last = (void*)page->page; 00119 return page->last; 00120 } 00121 00122 MRB_API mrb_bool 00123 mrb_pool_can_realloc(mrb_pool *pool, void *p, size_t len) 00124 { 00125 struct mrb_pool_page *page; 00126 00127 if (!pool) return FALSE; 00128 len += ALIGN_PADDING(len); 00129 page = pool->pages; 00130 while (page) { 00131 if (page->last == p) { 00132 size_t beg; 00133 00134 beg = (char*)p - page->page; 00135 if (beg + len > page->len) return FALSE; 00136 return TRUE; 00137 } 00138 page = page->next; 00139 } 00140 return FALSE; 00141 } 00142 00143 MRB_API void* 00144 mrb_pool_realloc(mrb_pool *pool, void *p, size_t oldlen, size_t newlen) 00145 { 00146 struct mrb_pool_page *page; 00147 void *np; 00148 00149 if (!pool) return NULL; 00150 oldlen += ALIGN_PADDING(oldlen); 00151 newlen += ALIGN_PADDING(newlen); 00152 page = pool->pages; 00153 while (page) { 00154 if (page->last == p) { 00155 size_t beg; 00156 00157 beg = (char*)p - page->page; 00158 if (beg + oldlen != page->offset) break; 00159 if (beg + newlen > page->len) { 00160 page->offset = beg; 00161 break; 00162 } 00163 page->offset = beg + newlen; 00164 return p; 00165 } 00166 page = page->next; 00167 } 00168 np = mrb_pool_alloc(pool, newlen); 00169 if (np == NULL) { 00170 return NULL; 00171 } 00172 memcpy(np, p, oldlen); 00173 return np; 00174 } 00175 00176 #ifdef TEST_POOL 00177 int 00178 main(void) 00179 { 00180 int i, len = 250; 00181 mrb_pool *pool; 00182 void *p; 00183 00184 pool = mrb_pool_open(NULL); 00185 p = mrb_pool_alloc(pool, len); 00186 for (i=1; i<20; i++) { 00187 printf("%p (len=%d) %ud\n", p, len, mrb_pool_can_realloc(pool, p, len*2)); 00188 p = mrb_pool_realloc(pool, p, len, len*2); 00189 len *= 2; 00190 } 00191 mrb_pool_close(pool); 00192 return 0; 00193 } 00194 #endif 00195
Generated on Tue Jul 12 2022 18:00:35 by 1.7.2