Fix libogc hardware lighting (GX_SetChanCtrl) - patch from https://sourceforge.net...
[libogc.git] / libogc / sbrk.c
blobf74bc977f936ee82372fa064b111b300dd9eb9db
1 #include <_ansi.h>
2 #include <_syslist.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <reent.h>
6 #include <errno.h>
8 #include "asm.h"
9 #include "processor.h"
10 #include "system.h"
12 #if defined(HW_RVL)
13 u32 MALLOC_MEM2 __attribute__((weak)) = 1;
14 #endif
16 void* _DEFUN(__libogc_sbrk_r,(ptr,incr),
17 struct _reent *ptr _AND
18 ptrdiff_t incr)
20 u32 level;
21 char *heap_end = 0;
22 char *prev_heap = 0;
23 #if defined(HW_RVL)
24 static char *mem2_start = NULL;
25 #endif
27 _CPU_ISR_Disable(level);
28 #if defined(HW_RVL)
29 if(MALLOC_MEM2) {
30 // use MEM2 aswell for malloc
31 if(mem2_start==NULL)
32 heap_end = (char*)SYS_GetArenaLo();
33 else
34 heap_end = (char*)SYS_GetArena2Lo();
36 if(mem2_start) {
37 // we're in MEM2
38 if((heap_end+incr)>(char*)SYS_GetArena2Hi()) {
39 // out of MEM2 case
40 ptr->_errno = ENOMEM;
41 prev_heap = (char *)-1;
42 } else if ((heap_end+incr) < mem2_start) {
43 // trying to sbrk() back below the MEM2 start barrier
44 ptr->_errno = EINVAL;
45 prev_heap = (char *)-1;
46 } else {
47 // success case
48 prev_heap = heap_end;
49 SYS_SetArena2Lo((void*)(heap_end+incr));
51 // if MEM2 area is exactly at the barrier, transition back to MEM1 again
52 if(SYS_GetArena2Lo() == mem2_start) mem2_start = NULL;
53 } else {
54 // we're in MEM1
55 if((heap_end+incr)>(char*)SYS_GetArenaHi()) {
56 // out of MEM1, transition into MEM2
57 if(((char*)SYS_GetArena2Lo() + incr) > (char*)SYS_GetArena2Hi()) {
58 // this increment doesn't fit in available MEM2
59 ptr->_errno = ENOMEM;
60 prev_heap = (char *)-1;
61 } else {
62 // MEM2 is available, move into it
63 mem2_start = heap_end = prev_heap = SYS_GetArena2Lo();
64 SYS_SetArena2Lo((void*)(heap_end+incr));
66 } else {
67 // MEM1 is available (or we're freeing memory)
68 prev_heap = heap_end;
69 SYS_SetArenaLo((void*)(heap_end+incr));
72 } else {
73 #endif
74 heap_end = (char*)SYS_GetArenaLo();
76 if((heap_end+incr)>(char*)SYS_GetArenaHi()) {
78 ptr->_errno = ENOMEM;
79 prev_heap = (char *)-1;
81 } else {
83 prev_heap = heap_end;
84 SYS_SetArenaLo((void*)(heap_end+incr));
86 #if defined(HW_RVL)
88 #endif
89 _CPU_ISR_Restore(level);
91 return (void*)prev_heap;