1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - OS
3 File: os_alloc.c
4
5 Copyright 2003-2009 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2009-06-04#$
14 $Rev: 10698 $
15 $Author: okubata_ryoma $
16
17 *---------------------------------------------------------------------------*/
18 #include <nitro/os.h>
19 #include <nitro/os/common/alloc.h>
20
21 /*---------------------------------------------------------------------------*
22 Error messages of OSAlloc.c
23 *---------------------------------------------------------------------------*/
24 #define OS_ERR_ALLOCFROMHEAP_NOHEAP "OS_AllocFromHeap(): heap is not initialized."
25 #define OS_ERR_ALLOCFROMHEAP_INVSIZE "OS_AllocFromHeap(): invalid size."
26 #define OS_ERR_ALLOCFROMHEAP_INVHEAP "OS_AllocFromHeap(): invalid heap handle."
27 #define OS_ERR_ALLOCFROMHEAP_BROKENHEAP "OS_AllocFromHeap(): heap is broken."
28 #define OS_ERR_ALLOCFIXED_NOHEAP "OS_AllocFixed(): heap is not initialized."
29 #define OS_ERR_ALLOCFIXED_INVRANGE "OS_AllocFixed(): invalid range."
30 #define OS_ERR_FREETOHEAP_NOHEAP "OS_FreeToHeap(): heap is not initialized."
31 #define OS_ERR_FREETOHEAP_INVPTR "OS_FreeToHeap(): invalid pointer."
32 #define OS_ERR_FREETOHEAP_INVHEAP "OS_FreeToHeap(): invalid heap handle."
33 #define OS_ERR_SETCURRENTHEAP_NOHEAP "OS_SetCurrentHeap(): heap is not initialized."
34 #define OS_ERR_SETCURRENTHEAP_INVHEAP "OS_SetCurrentHeap(): invalid heap handle."
35 #define OS_ERR_INITALLOC_INVNUMHEAPS "OS_InitAlloc(): invalid number of heaps."
36 #define OS_ERR_INITALLOC_INVRANGE "OS_InitAlloc(): invalid range."
37 #define OS_ERR_INITALLOC_INSRANGE "OS_InitAlloc(): too small range."
38 #define OS_ERR_CLEARALLOC_INVID "OS_ClearAlloc(): invalid arena id."
39 #define OS_ERR_CREATEHEAP_NOHEAP "OS_CreateHeap(): heap is not initialized."
40 #define OS_ERR_CREATEHEAP_INVRANGE "OS_CreateHeap(): invalid range."
41 #define OS_ERR_CREATEHEAP_INSRANGE "OS_CreateHeap(): too small range."
42 #define OS_ERR_DESTROYHEAP_NOHEAP "OS_DestroyHeap(): heap is not initialized."
43 #define OS_ERR_DESTROYHEAP_INVHEAP "OS_DestroyHeap(): invalid heap handle."
44 #define OS_ERR_ADDTOHEAP_NOHEAP "OS_AddToHeap(): heap is not initialized."
45 #define OS_ERR_ADDTOHEAP_INVHEAP "OS_AddToHeap(): invalid heap handle."
46 #define OS_ERR_ADDTOHEAP_INVRANGE "OS_AddToHeap(): invalid range."
47 #define OS_ERR_ADDTOHEAP_INSRANGE "OS_AddToHeap(): too small range."
48 #define OS_ERR_REFERENT_NOHEAP "OS_ReferentSize(): heap is not initialized."
49 #define OS_ERR_REFERENT_INVPTR "OS_ReferentSize(): invalid pointer."
50 #define OS_ERR_DUMPHEAP_NOHEAP "OS_DumpHeap(): heap is not initialized."
51 #define OS_ERR_DUMPHEAP_INVHEAP "OS_DumpHeap(): invalid heap handle."
52 #define OS_ERR_DUMPHEAP_BROKENHEAP "OS_DumpHeap(): heap is broken."
53 #define OS_ERR_ALLOCFROMHEAP_INVID "OS_AllocFromHeap(): illegal arena id."
54 #define OS_ERR_ALLOCFROMHEAP_NOINFO "OS_AllocFromHeap(): heap not initialized."
55 #define OS_ERR_ALLOCFIXED_INVID "OS_AllocFixed(): illegal arena id."
56 #define OS_ERR_ALLOCFIXED_NOINFO "OS_AllocFixed(): heap not initialized."
57 #define OS_ERR_FREETOHEAP_INVID "OS_FreeToHeap(): illegal arena id."
58 #define OS_ERR_FREETOHEAP_NOINFO "OS_FreeToHeap(): heap not initialized."
59 #define OS_ERR_SETCURRENTHEAP_INVID "OS_SetCurrentHeap(): illegal arena id."
60 #define OS_ERR_SETCURRENTHEAP_NOINFO "OS_SetCurrentHeap(): heap not initialized."
61 #define OS_ERR_INITALLOC_INVID "OS_SetInitAlloc(): illegal arena id."
62 #define OS_ERR_INITALLOC_INVINFO "OS_SetInitAlloc(): heap already initialized."
63 #define OS_ERR_CREATEHEAP_INVID "OS_CreateHeap(): illegal arena id."
64 #define OS_ERR_CREATEHEAP_NOINFO "OS_CreateHeap(): heap not initialized."
65 #define OS_ERR_DESTROYHEAP_INVID "OS_DestroyHeap(): illegal arena id."
66 #define OS_ERR_DESTROYHEAP_NOINFO "OS_DestroyHeap(): heap not initialized."
67 #define OS_ERR_ADDTOHEAP_INVID "OS_AddToHeap(): illegal arena id."
68 #define OS_ERR_ADDTOHEAP_NOINFO "OS_AddToHeap(): heap not initialized."
69 #define OS_ERR_CHECKHEAP_INVID "OS_CheckHeap(): illegal arena id."
70 #define OS_ERR_CHECKHEAP_NOINFO "OS_CheckHeap(): heap not initialized."
71 #define OS_ERR_REFERENTSIZE_INVID "OS_ReferentSize(): illegal arena id."
72 #define OS_ERR_REFERENTSIZE_NOINFO "OS_ReferrentSize(): heap not initialized."
73 #define OS_ERR_DUMPHEAP_INVID "OS_DumpHeap(): illegal arena id."
74 #define OS_ERR_DUMPHEAP_NOINFO "OS_DumpHeap(): heap not initialized."
75 #define OS_ERR_VISITALLOCATED_INVID "OS_VisitAllocated(): illegal arena id."
76 #define OS_ERR_VISITALLOCATED_NOINFO "OS_VisitAllocated(): heap not initialized."
77
78
79 #define OFFSET(n, a) (((u32) (n)) & ((a) - 1))
80 #define TRUNC(n, a) (((u32) (n)) & ~((a) - 1))
81 #define ROUND(n, a) (((u32) (n) + (a) - 1) & ~((a) - 1))
82
83 #define ALIGNMENT 32 // alignment in bytes
84 #define MINOBJSIZE (HEADERSIZE + ALIGNMENT) // smallest object
85 #define HEADERSIZE ROUND(sizeof(Cell), ALIGNMENT)
86
87 //---- InRange(): True if a <= targ < b
88 #define InRange(targ, a, b) \
89 ((u32)(a) <= (u32)(targ) && (u32)(targ) < (u32)(b))
90
91 //---- RangeOverlap(): True if the ranges a and b overlap in any way.
92 #define RangeOverlap(aStart, aEnd, bStart, bEnd) \
93 ((u32)(bStart) <= (u32)(aStart) && (u32)(aStart) < (u32)(bEnd) || \
94 (u32)(bStart) < (u32)(aEnd) && (u32)(aEnd) <= (u32)(bEnd))
95
96 //---- RangeSubset(): True if range a is a subset of range b
97 // Assume (aStart < aEnd) and (bStart < bEnd)
98 #define RangeSubset(aStart, aEnd, bStart, bEnd) \
99 ((u32)(bStart) <= (u32)(aStart) && (u32)(aEnd) <= (u32)(bEnd))
100
101 typedef struct Cell Cell;
102 typedef struct HeapDesc HeapDesc;
103
104 // Cell: header of object which resides HEADERSIZE bytes before payload.
105 // doubly linked list are needed because of non-contiguous heaps
106 struct Cell
107 {
108 Cell *prev;
109 Cell *next;
110 long size; // size of object plus HEADERSIZE
111
112 #ifdef SDK_DEBUG
113 HeapDesc *hd; // from which the block is allocated
114 // (NULL in free list).
115 long requested; // size of object to have been requested
116 #endif // SDK_DEBUG
117 };
118
119 struct HeapDesc
120 {
121 long size; // if -1 then heap is free. Note OS_AllocFixed()
122 // could make a heap empty.
123 Cell *free; // pointer to the first free cell
124 Cell *allocated; // pointer to the first used cell
125
126 #ifdef SDK_DEBUG
127 u32 paddingBytes;
128 u32 headerBytes;
129 u32 payloadBytes;
130 #endif // SDK_DEBUG
131 };
132
133 #if defined(SDK_TWL) && !defined(SDK_TWLLTD)
134 static OSArenaId OSi_ExtraHeapArenaId = (OSArenaId)-1;
135 static OSHeapHandle OSi_ExtraHeapHandle = -1;
136 #endif
137
138 //----------------
139 //---- struct of Heap infomation
140 typedef struct
141 {
142 // volatile because some functions use this as hidden macro parameter
143 volatile OSHeapHandle currentHeap;
144 int numHeaps;
145 void *arenaStart;
146 void *arenaEnd;
147 HeapDesc *heapArray;
148 }
149 OSHeapInfo;
150
151 void *OSiHeapInfo[OS_ARENA_MAX] = {
152 NULL,
153 NULL,
154 NULL,
155 NULL,
156 NULL,
157 NULL,
158 NULL,
159 NULL,
160 NULL
161 }; // because OS_ARENA_MAX = 9
162
163 //================================================================================
164 /*---------------------------------------------------------------------------*
165 Name: DLAddFront
166
167 Description: Inserts /cell/ into the head of the list pointed to by /list/
168
169 Arguments: list : pointer to the first cell in the list
170 cell : pointer to a cell to be inserted
171
172 Returns: a pointer to the new first cell
173 *---------------------------------------------------------------------------*/
DLAddFront(Cell * list,Cell * cell)174 static Cell *DLAddFront(Cell * list, Cell * cell)
175 {
176 cell->next = list;
177 cell->prev = NULL;
178 if (list)
179 {
180 list->prev = cell;
181 }
182 return cell;
183 }
184
185 /*---------------------------------------------------------------------------*
186 Name: DLLookup
187
188 Description: Returns /cell/ if /cell/ is found in /list/.
189
190 Arguments: list : pointer to the first cell in the list
191 cell : pointer to a cell to look for
192
193 Returns: /cell/ if /cell/ is in /list/. Otherwise, NULL.
194 *---------------------------------------------------------------------------*/
DLLookup(Cell * list,Cell * cell)195 static Cell *DLLookup(Cell * list, Cell * cell)
196 {
197 for (; list; list = list->next)
198 {
199 if (list == cell)
200 {
201 return list;
202 }
203 }
204 return NULL;
205 }
206
207 /*---------------------------------------------------------------------------*
208 Name: DLExtract
209
210 Description: Extracts /target/ from the list pointed to by /list/.
211 If /target/ is at the head of the list, /list/ will be changed
212 to reflect its removal.
213
214 Arguments: list : pointer to the first cell in the list
215 cell : pointer to a cell to remove
216
217 Returns: a pointer to the new first cell
218 *---------------------------------------------------------------------------*/
DLExtract(Cell * list,Cell * cell)219 static Cell *DLExtract(Cell * list, Cell * cell)
220 {
221 if (cell->next)
222 {
223 cell->next->prev = cell->prev;
224 }
225
226 if (cell->prev == NULL)
227 {
228 return cell->next;
229 }
230 else
231 {
232 cell->prev->next = cell->next;
233 return list;
234 }
235 }
236
237 /*---------------------------------------------------------------------------*
238 Name: DLInsert
239
240 Description: Inserts /cell/ into the list pointed to by /list/ in sorted
241 order by address. Also attempts to coalesce forward and
242 backward blocks if possible.
243
244 Arguments: list : pointer to the first cell in the list
245 cell : pointer to a cell to be inserted
246
247 Returns: a pointer to the new first cell
248 *---------------------------------------------------------------------------*/
DLInsert(Cell * list,Cell * cell)249 static Cell *DLInsert(Cell * list, Cell * cell)
250 {
251 Cell *prev;
252 Cell *next;
253
254 for (next = list, prev = NULL; next; prev = next, next = next->next)
255 {
256 if (cell <= next)
257 {
258 break;
259 }
260 }
261
262 cell->next = next;
263 cell->prev = prev;
264 if (next)
265 {
266 next->prev = cell;
267 if ((char *)cell + cell->size == (char *)next)
268 {
269 //---- Coalesce forward
270 cell->size += next->size;
271 cell->next = next = next->next;
272 if (next)
273 {
274 next->prev = cell;
275 }
276 }
277 }
278 if (prev)
279 {
280 prev->next = cell;
281 if ((char *)prev + prev->size == (char *)cell)
282 {
283 //---- Coalesce back
284 prev->size += cell->size;
285 prev->next = next;
286 if (next)
287 {
288 next->prev = prev;
289 }
290 }
291 return list;
292 }
293 else
294 {
295 return cell; // cell becomes new head of list
296 }
297 }
298
299 /*---------------------------------------------------------------------------*
300 Name: DLOverlap
301
302 Description: returns true if the range delimited by /start/ and /end/
303 overlaps with any element of /list/.
304
305 Arguments: list : pointer to the first cell in the list
306 start : start of range
307 end : end of range
308
309 Returns: TRUE if /start/-/end/ overlaps with any element of /list/
310 *---------------------------------------------------------------------------*/
DLOverlap(Cell * list,void * start,void * end)311 static BOOL DLOverlap(Cell * list, void *start, void *end)
312 {
313 Cell *cell;
314
315 for (cell = list; cell; cell = cell->next)
316 {
317 if (RangeOverlap(cell, (char *)cell + cell->size, start, end))
318 {
319 return TRUE;
320 }
321 }
322 return FALSE;
323 }
324
325 /*---------------------------------------------------------------------------*
326 Name: DLSize
327
328 Description: returns total number of bytes used by every element of /list/.
329
330 Arguments: list : pointer to the first cell in the list
331
332 Returns: total number of bytes used by every cell of /list/
333 *---------------------------------------------------------------------------*/
DLSize(Cell * list)334 static long DLSize(Cell * list)
335 {
336 Cell *cell;
337 long size = 0;
338
339 for (cell = list; cell; cell = cell->next)
340 {
341 size += cell->size;
342 }
343 return size;
344 }
345
346 //================================================================================
347 /*---------------------------------------------------------------------------*
348 Name: OS_AllocFromHeap
349
350 Description: Allocates /size/ bytes from /heap/. Some additional memory
351 will also be consumed from /heap/.
352
353 Arguments: id : arena ID
354 heap : handle to a heap that was returned from OS_CreateHeap()
355 size : size of object to be allocated
356
357 Returns: a null pointer or a pointer to the allocated space aligned
358 with ALIGNMENT bytes boundaries
359 *---------------------------------------------------------------------------*/
OS_AllocFromHeap(OSArenaId id,OSHeapHandle heap,u32 size)360 void *OS_AllocFromHeap(OSArenaId id, OSHeapHandle heap, u32 size)
361 {
362 OSHeapInfo *heapInfo;
363 HeapDesc *hd;
364 Cell *cell; // candidate block
365 Cell *newCell; // ptr to leftover block
366 long leftoverSize; // size of any leftover
367 OSIntrMode enabled = OS_DisableInterrupts();
368
369 //OS_Printf( "id=%d heap=%x size=%x\n",id, heap, size );
370
371 #ifdef SDK_DEBUG
372 long requested = (long)size;
373 #endif // SDK_DEBUG
374
375 //---- check arena id
376 SDK_ASSERTMSG(id < OS_ARENA_MAX, OS_ERR_ALLOCFROMHEAP_INVID);
377 SDK_ASSERTMSG(OSiHeapInfo[id], OS_ERR_ALLOCFROMHEAP_NOINFO);
378 heapInfo = OSiHeapInfo[id];
379
380 //---- check exist heap and size>0
381 if (!heapInfo)
382 {
383 (void)OS_RestoreInterrupts(enabled);
384 return NULL;
385 }
386
387 //---- heap<0 means current heap
388 if (heap < 0)
389 {
390 heap = heapInfo->currentHeap;
391 }
392
393 SDK_ASSERTMSG(heapInfo->heapArray, OS_ERR_ALLOCFROMHEAP_NOHEAP);
394 SDK_ASSERTMSG(0 < ((long)size), OS_ERR_ALLOCFROMHEAP_INVSIZE);
395 SDK_ASSERTMSG(0 <= heap && heap < heapInfo->numHeaps, OS_ERR_ALLOCFROMHEAP_INVHEAP);
396 SDK_ASSERTMSG(0 <= heapInfo->heapArray[heap].size, OS_ERR_ALLOCFROMHEAP_INVHEAP);
397
398 hd = &heapInfo->heapArray[heap];
399
400 // Enlarge size to smallest possible cell size
401 size += HEADERSIZE;
402 size = ROUND(size, ALIGNMENT);
403
404 // Search for block large enough
405 for (cell = hd->free; cell != NULL; cell = cell->next)
406 {
407 if ((long)size <= cell->size)
408 {
409 break;
410 }
411 }
412
413 if (cell == NULL)
414 {
415 #ifdef SDK_DEBUG
416 OS_Printf("OS_AllocFromHeap: Warning- failed to allocate %d bytes\n", size);
417 #endif // SDK_DEBUG
418 (void)OS_RestoreInterrupts(enabled);
419 return NULL;
420 }
421
422 SDK_ASSERTMSG(OFFSET(cell, ALIGNMENT) == 0, OS_ERR_ALLOCFROMHEAP_BROKENHEAP);
423 SDK_ASSERTMSG(cell->hd == NULL, OS_ERR_ALLOCFROMHEAP_BROKENHEAP);
424
425 leftoverSize = cell->size - (long)size;
426 if (leftoverSize < MINOBJSIZE)
427 {
428 //---- Just extract this cell out since it's too small to split
429 hd->free = DLExtract(hd->free, cell);
430 }
431 else
432 {
433 //---- cell is large enough to split into two pieces
434 cell->size = (long)size;
435
436 //---- Create a new cell
437 newCell = (Cell *) ((char *)cell + size);
438 newCell->size = leftoverSize;
439 #ifdef SDK_DEBUG
440 newCell->hd = NULL;
441 #endif
442
443 //---- Leave newCell in free, and take cell away
444 newCell->prev = cell->prev;
445 newCell->next = cell->next;
446
447 if (newCell->next != NULL)
448 {
449 newCell->next->prev = newCell;
450 }
451
452 if (newCell->prev != NULL)
453 {
454 newCell->prev->next = newCell;
455 }
456 else
457 {
458 SDK_ASSERTMSG(hd->free == cell, OS_ERR_ALLOCFROMHEAP_BROKENHEAP);
459 hd->free = newCell;
460 }
461 }
462
463 //---- Add to allocated list
464 hd->allocated = DLAddFront(hd->allocated, cell);
465
466 #ifdef SDK_DEBUG
467 cell->hd = hd;
468 cell->requested = requested;
469 hd->headerBytes += HEADERSIZE;
470 hd->paddingBytes += cell->size - (HEADERSIZE + requested);
471 hd->payloadBytes += requested;
472 #endif // SDK_DEBUG
473
474 (void)OS_RestoreInterrupts(enabled);
475
476 return (void *)((char *)cell + HEADERSIZE);
477 }
478
479 /*---------------------------------------------------------------------------*
480 Name: OS_AllocFixed
481
482 Description: Allocates the block of memory specified by /rstart/ and
483 /rend/. Will break up any heap. Will not check for overlap
484 with other fixed blocks. May create a zero-length heap.
485
486 Arguments: id : arena ID
487 rstart : pointer to starting addr of block
488 rend : pointer to ending addr of block
489
490 Returns: a null pointer or a pointer to the allocated space aligned
491 with ALIGNMENT bytes boundaries. /rstart/ and /rend/ might be
492 adjusted to the boundaries of really allocated region.
493 *---------------------------------------------------------------------------*/
OS_AllocFixed(OSArenaId id,void ** rstart,void ** rend)494 void *OS_AllocFixed(OSArenaId id, void **rstart, void **rend)
495 {
496 OSHeapInfo *heapInfo;
497 OSHeapHandle i; // heap iterator
498 Cell *cell; // object iterator
499 Cell *newCell; // for creating new objects if necessary
500 HeapDesc *hd;
501 void *start = (void *)TRUNC(*rstart, ALIGNMENT);
502 void *end = (void *)ROUND(*rend, ALIGNMENT);
503 OSIntrMode enabled = OS_DisableInterrupts();
504
505 //---- check arena id
506 SDK_ASSERTMSG(id < OS_ARENA_MAX, OS_ERR_ALLOCFIXED_INVID);
507 SDK_ASSERTMSG(OSiHeapInfo[id], OS_ERR_ALLOCFIXED_NOINFO);
508 heapInfo = OSiHeapInfo[id];
509
510 SDK_ASSERTMSG(heapInfo->heapArray, OS_ERR_ALLOCFIXED_NOHEAP);
511 SDK_ASSERTMSG(start < end, OS_ERR_ALLOCFIXED_INVRANGE);
512 SDK_ASSERTMSG(RangeSubset(start, end, heapInfo->arenaStart, heapInfo->arenaEnd), OS_ERR_ALLOCFIXED_INVRANGE);
513
514 //---- Check overlap with any allocated blocks.
515 for (i = 0; i < heapInfo->numHeaps; i++)
516 {
517 hd = &heapInfo->heapArray[i];
518 if (hd->size < 0) // Is inactive?
519 {
520 continue;
521 }
522
523 if (DLOverlap(hd->allocated, start, end))
524 {
525 #ifdef SDK_DEBUG
526 OS_Printf("OS_AllocFixed: Warning - failed to allocate from %p to %p\n", start, end);
527 #endif // SDK_DEBUG
528 (void)OS_RestoreInterrupts(enabled);
529 return NULL;
530 }
531 }
532
533 /*
534 ASSUME : if we get past all this, the fixed request will
535 not overlap with any non-contiguous free memory.
536
537 Iterate over heaps breaking up appropriate blocks.
538 note that we cannot change the size of the heap by simply subtracting
539 out the overlap area, since the heaps may be non-contiguous.
540 */
541 for (i = 0; i < heapInfo->numHeaps; i++)
542 {
543 //---- for each free obj in heap, find and break overlaps.
544 hd = &heapInfo->heapArray[i];
545
546 if (hd->size < 0) // Is inactive?
547 {
548 continue;
549 }
550
551 for (cell = hd->free; cell; cell = cell->next)
552 {
553 void *cellEnd = (char *)cell + cell->size;
554
555 if ((char *)cellEnd <= (char *)start)
556 {
557 continue;
558 }
559
560 if ((char *)end <= (char *)cell)
561 {
562 break; // Since free is sorted in order of start addresses
563 }
564
565 if (InRange(cell, (char *)start - HEADERSIZE, end) && InRange((char *)cellEnd, start, (char *)end + MINOBJSIZE))
566 {
567 if ((char *)cell < (char *)start)
568 {
569 start = (void *)cell;
570 }
571 if ((char *)end < (char *)cellEnd)
572 {
573 end = (void *)cellEnd;
574 }
575
576 //---- cell is completely overlaped. Just extract this block
577 hd->free = DLExtract(hd->free, cell); // Note cell->next is intact. XXX
578 hd->size -= cell->size; // Update stats
579 continue;
580 }
581
582 if (InRange(cell, (char *)start - HEADERSIZE, end))
583 {
584 if ((char *)cell < (char *)start)
585 {
586 start = (void *)cell;
587 }
588
589 // Start of object in middle of range. break off top.
590 // Avoid DLExtract() and DLInsert() since we already know
591 // exactly where the block should go
592 SDK_ASSERT(MINOBJSIZE <= (char *)cellEnd - (char *)end);
593 newCell = (Cell *) end;
594 newCell->size = (char *)cellEnd - (char *)end;
595 #ifdef SDK_DEBUG
596 newCell->hd = NULL;
597 #endif // SDK_DEBUG
598 newCell->next = cell->next;
599 if (newCell->next)
600 {
601 newCell->next->prev = newCell;
602 }
603 newCell->prev = cell->prev;
604 if (newCell->prev)
605 {
606 newCell->prev->next = newCell;
607 }
608 else
609 {
610 hd->free = newCell; // new head
611 }
612 hd->size -= (char *)end - (char *)cell;
613 break;
614 }
615
616 if (InRange((char *)cellEnd, start, (char *)end + MINOBJSIZE))
617 {
618 if ((char *)end < (char *)cellEnd)
619 {
620 end = (void *)cellEnd;
621 }
622
623 //---- Nothing to change except size
624 SDK_ASSERT(MINOBJSIZE <= (char *)start - (char *)cell);
625 hd->size -= (char *)cellEnd - (char *)start;
626 cell->size = (char *)start - (char *)cell;
627 continue;
628 }
629
630 //---- Create a new cell after end of the fixed block.
631 SDK_ASSERT(MINOBJSIZE <= (char *)cellEnd - (char *)end);
632 newCell = (Cell *) end;
633 newCell->size = (char *)cellEnd - (char *)end;
634 #ifdef SDK_DEBUG
635 newCell->hd = NULL;
636 #endif // SDK_DEBUG
637 newCell->next = cell->next;
638 if (newCell->next)
639 {
640 newCell->next->prev = newCell;
641 }
642 newCell->prev = cell;
643 cell->next = newCell; // cell is before newCell
644 cell->size = (char *)start - (char *)cell;
645 hd->size -= (char *)end - (char *)start;
646 break;
647 }
648 SDK_ASSERT(0 <= hd->size);
649 }
650
651 SDK_ASSERT(OFFSET(start, ALIGNMENT) == 0);
652 SDK_ASSERT(OFFSET(end, ALIGNMENT) == 0);
653 SDK_ASSERT(start < end);
654 *rstart = start;
655 *rend = end;
656
657 (void)OS_RestoreInterrupts(enabled);
658 return *rstart;
659 }
660
661 /*---------------------------------------------------------------------------*
662 Name: OS_FreeToHeap
663
664 Description: Returns obj /ptr/ to /heap/.
665
666 Arguments: id : arena ID
667 heap : handle to the heap that /ptr/ was allocated from
668 ptr : pointer to object previously returned from
669 OS_Alloc() or OS_AllocFromHeap().
670
671 Returns: None.
672 *---------------------------------------------------------------------------*/
OS_FreeToHeap(OSArenaId id,OSHeapHandle heap,void * ptr)673 void OS_FreeToHeap(OSArenaId id, OSHeapHandle heap, void *ptr)
674 {
675 OSHeapInfo *heapInfo;
676 HeapDesc *hd;
677 Cell *cell;
678
679 OSIntrMode enabled = OS_DisableInterrupts();
680
681 //---- check arena id
682 SDK_ASSERTMSG(id < OS_ARENA_MAX, OS_ERR_FREETOHEAP_INVID);
683 SDK_ASSERTMSG(OSiHeapInfo[id], OS_ERR_FREETOHEAP_NOINFO);
684 heapInfo = OSiHeapInfo[id];
685
686 if (heap < 0)
687 {
688 heap = heapInfo->currentHeap;
689 }
690
691 SDK_ASSERTMSG(heapInfo->heapArray, OS_ERR_FREETOHEAP_NOHEAP);
692 #ifdef SDK_DEBUG
693 #if defined(SDK_TWL) && !defined(SDK_TWLLTD)
694 if ( OSi_ExtraHeapArenaId != id || OSi_ExtraHeapHandle != heap )
695 {
696 #endif
697 SDK_ASSERTMSG(InRange(ptr, (char *)heapInfo->arenaStart + HEADERSIZE, (char *)heapInfo->arenaEnd), OS_ERR_FREETOHEAP_INVPTR);
698 #if defined(SDK_TWL) && !defined(SDK_TWLLTD)
699 }
700 #endif
701 #endif
702 SDK_ASSERTMSG(OFFSET(ptr, ALIGNMENT) == 0, OS_ERR_FREETOHEAP_INVPTR);
703 SDK_ASSERTMSG(0 <= heapInfo->heapArray[heap].size, OS_ERR_FREETOHEAP_INVHEAP);
704
705 cell = (Cell *) ((char *)ptr - HEADERSIZE);
706 hd = &heapInfo->heapArray[heap];
707
708 SDK_ASSERTMSG(cell->hd == hd, OS_ERR_FREETOHEAP_INVPTR);
709 SDK_ASSERTMSG(DLLookup(hd->allocated, cell), OS_ERR_FREETOHEAP_INVPTR);
710
711 #ifdef SDK_DEBUG
712 cell->hd = NULL;
713 hd->headerBytes -= HEADERSIZE;
714 hd->paddingBytes -= cell->size - (HEADERSIZE + cell->requested);
715 hd->payloadBytes -= cell->requested;
716 #endif // SDK_DEBUG
717
718 //---- Extract from the allocated list
719 hd->allocated = DLExtract(hd->allocated, cell);
720
721 //---- Add in sorted order to free list (coalesced with next and prev)
722 hd->free = DLInsert(hd->free, cell);
723
724 (void)OS_RestoreInterrupts(enabled);
725 }
726
727 /*---------------------------------------------------------------------------*
728 Name: OS_FreeAllToHeap
729
730 Description: free all allocated block in the specified heap
731
732 Arguments: id : arena ID
733 heap : handle to the heap
734
735 Returns: None.
736 *---------------------------------------------------------------------------*/
OS_FreeAllToHeap(OSArenaId id,OSHeapHandle heap)737 void OS_FreeAllToHeap(OSArenaId id, OSHeapHandle heap)
738 {
739 OSHeapInfo *heapInfo;
740 HeapDesc *hd;
741 Cell *cell;
742
743 OSIntrMode enabled = OS_DisableInterrupts();
744
745 //---- check arena id
746 SDK_ASSERTMSG(id < OS_ARENA_MAX, OS_ERR_FREETOHEAP_INVID);
747 SDK_ASSERTMSG(OSiHeapInfo[id], OS_ERR_FREETOHEAP_NOINFO);
748 heapInfo = OSiHeapInfo[id];
749
750 if (heap < 0)
751 {
752 heap = heapInfo->currentHeap;
753 }
754
755 SDK_ASSERTMSG(heapInfo->heapArray, "heap not initialized");
756 SDK_ASSERTMSG(0 <= heapInfo->heapArray[heap].size, "invalid heap handle");
757
758 hd = &heapInfo->heapArray[heap];
759 while ((cell = hd->allocated) != NULL)
760 {
761 SDK_ASSERT(cell->hd == hd);
762 SDK_ASSERT(DLLookup(hd->allocated, cell));
763
764 #ifdef SDK_DEBUG
765 cell->hd = NULL;
766 hd->headerBytes -= HEADERSIZE;
767 hd->paddingBytes -= cell->size - (HEADERSIZE + cell->requested);
768 hd->payloadBytes -= cell->requested;
769 #endif // SDK_DEBUG
770
771 //---- Extract from the allocated list
772 hd->allocated = DLExtract(hd->allocated, cell);
773
774 //---- Add in sorted order to free list (coalesced with next and prev)
775 hd->free = DLInsert(hd->free, cell);
776 }
777
778 (void)OS_RestoreInterrupts(enabled);
779 }
780
781 /*---------------------------------------------------------------------------*
782 Name: OS_SetCurrentHeap
783
784 Description: Sets OSi_CurrentHeap to /heap/. All subsequent calls to
785 OS_Alloc() will be performed on this heap until another
786 call to OS_SetCurrentHeap().
787
788 Arguments: id : arena ID
789 heap : handle to a heap that was returned from OS_CreateHeap()
790
791 Returns: previous heap handle.
792 *---------------------------------------------------------------------------*/
OS_SetCurrentHeap(OSArenaId id,OSHeapHandle heap)793 OSHeapHandle OS_SetCurrentHeap(OSArenaId id, OSHeapHandle heap)
794 {
795 OSHeapInfo *heapInfo;
796 OSHeapHandle prev;
797 OSIntrMode enabled = OS_DisableInterrupts();
798
799 //---- check arena id
800 SDK_ASSERTMSG(id < OS_ARENA_MAX, OS_ERR_SETCURRENTHEAP_INVID);
801 SDK_ASSERTMSG(OSiHeapInfo[id], OS_ERR_SETCURRENTHEAP_NOINFO);
802 heapInfo = OSiHeapInfo[id];
803
804 SDK_ASSERTMSG(heapInfo->heapArray, OS_ERR_SETCURRENTHEAP_NOHEAP);
805 SDK_ASSERTMSG(0 <= heap && heap < heapInfo->numHeaps, OS_ERR_SETCURRENTHEAP_INVHEAP);
806 SDK_ASSERTMSG(0 <= heapInfo->heapArray[heap].size, OS_ERR_SETCURRENTHEAP_INVHEAP);
807 prev = heapInfo->currentHeap;
808 heapInfo->currentHeap = heap;
809
810 (void)OS_RestoreInterrupts(enabled);
811 return prev;
812 }
813
814 /*---------------------------------------------------------------------------*
815 Name: OS_InitAlloc
816
817 Description: Initializes the arena in which all heaps will reside.
818 Reserves some small amount of memory for array of heap
819 descriptors.
820
821 Arguments: id : arena ID
822 arenaStart : beginning addr of arena
823 arenaEnd : ending addr of arena
824 maxHeaps : Maximum number of active heaps that will be
825 : used in lifetime of program
826
827 Returns: start of real arena, aligned with 32 bytes boundaries, after
828 heap array has been allocated
829 *---------------------------------------------------------------------------*/
OS_InitAlloc(OSArenaId id,void * arenaStart,void * arenaEnd,int maxHeaps)830 void *OS_InitAlloc(OSArenaId id, void *arenaStart, void *arenaEnd, int maxHeaps)
831 {
832 OSHeapInfo *heapInfo;
833 u32 arraySize;
834 OSHeapHandle i;
835 OSIntrMode enabled = OS_DisableInterrupts();
836
837 //---- check arena id
838 SDK_ASSERTMSG(id < OS_ARENA_MAX, OS_ERR_INITALLOC_INVID);
839 SDK_ASSERTMSG(OSiHeapInfo[id] == NULL, OS_ERR_INITALLOC_INVINFO);
840
841 SDK_ASSERTMSG(0 < maxHeaps, OS_ERR_INITALLOC_INVNUMHEAPS);
842 SDK_ASSERTMSG((char *)arenaStart < (char *)arenaEnd, OS_ERR_INITALLOC_INVRANGE);
843 SDK_ASSERTMSG(maxHeaps <= ((char *)arenaEnd - (char *)arenaStart) / sizeof(HeapDesc), OS_ERR_INITALLOC_INSRANGE);
844
845 //---- save heapInfo
846 heapInfo = arenaStart;
847 OSiHeapInfo[id] = heapInfo;
848
849 //---- Place HeapArray at head of the arena
850 arraySize = sizeof(HeapDesc) * maxHeaps;
851 heapInfo->heapArray = (void *)((u32)arenaStart + sizeof(OSHeapInfo));
852 heapInfo->numHeaps = maxHeaps;
853
854 for (i = 0; i < heapInfo->numHeaps; i++)
855 {
856 HeapDesc *hd = &heapInfo->heapArray[i];
857
858 hd->size = -1;
859 hd->free = hd->allocated = NULL;
860 #ifdef SDK_DEBUG
861 hd->paddingBytes = hd->headerBytes = hd->payloadBytes = 0;
862 #endif // SDK_DEBUG
863 }
864
865 //---- Set OSi_CurrentHeap to an invalid value
866 heapInfo->currentHeap = -1;
867
868 //---- Reset arenaStart to the nearest reasonable location
869 arenaStart = (void *)((char *)heapInfo->heapArray + arraySize);
870 arenaStart = (void *)ROUND(arenaStart, ALIGNMENT);
871
872 heapInfo->arenaStart = arenaStart;
873 heapInfo->arenaEnd = (void *)TRUNC(arenaEnd, ALIGNMENT);
874 SDK_ASSERTMSG(MINOBJSIZE <= (char *)heapInfo->arenaEnd - (char *)heapInfo->arenaStart, OS_ERR_INITALLOC_INSRANGE);
875
876 (void)OS_RestoreInterrupts(enabled);
877 return heapInfo->arenaStart;
878 }
879
880 /*---------------------------------------------------------------------------*
881 Name: OS_ClearAlloc
882
883 Description: Clear heap pointer in system shared.
884 After calling this, you can call OS_InitAlloc() again.
885
886 Arguments: id : arena ID
887
888 Returns: None
889 *---------------------------------------------------------------------------*/
OS_ClearAlloc(OSArenaId id)890 void OS_ClearAlloc(OSArenaId id)
891 {
892 SDK_ASSERTMSG(id < OS_ARENA_MAX, OS_ERR_CLEARALLOC_INVID);
893 OSiHeapInfo[id] = NULL;
894 }
895
896 /*---------------------------------------------------------------------------*
897 Name: OS_CreateHeap
898
899 Description: Reserves area of memory from /start/ to /end/ for use as a
900 heap. Initializes heap descriptor and free list.
901 Will consume one entry in heap array.
902
903 Arguments: id : arena ID
904 start : starting addr of heap
905 end : ending addr of heap
906
907 Returns: If the function succeeds, it returns a new handle to heap
908 for use in OS_AllocFromHeap(), OS_FreeToHeap(), etc.
909 If the function fails, the return value is -1.
910 *---------------------------------------------------------------------------*/
OS_CreateHeap(OSArenaId id,void * start,void * end)911 OSHeapHandle OS_CreateHeap(OSArenaId id, void *start, void *end)
912 {
913 OSHeapInfo *heapInfo;
914 OSHeapHandle heap;
915 HeapDesc *hd;
916 Cell *cell;
917
918 OSIntrMode enabled = OS_DisableInterrupts();
919
920 //OS_Printf( "OS_CreateHeap id=%d start=%x, end=%x\n", id, start, end );
921 //---- check arena id
922 SDK_ASSERTMSG(id < OS_ARENA_MAX, OS_ERR_CREATEHEAP_INVID);
923 SDK_ASSERTMSG(OSiHeapInfo[id], OS_ERR_CREATEHEAP_NOINFO);
924 heapInfo = OSiHeapInfo[id];
925
926 SDK_ASSERTMSG(heapInfo->heapArray, OS_ERR_CREATEHEAP_NOHEAP);
927 SDK_ASSERTMSG(start < end, OS_ERR_CREATEHEAP_INVRANGE);
928 start = (void *)ROUND(start, ALIGNMENT);
929 end = (void *)TRUNC(end, ALIGNMENT);
930 SDK_ASSERTMSG(start < end, OS_ERR_CREATEHEAP_INVRANGE);
931 SDK_ASSERTMSG(RangeSubset(start, end, heapInfo->arenaStart, heapInfo->arenaEnd), OS_ERR_CREATEHEAP_INVRANGE);
932 SDK_ASSERTMSG(MINOBJSIZE <= (char *)end - (char *)start, OS_ERR_CREATEHEAP_INSRANGE);
933
934 #ifdef SDK_DEBUG
935 //---- Check that the range does not overlap with
936 // any other block in this or other heaps.
937 for (heap = 0; heap < heapInfo->numHeaps; heap++)
938 {
939 if (heapInfo->heapArray[heap].size < 0)
940 {
941 continue;
942 }
943 SDK_ASSERTMSG(!DLOverlap(heapInfo->heapArray[heap].free, start, end), OS_ERR_CREATEHEAP_INVRANGE);
944 SDK_ASSERTMSG(!DLOverlap(heapInfo->heapArray[heap].allocated, start, end), OS_ERR_CREATEHEAP_INVRANGE);
945 }
946 #endif // SDK_DEBUG
947
948 //---- Search for free descriptor
949 for (heap = 0; heap < heapInfo->numHeaps; heap++)
950 {
951 hd = &heapInfo->heapArray[heap];
952 if (hd->size < 0)
953 {
954 hd->size = (char *)end - (char *)start;
955
956 cell = (Cell *) start;
957 cell->prev = NULL;
958 cell->next = NULL;
959 cell->size = hd->size;
960 #ifdef SDK_DEBUG
961 cell->hd = NULL;
962 #endif // SDK_DEBUG
963
964 hd->free = cell;
965 hd->allocated = 0;
966 #ifdef SDK_DEBUG
967 hd->paddingBytes = hd->headerBytes = hd->payloadBytes = 0;
968 #endif // SDK_DEBUG
969
970 (void)OS_RestoreInterrupts(enabled);
971 return heap;
972 }
973 }
974
975 //---- Could not find free descriptor
976 #ifdef SDK_DEBUG
977 OS_Printf("OS_CreateHeap: Warning - Failed to find free heap descriptor.");
978 #endif // SDK_DEBUG
979
980 (void)OS_RestoreInterrupts(enabled);
981 return -1;
982 }
983
984 /*---------------------------------------------------------------------------*
985 Name: OS_CreateExtraHeap
986
987 Description: Create extra heap using the parameter area of TWL ROM.
988 So Cannot be available on TWL mode.
989 Available only on NITRO of HYBRID.
990
991 Arguments: id : arena ID
992
993 Returns: -1 ... Failed.
994 0< ... Success. Value is heap handle.
995 *---------------------------------------------------------------------------*/
996 #if defined(SDK_TWL) && !defined(SDK_TWLLTD)
OS_CreateExtraHeap(OSArenaId id)997 OSHeapHandle OS_CreateExtraHeap(OSArenaId id)
998 {
999 OSHeapInfo *heapInfo;
1000 OSHeapHandle heap;
1001 HeapDesc *hd;
1002 Cell *cell;
1003
1004 OSIntrMode enabled = OS_DisableInterrupts();
1005 SDK_ASSERTMSG(id < OS_ARENA_MAX, OS_ERR_CREATEHEAP_INVID);
1006
1007 heapInfo = OSiHeapInfo[id];
1008 SDK_ASSERTMSG(heapInfo, OS_ERR_CREATEHEAP_NOINFO);
1009 SDK_ASSERTMSG(heapInfo->heapArray, OS_ERR_CREATEHEAP_NOHEAP);
1010
1011 //---- available only on NITRO
1012 if ( ! OS_IsRunOnTwl() && OSi_ExtraHeapHandle < 0 )
1013 {
1014 //---- Search for free descriptor
1015 for (heap = 0; heap < heapInfo->numHeaps; heap++)
1016 {
1017 hd = &heapInfo->heapArray[heap];
1018 if (hd->size < 0)
1019 {
1020 hd->size = HW_MAIN_MEM_PARAMETER_BUF_SIZE;
1021
1022 //---- initial free cell is from whole parameter buffer (NITRO does not use)
1023 cell = (Cell*)HW_MAIN_MEM_PARAMETER_BUF;
1024 cell->prev = NULL;
1025 cell->next = NULL;
1026 cell->size = HW_MAIN_MEM_PARAMETER_BUF_SIZE;
1027 #ifdef SDK_DEBUG
1028 cell->hd = NULL;
1029 #endif
1030 hd->free = cell;
1031 hd->allocated = 0;
1032 #ifdef SDK_DEBUG
1033 hd->paddingBytes = hd->headerBytes = hd->payloadBytes = 0;
1034 #endif
1035 OSi_ExtraHeapArenaId = id;
1036 OSi_ExtraHeapHandle = heap;
1037
1038 (void) OS_RestoreInterrupts(enabled);
1039 return heap;
1040 }
1041 }
1042 }
1043
1044 //---- Could not find free descriptor
1045 (void)OS_RestoreInterrupts(enabled);
1046 return -1;
1047 }
1048 #endif // defined(SDK_TWL) && !defined(SDK_TWLLTD)
1049
1050 /*---------------------------------------------------------------------------*
1051 Name: OS_DestroyHeap
1052
1053 Description: Frees up the descriptor for the /heap/. Subsequent
1054 allocation requests from this heap will fail unless another
1055 heap is created with the same handle.
1056
1057 Arguments: id : arena ID
1058 heap : handle to a live heap, previously created with OS_CreateHeap().
1059
1060 Returns: None.
1061 *---------------------------------------------------------------------------*/
OS_DestroyHeap(OSArenaId id,OSHeapHandle heap)1062 void OS_DestroyHeap(OSArenaId id, OSHeapHandle heap)
1063 {
1064 OSHeapInfo *heapInfo;
1065 HeapDesc *hd;
1066 #ifdef SDK_DEBUG
1067 long size;
1068 #endif
1069 OSIntrMode enabled = OS_DisableInterrupts();
1070
1071 //---- check arena id
1072 SDK_ASSERTMSG(id < OS_ARENA_MAX, OS_ERR_DESTROYHEAP_INVID);
1073 SDK_ASSERTMSG(OSiHeapInfo[id], OS_ERR_DESTROYHEAP_NOINFO);
1074 heapInfo = OSiHeapInfo[id];
1075
1076 SDK_ASSERTMSG(heapInfo->heapArray, OS_ERR_DESTROYHEAP_NOHEAP);
1077 SDK_ASSERTMSG(0 <= heap && heap < heapInfo->numHeaps, OS_ERR_DESTROYHEAP_INVHEAP);
1078 SDK_ASSERTMSG(0 <= heapInfo->heapArray[heap].size, OS_ERR_DESTROYHEAP_INVHEAP);
1079
1080 hd = &heapInfo->heapArray[heap];
1081
1082 #ifdef SDK_DEBUG
1083 //---- Check whether entire heap is empty
1084 size = DLSize(hd->free);
1085 if (hd->size != size)
1086 {
1087 OS_Printf("OS_DestroyHeap(%d): Warning - free list size %d, heap size %d\n", heap, size, hd->size);
1088 }
1089 #endif // SDK_DEBUG
1090
1091 #if defined(SDK_TWL) && !defined(SDK_TWLLTD)
1092 //---- Check whether heap is the EXTRA HEAP
1093 if ( OSi_ExtraHeapArenaId == id && OSi_ExtraHeapHandle == heap )
1094 {
1095 OSi_ExtraHeapArenaId = (OSArenaId)-1;
1096 OSi_ExtraHeapHandle = -1;
1097 }
1098 #endif // defined(SDK_TWL) && !defined(SDK_TWLLTD)
1099
1100 hd->size = -1;
1101 hd->free = hd->allocated = NULL; // add to dolphin src
1102
1103 #ifdef SDK_DEBUG
1104 hd->paddingBytes = hd->headerBytes = hd->payloadBytes = 0;
1105 if (heapInfo->currentHeap == heap)
1106 {
1107 heapInfo->currentHeap = -1;
1108 }
1109 #endif // SDK_DEBUG
1110
1111 (void)OS_RestoreInterrupts(enabled);
1112 }
1113
1114 /*---------------------------------------------------------------------------*
1115 Name: OS_AddToHeap
1116
1117 Description: Adds an arbitrary block of memory to /heap/. Used to free
1118 blocks previously allocated with OS_AllocFixed(), or to
1119 create non-contiguous heaps.
1120
1121 Arguments: id : arena ID
1122 heap : handle to live heap, previously created with OS_CreateHeap().
1123 start : starting addr of block to add to /heap/
1124 end : ending addr of block to add to /heap/
1125
1126 Returns: None.
1127 *---------------------------------------------------------------------------*/
OS_AddToHeap(OSArenaId id,OSHeapHandle heap,void * start,void * end)1128 void OS_AddToHeap(OSArenaId id, OSHeapHandle heap, void *start, void *end)
1129 {
1130 OSHeapInfo *heapInfo;
1131 HeapDesc *hd;
1132 Cell *cell;
1133 #ifdef SDK_DEBUG
1134 OSHeapHandle i;
1135 #endif // SDK_DEBUG
1136 OSIntrMode enabled = OS_DisableInterrupts();
1137
1138 //---- check arena id
1139 SDK_ASSERTMSG(id < OS_ARENA_MAX, OS_ERR_ADDTOHEAP_INVID);
1140 SDK_ASSERTMSG(OSiHeapInfo[id], OS_ERR_ADDTOHEAP_NOINFO);
1141 heapInfo = OSiHeapInfo[id];
1142
1143 SDK_ASSERTMSG(heapInfo->heapArray, OS_ERR_ADDTOHEAP_NOHEAP);
1144 SDK_ASSERTMSG(0 <= heap && heap < heapInfo->numHeaps, OS_ERR_ADDTOHEAP_INVHEAP);
1145 SDK_ASSERTMSG(0 <= heapInfo->heapArray[heap].size, OS_ERR_ADDTOHEAP_INVHEAP);
1146
1147 hd = &heapInfo->heapArray[heap];
1148
1149 SDK_ASSERTMSG(start < end, OS_ERR_ADDTOHEAP_INVRANGE);
1150
1151 start = (void *)ROUND(start, ALIGNMENT);
1152 end = (void *)TRUNC(end, ALIGNMENT);
1153 SDK_ASSERTMSG(MINOBJSIZE <= (char *)end - (char *)start, OS_ERR_ADDTOHEAP_INSRANGE);
1154
1155 #ifdef SDK_DEBUG
1156 #if defined(SDK_TWL) && !defined(SDK_TWLLTD)
1157 if ((u32)start != (u32)HW_MAIN_MEM_PARAMETER_BUF && (u32)end != (u32)(HW_MAIN_MEM_PARAMETER_BUF + HW_MAIN_MEM_PARAMETER_BUF_SIZE) )
1158 {
1159 #endif
1160 SDK_ASSERTMSG(RangeSubset(start, end, heapInfo->arenaStart, heapInfo->arenaEnd), OS_ERR_ADDTOHEAP_INVRANGE);
1161 #if defined(SDK_TWL) && !defined(SDK_TWLLTD)
1162 }
1163 #endif
1164 #endif
1165
1166 #ifdef SDK_DEBUG
1167 //---- Check that the range does not already overlap with
1168 // any other block in this or other heaps.
1169 for (i = 0; i < heapInfo->numHeaps; i++)
1170 {
1171 if (heapInfo->heapArray[i].size < 0)
1172 {
1173 continue;
1174 }
1175 SDK_ASSERTMSG(!DLOverlap(heapInfo->heapArray[i].free, start, end), OS_ERR_ADDTOHEAP_INVRANGE);
1176 SDK_ASSERTMSG(!DLOverlap(heapInfo->heapArray[i].allocated, start, end), OS_ERR_ADDTOHEAP_INVRANGE);
1177 }
1178 #endif // SDK_DEBUG
1179
1180 //---- Create a new cell
1181 cell = (Cell *) start;
1182 cell->size = (char *)end - (char *)start;
1183 #ifdef SDK_DEBUG
1184 cell->hd = NULL;
1185 #endif // SDK_DEBUG
1186
1187 //---- Insert new cell in free
1188 hd->size += cell->size;
1189 hd->free = DLInsert(hd->free, cell);
1190
1191 (void)OS_RestoreInterrupts(enabled);
1192 }
1193
1194 /*---------------------------------------------------------------------------*
1195 Name: OS_AddExtraToHeap
1196
1197 Description: Adds extra area (top 16KB of main memory ) to /heap/. Used to
1198 free blocks previously allocated with OS_AllocFixed(), or to
1199 create non-contiguous heaps.
1200
1201 Arguments: id : arena ID
1202 heap : handle to live heap, previously created with OS_CreateHeap().
1203
1204 Returns: None.
1205 *---------------------------------------------------------------------------*/
1206 #if defined(SDK_TWL) && !defined(SDK_TWLLTD)
OS_AddExtraAreaToHeap(OSArenaId id,OSHeapHandle heap)1207 void OS_AddExtraAreaToHeap(OSArenaId id, OSHeapHandle heap)
1208 {
1209 if ( ! OS_IsRunOnTwl() )
1210 {
1211 OS_AddToHeap(id, heap,
1212 (void*)HW_MAIN_MEM_PARAMETER_BUF,
1213 (void*)(HW_MAIN_MEM_PARAMETER_BUF + HW_MAIN_MEM_PARAMETER_BUF_SIZE ) );
1214 OSi_ExtraHeapArenaId = id;
1215 OSi_ExtraHeapHandle = heap;
1216 }
1217 }
1218 #endif
1219
1220 /*---------------------------------------------------------------------------*
1221 Name: OS_CheckHeap
1222
1223 Description: Checks heap sanity for debugging
1224
1225 Arguments: id : arena ID
1226 heap : handle to a live heap.
1227
1228 Returns: -1 if heap is not consistent. Otherwise, returns number
1229 of bytes available in free.
1230 *---------------------------------------------------------------------------*/
1231
1232 #ifndef SDK_NO_MESSAGE
1233 #ifdef SDK_ARM9
1234 #define OSi_CHECK( exp ) \
1235 do \
1236 { \
1237 if ( !(exp) ) \
1238 { \
1239 OS_Printf( "OS_CheckHeap: Failed " #exp " in %d\n", __LINE__ ); \
1240 goto exit_OS_CheckHeap; /* goto is not beautiful, but less codes */ \
1241 } \
1242 } while (0)
1243 #else /* SDK_ARM9 */
1244 #define OSi_CHECK( exp ) \
1245 do \
1246 { \
1247 if ( !(exp) ) \
1248 { \
1249 OS_Printf( "OS_CheckHeap: Failed in %d\n", __LINE__ ); \
1250 goto exit_OS_CheckHeap; /* goto is not beautiful, but less codes */ \
1251 } \
1252 } while (0)
1253 #endif
1254 #else
1255 #define OSi_CHECK( exp ) \
1256 do \
1257 { \
1258 if ( !(exp) ) \
1259 { \
1260 goto exit_OS_CheckHeap; /* goto is not beautiful, but less codes */ \
1261 } \
1262 } while (0)
1263 #endif
1264
OS_CheckHeap(OSArenaId id,OSHeapHandle heap)1265 s32 OS_CheckHeap(OSArenaId id, OSHeapHandle heap)
1266 {
1267 OSHeapInfo *heapInfo;
1268 HeapDesc *hd;
1269 Cell *cell;
1270 long total = 0;
1271 long free = 0;
1272 long retValue = -1;
1273 OSIntrMode enabled = OS_DisableInterrupts();
1274
1275 //---- check arena id
1276 SDK_ASSERTMSG(id < OS_ARENA_MAX, OS_ERR_CHECKHEAP_INVID);
1277 SDK_ASSERTMSG(OSiHeapInfo[id], OS_ERR_CHECKHEAP_NOINFO);
1278 heapInfo = OSiHeapInfo[id];
1279
1280 //---- heap<0 means current heap
1281 if (heap == OS_CURRENT_HEAP_HANDLE)
1282 {
1283 heap = heapInfo->currentHeap;
1284 }
1285 SDK_ASSERT(heap >= 0);
1286
1287 OSi_CHECK(heapInfo->heapArray);
1288 OSi_CHECK(0 <= heap && heap < heapInfo->numHeaps);
1289
1290 hd = &heapInfo->heapArray[heap];
1291 OSi_CHECK(0 <= hd->size);
1292
1293 OSi_CHECK(hd->allocated == NULL || hd->allocated->prev == NULL);
1294 for (cell = hd->allocated; cell; cell = cell->next)
1295 {
1296 #ifdef SDK_DEBUG
1297 #if defined(SDK_TWL) && !defined(SDK_TWLLTD)
1298 if ( OSi_ExtraHeapArenaId != id || OSi_ExtraHeapHandle != heap )
1299 {
1300 #endif
1301 OSi_CHECK(InRange(cell, heapInfo->arenaStart, heapInfo->arenaEnd));
1302 #if defined(SDK_TWL) && !defined(SDK_TWLLTD)
1303 }
1304 #endif
1305 #endif
1306 OSi_CHECK(OFFSET(cell, ALIGNMENT) == 0);
1307 OSi_CHECK(cell->next == NULL || cell->next->prev == cell);
1308 OSi_CHECK(MINOBJSIZE <= cell->size);
1309 OSi_CHECK(OFFSET(cell->size, ALIGNMENT) == 0);
1310
1311 total += cell->size;
1312 OSi_CHECK(0 < total && total <= hd->size);
1313
1314 #ifdef SDK_DEBUG
1315 OSi_CHECK(cell->hd == hd);
1316 OSi_CHECK(HEADERSIZE + cell->requested <= cell->size);
1317 #endif // SDK_DEBUG
1318 }
1319
1320 OSi_CHECK(hd->free == NULL || hd->free->prev == NULL);
1321 for (cell = hd->free; cell; cell = cell->next)
1322 {
1323 #ifdef SDK_DEBUG
1324 #if defined(SDK_TWL) && !defined(SDK_TWLLTD)
1325 if ( OSi_ExtraHeapArenaId != id || OSi_ExtraHeapHandle != heap )
1326 {
1327 #endif
1328 OSi_CHECK(InRange(cell, heapInfo->arenaStart, heapInfo->arenaEnd));
1329 #if defined(SDK_TWL) && !defined(SDK_TWLLTD)
1330 }
1331 #endif
1332 #endif
1333 OSi_CHECK(OFFSET(cell, ALIGNMENT) == 0);
1334 OSi_CHECK(cell->next == NULL || cell->next->prev == cell);
1335 OSi_CHECK(MINOBJSIZE <= cell->size);
1336 OSi_CHECK(OFFSET(cell->size, ALIGNMENT) == 0);
1337 OSi_CHECK(cell->next == NULL || (char *)cell + cell->size < (char *)cell->next);
1338
1339 total += cell->size;
1340 free += cell->size - HEADERSIZE;
1341 OSi_CHECK(0 < total && total <= hd->size);
1342
1343 #ifdef SDK_DEBUG
1344 OSi_CHECK(cell->hd == NULL);
1345 #endif // SDK_DEBUG
1346 }
1347
1348 OSi_CHECK(total == hd->size);
1349 retValue = free;
1350
1351 exit_OS_CheckHeap:
1352 (void)OS_RestoreInterrupts(enabled);
1353 return retValue;
1354 }
1355
1356 /*---------------------------------------------------------------------------*
1357 Name: OS_ReferentSize
1358
1359 Description: Returns size of payload
1360
1361 Arguments: id : arena ID
1362 ptr : pointer to object previously returned from
1363 OS_Alloc() or OSAllocFromHeap().
1364
1365 Returns: size of payload
1366 *---------------------------------------------------------------------------*/
OS_ReferentSize(OSArenaId id,void * ptr)1367 u32 OS_ReferentSize(OSArenaId id, void *ptr)
1368 {
1369 OSHeapInfo *heapInfo;
1370 Cell *cell;
1371 OSIntrMode enabled = OS_DisableInterrupts();
1372
1373 //---- check arena id
1374 SDK_ASSERTMSG(id < OS_ARENA_MAX, OS_ERR_REFERENTSIZE_INVID);
1375 SDK_ASSERTMSG(OSiHeapInfo[id], OS_ERR_REFERENTSIZE_NOINFO);
1376 heapInfo = OSiHeapInfo[id];
1377
1378 SDK_ASSERTMSG(heapInfo->heapArray, OS_ERR_REFERENT_NOHEAP);
1379 #ifdef SDK_DEBUG
1380 #if defined(SDK_TWL) && !defined(SDK_TWLLTD)
1381 if ( OSi_ExtraHeapArenaId != id )
1382 {
1383 #endif
1384 SDK_ASSERTMSG(InRange(ptr, (char *)heapInfo->arenaStart + HEADERSIZE, (char *)heapInfo->arenaEnd), OS_ERR_REFERENT_INVPTR);
1385 #if defined(SDK_TWL) && !defined(SDK_TWLLTD)
1386 }
1387 #endif
1388 #endif
1389 SDK_ASSERTMSG(OFFSET(ptr, ALIGNMENT) == 0, OS_ERR_REFERENT_INVPTR);
1390
1391 cell = (Cell *) ((char *)ptr - HEADERSIZE);
1392
1393 SDK_ASSERTMSG(cell->hd, OS_ERR_REFERENT_INVPTR);
1394 SDK_ASSERTMSG(((char *)cell->hd - (char *)heapInfo->heapArray) % sizeof(HeapDesc) == 0, OS_ERR_REFERENT_INVPTR);
1395 SDK_ASSERTMSG(heapInfo->heapArray <= cell->hd && cell->hd < &heapInfo->heapArray[heapInfo->numHeaps], OS_ERR_REFERENT_INVPTR);
1396 SDK_ASSERTMSG(0 <= cell->hd->size, OS_ERR_REFERENT_INVPTR);
1397 SDK_ASSERTMSG(DLLookup(cell->hd->allocated, cell), OS_ERR_REFERENT_INVPTR);
1398
1399 (void)OS_RestoreInterrupts(enabled);
1400 return (u32)(cell->size - HEADERSIZE);
1401 }
1402
1403 /*---------------------------------------------------------------------------*
1404 Name: OS_DumpHeap
1405
1406 Description: Dumps statistics and elements of a heap
1407
1408 Arguments: id : arena ID
1409 heap : handle to a heap.
1410
1411 Returns: None.
1412 *---------------------------------------------------------------------------*/
OS_DumpHeap(OSArenaId id,OSHeapHandle heap)1413 void OS_DumpHeap(OSArenaId id, OSHeapHandle heap)
1414 {
1415 #ifndef SDK_FINALROM
1416 OSHeapInfo *heapInfo;
1417 HeapDesc *hd;
1418 Cell *cell;
1419 OSIntrMode enabled = OS_DisableInterrupts();
1420
1421 //---- check arena id
1422 SDK_ASSERTMSG(id < OS_ARENA_MAX, OS_ERR_DUMPHEAP_INVID);
1423 SDK_ASSERTMSG(OSiHeapInfo[id], OS_ERR_DUMPHEAP_NOINFO);
1424 heapInfo = OSiHeapInfo[id];
1425
1426 SDK_ASSERTMSG(heapInfo && heapInfo->heapArray, OS_ERR_DUMPHEAP_NOHEAP);
1427
1428 //---- heap<0 means current heap
1429 if (heap < 0)
1430 {
1431 heap = heapInfo->currentHeap;
1432 }
1433 SDK_ASSERTMSG(0 <= heap && heap < heapInfo->numHeaps, OS_ERR_DUMPHEAP_INVHEAP);
1434
1435 hd = &heapInfo->heapArray[heap];
1436 if (hd->size < 0)
1437 {
1438 OS_Printf("----Inactive\n");
1439 return;
1440 }
1441
1442 SDK_ASSERTMSG(0 <= OS_CheckHeap(id, heap), OS_ERR_DUMPHEAP_BROKENHEAP);
1443
1444 #ifdef SDK_DEBUG
1445 OS_Printf("padding %d/(%f%%) header %d/(%f%%) payload %d/(%f%%)\n",
1446 hd->paddingBytes, 100.0 * hd->paddingBytes / hd->size,
1447 hd->headerBytes, 100.0 * hd->headerBytes / hd->size,
1448 hd->payloadBytes, 100.0 * hd->payloadBytes / hd->size);
1449 #endif // SDK_DEBUG
1450
1451 OS_Printf(" addr size end prev next\n");
1452
1453 OS_Printf("----Allocated\n");
1454 SDK_ASSERTMSG(hd->allocated == NULL || hd->allocated->prev == NULL, OS_ERR_DUMPHEAP_BROKENHEAP);
1455 if ( ! hd->allocated )
1456 {
1457 OS_Printf("None.\n");
1458 }
1459 else
1460 {
1461 for (cell = hd->allocated; cell; cell = cell->next)
1462 {
1463 OS_Printf("%08x %6x %08x %08x %08x\n",
1464 cell, cell->size, (char *)cell + cell->size, cell->prev, cell->next);
1465 }
1466 }
1467
1468 OS_Printf("----Free\n");
1469 if ( ! hd->free )
1470 {
1471 OS_Printf("None.\n");
1472 }
1473 else
1474 {
1475 for (cell = hd->free; cell; cell = cell->next)
1476 {
1477 OS_Printf("%08x %6x %08x %08x %08x\n",
1478 cell, cell->size, (char *)cell + cell->size, cell->prev, cell->next);
1479 }
1480 }
1481
1482 (void)OS_RestoreInterrupts(enabled);
1483 #else // ifndef SDK_FINALROM
1484
1485 #pragma unused( id, heap )
1486
1487 #endif // ifndef SDK_FINALROM
1488 }
1489
1490
1491 /*---------------------------------------------------------------------------*
1492 Name: OS_VisitAllocated
1493
1494 Description: Visits every element of every allocated block of memory,
1495 calling a routine on each one.
1496
1497 Arguments: id : arena ID
1498 visitor : function to be called on each cell
1499
1500 Returns: None.
1501 *---------------------------------------------------------------------------*/
OS_VisitAllocated(OSArenaId id,OSAllocVisitor visitor)1502 void OS_VisitAllocated(OSArenaId id, OSAllocVisitor visitor)
1503 {
1504 OSHeapInfo *heapInfo;
1505 u32 heap;
1506 Cell *cell;
1507
1508 OSIntrMode enabled = OS_DisableInterrupts();
1509
1510 //---- check arena id
1511 SDK_ASSERTMSG(id < OS_ARENA_MAX, OS_ERR_VISITALLOCATED_INVID);
1512 SDK_ASSERTMSG(OSiHeapInfo[id], OS_ERR_VISITALLOCATED_NOINFO);
1513 heapInfo = OSiHeapInfo[id];
1514
1515 for (heap = 0; heap < heapInfo->numHeaps; heap++)
1516 {
1517 if (heapInfo->heapArray[heap].size >= 0)
1518 {
1519 for (cell = heapInfo->heapArray[heap].allocated; cell; cell = cell->next)
1520 {
1521 visitor((void *)((u8 *)cell + HEADERSIZE), (u32)(cell->size - HEADERSIZE));
1522 }
1523 }
1524 }
1525
1526 (void)OS_RestoreInterrupts(enabled);
1527 }
1528
1529 //================================================================================
1530 // Get information about heap
1531 //================================================================================
1532 /*---------------------------------------------------------------------------*
1533 Name: OSi_GetTotalAllocSize
1534
1535 Description: Get sum of allocated block size.
1536 Subroutine for OS_GetTotalAllocSize and OS_GetTotalOccupiedSize.
1537
1538 Arguments: id : arena ID
1539 heap : handle to a heap.
1540 isHeadInclude : whether if including block header.
1541
1542 Returns: sum of allocated block size
1543 *---------------------------------------------------------------------------*/
OSi_GetTotalAllocSize(OSArenaId id,OSHeapHandle heap,BOOL isHeadInclude)1544 u32 OSi_GetTotalAllocSize(OSArenaId id, OSHeapHandle heap, BOOL isHeadInclude)
1545 {
1546 OSHeapInfo *heapInfo;
1547 Cell *cell;
1548 u32 sum = 0;
1549 OSIntrMode enabled = OS_DisableInterrupts();
1550
1551 SDK_ASSERT(id < OS_ARENA_MAX);
1552 heapInfo = OSiHeapInfo[id];
1553 SDK_ASSERT(heapInfo);
1554 SDK_ASSERT(heap < heapInfo->numHeaps);
1555
1556 //---- heap<0 means current heap
1557 if (heap < 0)
1558 {
1559 heap = heapInfo->currentHeap;
1560 }
1561
1562 if (isHeadInclude)
1563 {
1564 for (cell = heapInfo->heapArray[heap].allocated; cell; cell = cell->next)
1565 {
1566 sum += (u32)(cell->size);
1567 }
1568 }
1569 else
1570 {
1571 for (cell = heapInfo->heapArray[heap].allocated; cell; cell = cell->next)
1572 {
1573 sum += (u32)(cell->size - HEADERSIZE);
1574 }
1575 }
1576
1577 (void)OS_RestoreInterrupts(enabled);
1578
1579 return sum;
1580 }
1581
1582 /*---------------------------------------------------------------------------*
1583 Name: OS_GetTotalFreeSize
1584
1585 Description: Get sum of free block size,
1586 not includeing of block header.
1587
1588 Arguments: id : arena ID
1589 heap : handle to a heap.
1590
1591 Returns: sum of free block size
1592 *---------------------------------------------------------------------------*/
OS_GetTotalFreeSize(OSArenaId id,OSHeapHandle heap)1593 u32 OS_GetTotalFreeSize(OSArenaId id, OSHeapHandle heap)
1594 {
1595 OSHeapInfo *heapInfo;
1596 Cell *cell;
1597 u32 sum = 0;
1598 OSIntrMode enabled = OS_DisableInterrupts();
1599
1600 SDK_ASSERT(id < OS_ARENA_MAX);
1601 heapInfo = OSiHeapInfo[id];
1602 SDK_ASSERT(heapInfo);
1603 SDK_ASSERT(heap < heapInfo->numHeaps);
1604
1605 //---- heap<0 means current heap
1606 if (heap < 0)
1607 {
1608 heap = heapInfo->currentHeap;
1609 }
1610
1611 for (cell = heapInfo->heapArray[heap].free; cell; cell = cell->next)
1612 {
1613 sum += (u32)(cell->size - HEADERSIZE);
1614 }
1615
1616 (void)OS_RestoreInterrupts(enabled);
1617
1618 return sum;
1619 }
1620
1621 /*---------------------------------------------------------------------------*
1622 Name: OS_GetMaxFreeSize
1623
1624 Description: Get maximun free block size
1625
1626 Arguments: id : arena ID
1627 heap : handle to a heap.
1628
1629 Returns: maximum free block size.
1630 *---------------------------------------------------------------------------*/
OS_GetMaxFreeSize(OSArenaId id,OSHeapHandle heap)1631 u32 OS_GetMaxFreeSize(OSArenaId id, OSHeapHandle heap)
1632 {
1633 OSHeapInfo *heapInfo;
1634 Cell *cell;
1635 u32 candidate = 0;
1636 OSIntrMode enabled = OS_DisableInterrupts();
1637
1638 SDK_ASSERT(id < OS_ARENA_MAX);
1639 heapInfo = OSiHeapInfo[id];
1640 SDK_ASSERT(heapInfo);
1641 SDK_ASSERT(heap < heapInfo->numHeaps);
1642
1643 //---- heap<0 means current heap
1644 if (heap < 0)
1645 {
1646 heap = heapInfo->currentHeap;
1647 }
1648
1649 for (cell = heapInfo->heapArray[heap].free; cell; cell = cell->next)
1650 {
1651 u32 size = (u32)(cell->size - HEADERSIZE);
1652 if (size > candidate)
1653 {
1654 candidate = size;
1655 }
1656 }
1657
1658 (void)OS_RestoreInterrupts(enabled);
1659
1660 return candidate;
1661 }
1662
1663 //================================================================================
1664 // re-initialize heap.
1665 //================================================================================
1666 /*---------------------------------------------------------------------------*
1667 Name: OS_ClearHeap
1668
1669 Description: re-initialize heap.
1670
1671 Arguments: id : arena ID
1672 heap : handle to a heap.
1673 start: starting addr of heap
1674 end : endinf addr of heap
1675
1676 Returns: None.
1677 *---------------------------------------------------------------------------*/
OS_ClearHeap(OSArenaId id,OSHeapHandle heap,void * start,void * end)1678 void OS_ClearHeap(OSArenaId id, OSHeapHandle heap, void *start, void *end)
1679 {
1680 OSHeapInfo *heapInfo;
1681 HeapDesc *hd;
1682 Cell *cell;
1683
1684 OSIntrMode enabled = OS_DisableInterrupts();
1685
1686 //---- check arena id
1687 SDK_ASSERTMSG(id < OS_ARENA_MAX, "invalid id");
1688
1689 heapInfo = OSiHeapInfo[id];
1690
1691 SDK_ASSERTMSG(heapInfo && heapInfo->heapArray, "heap not initialized");
1692 SDK_ASSERTMSG(start < end, "invalid range");
1693 start = (void *)ROUND(start, ALIGNMENT);
1694 end = (void *)TRUNC(end, ALIGNMENT);
1695 SDK_ASSERTMSG(start < end, "invalid range");
1696 #ifdef SDK_DEBUG
1697 #if defined(SDK_TWL) && !defined(SDK_TWLLTD)
1698 if ( OSi_ExtraHeapArenaId != id || OSi_ExtraHeapHandle != heap )
1699 {
1700 #endif
1701 SDK_ASSERTMSG(RangeSubset(start, end, heapInfo->arenaStart, heapInfo->arenaEnd), "invalid range");
1702 #if defined(SDK_TWL) && !defined(SDK_TWLLTD)
1703 }
1704 #endif
1705 #endif
1706 SDK_ASSERTMSG(MINOBJSIZE <= (char *)end - (char *)start, "too small range");
1707
1708 //---- heap<0 means current heap
1709 if (heap < 0)
1710 {
1711 heap = heapInfo->currentHeap;
1712 }
1713
1714 //---- Search for free descriptor
1715 hd = &heapInfo->heapArray[heap];
1716 hd->size = (char *)end - (char *)start;
1717
1718 cell = (Cell *) start;
1719 cell->prev = NULL;
1720 cell->next = NULL;
1721 cell->size = hd->size;
1722 #ifdef SDK_DEBUG
1723 cell->hd = NULL;
1724 #endif // SDK_DEBUG
1725
1726 hd->free = cell;
1727 hd->allocated = 0;
1728 #ifdef SDK_DEBUG
1729 hd->paddingBytes = hd->headerBytes = hd->payloadBytes = 0;
1730 #endif // SDK_DEBUG
1731
1732 (void)OS_RestoreInterrupts(enabled);
1733 }
1734 /*---------------------------------------------------------------------------*
1735 Name: OS_ClearExtraHeap
1736
1737 Description: re-initialize extra heap.
1738
1739 Arguments: id : arena ID
1740 heap : handle to a heap.
1741
1742 Returns: None.
1743 *---------------------------------------------------------------------------*/
1744 #if defined(SDK_TWL) && !defined(SDK_TWLLTD)
OS_ClearExtraHeap(OSArenaId id,OSHeapHandle heap)1745 void OS_ClearExtraHeap(OSArenaId id, OSHeapHandle heap)
1746 {
1747 if ( ! OS_IsRunOnTwl() )
1748 {
1749 if ( OSi_ExtraHeapArenaId == id || OSi_ExtraHeapHandle == heap )
1750 {
1751 OS_ClearHeap(id, heap,
1752 (void*)HW_MAIN_MEM_PARAMETER_BUF,
1753 (void*)(HW_MAIN_MEM_PARAMETER_BUF + HW_MAIN_MEM_PARAMETER_BUF_SIZE ) );
1754 }
1755 }
1756 }
1757 #endif
1758
1759 //================================================================================
1760 // Check Alocated Memory
1761 //================================================================================
1762 /*---------------------------------------------------------------------------*
1763 Name: OS_IsOnMainMemory
1764
1765 Description: check memory address to which a pointer points is on main RAM.
1766
1767 Arguments: ptr : pointer
1768
1769 Returns: TRUE if ptr points is on main RAM.
1770 *---------------------------------------------------------------------------*/
OS_IsOnMainMemory(void * ptr)1771 BOOL OS_IsOnMainMemory(void* ptr)
1772 {
1773 #ifdef SDK_TWL
1774 if( OS_IsRunOnTwl() )
1775 {
1776 /* TWL */
1777 if( (u32)ptr >= HW_TWL_MAIN_MEM && (u32)ptr < HW_TWL_MAIN_MEM_END )
1778 {
1779 return TRUE;
1780 }
1781 else
1782 {
1783 return FALSE;
1784 }
1785 }
1786 else
1787 #endif //SDK_TWL
1788 {
1789 /* NITRO */
1790 if( (u32)ptr >= HW_MAIN_MEM && (u32)ptr < HW_MAIN_MEM_END )
1791 {
1792 return TRUE;
1793 }
1794 else
1795 {
1796 return FALSE;
1797 }
1798 }
1799 return FALSE; /* Do Not Return HERE */
1800 }
1801
1802 /*---------------------------------------------------------------------------*
1803 Name: OS_IsOnExtendedMainMemory
1804
1805 Description: check memory address to which a pointer points is on extended main RAM.
1806
1807 Arguments: ptr : pointer
1808
1809 Returns: TRUE if ptr points is on extended main RAM.
1810 *---------------------------------------------------------------------------*/
OS_IsOnExtendedMainMemory(void * ptr)1811 BOOL OS_IsOnExtendedMainMemory(void* ptr)
1812 {
1813 #ifdef SDK_TWL
1814 if( OS_IsRunOnTwl() )
1815 {
1816 /* TWL */
1817 if( (u32)ptr >= HW_TWL_MAIN_MEM_EX && (u32)ptr < HW_TWL_MAIN_MEM_EX_END )
1818 {
1819 return TRUE;
1820 }
1821 else
1822 {
1823 return FALSE;
1824 }
1825 }
1826 else
1827 #endif //SDK_TWL
1828 {
1829 /* NITRO */
1830 if( (u32)ptr >= HW_MAIN_MEM_END && (u32)ptr < HW_MAIN_MEM_EX_END )
1831 {
1832 return TRUE;
1833 }
1834 else
1835 {
1836 return FALSE;
1837 }
1838 }
1839 return FALSE; /* Do Not Return HERE */
1840 }
1841
1842
1843
1844
1845 /*---------------------------------------------------------------------------*
1846 Name: OS_IsOnWramB
1847
1848 Description: check memory address to which a pointer points is on WRAM B.
1849
1850 Arguments: ptr : pointer
1851
1852 Returns: TRUE if ptr points is on WRAM B.
1853 *---------------------------------------------------------------------------*/
OS_IsOnWramB(void * ptr)1854 BOOL OS_IsOnWramB(void* ptr)
1855 {
1856 #ifdef SDK_TWL
1857 if( OS_IsRunOnTwl() )
1858 {
1859 /* TWL */
1860 if( (u32)ptr >= HW_WRAM_B && (u32)ptr < HW_WRAM_B_END )
1861 {
1862 return TRUE;
1863 }
1864 else
1865 {
1866 return FALSE;
1867 }
1868 }
1869 #else
1870 #pragma unused(ptr)
1871 #endif //SDK_TWL
1872 return FALSE;
1873 }
1874
1875 /*---------------------------------------------------------------------------*
1876 Name: OSi_IsOnWramC
1877
1878 Description: check memory address to which a pointer points is on WRAM C.
1879
1880 Arguments: ptr : pointer
1881
1882 Returns: TRUE if ptr points is on WRAM C.
1883 *---------------------------------------------------------------------------*/
OS_IsOnWramC(void * ptr)1884 BOOL OS_IsOnWramC(void* ptr)
1885 {
1886 #ifdef SDK_TWL
1887 if( OS_IsRunOnTwl() )
1888 {
1889 /* TWL */
1890 if( (u32)ptr >= HW_WRAM_C && (u32)ptr < HW_WRAM_C_END )
1891 {
1892 return TRUE;
1893 }
1894 else
1895 {
1896 return FALSE;
1897 }
1898 }
1899 #else
1900 #pragma unused(ptr)
1901 #endif //SDK_TWL
1902 return FALSE;
1903 }
1904
1905 /*---------------------------------------------------------------------------*
1906 Name: OS_IsOnWram0
1907
1908 Description: check memory address to which a pointer points is on WRAM 0.
1909
1910 Arguments: ptr : pointer
1911
1912 Returns: TRUE if ptr points is on WRAM 0.
1913 *---------------------------------------------------------------------------*/
OS_IsOnWram0(void * ptr)1914 BOOL OS_IsOnWram0(void* ptr)
1915 {
1916 #ifdef SDK_TWL
1917 #ifdef SDK_ARM7
1918 if( OS_IsRunOnTwl() )
1919 {
1920 #ifdef SDK_TWLLTD
1921 if( (u32)ptr >= HW_WRAM_0_LTD && (u32)ptr < HW_WRAM_0_LTD_END )
1922 {
1923 return TRUE;
1924 }
1925 else
1926 {
1927 return FALSE;
1928 }
1929 #else
1930 // !SDK_TWLLTD
1931 if( (u32)ptr >= HW_WRAM_0_HYB && (u32)ptr < HW_WRAM_0_HYB_END )
1932 {
1933 return TRUE;
1934 }
1935 else
1936 {
1937 return FALSE;
1938 }
1939 #endif //SDK_TWLLTD
1940 }
1941 #else
1942 //!SDK_ARM7
1943 #pragma unused(ptr)
1944 #endif //SDK_ARM7
1945 #else
1946 //!SDK_TWL
1947 {
1948 if( (u32)ptr >= HW_WRAM_0 && (u32)ptr < HW_WRAM_0_END )
1949 {
1950 return TRUE;
1951 }
1952 else
1953 {
1954 return FALSE;
1955 }
1956 }
1957 #endif // SDK_ARM7
1958
1959 return FALSE;
1960 }
1961
1962 /*---------------------------------------------------------------------------*
1963 Name: OS_IsOnWram1
1964
1965 Description: check memory address to which a pointer points is on WRAM 1.
1966
1967 Arguments: ptr : pointer
1968
1969 Returns: TRUE if ptr points is on WRAM 1.
1970 *---------------------------------------------------------------------------*/
OS_IsOnWram1(void * ptr)1971 BOOL OS_IsOnWram1(void* ptr)
1972 {
1973 #ifdef SDK_TWL
1974 #ifdef SDK_ARM7
1975 if( OS_IsRunOnTwl() )
1976 {
1977 #ifdef SDK_TWLLTD
1978 if( (u32)ptr >= HW_WRAM_1_LTD && (u32)ptr < HW_WRAM_1_LTD_END )
1979 {
1980 return TRUE;
1981 }
1982 else
1983 {
1984 return FALSE;
1985 }
1986 #else
1987 // !SDK_TWLLTD
1988 if( (u32)ptr >= HW_WRAM_1_HYB && (u32)ptr < HW_WRAM_1_HYB_END )
1989 {
1990 return TRUE;
1991 }
1992 else
1993 {
1994 return FALSE;
1995 }
1996 #endif //SDK_TWLLTD
1997 }
1998 #else
1999 //SDK_TWL && !SDK_ARM7
2000 #pragma unused(ptr)
2001 #endif //SDK_ARM7
2002 #else
2003 //!SDK_TWL
2004 {
2005 if( (u32)ptr >= HW_WRAM_1 && (u32)ptr < HW_WRAM_1_END )
2006 {
2007 return TRUE;
2008 }
2009 else
2010 {
2011 return FALSE;
2012 }
2013 }
2014 #endif // SDK_ARM7
2015
2016 return FALSE;
2017 }
2018
2019 /*---------------------------------------------------------------------------*
2020 Name: OS_IsOnWram
2021
2022 Description: check memory address to which a pointer points is on WRAM.
2023
2024 Arguments: ptr : pointer
2025
2026 Returns: TRUE if ptr points is on WRAM.
2027 *---------------------------------------------------------------------------*/
OS_IsOnWram(void * ptr)2028 BOOL OS_IsOnWram(void* ptr)
2029 {
2030 return ( OS_IsOnWramA(ptr) || OS_IsOnWramB(ptr) || OS_IsOnWramC(ptr) ||OS_IsOnWram0(ptr) ||OS_IsOnWram1(ptr) );
2031 }
2032
2033
2034 /*---------------------------------------------------------------------------*
2035 Name: OS_IsOnVram
2036
2037 Description: check memory address to which a pointer points is on VRAM.
2038
2039 Arguments: ptr : pointer
2040
2041 Returns: TRUE if ptr points is on VRAM.
2042 *---------------------------------------------------------------------------*/
OS_IsOnVram(void * ptr)2043 BOOL OS_IsOnVram(void* ptr)
2044 {
2045 #ifdef SDK_ARM9
2046 if( (u32)ptr >= HW_PLTT && (u32)ptr < HW_DB_OAM_END )
2047 {
2048 return TRUE;
2049 }
2050 #else
2051 #pragma unused(ptr)
2052 #endif
2053 return FALSE;
2054 }
2055
2056
2057 /*---------------------------------------------------------------------------*
2058 Name: OS_IsOnDtcm
2059
2060 Description: check memory address to which a pointer points is on DTCM.
2061
2062 Arguments: ptr : pointer
2063
2064 Returns: TRUE if ptr points is on DTCM.
2065 *---------------------------------------------------------------------------*/
OS_IsOnDtcm(void * ptr)2066 BOOL OS_IsOnDtcm(void* ptr)
2067 {
2068 #ifdef SDK_ARM9
2069 u32 dtcm;
2070 u32 dtcm_end;
2071
2072 dtcm = OS_GetDTCMAddress();
2073 dtcm_end = dtcm + HW_DTCM_SIZE;
2074
2075 if( (u32)ptr >= dtcm && (u32)ptr < dtcm_end )
2076 {
2077 return TRUE;
2078 }
2079 #else
2080 #pragma unused(ptr)
2081 #endif
2082 return FALSE;
2083 }
2084
2085 /*---------------------------------------------------------------------------*
2086 Name: OS_IsOnItcm
2087
2088 Description: check memory address to which a pointer points is on ITCM.
2089
2090 Arguments: ptr : pointer
2091
2092 Returns: TRUE if ptr points is on ITCM.
2093 *---------------------------------------------------------------------------*/
OS_IsOnItcm(void * ptr)2094 BOOL OS_IsOnItcm(void* ptr)
2095 {
2096 #ifdef SDK_ARM9
2097 u32 itcm;
2098 u32 itcm_end;
2099
2100 itcm = OS_GetITCMAddress();
2101 itcm_end = itcm + HW_ITCM_SIZE;
2102
2103 if( (u32)ptr >= itcm && (u32)ptr < itcm_end )
2104 {
2105 return TRUE;
2106 }
2107 #else
2108 #pragma unused(ptr)
2109 #endif
2110 return FALSE;
2111 }
2112
2113 /*---------------------------------------------------------------------------*
2114 Name: OS_IsOnWramA
2115
2116 Description: check memory address to which a pointer points is on WRAM A.
2117
2118 Arguments: ptr : pointer
2119
2120 Returns: TRUE if ptr points is on WRAM A.
2121 *---------------------------------------------------------------------------*/
OS_IsOnWramA(void * ptr)2122 BOOL OS_IsOnWramA(void* ptr)
2123 {
2124 #ifdef SDK_TWL
2125 #ifdef SDK_ARM7
2126 if( OS_IsRunOnTwl() )
2127 {
2128 #ifdef SDK_TWLLTD
2129 /* TWL LTD */
2130 if( (u32)ptr >= HW_WRAM_A_LTD && (u32)ptr < HW_WRAM_A_LTD_END )
2131 {
2132 return TRUE;
2133 }
2134 else
2135 {
2136 return FALSE;
2137 }
2138 #else
2139 /* TWL HYB */
2140 if( (u32)ptr >= HW_WRAM_A_HYB && (u32)ptr < HW_WRAM_A_HYB_END )
2141 {
2142 return TRUE;
2143 }
2144 else
2145 {
2146 return FALSE;
2147 }
2148 #endif //SDK_TWLLTD
2149 }
2150 #else
2151 // SDK_TWL && !SDK_ARM7
2152 #pragma unused(ptr)
2153 #endif //SDK_ARM7
2154
2155 #else
2156 // !SDK_TWL
2157 #pragma unused(ptr)
2158 #endif //SDK_TWL
2159 return FALSE;
2160 }
2161
2162 /*---------------------------------------------------------------------------*
2163 Name: OS_IsOnArm7PrvWram
2164
2165 Description: check memory address to which a pointer points is on ARM7 Private WRAM.
2166
2167 Arguments: ptr : pointer
2168
2169 Returns: TRUE if ptr points is on ARM7 Private WRAM.
2170 *---------------------------------------------------------------------------*/
OS_IsOnArm7PrvWram(void * ptr)2171 BOOL OS_IsOnArm7PrvWram(void* ptr)
2172 {
2173 #ifdef SDK_ARM7
2174 if( (u32)ptr >= HW_PRV_WRAM && (u32)ptr < HW_PRV_WRAM_END )
2175 {
2176 return TRUE;
2177 }
2178 #else
2179 #pragma unused(ptr)
2180 #endif //SDK_ARM7
2181 return FALSE;
2182 }
2183
2184