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-19#$
14 $Rev: 10786 $
15 $Author: okajima_manabu $
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_TPrintf( "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_TASSERTMSG(id < OS_ARENA_MAX, OS_ERR_ALLOCFROMHEAP_INVID);
377 SDK_TASSERTMSG(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_TASSERTMSG(heapInfo->heapArray, OS_ERR_ALLOCFROMHEAP_NOHEAP);
394 SDK_TASSERTMSG(0 < ((long)size), OS_ERR_ALLOCFROMHEAP_INVSIZE);
395 SDK_TASSERTMSG(0 <= heap && heap < heapInfo->numHeaps, OS_ERR_ALLOCFROMHEAP_INVHEAP);
396 SDK_TASSERTMSG(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_TPrintf("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_TASSERTMSG(OFFSET(cell, ALIGNMENT) == 0, OS_ERR_ALLOCFROMHEAP_BROKENHEAP);
423 SDK_TASSERTMSG(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_TASSERTMSG(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_TASSERTMSG(id < OS_ARENA_MAX, OS_ERR_ALLOCFIXED_INVID);
507 SDK_TASSERTMSG(OSiHeapInfo[id], OS_ERR_ALLOCFIXED_NOINFO);
508 heapInfo = OSiHeapInfo[id];
509
510 SDK_TASSERTMSG(heapInfo->heapArray, OS_ERR_ALLOCFIXED_NOHEAP);
511 SDK_TASSERTMSG(start < end, OS_ERR_ALLOCFIXED_INVRANGE);
512 SDK_TASSERTMSG(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_TPrintf("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_TASSERTMSG(id < OS_ARENA_MAX, OS_ERR_FREETOHEAP_INVID);
683 SDK_TASSERTMSG(OSiHeapInfo[id], OS_ERR_FREETOHEAP_NOINFO);
684 heapInfo = OSiHeapInfo[id];
685
686 if (heap < 0)
687 {
688 heap = heapInfo->currentHeap;
689 }
690
691 SDK_TASSERTMSG(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_TASSERTMSG(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_TASSERTMSG(OFFSET(ptr, ALIGNMENT) == 0, OS_ERR_FREETOHEAP_INVPTR);
703 SDK_TASSERTMSG(0 <= heapInfo->heapArray[heap].size, OS_ERR_FREETOHEAP_INVHEAP);
704
705 cell = (Cell *) ((char *)ptr - HEADERSIZE);
706 hd = &heapInfo->heapArray[heap];
707
708 SDK_TASSERTMSG(cell->hd == hd, OS_ERR_FREETOHEAP_INVPTR);
709 SDK_TASSERTMSG(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_TASSERTMSG(id < OS_ARENA_MAX, OS_ERR_FREETOHEAP_INVID);
747 SDK_TASSERTMSG(OSiHeapInfo[id], OS_ERR_FREETOHEAP_NOINFO);
748 heapInfo = OSiHeapInfo[id];
749
750 if (heap < 0)
751 {
752 heap = heapInfo->currentHeap;
753 }
754
755 SDK_TASSERTMSG(heapInfo->heapArray, "heap not initialized");
756 SDK_TASSERTMSG(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_TASSERTMSG(id < OS_ARENA_MAX, OS_ERR_SETCURRENTHEAP_INVID);
801 SDK_TASSERTMSG(OSiHeapInfo[id], OS_ERR_SETCURRENTHEAP_NOINFO);
802 heapInfo = OSiHeapInfo[id];
803
804 SDK_TASSERTMSG(heapInfo->heapArray, OS_ERR_SETCURRENTHEAP_NOHEAP);
805 SDK_TASSERTMSG(0 <= heap && heap < heapInfo->numHeaps, OS_ERR_SETCURRENTHEAP_INVHEAP);
806 SDK_TASSERTMSG(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_TASSERTMSG(id < OS_ARENA_MAX, OS_ERR_INITALLOC_INVID);
839 SDK_TASSERTMSG(OSiHeapInfo[id] == NULL, OS_ERR_INITALLOC_INVINFO);
840
841 SDK_TASSERTMSG(0 < maxHeaps, OS_ERR_INITALLOC_INVNUMHEAPS);
842 SDK_TASSERTMSG((char *)arenaStart < (char *)arenaEnd, OS_ERR_INITALLOC_INVRANGE);
843 SDK_TASSERTMSG(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_TASSERTMSG(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_TASSERTMSG(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_TPrintf( "OS_CreateHeap id=%d start=%x, end=%x\n", id, start, end );
921 //---- check arena id
922 SDK_TASSERTMSG(id < OS_ARENA_MAX, OS_ERR_CREATEHEAP_INVID);
923 SDK_TASSERTMSG(OSiHeapInfo[id], OS_ERR_CREATEHEAP_NOINFO);
924 heapInfo = OSiHeapInfo[id];
925
926 SDK_TASSERTMSG(heapInfo->heapArray, OS_ERR_CREATEHEAP_NOHEAP);
927 SDK_TASSERTMSG(start < end, OS_ERR_CREATEHEAP_INVRANGE);
928 start = (void *)ROUND(start, ALIGNMENT);
929 end = (void *)TRUNC(end, ALIGNMENT);
930 SDK_TASSERTMSG(start < end, OS_ERR_CREATEHEAP_INVRANGE);
931 SDK_TASSERTMSG(RangeSubset(start, end, heapInfo->arenaStart, heapInfo->arenaEnd), OS_ERR_CREATEHEAP_INVRANGE);
932 SDK_TASSERTMSG(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_TASSERTMSG(!DLOverlap(heapInfo->heapArray[heap].free, start, end), OS_ERR_CREATEHEAP_INVRANGE);
944 SDK_TASSERTMSG(!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_TPrintf("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_TASSERTMSG(id < OS_ARENA_MAX, OS_ERR_CREATEHEAP_INVID);
1006
1007 heapInfo = OSiHeapInfo[id];
1008 SDK_TASSERTMSG(heapInfo, OS_ERR_CREATEHEAP_NOINFO);
1009 SDK_TASSERTMSG(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_TASSERTMSG(id < OS_ARENA_MAX, OS_ERR_DESTROYHEAP_INVID);
1073 SDK_TASSERTMSG(OSiHeapInfo[id], OS_ERR_DESTROYHEAP_NOINFO);
1074 heapInfo = OSiHeapInfo[id];
1075
1076 SDK_TASSERTMSG(heapInfo->heapArray, OS_ERR_DESTROYHEAP_NOHEAP);
1077 SDK_TASSERTMSG(0 <= heap && heap < heapInfo->numHeaps, OS_ERR_DESTROYHEAP_INVHEAP);
1078 SDK_TASSERTMSG(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_TPrintf("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_TASSERTMSG(id < OS_ARENA_MAX, OS_ERR_ADDTOHEAP_INVID);
1140 SDK_TASSERTMSG(OSiHeapInfo[id], OS_ERR_ADDTOHEAP_NOINFO);
1141 heapInfo = OSiHeapInfo[id];
1142
1143 SDK_TASSERTMSG(heapInfo->heapArray, OS_ERR_ADDTOHEAP_NOHEAP);
1144 SDK_TASSERTMSG(0 <= heap && heap < heapInfo->numHeaps, OS_ERR_ADDTOHEAP_INVHEAP);
1145 SDK_TASSERTMSG(0 <= heapInfo->heapArray[heap].size, OS_ERR_ADDTOHEAP_INVHEAP);
1146
1147 hd = &heapInfo->heapArray[heap];
1148
1149 SDK_TASSERTMSG(start < end, OS_ERR_ADDTOHEAP_INVRANGE);
1150
1151 start = (void *)ROUND(start, ALIGNMENT);
1152 end = (void *)TRUNC(end, ALIGNMENT);
1153 SDK_TASSERTMSG(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_TASSERTMSG(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_TASSERTMSG(!DLOverlap(heapInfo->heapArray[i].free, start, end), OS_ERR_ADDTOHEAP_INVRANGE);
1176 SDK_TASSERTMSG(!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_TPrintf( "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_TPrintf( "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_TASSERTMSG(id < OS_ARENA_MAX, OS_ERR_CHECKHEAP_INVID);
1277 SDK_TASSERTMSG(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_TASSERTMSG(id < OS_ARENA_MAX, OS_ERR_REFERENTSIZE_INVID);
1375 SDK_TASSERTMSG(OSiHeapInfo[id], OS_ERR_REFERENTSIZE_NOINFO);
1376 heapInfo = OSiHeapInfo[id];
1377
1378 SDK_TASSERTMSG(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_TASSERTMSG(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_TASSERTMSG(OFFSET(ptr, ALIGNMENT) == 0, OS_ERR_REFERENT_INVPTR);
1390
1391 cell = (Cell *) ((char *)ptr - HEADERSIZE);
1392
1393 SDK_TASSERTMSG(cell->hd, OS_ERR_REFERENT_INVPTR);
1394 SDK_TASSERTMSG(((char *)cell->hd - (char *)heapInfo->heapArray) % sizeof(HeapDesc) == 0, OS_ERR_REFERENT_INVPTR);
1395 SDK_TASSERTMSG(heapInfo->heapArray <= cell->hd && cell->hd < &heapInfo->heapArray[heapInfo->numHeaps], OS_ERR_REFERENT_INVPTR);
1396 SDK_TASSERTMSG(0 <= cell->hd->size, OS_ERR_REFERENT_INVPTR);
1397 SDK_TASSERTMSG(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_TASSERTMSG(id < OS_ARENA_MAX, OS_ERR_DUMPHEAP_INVID);
1423 SDK_TASSERTMSG(OSiHeapInfo[id], OS_ERR_DUMPHEAP_NOINFO);
1424 heapInfo = OSiHeapInfo[id];
1425
1426 SDK_TASSERTMSG(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_TASSERTMSG(0 <= heap && heap < heapInfo->numHeaps, OS_ERR_DUMPHEAP_INVHEAP);
1434
1435 hd = &heapInfo->heapArray[heap];
1436 if (hd->size < 0)
1437 {
1438 OS_TPrintf("----Inactive\n");
1439 return;
1440 }
1441
1442 SDK_TASSERTMSG(0 <= OS_CheckHeap(id, heap), OS_ERR_DUMPHEAP_BROKENHEAP);
1443
1444 #ifdef SDK_ARM9
1445 #ifdef SDK_DEBUG
1446 OS_Printf("padding %d/(%f%%) header %d/(%f%%) payload %d/(%f%%)\n",
1447 hd->paddingBytes, 100.0 * hd->paddingBytes / hd->size,
1448 hd->headerBytes, 100.0 * hd->headerBytes / hd->size,
1449 hd->payloadBytes, 100.0 * hd->payloadBytes / hd->size);
1450 #endif // SDK_DEBUG
1451 #endif /* SDK_ARM9 */
1452
1453 OS_TPrintf(" addr size end prev next\n");
1454
1455 OS_TPrintf("----Allocated\n");
1456 SDK_TASSERTMSG(hd->allocated == NULL || hd->allocated->prev == NULL, OS_ERR_DUMPHEAP_BROKENHEAP);
1457 if ( ! hd->allocated )
1458 {
1459 OS_TPrintf("None.\n");
1460 }
1461 else
1462 {
1463 for (cell = hd->allocated; cell; cell = cell->next)
1464 {
1465 OS_TPrintf("%08x %6x %08x %08x %08x\n",
1466 cell, cell->size, (char *)cell + cell->size, cell->prev, cell->next);
1467 }
1468 }
1469
1470 OS_TPrintf("----Free\n");
1471 if ( ! hd->free )
1472 {
1473 OS_TPrintf("None.\n");
1474 }
1475 else
1476 {
1477 for (cell = hd->free; cell; cell = cell->next)
1478 {
1479 OS_TPrintf("%08x %6x %08x %08x %08x\n",
1480 cell, cell->size, (char *)cell + cell->size, cell->prev, cell->next);
1481 }
1482 }
1483
1484 (void)OS_RestoreInterrupts(enabled);
1485 #else // ifndef SDK_FINALROM
1486
1487 #pragma unused( id, heap )
1488
1489 #endif // ifndef SDK_FINALROM
1490 }
1491
1492
1493 /*---------------------------------------------------------------------------*
1494 Name: OS_VisitAllocated
1495
1496 Description: Visits every element of every allocated block of memory,
1497 calling a routine on each one.
1498
1499 Arguments: id : arena ID
1500 visitor : function to be called on each cell
1501
1502 Returns: None.
1503 *---------------------------------------------------------------------------*/
OS_VisitAllocated(OSArenaId id,OSAllocVisitor visitor)1504 void OS_VisitAllocated(OSArenaId id, OSAllocVisitor visitor)
1505 {
1506 OSHeapInfo *heapInfo;
1507 u32 heap;
1508 Cell *cell;
1509
1510 OSIntrMode enabled = OS_DisableInterrupts();
1511
1512 //---- check arena id
1513 SDK_TASSERTMSG(id < OS_ARENA_MAX, OS_ERR_VISITALLOCATED_INVID);
1514 SDK_TASSERTMSG(OSiHeapInfo[id], OS_ERR_VISITALLOCATED_NOINFO);
1515 heapInfo = OSiHeapInfo[id];
1516
1517 for (heap = 0; heap < heapInfo->numHeaps; heap++)
1518 {
1519 if (heapInfo->heapArray[heap].size >= 0)
1520 {
1521 for (cell = heapInfo->heapArray[heap].allocated; cell; cell = cell->next)
1522 {
1523 visitor((void *)((u8 *)cell + HEADERSIZE), (u32)(cell->size - HEADERSIZE));
1524 }
1525 }
1526 }
1527
1528 (void)OS_RestoreInterrupts(enabled);
1529 }
1530
1531 //================================================================================
1532 // Get information about heap
1533 //================================================================================
1534 /*---------------------------------------------------------------------------*
1535 Name: OSi_GetTotalAllocSize
1536
1537 Description: Get sum of allocated block size.
1538 Subroutine for OS_GetTotalAllocSize and OS_GetTotalOccupiedSize.
1539
1540 Arguments: id : arena ID
1541 heap : handle to a heap.
1542 isHeadInclude : whether if including block header.
1543
1544 Returns: sum of allocated block size
1545 *---------------------------------------------------------------------------*/
OSi_GetTotalAllocSize(OSArenaId id,OSHeapHandle heap,BOOL isHeadInclude)1546 u32 OSi_GetTotalAllocSize(OSArenaId id, OSHeapHandle heap, BOOL isHeadInclude)
1547 {
1548 OSHeapInfo *heapInfo;
1549 Cell *cell;
1550 u32 sum = 0;
1551 OSIntrMode enabled = OS_DisableInterrupts();
1552
1553 SDK_ASSERT(id < OS_ARENA_MAX);
1554 heapInfo = OSiHeapInfo[id];
1555 SDK_ASSERT(heapInfo);
1556 SDK_ASSERT(heap < heapInfo->numHeaps);
1557
1558 //---- heap<0 means current heap
1559 if (heap < 0)
1560 {
1561 heap = heapInfo->currentHeap;
1562 }
1563
1564 if (isHeadInclude)
1565 {
1566 for (cell = heapInfo->heapArray[heap].allocated; cell; cell = cell->next)
1567 {
1568 sum += (u32)(cell->size);
1569 }
1570 }
1571 else
1572 {
1573 for (cell = heapInfo->heapArray[heap].allocated; cell; cell = cell->next)
1574 {
1575 sum += (u32)(cell->size - HEADERSIZE);
1576 }
1577 }
1578
1579 (void)OS_RestoreInterrupts(enabled);
1580
1581 return sum;
1582 }
1583
1584 /*---------------------------------------------------------------------------*
1585 Name: OS_GetTotalFreeSize
1586
1587 Description: Get sum of free block size,
1588 not includeing of block header.
1589
1590 Arguments: id : arena ID
1591 heap : handle to a heap.
1592
1593 Returns: sum of free block size
1594 *---------------------------------------------------------------------------*/
OS_GetTotalFreeSize(OSArenaId id,OSHeapHandle heap)1595 u32 OS_GetTotalFreeSize(OSArenaId id, OSHeapHandle heap)
1596 {
1597 OSHeapInfo *heapInfo;
1598 Cell *cell;
1599 u32 sum = 0;
1600 OSIntrMode enabled = OS_DisableInterrupts();
1601
1602 SDK_ASSERT(id < OS_ARENA_MAX);
1603 heapInfo = OSiHeapInfo[id];
1604 SDK_ASSERT(heapInfo);
1605 SDK_ASSERT(heap < heapInfo->numHeaps);
1606
1607 //---- heap<0 means current heap
1608 if (heap < 0)
1609 {
1610 heap = heapInfo->currentHeap;
1611 }
1612
1613 for (cell = heapInfo->heapArray[heap].free; cell; cell = cell->next)
1614 {
1615 sum += (u32)(cell->size - HEADERSIZE);
1616 }
1617
1618 (void)OS_RestoreInterrupts(enabled);
1619
1620 return sum;
1621 }
1622
1623 /*---------------------------------------------------------------------------*
1624 Name: OS_GetMaxFreeSize
1625
1626 Description: Get maximun free block size
1627
1628 Arguments: id : arena ID
1629 heap : handle to a heap.
1630
1631 Returns: maximum free block size.
1632 *---------------------------------------------------------------------------*/
OS_GetMaxFreeSize(OSArenaId id,OSHeapHandle heap)1633 u32 OS_GetMaxFreeSize(OSArenaId id, OSHeapHandle heap)
1634 {
1635 OSHeapInfo *heapInfo;
1636 Cell *cell;
1637 u32 candidate = 0;
1638 OSIntrMode enabled = OS_DisableInterrupts();
1639
1640 SDK_ASSERT(id < OS_ARENA_MAX);
1641 heapInfo = OSiHeapInfo[id];
1642 SDK_ASSERT(heapInfo);
1643 SDK_ASSERT(heap < heapInfo->numHeaps);
1644
1645 //---- heap<0 means current heap
1646 if (heap < 0)
1647 {
1648 heap = heapInfo->currentHeap;
1649 }
1650
1651 for (cell = heapInfo->heapArray[heap].free; cell; cell = cell->next)
1652 {
1653 u32 size = (u32)(cell->size - HEADERSIZE);
1654 if (size > candidate)
1655 {
1656 candidate = size;
1657 }
1658 }
1659
1660 (void)OS_RestoreInterrupts(enabled);
1661
1662 return candidate;
1663 }
1664
1665 //================================================================================
1666 // re-initialize heap.
1667 //================================================================================
1668 /*---------------------------------------------------------------------------*
1669 Name: OS_ClearHeap
1670
1671 Description: re-initialize heap.
1672
1673 Arguments: id : arena ID
1674 heap : handle to a heap.
1675 start: starting addr of heap
1676 end : endinf addr of heap
1677
1678 Returns: None.
1679 *---------------------------------------------------------------------------*/
OS_ClearHeap(OSArenaId id,OSHeapHandle heap,void * start,void * end)1680 void OS_ClearHeap(OSArenaId id, OSHeapHandle heap, void *start, void *end)
1681 {
1682 OSHeapInfo *heapInfo;
1683 HeapDesc *hd;
1684 Cell *cell;
1685
1686 OSIntrMode enabled = OS_DisableInterrupts();
1687
1688 //---- check arena id
1689 SDK_TASSERTMSG(id < OS_ARENA_MAX, "invalid id");
1690
1691 heapInfo = OSiHeapInfo[id];
1692
1693 SDK_TASSERTMSG(heapInfo && heapInfo->heapArray, "heap not initialized");
1694 SDK_TASSERTMSG(start < end, "invalid range");
1695 start = (void *)ROUND(start, ALIGNMENT);
1696 end = (void *)TRUNC(end, ALIGNMENT);
1697 SDK_TASSERTMSG(start < end, "invalid range");
1698 #ifdef SDK_DEBUG
1699 #if defined(SDK_TWL) && !defined(SDK_TWLLTD)
1700 if ( OSi_ExtraHeapArenaId != id || OSi_ExtraHeapHandle != heap )
1701 {
1702 #endif
1703 SDK_TASSERTMSG(RangeSubset(start, end, heapInfo->arenaStart, heapInfo->arenaEnd), "invalid range");
1704 #if defined(SDK_TWL) && !defined(SDK_TWLLTD)
1705 }
1706 #endif
1707 #endif
1708 SDK_TASSERTMSG(MINOBJSIZE <= (char *)end - (char *)start, "too small range");
1709
1710 //---- heap<0 means current heap
1711 if (heap < 0)
1712 {
1713 heap = heapInfo->currentHeap;
1714 }
1715
1716 //---- Search for free descriptor
1717 hd = &heapInfo->heapArray[heap];
1718 hd->size = (char *)end - (char *)start;
1719
1720 cell = (Cell *) start;
1721 cell->prev = NULL;
1722 cell->next = NULL;
1723 cell->size = hd->size;
1724 #ifdef SDK_DEBUG
1725 cell->hd = NULL;
1726 #endif // SDK_DEBUG
1727
1728 hd->free = cell;
1729 hd->allocated = 0;
1730 #ifdef SDK_DEBUG
1731 hd->paddingBytes = hd->headerBytes = hd->payloadBytes = 0;
1732 #endif // SDK_DEBUG
1733
1734 (void)OS_RestoreInterrupts(enabled);
1735 }
1736 /*---------------------------------------------------------------------------*
1737 Name: OS_ClearExtraHeap
1738
1739 Description: re-initialize extra heap.
1740
1741 Arguments: id : arena ID
1742 heap : handle to a heap.
1743
1744 Returns: None.
1745 *---------------------------------------------------------------------------*/
1746 #if defined(SDK_TWL) && !defined(SDK_TWLLTD)
OS_ClearExtraHeap(OSArenaId id,OSHeapHandle heap)1747 void OS_ClearExtraHeap(OSArenaId id, OSHeapHandle heap)
1748 {
1749 if ( ! OS_IsRunOnTwl() )
1750 {
1751 if ( OSi_ExtraHeapArenaId == id || OSi_ExtraHeapHandle == heap )
1752 {
1753 OS_ClearHeap(id, heap,
1754 (void*)HW_MAIN_MEM_PARAMETER_BUF,
1755 (void*)(HW_MAIN_MEM_PARAMETER_BUF + HW_MAIN_MEM_PARAMETER_BUF_SIZE ) );
1756 }
1757 }
1758 }
1759 #endif
1760
1761 //================================================================================
1762 // Check Alocated Memory
1763 //================================================================================
1764 /*---------------------------------------------------------------------------*
1765 Name: OS_IsOnMainMemory
1766
1767 Description: check memory address to which a pointer points is on main RAM.
1768
1769 Arguments: ptr : pointer
1770
1771 Returns: TRUE if ptr points is on main RAM.
1772 *---------------------------------------------------------------------------*/
OS_IsOnMainMemory(void * ptr)1773 BOOL OS_IsOnMainMemory(void* ptr)
1774 {
1775 #ifdef SDK_TWL
1776 if( OS_IsRunOnTwl() )
1777 {
1778 /* TWL */
1779 if( (u32)ptr >= HW_TWL_MAIN_MEM && (u32)ptr < HW_TWL_MAIN_MEM_END )
1780 {
1781 return TRUE;
1782 }
1783 else
1784 {
1785 return FALSE;
1786 }
1787 }
1788 else
1789 #endif //SDK_TWL
1790 {
1791 /* NITRO */
1792 if( (u32)ptr >= HW_MAIN_MEM && (u32)ptr < HW_MAIN_MEM_END )
1793 {
1794 return TRUE;
1795 }
1796 else
1797 {
1798 return FALSE;
1799 }
1800 }
1801 return FALSE; /* Do Not Return HERE */
1802 }
1803
1804 /*---------------------------------------------------------------------------*
1805 Name: OS_IsOnExtendedMainMemory
1806
1807 Description: check memory address to which a pointer points is on extended main RAM.
1808
1809 Arguments: ptr : pointer
1810
1811 Returns: TRUE if ptr points is on extended main RAM.
1812 *---------------------------------------------------------------------------*/
OS_IsOnExtendedMainMemory(void * ptr)1813 BOOL OS_IsOnExtendedMainMemory(void* ptr)
1814 {
1815 #ifdef SDK_TWL
1816 if( OS_IsRunOnTwl() )
1817 {
1818 /* TWL */
1819 if( (u32)ptr >= HW_TWL_MAIN_MEM_EX && (u32)ptr < HW_TWL_MAIN_MEM_EX_END )
1820 {
1821 return TRUE;
1822 }
1823 else
1824 {
1825 return FALSE;
1826 }
1827 }
1828 else
1829 #endif //SDK_TWL
1830 {
1831 /* NITRO */
1832 if( (u32)ptr >= HW_MAIN_MEM_END && (u32)ptr < HW_MAIN_MEM_EX_END )
1833 {
1834 return TRUE;
1835 }
1836 else
1837 {
1838 return FALSE;
1839 }
1840 }
1841 return FALSE; /* Do Not Return HERE */
1842 }
1843
1844
1845
1846
1847 /*---------------------------------------------------------------------------*
1848 Name: OS_IsOnWramB
1849
1850 Description: check memory address to which a pointer points is on WRAM B.
1851
1852 Arguments: ptr : pointer
1853
1854 Returns: TRUE if ptr points is on WRAM B.
1855 *---------------------------------------------------------------------------*/
OS_IsOnWramB(void * ptr)1856 BOOL OS_IsOnWramB(void* ptr)
1857 {
1858 #ifdef SDK_TWL
1859 if( OS_IsRunOnTwl() )
1860 {
1861 /* TWL */
1862 if( (u32)ptr >= HW_WRAM_B && (u32)ptr < HW_WRAM_B_END )
1863 {
1864 return TRUE;
1865 }
1866 else
1867 {
1868 return FALSE;
1869 }
1870 }
1871 #else
1872 #pragma unused(ptr)
1873 #endif //SDK_TWL
1874 return FALSE;
1875 }
1876
1877 /*---------------------------------------------------------------------------*
1878 Name: OSi_IsOnWramC
1879
1880 Description: check memory address to which a pointer points is on WRAM C.
1881
1882 Arguments: ptr : pointer
1883
1884 Returns: TRUE if ptr points is on WRAM C.
1885 *---------------------------------------------------------------------------*/
OS_IsOnWramC(void * ptr)1886 BOOL OS_IsOnWramC(void* ptr)
1887 {
1888 #ifdef SDK_TWL
1889 if( OS_IsRunOnTwl() )
1890 {
1891 /* TWL */
1892 if( (u32)ptr >= HW_WRAM_C && (u32)ptr < HW_WRAM_C_END )
1893 {
1894 return TRUE;
1895 }
1896 else
1897 {
1898 return FALSE;
1899 }
1900 }
1901 #else
1902 #pragma unused(ptr)
1903 #endif //SDK_TWL
1904 return FALSE;
1905 }
1906
1907 /*---------------------------------------------------------------------------*
1908 Name: OS_IsOnWram0
1909
1910 Description: check memory address to which a pointer points is on WRAM 0.
1911
1912 Arguments: ptr : pointer
1913
1914 Returns: TRUE if ptr points is on WRAM 0.
1915 *---------------------------------------------------------------------------*/
OS_IsOnWram0(void * ptr)1916 BOOL OS_IsOnWram0(void* ptr)
1917 {
1918 #ifdef SDK_TWL
1919 #ifdef SDK_ARM7
1920 if( OS_IsRunOnTwl() )
1921 {
1922 #ifdef SDK_TWLLTD
1923 if( (u32)ptr >= HW_WRAM_0_LTD && (u32)ptr < HW_WRAM_0_LTD_END )
1924 {
1925 return TRUE;
1926 }
1927 else
1928 {
1929 return FALSE;
1930 }
1931 #else
1932 // !SDK_TWLLTD
1933 if( (u32)ptr >= HW_WRAM_0_HYB && (u32)ptr < HW_WRAM_0_HYB_END )
1934 {
1935 return TRUE;
1936 }
1937 else
1938 {
1939 return FALSE;
1940 }
1941 #endif //SDK_TWLLTD
1942 }
1943 #else
1944 //!SDK_ARM7
1945 #pragma unused(ptr)
1946 #endif //SDK_ARM7
1947 #else
1948 //!SDK_TWL
1949 {
1950 if( (u32)ptr >= HW_WRAM_0 && (u32)ptr < HW_WRAM_0_END )
1951 {
1952 return TRUE;
1953 }
1954 else
1955 {
1956 return FALSE;
1957 }
1958 }
1959 #endif // SDK_ARM7
1960
1961 return FALSE;
1962 }
1963
1964 /*---------------------------------------------------------------------------*
1965 Name: OS_IsOnWram1
1966
1967 Description: check memory address to which a pointer points is on WRAM 1.
1968
1969 Arguments: ptr : pointer
1970
1971 Returns: TRUE if ptr points is on WRAM 1.
1972 *---------------------------------------------------------------------------*/
OS_IsOnWram1(void * ptr)1973 BOOL OS_IsOnWram1(void* ptr)
1974 {
1975 #ifdef SDK_TWL
1976 #ifdef SDK_ARM7
1977 if( OS_IsRunOnTwl() )
1978 {
1979 #ifdef SDK_TWLLTD
1980 if( (u32)ptr >= HW_WRAM_1_LTD && (u32)ptr < HW_WRAM_1_LTD_END )
1981 {
1982 return TRUE;
1983 }
1984 else
1985 {
1986 return FALSE;
1987 }
1988 #else
1989 // !SDK_TWLLTD
1990 if( (u32)ptr >= HW_WRAM_1_HYB && (u32)ptr < HW_WRAM_1_HYB_END )
1991 {
1992 return TRUE;
1993 }
1994 else
1995 {
1996 return FALSE;
1997 }
1998 #endif //SDK_TWLLTD
1999 }
2000 #else
2001 //SDK_TWL && !SDK_ARM7
2002 #pragma unused(ptr)
2003 #endif //SDK_ARM7
2004 #else
2005 //!SDK_TWL
2006 {
2007 if( (u32)ptr >= HW_WRAM_1 && (u32)ptr < HW_WRAM_1_END )
2008 {
2009 return TRUE;
2010 }
2011 else
2012 {
2013 return FALSE;
2014 }
2015 }
2016 #endif // SDK_ARM7
2017
2018 return FALSE;
2019 }
2020
2021 /*---------------------------------------------------------------------------*
2022 Name: OS_IsOnWram
2023
2024 Description: check memory address to which a pointer points is on WRAM.
2025
2026 Arguments: ptr : pointer
2027
2028 Returns: TRUE if ptr points is on WRAM.
2029 *---------------------------------------------------------------------------*/
OS_IsOnWram(void * ptr)2030 BOOL OS_IsOnWram(void* ptr)
2031 {
2032 return ( OS_IsOnWramA(ptr) || OS_IsOnWramB(ptr) || OS_IsOnWramC(ptr) ||OS_IsOnWram0(ptr) ||OS_IsOnWram1(ptr) );
2033 }
2034
2035
2036 /*---------------------------------------------------------------------------*
2037 Name: OS_IsOnVram
2038
2039 Description: check memory address to which a pointer points is on VRAM.
2040
2041 Arguments: ptr : pointer
2042
2043 Returns: TRUE if ptr points is on VRAM.
2044 *---------------------------------------------------------------------------*/
OS_IsOnVram(void * ptr)2045 BOOL OS_IsOnVram(void* ptr)
2046 {
2047 #ifdef SDK_ARM9
2048 if( (u32)ptr >= HW_PLTT && (u32)ptr < HW_DB_OAM_END )
2049 {
2050 return TRUE;
2051 }
2052 #else
2053 #pragma unused(ptr)
2054 #endif
2055 return FALSE;
2056 }
2057
2058
2059 /*---------------------------------------------------------------------------*
2060 Name: OS_IsOnDtcm
2061
2062 Description: check memory address to which a pointer points is on DTCM.
2063
2064 Arguments: ptr : pointer
2065
2066 Returns: TRUE if ptr points is on DTCM.
2067 *---------------------------------------------------------------------------*/
OS_IsOnDtcm(void * ptr)2068 BOOL OS_IsOnDtcm(void* ptr)
2069 {
2070 #ifdef SDK_ARM9
2071 u32 dtcm;
2072 u32 dtcm_end;
2073
2074 dtcm = OS_GetDTCMAddress();
2075 dtcm_end = dtcm + HW_DTCM_SIZE;
2076
2077 if( (u32)ptr >= dtcm && (u32)ptr < dtcm_end )
2078 {
2079 return TRUE;
2080 }
2081 #else
2082 #pragma unused(ptr)
2083 #endif
2084 return FALSE;
2085 }
2086
2087 /*---------------------------------------------------------------------------*
2088 Name: OS_IsOnItcm
2089
2090 Description: check memory address to which a pointer points is on ITCM.
2091
2092 Arguments: ptr : pointer
2093
2094 Returns: TRUE if ptr points is on ITCM.
2095 *---------------------------------------------------------------------------*/
OS_IsOnItcm(void * ptr)2096 BOOL OS_IsOnItcm(void* ptr)
2097 {
2098 #ifdef SDK_ARM9
2099 u32 itcm;
2100 u32 itcm_end;
2101
2102 itcm = OS_GetITCMAddress();
2103 itcm_end = itcm + HW_ITCM_SIZE;
2104
2105 if( (u32)ptr >= itcm && (u32)ptr < itcm_end )
2106 {
2107 return TRUE;
2108 }
2109 #else
2110 #pragma unused(ptr)
2111 #endif
2112 return FALSE;
2113 }
2114
2115 /*---------------------------------------------------------------------------*
2116 Name: OS_IsOnWramA
2117
2118 Description: check memory address to which a pointer points is on WRAM A.
2119
2120 Arguments: ptr : pointer
2121
2122 Returns: TRUE if ptr points is on WRAM A.
2123 *---------------------------------------------------------------------------*/
OS_IsOnWramA(void * ptr)2124 BOOL OS_IsOnWramA(void* ptr)
2125 {
2126 #ifdef SDK_TWL
2127 #ifdef SDK_ARM7
2128 if( OS_IsRunOnTwl() )
2129 {
2130 #ifdef SDK_TWLLTD
2131 /* TWL LTD */
2132 if( (u32)ptr >= HW_WRAM_A_LTD && (u32)ptr < HW_WRAM_A_LTD_END )
2133 {
2134 return TRUE;
2135 }
2136 else
2137 {
2138 return FALSE;
2139 }
2140 #else
2141 /* TWL HYB */
2142 if( (u32)ptr >= HW_WRAM_A_HYB && (u32)ptr < HW_WRAM_A_HYB_END )
2143 {
2144 return TRUE;
2145 }
2146 else
2147 {
2148 return FALSE;
2149 }
2150 #endif //SDK_TWLLTD
2151 }
2152 #else
2153 // SDK_TWL && !SDK_ARM7
2154 #pragma unused(ptr)
2155 #endif //SDK_ARM7
2156
2157 #else
2158 // !SDK_TWL
2159 #pragma unused(ptr)
2160 #endif //SDK_TWL
2161 return FALSE;
2162 }
2163
2164 /*---------------------------------------------------------------------------*
2165 Name: OS_IsOnArm7PrvWram
2166
2167 Description: check memory address to which a pointer points is on ARM7 Private WRAM.
2168
2169 Arguments: ptr : pointer
2170
2171 Returns: TRUE if ptr points is on ARM7 Private WRAM.
2172 *---------------------------------------------------------------------------*/
OS_IsOnArm7PrvWram(void * ptr)2173 BOOL OS_IsOnArm7PrvWram(void* ptr)
2174 {
2175 #ifdef SDK_ARM7
2176 if( (u32)ptr >= HW_PRV_WRAM && (u32)ptr < HW_PRV_WRAM_END )
2177 {
2178 return TRUE;
2179 }
2180 #else
2181 #pragma unused(ptr)
2182 #endif //SDK_ARM7
2183 return FALSE;
2184 }
2185
2186