GadgetSeed  0.9.6
memory.c
[詳解]
1 /** @file
2  @brief メモリ管理
3 
4  @date 2008.03.18
5  @author Takashi SHUDO
6 
7  @page memory_manage メモリ管理
8 
9  GadgetSeedはヒープメモリとヒープメモリを取得、開放するAPIがあります。
10 
11  GadgetSeedのヒープメモリ構成は以下の2種類よ選択することが出来ます。
12 
13  - newlibのAPIであるmalloc()、free()を使用する
14  - GadgetSeedの独自APIを使用する
15 
16  newlibのAPIを使用する場合マクロ @ref GSC_MEMORY_HEAP_IS_NEWLIB を定義して下さい。
17  この場合ヒープメモリエリアは .bss の最終アドレス以降となります。
18 
19  GadgetSeedの独自APIを使用する場合、ヒープメモリサイズはマクロ @ref GSC_MEMORY_HEAP_SIZE で定義して下さい。
20 
21 
22  ---
23  @section memory_api メモリ管理API
24 
25  include ファイル : memory.h
26 
27  | API名 | 機能 |
28  |:--------------------------|:------------------------------|
29  | alloc_memory() | @copybrief alloc_memory |
30  | free_memory() | @copybrief free_memory |
31  | heap_total_size() | @copybrief heap_total_size |
32  | heap_free_size() | @copybrief heap_free_size |
33 
34  GadgetSeedの独自APIを使用する場合、更に以下のAPIが使用できます。
35 
36  include ファイル : memory.h
37 
38  | API名 | 機能 |
39  |:--------------------------|:------------------------------|
40  | memory_size() | @copybrief memory_size |
41 */
42 
43 #include "sysconfig.h"
44 #include "memory.h"
45 #include "tkprintf.h"
46 #include "str.h"
47 
48 //#define DEBUGKBITS 0x03
49 #include "dkprintf.h"
50 
51 
52 #ifdef TEST
53 #include <stdio.h>
54 #define tprintf printf
55 #define eprintf printf
56 #endif
57 
58 #ifndef GSC_MEMORY_HEAP_IS_NEWLIB ///< $gsc ヒープメモリ管理をnewlibで行う
59 #ifndef GSC_MEMORY_HEAP_SIZE
60 #define GSC_MEMORY_HEAP_SIZE 0x8000 ///< $gsc ヒープメモリサイズ(newlibを使わない場合)
61 #endif
62 
63 typedef union memhdr {
64  struct {
65  union memhdr *next;
66  unsigned long size;
67  } s;
68  long align;
69 } memhdr;
70 
71 #if 0
72 unsigned char gs_heap_mem[GSC_MEMORY_HEAP_SIZE] __attribute__ ((aligned(256)));
73 void *MEM_END = &gs_heap_mem[GSC_MEMORY_HEAP_SIZE];
74 #else
75 #define GHALIGN (sizeof(memhdr)*4)
76 unsigned char gs_heap_mem[(GSC_MEMORY_HEAP_SIZE/GHALIGN)*GHALIGN] __attribute__ ((aligned(GHALIGN)));
77 void *MEM_END = &gs_heap_mem[(GSC_MEMORY_HEAP_SIZE/GHALIGN)*GHALIGN];
78 #endif
79 void *MEM_START = gs_heap_mem;
80 
81 memhdr *base;
82 memhdr *freep;
83 #else // GSC_MEMORY_HEAP_IS_NEWLIB
84  #include <stdlib.h>
85  #ifdef GSC_TARGET_SYSTEM_EMU
86  unsigned int system_heap_size(void) { return 0; }
87  unsigned int system_heap_total_size(void) { return 0; }
88  #else
89  extern unsigned int system_heap_size(void);
90  extern unsigned int system_heap_total_size(void);
91  #endif
92 #endif // GSC_MEMORY_HEAP_IS_NEWLIB
93 
94 /**
95  @brief メモリ管理の初期化
96 */
97 void init_memory(void)
98 {
99 #ifndef GSC_MEMORY_HEAP_IS_NEWLIB
100  base = (memhdr *)(((unsigned long)MEM_START -
101  sizeof(memhdr)-1) & ~(sizeof(memhdr)-1));
102  base->s.next = base + 1;
103  base->s.size = 0;
104  freep = base->s.next;
105  freep->s.next = base;
106  freep->s.size = ((char*)MEM_END - (char*)freep) / sizeof(memhdr);
107 #else
108  tkprintf("GS Memory Alloc API is newlib API\n");
109 #endif
110 }
111 
112 /**
113  @brief メモリ状態表示
114 */
116 {
117 #ifndef GSC_MEMORY_HEAP_IS_NEWLIB
118  DKPRINTF(0x02, "### memhdr = %d\n", sizeof(memhdr));
119  DKPRINTF(0x02, "### base = 0x%p\n", base);
120  DKPRINTF(0x02, "### freep = 0x%p\n", freep);
121 
122  tkprintf("Heap area : 0x%p - 0x%p\n",
123  MEM_START, MEM_END);
124  tkprintf("%ld K byte free\n", heap_total_size()/1024);
125 #else
126  unsigned long ms = system_heap_total_size();
127  tkprintf("%ld K byte free\n", ms/1024);
128 #endif
129 }
130 
131 /**
132  @brief メモリを確保する
133 
134  @param[in] size 確保するメモリバイト数
135 
136  @return 確保したメモリのポインタ
137 */
138 void * alloc_memory(unsigned int size)
139 {
140 #ifndef GSC_MEMORY_HEAP_IS_NEWLIB
141  memhdr *p, *prevp = freep;
142  unsigned int nunits;
143 
144  DKPRINTF(0x02, "### alloc size = %08lX(%ld)\n", size, size);
145  DKPRINTF(0x02, "### freep = %p\n", freep);
146  DKPRINTF(0x02, "### freep->s.next = %p\n", freep->s.next);
147 // tkprintf("###? freep->s.next = %08lX\n", (unsigned long)freep->s.next); //!!!
148  nunits = (size + sizeof(memhdr)-1)/sizeof(memhdr) + 1;
149  DKPRINTF(0x02, "### nunits = %08lX(%ld)\n", nunits, nunits);
150  for(p = prevp->s.next; ; prevp = p, p = p->s.next) {
151  DKPRINTF(0x02, "### p = %p\n", p);
152  DKPRINTF(0x02, "### prevp = %p\n", prevp);
153  DKPRINTF(0x02, "### p->s.size = %08lX(%ld)\n", p->s.size, p->s.size);
154  if(p->s.size >= nunits) {
155  break;
156  }
157  if(p == freep) {
158  SYSERR_PRINT("Memory empty(size=%ld)\n", size);
159  return 0;
160  }
161  }
162  if(p->s.size == nunits) {
163  prevp->s.next = p->s.next;
164  } else {
165  DKPRINTF(0x02, "### newmem(%ld)\n", nunits);
166  DKPRINTF(0x02, "### p->s.size = %08lX(%ld)\n", p->s.size, p->s.size);
167  p->s.size -= nunits;
168  DKPRINTF(0x02, "### p->s.size = %08lX(%ld)\n", p->s.size, p->s.size);
169  DKPRINTF(0x02, "### p = %p\n", p);
170  p += p->s.size;
171  DKPRINTF(0x02, "### p = %p\n", p);
172  DKPRINTF(0x02, "### p->s.size = %08lX(%ld)\n", p->s.size, p->s.size);
173  p->s.size = nunits;
174  DKPRINTF(0x02, "### p->s.size = %08lX(%ld)\n", p->s.size, p->s.size);
175  DKPRINTF(0x02, "### prevp = %p\n", prevp);
176  }
177  freep = prevp;
178  DKPRINTF(0x02, "### freep = %p\n", freep);
179 // memoryset((void *)(p+1), 0, size); // calloc
180  DKPRINTF(0x02, "### address = %p\n", (p + 1));
181 
182  DKPRINTF(0x01, "alloc ptr=%p size=%ld\n", (p + 1), size);
183 
184  return (void *)(p+1);
185 #else
186  return malloc(size);
187 #endif
188 }
189 
190 /**
191  @brief 確保したメモリを開放する
192 
193  @param[in] ptr 開放するメモリのポインタ
194 */
195 void free_memory(void *ptr)
196 {
197 #ifndef GSC_MEMORY_HEAP_IS_NEWLIB
198  memhdr *bp, *p;
199 
200  DKPRINTF(0x01, "free ptr=%p\n", ptr);
201 
202  // ptr の範囲をチェック(すべき)
203  DKPRINTF(0x02, "### free ptr = %p\n", ptr);
204  DKPRINTF(0x02, "### freep = %p\n", freep);
205  DKPRINTF(0x02, "### freep->s.next = %08lX\n", (unsigned long)freep->s.next);
206 // tkrintf("###? freep->s.next = %08lX\n", (unsigned long)freep->s.next); //!!!
207 
208  bp = (memhdr *)ptr -1;
209  for(p = freep; !(bp > p && bp < p->s.next); p = p->s.next) {
210  if(p >= p->s.next && (bp > p || bp < p->s.next)) {
211  break;
212  }
213  }
214 
215  if(bp + bp->s.size == p->s.next) {
216  bp->s.size += p->s.next->s.size;
217  bp->s.next = p->s.next->s.next;
218  } else {
219  bp->s.next = p->s.next;
220  }
221 
222  if(p + p->s.size == bp) {
223  p->s.size += bp->s.size;
224  p->s.next = bp->s.next;
225  } else {
226  p->s.next = bp;
227  }
228  freep = p;
229 #else
230  free(ptr);
231 #endif
232 }
233 
234 /**
235  @brief 確保したメモリのバイト数を取得する
236 
237  @param[in] ptr 確保したメモリのポインタ
238 
239  @return 確保したメモリのバイト数
240 */
241 unsigned long memory_size(void *ptr)
242 {
243 #ifndef GSC_MEMORY_HEAP_IS_NEWLIB
244  return (((memhdr *)ptr -1)->s.size -1) * sizeof(memhdr);
245 #else
246  return 0; // [TODO]
247 #endif
248 }
249 
250 /**
251  @brief 未確保のメモリの合計バイト数を取得する
252 
253  @return 未確保のメモリの合計バイト数
254 */
255 unsigned long heap_free_size(void)
256 {
257 #ifndef GSC_MEMORY_HEAP_IS_NEWLIB
258  memhdr *p;
259  unsigned long size = 0;
260 
261  for(p= freep->s.next; ; p = p->s.next) {
262  size += p->s.size;
263  if(p == freep) break;;
264  }
265  return size * sizeof(memhdr);
266 #else
267  return system_heap_size();
268 #endif
269 }
270 
271 /**
272  @brief 全てのメモリのバイト数を取得する
273 
274  @return 全てのメモリのバイト数
275 */
276 unsigned long heap_total_size(void)
277 {
278 #ifndef GSC_MEMORY_HEAP_IS_NEWLIB
279  return (unsigned long)(MEM_END - MEM_START);
280 #else
281  return system_heap_total_size();
282 #endif
283 }
284 
285 
286 //#ifndef TARGET_SYSTEM_EMU
287 #if 0
288 /*
289  *
290  */
291 #include <sys/reent.h>
292 
293 void * _sbrk_r(struct _reent *r, int incr)
294 {
295  //tprintf("incr = %d 0x%08X\n", incr, incr);
296  return alloc_memory(incr);
297 }
298 
299 void * _sbrk(ptrdiff_t incr)
300 {
301  return alloc_memory(incr);
302 }
303 
304 #endif // TARGET_SYSTEM_EMU
305 
306 
307 #ifdef TEST
308 /*
309  * テスト
310  */
311 #define MEMSIZE 0x10000
312 static unsigned char mem[MEMSIZE];
313 
314 void * memalloc(unsigned long size)
315 {
316  void *mp;
317  printf("MALLOC(%ld)\n", size);
318  mp = alloc_memory(size);
319  if(mp == 0) {
320  printf("Error\n");
321  } else {
322  printf("pointer : %08X\n", mp - MEM_START);
323  printf("size = %ld\n", memory_size(mp));
324  printf("free = %ld\n", heap_free_size());
325  }
326  return mp;
327 }
328 
329 void memfree(void *ptr)
330 {
331  printf("FREE(%08x)\n", ptr - MEM_START);
332  free_memory(ptr);
333  printf("free = %ld\n", heap_free_size());
334 }
335 
336 void memlist(void)
337 {
338  memhdr *p, *prevp = freep;
339  for(p= prevp->s.next; ; prevp = p, p = p->s.next) {
340  if(p == freep) return;
341  tprintf("alloced : %08lx (%ld)\n", (unsigned long)p+1,
342  (unsigned long)p->s.size*sizeof(memhdr));
343  }
344 }
345 
346 int main(int argc, char *argv[])
347 {
348  void *mp[10];
349  int i;
350 
351  for(i=0; i< MEMSIZE; i++) {
352  mem[i] = 0xff;
353  }
354 
355  MEM_START = mem;
356  MEM_END = &mem[MEMSIZE];
357 
358  init_memory();
359 
360  printf("%ld byte free\n", heap_free_size());
361 
362  printf("base = %08lx\n", (unsigned long)base);
363  printf("freep = %08lx\n", (unsigned long)freep);
364 
365  mp[0] = memalloc(100);
366  mp[1] = memalloc(100);
367  memfree(mp[0]);
368  printf("free\n");
369  mp[2] = memalloc(100);
370  mp[3] = memalloc(1000);
371  mp[4] = memalloc(10000);
372  memfree(mp[2]);
373  mp[5] = memalloc(10000);
374  memlist();
375 // memfree(mp[1]);
376  memfree(mp[4]);
377  memfree(mp[3]);
378  memfree(mp[5]);
379 
380  mp[6] = memalloc(20000);
381  mp[7] = memalloc(30000);
382  memlist();
383  mp[8] = memalloc(15280);
384  memlist();
385  mp[9] = memalloc(100);
386 
387  return 0;
388 }
389 #endif
unsigned int system_heap_size(void)
< $gsc ヒープメモリ管理をnewlibで行う
Definition: syscalls.c:106
メモリ管理
void init_memory(void)
メモリ管理の初期化
Definition: memory.c:97
unsigned long heap_total_size(void)
全てのメモリのバイト数を取得する
Definition: memory.c:276
void free_memory(void *ptr)
確保したメモリを開放する
Definition: memory.c:195
文字列処理
void display_memory_info(void)
メモリ状態表示
Definition: memory.c:115
int tkprintf(const char *fmt,...)
非タスクコンテキスト実行用メッセージ出力
Definition: tkprintf.c:100
カーネル用機能限定printf
unsigned long memory_size(void *ptr)
確保したメモリのバイト数を取得する
Definition: memory.c:241
void * alloc_memory(unsigned int size)
メモリを確保する
Definition: memory.c:138
int tprintf(const char *fmt,...)
簡易printf
Definition: tprintf.c:85
カーネル、ドライバ(非タスク)デバッグ用マクロ
unsigned long heap_free_size(void)
未確保のメモリの合計バイト数を取得する
Definition: memory.c:255