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