17 IRX_ID(
"System_Memory_Manager", 2, 3);
22 static KprintfHandler_t *g_kprintf_cb;
23 static void *g_kprintf_cb_userdata;
25 extern int sysmem_reinit(
void);
26 static int cCpuSuspendIntr(
int *state);
27 static int cCpuResumeIntr(
int state);
28 static void *allocSysMemory_internal(
int flags,
int size,
const void *mem);
29 static int freeSysMemory_internal(
const void *ptr);
30 static void updateSmemCtlBlk(
void);
35 int (*cbCpuSuspendIntr)(
int *state);
36 int (*cbCpuResumeIntr)(
int state);
38 int (*cbQueryIntrContext)(void);
41 int _start(
unsigned int memsize)
43 memsize = (memsize > 0x7FFF00) ? 0x7FFF00 : memsize;
44 g_sysmem_internals.m_alloclist =
45 ((memsize & 0xFFFFFF00) >= ((((uiptr)((&g_sysmem_internals))) +
sizeof(g_sysmem_internals) + 255) >> 8 << 8)
47 (
sysmem_alloc_table_t *)((((uiptr)((&g_sysmem_internals))) +
sizeof(g_sysmem_internals) + 255) >> 8 << 8) :
49 g_sysmem_internals.m_memsize = memsize & 0xFFFFFF00;
50 g_sysmem_internals.m_intr_suspend_tbl = NULL;
51 g_sysmem_internals.m_allocation_count = 0;
52 g_sysmem_internals.m_smemupdate_cur = NULL;
53 return g_sysmem_internals.m_alloclist ? sysmem_reinit() : 0;
56 int sysmem_reinit(
void)
62 alloclist = g_sysmem_internals.m_alloclist;
65 alloclist->m_next = NULL;
66 for ( i = 0; i < (
sizeof(alloclist->m_blkarray) /
sizeof(alloclist->m_blkarray[0])); i += 1 )
68 alloclist->m_blkarray[i].m_next = &(alloclist->m_blkarray[i + 1]);
69 alloclist->m_blkarray[i].m_info.m_allocated = 0;
70 alloclist->m_blkarray[i].m_info.m_address = 0;
71 alloclist->m_blkarray[i].m_info.m_pad = 0;
72 alloclist->m_blkarray[i].m_info.m_size = 0;
74 alloclist->m_blkarray[(
sizeof(alloclist->m_blkarray) /
sizeof(alloclist->m_blkarray[0])) - 1].m_next = NULL;
75 alloclist->m_blkarray[0].m_info.m_size = g_sysmem_internals.m_memsize >> 8;
76 g_sysmem_internals.m_allocation_count = 1;
78 AllocSysMemory(ALLOC_FIRST, (
int)alloclist, NULL) != NULL
79 || (
sysmem_alloc_table_t *)AllocSysMemory(ALLOC_FIRST,
sizeof(*alloclist) -
sizeof(alloclist->m_padding), NULL)
82 g_sysmem_internals.m_alloclist = NULL;
85 for ( blklist = alloclist->m_blkarray; blklist; blklist = blklist->m_next )
86 if ( !blklist->m_info.m_allocated )
87 return blklist->m_info.m_address << 8;
93 return g_sysmem_internals.m_alloclist ? g_sysmem_internals.m_memsize : 0;
96 u32 QueryMaxFreeMemSize()
103 if ( !g_sysmem_internals.m_alloclist )
105 cCpuSuspendIntr(&state);
106 for ( blklist = g_sysmem_internals.m_alloclist->m_blkarray; blklist; blklist = blklist->m_next )
107 if ( !blklist->m_info.m_allocated && retval < blklist->m_info.m_size )
108 retval = blklist->m_info.m_size;
109 cCpuResumeIntr(state);
114 u32 QueryTotalFreeMemSize()
120 if ( !g_sysmem_internals.m_alloclist )
123 cCpuSuspendIntr(&state);
124 for ( blklist = g_sysmem_internals.m_alloclist->m_blkarray; blklist; blklist = blklist->m_next )
125 retval += !blklist->m_info.m_allocated ? blklist->m_info.m_size : 0;
126 cCpuResumeIntr(state);
131 void *AllocSysMemory(
int mode,
int size,
void *ptr)
136 if ( !g_sysmem_internals.m_alloclist || (
unsigned int)mode >= 3 )
138 cCpuSuspendIntr(&state);
139 retval = allocSysMemory_internal(mode, size, ptr);
141 cCpuResumeIntr(state);
145 int FreeSysMemory(
void *ptr)
151 for ( alloclist = g_sysmem_internals.m_alloclist; alloclist && ptr != alloclist; alloclist = alloclist->m_next )
155 cCpuSuspendIntr(&state);
156 retval = freeSysMemory_internal(ptr);
159 cCpuResumeIntr(state);
163 void *QueryBlockTopAddress(
void *address)
169 cCpuSuspendIntr(&state);
170 blk = search_block(address);
171 retval = blk ? ((blk->m_info.m_address << 8) | (
int)(!blk->m_info.m_allocated ? FREE : USED)) : -1;
172 cCpuResumeIntr(state);
173 return (
void *)retval;
176 int QueryBlockSize(
void *address)
182 cCpuSuspendIntr(&state);
183 blk = search_block(address);
184 retval = blk ? ((blk->m_info.m_size << 8) | (
int)(!blk->m_info.m_allocated ? FREE : USED)) : -1;
185 cCpuResumeIntr(state);
193 cCpuSuspendIntr(&state);
196 info->m_meminfo.m_allocation_count = g_sysmem_internals.m_allocation_count;
197 info->m_meminfo.m_memsize = g_sysmem_internals.m_memsize;
198 info->m_meminfo.m_memlist_last = g_sysmem_internals.m_smemupdate_cur;
200 cCpuResumeIntr(state);
203 if (
info->m_meminfo.m_memlist_last != g_sysmem_internals.m_smemupdate_cur )
205 info->m_blockinfo.m_block_address = (
void *)-1;
206 info->m_blockinfo.m_flags_memsize = -1;
207 info->m_blockinfo.m_table_info = NULL;
208 cCpuResumeIntr(state);
211 if ( !
info->m_blockinfo.m_table_info )
213 info->m_blockinfo.m_flags_memsize = 1;
214 info->m_blockinfo.m_block_address = (
void *)g_sysmem_internals.m_memsize;
215 cCpuResumeIntr(state);
218 info->m_blockinfo.m_block_address =
219 (
void *)((((
unsigned int)
info->m_blockinfo.m_table_info->m_blkarray[0].m_next >> 1) & 0x7FFF) << 8);
220 info->m_blockinfo.m_flags_memsize = (
unsigned int)
info->m_blockinfo.m_table_info->m_blkarray[0].m_next >> 17 << 8;
221 if ( ((
int)
info->m_blockinfo.m_table_info->m_blkarray[0].m_next & 1) )
225 for ( alloclist = g_sysmem_internals.m_alloclist; alloclist && alloclist !=
info->m_blockinfo.m_block_address;
226 alloclist = alloclist->m_next )
228 info->m_blockinfo.m_flags_memsize |= alloclist ? 2 : 0;
231 info->m_blockinfo.m_flags_memsize |= 1;
232 info->m_blockinfo.m_table_info = ((
unsigned int)
info->m_blockinfo.m_table_info->m_blkarray[0].m_next >> 17) ?
233 info->m_blockinfo.m_table_info->m_next :
235 cCpuResumeIntr(state);
240 return &g_sysmem_internals;
243 static void *allocSysMemory_internal(
int flags,
int size,
const void *mem)
245 unsigned int size_rounded;
247 size_rounded = (
unsigned int)(size + 255) >> 8;
259 if ( !g_sysmem_internals.m_alloclist )
261 for ( i = g_sysmem_internals.m_alloclist->m_blkarray; i; i = i->m_next )
262 if ( !i->m_info.m_allocated && i->m_info.m_size >= size_rounded )
266 if ( i->m_info.m_size == size_rounded )
268 i->m_info.m_allocated = 1;
269 return (
void *)(uiptr)(i->m_info.m_address << 8);
271 g_sysmem_internals.m_allocation_count += 1;
272 blkinfo.m_address = i->m_info.m_address + size_rounded;
273 blkinfo.m_size = i->m_info.m_size - size_rounded;
274 blkinfo.m_allocated = i->m_info.m_allocated;
275 blkinfo.m_pad = i->m_info.m_pad;
276 i->m_info.m_allocated = 1;
277 i->m_info.m_size = size_rounded;
279 for ( next = i->m_next; next && blkinfo.m_size; next = next->m_next )
283 blkinfo_tmp = next->m_info;
284 next->m_info = blkinfo;
285 blkinfo = blkinfo_tmp;
287 return (
void *)(uiptr)(i->m_info.m_address << 8);
294 unsigned int retaddr;
298 if ( !g_sysmem_internals.m_alloclist )
301 for ( list = g_sysmem_internals.m_alloclist->m_blkarray; list; list = list->m_next )
302 if ( !list->m_info.m_allocated && list->m_info.m_size >= size_rounded )
306 if ( i->m_info.m_size == size_rounded )
308 i->m_info.m_allocated = 1;
309 return (
void *)(uiptr)(i->m_info.m_address << 8);
311 g_sysmem_internals.m_allocation_count += 1;
312 i->m_info.m_size -= size_rounded;
313 retaddr = i->m_info.m_address + i->m_info.m_size;
314 blkinfo.m_address = retaddr;
315 blkinfo.m_size = size_rounded;
316 blkinfo.m_allocated = 1;
319 for ( next = i->m_next; next && blkinfo.m_size; next = next->m_next )
323 blkinfo_tmp = next->m_info;
324 next->m_info = blkinfo;
325 blkinfo = blkinfo_tmp;
327 return (
void *)(uiptr)(retaddr << 8);
333 unsigned int mem_rounded;
336 if ( (((uiptr)mem) & 0xFF) )
338 mem_rounded = (
unsigned int)mem >> 8;
340 if ( !g_sysmem_internals.m_alloclist )
342 for ( i = g_sysmem_internals.m_alloclist->m_blkarray; i; i = i->m_next )
344 if ( mem_rounded < i->m_info.m_address )
346 if ( !i->m_info.m_allocated && (u32)(i->m_info.m_address + i->m_info.m_size) >= mem_rounded + size_rounded )
351 if ( i->m_info.m_address < mem_rounded )
357 g_sysmem_internals.m_allocation_count += 1;
358 sz_tmp = i->m_info.m_address + i->m_info.m_size - mem_rounded;
359 i->m_info.m_size -= sz_tmp;
360 blkinfo_nest.m_address = i->m_info.m_address + i->m_info.m_size;
361 blkinfo_nest.m_size = sz_tmp;
362 blkinfo_nest.m_allocated = 0;
363 blkinfo_nest.m_pad = 0;
366 while ( blkinfo_nest.m_size )
370 blkinfo_tmp = blk_tmp->m_info;
371 blk_tmp->m_info = blkinfo_nest;
372 blkinfo_nest = blkinfo_tmp;
373 blk_tmp = blk_tmp->m_next;
376 if ( i->m_info.m_size == size_rounded )
378 i->m_info.m_allocated = 1;
379 return (
void *)(uiptr)(i->m_info.m_address << 8);
381 g_sysmem_internals.m_allocation_count += 1;
382 blkinfo.m_address = i->m_info.m_address + size_rounded;
383 blkinfo.m_size = i->m_info.m_size - size_rounded;
384 blkinfo.m_allocated = i->m_info.m_allocated;
385 blkinfo.m_pad = i->m_info.m_pad;
386 i->m_info.m_allocated = 1;
387 i->m_info.m_size = size_rounded;
389 for ( next = i->m_next; next && blkinfo.m_size; next = next->m_next )
393 blkinfo_tmp = next->m_info;
394 next->m_info = blkinfo;
395 blkinfo = blkinfo_tmp;
397 return (
void *)(uiptr)(i->m_info.m_address << 8);
404 static int freeSysMemory_internal(
const void *ptr)
406 unsigned int ptr_rounded;
414 ptr_rounded = (
unsigned int)ptr >> 8;
415 if ( (((uiptr)ptr) & 0xFF) )
419 if ( !g_sysmem_internals.m_alloclist )
421 for ( blklist = &g_sysmem_internals.m_alloclist->m_blkarray[2]; blklist; blklist = blklist->m_next )
423 if ( blklist->m_info.m_size && blklist->m_info.m_address == ptr_rounded )
427 if ( !blklist || !blklist->m_info.m_allocated )
431 next = blklist->m_next;
432 blklist->m_info.m_allocated = 0;
433 if ( next && next->m_info.m_size && !next->m_info.m_allocated )
436 g_sysmem_internals.m_allocation_count -= 1;
437 merge_blk = blklist->m_next;
438 blklist->m_info.m_size += merge_blk->m_info.m_size;
440 if ( prev_blk && !prev_blk->m_info.m_allocated )
444 g_sysmem_internals.m_allocation_count -= 1;
445 prev_blk->m_info.m_size += blklist->m_info.m_size;
450 for ( i = merge_blk; blk_modcnt != -1; blk_modcnt -= 1 )
452 for ( ; i; i = i->m_next )
454 merge_blk->m_info = i->m_info;
455 merge_blk = merge_blk->m_next;
460 static void updateSmemCtlBlk(
void)
464 g_sysmem_internals.m_smemupdate_cur += 1;
465 for ( alloclist = g_sysmem_internals.m_alloclist; alloclist->m_next; alloclist = alloclist->m_next )
466 if ( alloclist->m_blkarray[(
sizeof(alloclist->m_blkarray) /
sizeof(alloclist->m_blkarray[0])) - 4].m_info.m_size )
470 if ( alloclist->m_next )
475 next = alloclist->m_next;
476 alloclist->m_blkarray[(
sizeof(alloclist->m_blkarray) /
sizeof(alloclist->m_blkarray[0])) - 1].m_next =
477 &(next->m_blkarray[0]);
479 for ( i = 0; i < (
sizeof(next->m_blkarray) /
sizeof(next->m_blkarray[0])); i += 1 )
481 next->m_blkarray[i].m_next = &(next->m_blkarray[i + 1]);
482 next->m_blkarray[i].m_info.m_allocated = 0;
483 next->m_blkarray[i].m_info.m_address = 0;
484 next->m_blkarray[i].m_info.m_pad = 0;
485 next->m_blkarray[i].m_info.m_size = 0;
487 next->m_blkarray[(
sizeof(next->m_blkarray) /
sizeof(next->m_blkarray[0])) - 1].m_next = NULL;
490 alloclist = g_sysmem_internals.m_alloclist;
492 if ( alloclist && alloclist->m_next )
496 for ( ; alloclist->m_next->m_next; alloclist = alloclist->m_next )
498 next = alloclist->m_next;
501 && !alloclist->m_blkarray[(
sizeof(alloclist->m_blkarray) /
sizeof(alloclist->m_blkarray[0])) - 4].m_info.m_size )
503 alloclist->m_blkarray[(
sizeof(alloclist->m_blkarray) /
sizeof(alloclist->m_blkarray[0])) - 1].m_next = NULL;
504 alloclist->m_next = NULL;
505 freeSysMemory_internal(next);
515 if ( !g_sysmem_internals.m_alloclist )
517 for ( blklist = g_sysmem_internals.m_alloclist->m_blkarray; blklist; blklist = blklist->m_next )
519 (uiptr)address >= (uiptr)(blklist->m_info.m_address << 8)
520 && (uiptr)address < (uiptr)((blklist->m_info.m_address + blklist->m_info.m_size) << 8) )
525 static int cCpuSuspendIntr(
int *state)
528 return (intrman_callbacks && intrman_callbacks->cbCpuSuspendIntr) ? intrman_callbacks->cbCpuSuspendIntr(state) : 0;
531 static int cCpuResumeIntr(
int state)
534 return (intrman_callbacks && intrman_callbacks->cbCpuResumeIntr) ? intrman_callbacks->cbCpuResumeIntr(state) : 0;
538 static int cQueryIntrContext(
void)
541 return ( intrman_callbacks && intrman_callbacks->cbQueryIntrContext ) ? intrman_callbacks->cbQueryIntrContext() : 0;
545 int Kprintf(
const char *format, ...)
552 va_start(va, format);
553 ret = g_kprintf_cb(g_kprintf_cb_userdata, format, va);
558 void KprintfSet(KprintfHandler_t *new_cb,
void *context)
560 if ( g_kprintf_cb && new_cb )
561 new_cb(context, (
const char *)(uiptr)Kprintf(NULL), NULL);
562 g_kprintf_cb = new_cb;
563 g_kprintf_cb_userdata = context;