|
|
|
@ -14,32 +14,47 @@ |
|
|
|
namespace Kernel { |
|
|
|
namespace { |
|
|
|
constexpr u16 GetSlot(Handle handle) { |
|
|
|
return handle >> 15; |
|
|
|
return static_cast<u16>(handle >> 15); |
|
|
|
} |
|
|
|
|
|
|
|
constexpr u16 GetGeneration(Handle handle) { |
|
|
|
return handle & 0x7FFF; |
|
|
|
return static_cast<u16>(handle & 0x7FFF); |
|
|
|
} |
|
|
|
} // Anonymous namespace
|
|
|
|
|
|
|
|
HandleTable::HandleTable() { |
|
|
|
next_generation = 1; |
|
|
|
Clear(); |
|
|
|
} |
|
|
|
|
|
|
|
HandleTable::~HandleTable() = default; |
|
|
|
|
|
|
|
ResultCode HandleTable::SetSize(s32 handle_table_size) { |
|
|
|
if (static_cast<u32>(handle_table_size) > MAX_COUNT) { |
|
|
|
return ERR_OUT_OF_MEMORY; |
|
|
|
} |
|
|
|
|
|
|
|
// Values less than or equal to zero indicate to use the maximum allowable
|
|
|
|
// size for the handle table in the actual kernel, so we ignore the given
|
|
|
|
// value in that case, since we assume this by default unless this function
|
|
|
|
// is called.
|
|
|
|
if (handle_table_size > 0) { |
|
|
|
table_size = static_cast<u16>(handle_table_size); |
|
|
|
} |
|
|
|
|
|
|
|
return RESULT_SUCCESS; |
|
|
|
} |
|
|
|
|
|
|
|
ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) { |
|
|
|
DEBUG_ASSERT(obj != nullptr); |
|
|
|
|
|
|
|
u16 slot = next_free_slot; |
|
|
|
if (slot >= generations.size()) { |
|
|
|
const u16 slot = next_free_slot; |
|
|
|
if (slot >= table_size) { |
|
|
|
LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use."); |
|
|
|
return ERR_HANDLE_TABLE_FULL; |
|
|
|
} |
|
|
|
next_free_slot = generations[slot]; |
|
|
|
|
|
|
|
u16 generation = next_generation++; |
|
|
|
const u16 generation = next_generation++; |
|
|
|
|
|
|
|
// Overflow count so it fits in the 15 bits dedicated to the generation in the handle.
|
|
|
|
// Horizon OS uses zero to represent an invalid handle, so skip to 1.
|
|
|
|
@ -64,10 +79,11 @@ ResultVal<Handle> HandleTable::Duplicate(Handle handle) { |
|
|
|
} |
|
|
|
|
|
|
|
ResultCode HandleTable::Close(Handle handle) { |
|
|
|
if (!IsValid(handle)) |
|
|
|
if (!IsValid(handle)) { |
|
|
|
return ERR_INVALID_HANDLE; |
|
|
|
} |
|
|
|
|
|
|
|
u16 slot = GetSlot(handle); |
|
|
|
const u16 slot = GetSlot(handle); |
|
|
|
|
|
|
|
objects[slot] = nullptr; |
|
|
|
|
|
|
|
@ -77,10 +93,10 @@ ResultCode HandleTable::Close(Handle handle) { |
|
|
|
} |
|
|
|
|
|
|
|
bool HandleTable::IsValid(Handle handle) const { |
|
|
|
std::size_t slot = GetSlot(handle); |
|
|
|
u16 generation = GetGeneration(handle); |
|
|
|
const std::size_t slot = GetSlot(handle); |
|
|
|
const u16 generation = GetGeneration(handle); |
|
|
|
|
|
|
|
return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation; |
|
|
|
return slot < table_size && objects[slot] != nullptr && generations[slot] == generation; |
|
|
|
} |
|
|
|
|
|
|
|
SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const { |
|
|
|
@ -97,7 +113,7 @@ SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const { |
|
|
|
} |
|
|
|
|
|
|
|
void HandleTable::Clear() { |
|
|
|
for (u16 i = 0; i < MAX_COUNT; ++i) { |
|
|
|
for (u16 i = 0; i < table_size; ++i) { |
|
|
|
generations[i] = i + 1; |
|
|
|
objects[i] = nullptr; |
|
|
|
} |
|
|
|
|