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