2015-08-02 04:15:49 +02:00
|
|
|
#include "stdafx.h"
|
|
|
|
|
#include "Emu/System.h"
|
2015-08-13 18:39:35 +02:00
|
|
|
#include "Emu/IdManager.h"
|
2016-03-21 20:42:14 +01:00
|
|
|
#include "Emu/Cell/PPUModule.h"
|
2015-08-02 04:15:49 +02:00
|
|
|
|
|
|
|
|
#include "sysPrxForUser.h"
|
|
|
|
|
|
2016-03-21 20:42:14 +01:00
|
|
|
extern _log::channel sysPrxForUser;
|
2015-08-02 04:15:49 +02:00
|
|
|
|
2015-08-13 18:39:35 +02:00
|
|
|
using sys_mempool_t = u32;
|
|
|
|
|
|
|
|
|
|
struct memory_pool_t
|
|
|
|
|
{
|
|
|
|
|
vm::ptr<void> chunk;
|
|
|
|
|
u64 chunk_size;
|
|
|
|
|
u64 block_size;
|
|
|
|
|
u64 ralignment;
|
|
|
|
|
std::vector<vm::ptr<void>> free_blocks;
|
|
|
|
|
};
|
|
|
|
|
|
2015-08-02 04:15:49 +02:00
|
|
|
s32 sys_mempool_allocate_block()
|
|
|
|
|
{
|
|
|
|
|
throw EXCEPTION("");
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-13 18:39:35 +02:00
|
|
|
s32 sys_mempool_create(vm::ptr<sys_mempool_t> mempool, vm::ptr<void> chunk, const u64 chunk_size, const u64 block_size, const u64 ralignment)
|
2015-08-02 04:15:49 +02:00
|
|
|
{
|
2016-01-12 22:57:16 +01:00
|
|
|
sysPrxForUser.warning("sys_mempool_create(mempool=*0x%x, chunk=*0x%x, chunk_size=%d, block_size=%d, ralignment=%d)", mempool, chunk, chunk_size, block_size, ralignment);
|
2015-08-13 18:39:35 +02:00
|
|
|
|
|
|
|
|
if (block_size > chunk_size)
|
|
|
|
|
{
|
2015-08-14 09:48:26 +02:00
|
|
|
return CELL_EINVAL;
|
2015-08-13 18:39:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u64 alignment = ralignment;
|
|
|
|
|
if (ralignment == 0 || ralignment == 2)
|
|
|
|
|
{
|
|
|
|
|
alignment = 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if alignment is power of two
|
|
|
|
|
if ((alignment & (alignment - 1)) != 0)
|
|
|
|
|
{
|
2015-08-14 09:48:26 +02:00
|
|
|
return CELL_EINVAL;
|
2015-08-13 18:39:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Test chunk address aligment
|
2015-08-14 09:48:26 +02:00
|
|
|
if (chunk % 8)
|
2015-08-13 18:39:35 +02:00
|
|
|
{
|
2015-08-14 09:48:26 +02:00
|
|
|
return CELL_EINVAL;
|
2015-08-13 18:39:35 +02:00
|
|
|
}
|
|
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
auto id = idm::make<memory_pool_t>();
|
2015-08-14 09:48:26 +02:00
|
|
|
*mempool = id;
|
|
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
auto memory_pool = idm::get<memory_pool_t>(id);
|
2015-08-13 18:39:35 +02:00
|
|
|
|
|
|
|
|
memory_pool->chunk = chunk;
|
|
|
|
|
memory_pool->chunk_size = chunk_size;
|
|
|
|
|
memory_pool->block_size = block_size;
|
|
|
|
|
memory_pool->ralignment = alignment;
|
|
|
|
|
|
|
|
|
|
// TODO: check blocks alignment wrt ralignment
|
|
|
|
|
u64 num_blocks = chunk_size / block_size;
|
2015-08-14 09:48:26 +02:00
|
|
|
memory_pool->free_blocks.resize(num_blocks);
|
2015-08-13 18:39:35 +02:00
|
|
|
for (int i = 0; i < num_blocks; ++i)
|
|
|
|
|
{
|
2015-08-14 09:48:26 +02:00
|
|
|
memory_pool->free_blocks[i] = vm::ptr<void>::make(chunk.addr() + i * block_size);
|
2015-08-13 18:39:35 +02:00
|
|
|
}
|
2015-08-14 09:48:26 +02:00
|
|
|
|
2015-08-13 18:39:35 +02:00
|
|
|
return CELL_OK;
|
2015-08-02 04:15:49 +02:00
|
|
|
}
|
|
|
|
|
|
2015-08-13 18:39:35 +02:00
|
|
|
void sys_mempool_destroy(sys_mempool_t mempool)
|
2015-08-02 04:15:49 +02:00
|
|
|
{
|
2016-01-12 22:57:16 +01:00
|
|
|
sysPrxForUser.warning("sys_mempool_destroy(mempool=%d)", mempool);
|
2015-08-13 18:39:35 +02:00
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
idm::remove<memory_pool_t>(mempool);
|
2015-08-02 04:15:49 +02:00
|
|
|
}
|
|
|
|
|
|
2015-08-13 18:39:35 +02:00
|
|
|
s32 sys_mempool_free_block(sys_mempool_t mempool, vm::ptr<void> block)
|
2015-08-02 04:15:49 +02:00
|
|
|
{
|
2016-01-12 22:57:16 +01:00
|
|
|
sysPrxForUser.warning("sys_mempool_free_block(mempool=%d, block=*0x%x)", mempool, block);
|
2015-08-13 18:39:35 +02:00
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
auto memory_pool = idm::get<memory_pool_t>(mempool);
|
2015-08-13 18:39:35 +02:00
|
|
|
if (!memory_pool)
|
|
|
|
|
{
|
2015-08-14 09:48:26 +02:00
|
|
|
return CELL_EINVAL;
|
2015-08-13 18:39:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Cannot free a block not belonging to this memory pool
|
|
|
|
|
if (block.addr() > memory_pool->chunk.addr() + memory_pool->chunk_size)
|
|
|
|
|
{
|
2015-08-14 09:48:26 +02:00
|
|
|
return CELL_EINVAL;
|
2015-08-13 18:39:35 +02:00
|
|
|
}
|
|
|
|
|
memory_pool->free_blocks.push_back(block);
|
|
|
|
|
return CELL_OK;
|
2015-08-02 04:15:49 +02:00
|
|
|
}
|
|
|
|
|
|
2015-08-14 09:48:26 +02:00
|
|
|
u64 sys_mempool_get_count(sys_mempool_t mempool)
|
2015-08-02 04:15:49 +02:00
|
|
|
{
|
2016-01-12 22:57:16 +01:00
|
|
|
sysPrxForUser.warning("sys_mempool_get_count(mempool=%d)", mempool);
|
2015-08-13 18:39:35 +02:00
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
auto memory_pool = idm::get<memory_pool_t>(mempool);
|
2015-08-13 18:39:35 +02:00
|
|
|
if (!memory_pool)
|
|
|
|
|
{
|
2015-08-14 09:48:26 +02:00
|
|
|
return CELL_EINVAL;
|
2015-08-13 18:39:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return memory_pool->free_blocks.size();
|
2015-08-02 04:15:49 +02:00
|
|
|
}
|
|
|
|
|
|
2015-08-13 18:39:35 +02:00
|
|
|
vm::ptr<void> sys_mempool_try_allocate_block(sys_mempool_t mempool)
|
2015-08-02 04:15:49 +02:00
|
|
|
{
|
2016-01-12 22:57:16 +01:00
|
|
|
sysPrxForUser.warning("sys_mempool_try_allocate_block(mempool=%d)", mempool);
|
2015-08-13 18:39:35 +02:00
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
auto memory_pool = idm::get<memory_pool_t>(mempool);
|
2015-08-13 18:39:35 +02:00
|
|
|
|
|
|
|
|
if (!memory_pool || memory_pool->free_blocks.size() == 0)
|
|
|
|
|
{
|
|
|
|
|
return vm::null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto block_ptr = memory_pool->free_blocks.back();
|
|
|
|
|
memory_pool->free_blocks.pop_back();
|
|
|
|
|
return block_ptr;
|
2015-08-02 04:15:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void sysPrxForUser_sys_mempool_init()
|
|
|
|
|
{
|
|
|
|
|
REG_FUNC(sysPrxForUser, sys_mempool_allocate_block);
|
|
|
|
|
REG_FUNC(sysPrxForUser, sys_mempool_create);
|
|
|
|
|
REG_FUNC(sysPrxForUser, sys_mempool_destroy);
|
|
|
|
|
REG_FUNC(sysPrxForUser, sys_mempool_free_block);
|
|
|
|
|
REG_FUNC(sysPrxForUser, sys_mempool_get_count);
|
|
|
|
|
REG_FUNC(sysPrxForUser, sys_mempool_try_allocate_block);
|
|
|
|
|
}
|