1+ #include <coreinit/memexpheap.h>
2+ #include <coreinit/memdefaultheap.h>
3+ #include <coreinit/memorymap.h>
4+ #include <coreinit/debug.h>
5+ #include <malloc.h>
6+ #include <string.h>
7+ #include <errno.h>
8+ #include <assert.h>
9+
10+ /**
11+ * A special version of wutmalloc for RPLs.
12+ *
13+ * RPLs can't reliable assume that the main application is using ExpHeap,
14+ * which means that MEMGetSizeForMBlockExpHeap can't be used for realloc.
15+ * This version co-allocates a header alongside the memory to be able to
16+ * reallocate the memory.
17+ */
18+ void
19+ __init_wut_malloc_rpl (void )
20+ {
21+ }
22+
23+ void
24+ __fini_wut_malloc_rpl (void )
25+ {
26+ }
27+
28+ #define WUT_MALLOC_RPL_CANARY (0x376296a9)
29+
30+ struct wut_alloc_header_rpl
31+ {
32+ uint32_t canary ;
33+ size_t size ;
34+ size_t offset ;
35+ };
36+
37+ static struct wut_alloc_header_rpl * get_alloc_header (const void * ptr )
38+ {
39+ struct wut_alloc_header_rpl * header = (struct wut_alloc_header_rpl * )ptr - 1 ;
40+ assert (header -> canary == WUT_MALLOC_RPL_CANARY );
41+ if (header -> canary != WUT_MALLOC_RPL_CANARY )
42+ OSFatal ("WUT detected a memory corruption in get_alloc_header" );
43+ return header ;
44+ }
45+
46+ static void * get_alloc_base (struct wut_alloc_header_rpl * header )
47+ {
48+ return (char * )header - header -> offset ;
49+ }
50+
51+ void *
52+ _malloc_r (struct _reent * r , size_t size )
53+ {
54+ return _memalign_r (r , 0x40 , size );
55+ }
56+
57+ void
58+ _free_r (struct _reent * r , void * ptr )
59+ {
60+ if (ptr ) {
61+ void * basePtr = get_alloc_base (get_alloc_header (ptr ));
62+ MEMFreeToDefaultHeap (basePtr );
63+ }
64+ }
65+
66+ void *
67+ _realloc_r (struct _reent * r , void * ptr , size_t size )
68+ {
69+ void * new_ptr = _malloc_r (r , size );
70+ if (!new_ptr ) {
71+ r -> _errno = ENOMEM ;
72+ return new_ptr ;
73+ }
74+
75+ if (ptr ) {
76+ struct wut_alloc_header_rpl * header = get_alloc_header (ptr );
77+ size_t old_size = header -> size ;
78+ memcpy (new_ptr , ptr , old_size <= size ? old_size : size );
79+ MEMFreeToDefaultHeap (get_alloc_base (header ));
80+ }
81+ return new_ptr ;
82+ }
83+
84+ void *
85+ _calloc_r (struct _reent * r , size_t num , size_t size )
86+ {
87+ void * ptr = _malloc_r (r , num * size );
88+ if (ptr ) {
89+ memset (ptr , 0 , num * size );
90+ } else {
91+ r -> _errno = ENOMEM ;
92+ }
93+ return ptr ;
94+ }
95+
96+ void *
97+ _memalign_r (struct _reent * r , size_t align , size_t size )
98+ {
99+ if (align < 0x40 )
100+ align = 0x40 ;
101+ size_t offset ;
102+ void * basePtr ;
103+ if (sizeof (struct wut_alloc_header_rpl ) > align )
104+ offset = align - (sizeof (struct wut_alloc_header_rpl ) % align );
105+ else
106+ offset = align - sizeof (struct wut_alloc_header_rpl );
107+ basePtr = MEMAllocFromDefaultHeapEx (offset + sizeof (struct wut_alloc_header_rpl ) + size , align );
108+ if (!basePtr ) {
109+ r -> _errno = ENOMEM ;
110+ return basePtr ;
111+ }
112+ struct wut_alloc_header_rpl * header = (struct wut_alloc_header_rpl * )((char * )basePtr + offset );
113+ header -> canary = WUT_MALLOC_RPL_CANARY ;
114+ header -> size = size ;
115+ header -> offset = offset ;
116+ return (header + 1 );
117+ }
118+
119+ struct mallinfo _mallinfo_r (struct _reent * r )
120+ {
121+ struct mallinfo info = { 0 };
122+ return info ;
123+ }
124+
125+ void
126+ _malloc_stats_r (struct _reent * r )
127+ {
128+ }
129+
130+ int
131+ _mallopt_r (struct _reent * r , int param , int value )
132+ {
133+ return 0 ;
134+ }
135+
136+ size_t
137+ _malloc_usable_size_r (struct _reent * r , void * ptr )
138+ {
139+ return 0 ; // we do not know the total available size
140+ }
141+
142+ void *
143+ _valloc_r (struct _reent * r , size_t size )
144+ {
145+ return _memalign_r (r , OS_PAGE_SIZE , size );
146+ }
147+
148+ void *
149+ _pvalloc_r (struct _reent * r , size_t size )
150+ {
151+ return _memalign_r (r , OS_PAGE_SIZE , (size + (OS_PAGE_SIZE - 1 )) & ~(OS_PAGE_SIZE - 1 ));
152+ }
153+
154+ int
155+ _malloc_trim_r (struct _reent * r , size_t pad )
156+ {
157+ return 0 ;
158+ }
0 commit comments