2016-09-26 01:06:01 +02:00
|
|
|
#include <errno.h>
|
|
|
|
#include <reent.h>
|
2021-05-18 22:15:04 +02:00
|
|
|
#include <defines/psp_defines.h>
|
2017-01-17 18:12:23 +01:00
|
|
|
#include <psp2/kernel/sysmem.h>
|
|
|
|
#include <psp2/kernel/threadmgr.h>
|
|
|
|
|
2019-10-04 12:11:52 +02:00
|
|
|
|
2019-11-12 11:52:04 +01:00
|
|
|
int _newlib_heap_memblock;
|
|
|
|
unsigned _newlib_heap_size;
|
2019-10-04 12:11:52 +02:00
|
|
|
char *_newlib_heap_base, *_newlib_heap_end, *_newlib_heap_cur;
|
2016-09-26 01:06:01 +02:00
|
|
|
static char _newlib_sbrk_mutex[32] __attribute__ ((aligned (8)));
|
|
|
|
|
|
|
|
static int _newlib_vm_memblock;
|
|
|
|
|
2016-10-11 09:40:55 +02:00
|
|
|
extern int _newlib_heap_size_user __attribute__((weak));
|
2016-09-26 01:06:01 +02:00
|
|
|
extern int _newlib_vm_size_user __attribute__((weak));
|
|
|
|
|
2021-04-02 19:50:09 +02:00
|
|
|
#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
|
|
|
|
|
2016-09-26 01:06:01 +02:00
|
|
|
void * _sbrk_r(struct _reent *reent, ptrdiff_t incr) {
|
2016-10-02 14:03:15 +02:00
|
|
|
if (sceKernelLockLwMutex((struct SceKernelLwMutexWork*)_newlib_sbrk_mutex, 1, 0) < 0)
|
2016-09-26 01:06:01 +02:00
|
|
|
goto fail;
|
|
|
|
if (!_newlib_heap_base || _newlib_heap_cur + incr >= _newlib_heap_end) {
|
2016-10-02 14:03:15 +02:00
|
|
|
sceKernelUnlockLwMutex((struct SceKernelLwMutexWork*)_newlib_sbrk_mutex, 1);
|
2016-09-26 01:06:01 +02:00
|
|
|
fail:
|
|
|
|
reent->_errno = ENOMEM;
|
2016-10-02 14:03:15 +02:00
|
|
|
return (void*)-1;
|
2016-09-26 01:06:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
char *prev_heap_end = _newlib_heap_cur;
|
|
|
|
_newlib_heap_cur += incr;
|
|
|
|
|
2016-10-02 14:03:15 +02:00
|
|
|
sceKernelUnlockLwMutex((struct SceKernelLwMutexWork*)_newlib_sbrk_mutex, 1);
|
2016-09-26 01:06:01 +02:00
|
|
|
return (void*) prev_heap_end;
|
|
|
|
}
|
|
|
|
|
|
|
|
void _init_vita_heap(void) {
|
2016-10-11 09:40:55 +02:00
|
|
|
|
2016-09-26 01:06:01 +02:00
|
|
|
int _newlib_vm_size = 0;
|
|
|
|
if (&_newlib_vm_size_user != NULL) {
|
2021-04-02 19:50:09 +02:00
|
|
|
_newlib_vm_size = ALIGN(_newlib_vm_size_user, 0x100000);
|
|
|
|
_newlib_vm_memblock = sceKernelAllocMemBlockForVM("code", _newlib_vm_size);
|
2016-09-26 01:06:01 +02:00
|
|
|
|
|
|
|
if (_newlib_vm_memblock < 0){
|
2016-10-02 14:03:15 +02:00
|
|
|
//sceClibPrintf("sceKernelAllocMemBlockForVM failed\n");
|
2016-09-26 01:06:01 +02:00
|
|
|
}
|
|
|
|
}else{
|
|
|
|
_newlib_vm_memblock = 0;
|
|
|
|
}
|
2016-10-11 09:40:55 +02:00
|
|
|
|
2016-09-26 01:06:01 +02:00
|
|
|
// Create a mutex to use inside _sbrk_r
|
2016-10-02 14:03:15 +02:00
|
|
|
if (sceKernelCreateLwMutex((struct SceKernelLwMutexWork*)_newlib_sbrk_mutex, "sbrk mutex", 0, 0, 0) < 0) {
|
2016-09-26 01:06:01 +02:00
|
|
|
goto failure;
|
|
|
|
}
|
2019-10-04 12:11:52 +02:00
|
|
|
|
|
|
|
// Always allocating the max avaliable USER_RW mem on the system
|
|
|
|
SceKernelFreeMemorySizeInfo info;
|
|
|
|
info.size = sizeof(SceKernelFreeMemorySizeInfo);
|
|
|
|
sceKernelGetFreeMemorySize(&info);
|
2016-10-11 09:40:55 +02:00
|
|
|
|
2020-10-12 19:24:39 +02:00
|
|
|
printf("sceKernelGetFreeMemorySize %x\n", info.size_user);
|
|
|
|
|
2016-10-11 09:40:55 +02:00
|
|
|
if (&_newlib_heap_size_user != NULL) {
|
|
|
|
_newlib_heap_size = _newlib_heap_size_user;
|
|
|
|
}else{
|
2019-10-04 12:11:52 +02:00
|
|
|
_newlib_heap_size = info.size_user - RAM_THRESHOLD;
|
2016-10-11 09:40:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
_newlib_heap_size -= _newlib_vm_size;
|
|
|
|
|
2016-09-26 01:06:01 +02:00
|
|
|
_newlib_heap_memblock = sceKernelAllocMemBlock("Newlib heap", 0x0c20d060, _newlib_heap_size, 0);
|
|
|
|
if (_newlib_heap_memblock < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
2016-10-02 14:03:15 +02:00
|
|
|
if (sceKernelGetMemBlockBase(_newlib_heap_memblock, (void**)&_newlib_heap_base) < 0) {
|
2016-09-26 01:06:01 +02:00
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
_newlib_heap_end = _newlib_heap_base + _newlib_heap_size;
|
|
|
|
_newlib_heap_cur = _newlib_heap_base;
|
|
|
|
|
|
|
|
return;
|
|
|
|
failure:
|
|
|
|
_newlib_vm_memblock = 0;
|
|
|
|
_newlib_heap_memblock = 0;
|
|
|
|
_newlib_heap_base = 0;
|
|
|
|
_newlib_heap_cur = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int getVMBlock(){
|
|
|
|
return _newlib_vm_memblock;
|
|
|
|
}
|
|
|
|
|
|
|
|
void _free_vita_heap(void) {
|
2016-10-11 09:40:55 +02:00
|
|
|
|
2016-09-26 01:06:01 +02:00
|
|
|
// Destroy the sbrk mutex
|
2016-10-02 14:03:15 +02:00
|
|
|
sceKernelDeleteLwMutex((struct SceKernelLwMutexWork*)_newlib_sbrk_mutex);
|
2016-09-26 01:06:01 +02:00
|
|
|
|
|
|
|
// Free the heap memblock to avoid memory leakage.
|
|
|
|
sceKernelFreeMemBlock(_newlib_heap_memblock);
|
2016-10-11 09:40:55 +02:00
|
|
|
|
2022-01-25 05:19:00 +02:00
|
|
|
if (_newlib_vm_memblock > 0)
|
|
|
|
sceKernelFreeMemBlock(_newlib_vm_memblock);
|
2016-09-26 01:06:01 +02:00
|
|
|
|
|
|
|
_newlib_vm_memblock = 0;
|
|
|
|
_newlib_heap_memblock = 0;
|
|
|
|
_newlib_heap_base = 0;
|
|
|
|
_newlib_heap_cur = 0;
|
|
|
|
}
|