-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
/
Copy pathctr_memory.c
154 lines (123 loc) · 3.59 KB
/
ctr_memory.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include <3ds.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include "ctr_debug.h"
extern u32 __heapBase;
extern u32 __heap_size;
extern u32 __stack_bottom;
extern u32 __stack_size_extra;
extern u32 __stacksize__;
u32 ctr_get_linear_free(void);
u32 ctr_get_linear_unused(void);
u32 ctr_get_stack_free(void)
{
extern u32 __stack_bottom;
uint32_t* stack_bottom_current = (u32*)__stack_bottom;
while(*stack_bottom_current++ == 0xFCFCFCFC);
stack_bottom_current--;
return ((u32)stack_bottom_current - __stack_bottom);
}
u32 ctr_get_stack_usage(void)
{
extern u32 __stacksize__;
u32 stack_free = ctr_get_stack_free();
return __stacksize__ > stack_free? __stacksize__ - stack_free: 0;
}
void ctr_linear_free_pages(u32 pages);
void ctr_free_pages(u32 pages)
{
u32 linear_free_pages;
u32 stack_free, stack_usage, stack_free_pages;
if (!pages)
return;
linear_free_pages = ctr_get_linear_free() >> 12;
if ((ctr_get_linear_unused() >> 12) > pages + 0x100)
return ctr_linear_free_pages(pages);
#if 0
if (linear_free_pages > pages + 0x400)
return ctr_linear_free_pages(pages);
#endif
stack_free = ctr_get_stack_free();
stack_usage = __stacksize__ > stack_free
? __stacksize__ - stack_free
: 0;
stack_free = stack_free > __stack_size_extra
? __stack_size_extra
: stack_free;
stack_free_pages = stack_free >> 12;
if (linear_free_pages + (stack_free_pages - (stack_usage >> 12)) > pages)
{
stack_free_pages -= (stack_usage >> 12);
stack_free_pages = stack_free_pages > pages ? pages : stack_free_pages;
linear_free_pages = pages - stack_free_pages;
}
else if (linear_free_pages + stack_free_pages > pages)
stack_free_pages = pages - linear_free_pages;
else
return;
if (linear_free_pages)
ctr_linear_free_pages(linear_free_pages);
if (stack_free_pages)
{
u32 tmp;
svcControlMemory(&tmp, __stack_bottom,
0x0,
stack_free_pages << 12,
MEMOP_FREE, MEMPERM_READ | MEMPERM_WRITE);
__stack_bottom += stack_free_pages << 12;
__stack_size_extra -= stack_free_pages << 12;
__stacksize__ -= stack_free_pages << 12;
#if 0
printf("s:0x%08X-->0x%08X(-0x%08X) \n", stack_free,
stack_free - (stack_free_pages << 12),
stack_free_pages << 12);
DEBUG_HOLD();
#endif
}
}
u32 ctr_get_free_space(void)
{
s64 mem_used;
u32 app_memory = *((u32*)0x1FF80040);
svcGetSystemInfo(&mem_used, 0, 1);
return app_memory - (u32)mem_used;
}
void ctr_request_free_pages(u32 pages)
{
u32 free_pages = ctr_get_free_space() >> 12;
if (pages > free_pages)
{
ctr_free_pages(pages - free_pages);
free_pages = ctr_get_free_space() >> 12;
}
}
void* _sbrk_r(struct _reent *ptr, ptrdiff_t incr)
{
static u32 sbrk_top = 0;
u32 tmp;
int diff;
if (!sbrk_top)
sbrk_top = __heapBase;
diff = ((sbrk_top + incr + 0xFFF) & ~0xFFF)
- (__heapBase + __heap_size);
if (diff > 0)
{
ctr_request_free_pages(diff >> 12);
if (svcControlMemory(&tmp, __heapBase + __heap_size,
0x0, diff, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE) < 0)
{
ptr->_errno = ENOMEM;
return (caddr_t) -1;
}
}
__heap_size += diff;
while (diff < 0) {
int size = -diff < 0x100000 ? -diff : 0x100000;
diff += size;
svcControlMemory(&tmp, __heapBase + __heap_size - diff,
0x0, size, MEMOP_FREE, 0);
}
sbrk_top += incr;
return (caddr_t)(sbrk_top - incr);
}