mirror of https://gitlab.com/nakst/essence
remove KObject
This commit is contained in:
parent
c09eb6c78e
commit
1ad024a542
|
@ -79,63 +79,22 @@ struct HandleTable {
|
||||||
bool CloseHandle(EsHandle handle);
|
bool CloseHandle(EsHandle handle);
|
||||||
void ModifyFlags(EsHandle handle, uint32_t newFlags);
|
void ModifyFlags(EsHandle handle, uint32_t newFlags);
|
||||||
|
|
||||||
// Resolve the handle if it is valid and return the type in type.
|
// Resolve the handle if it is valid.
|
||||||
// The initial value of type is used as a mask of expected object types for the handle.
|
// The initial value of type is used as a mask of expected object types for the handle.
|
||||||
void ResolveHandle(struct KObject *object, EsHandle handle);
|
#define RESOLVE_HANDLE_FAILED (0)
|
||||||
|
#define RESOLVE_HANDLE_NO_CLOSE (1)
|
||||||
|
#define RESOLVE_HANDLE_NORMAL (2)
|
||||||
|
uint8_t ResolveHandle(Handle *outHandle, EsHandle inHandle, KernelObjectType typeMask);
|
||||||
|
|
||||||
void Destroy();
|
void Destroy();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct KObject {
|
|
||||||
void Initialise(HandleTable *handleTable, EsHandle _handle, KernelObjectType _type);
|
|
||||||
|
|
||||||
KObject() { EsMemoryZero(this, sizeof(*this)); }
|
|
||||||
KObject(Process *process, EsHandle _handle, KernelObjectType _type);
|
|
||||||
KObject(HandleTable *handleTable, EsHandle _handle, KernelObjectType _type);
|
|
||||||
|
|
||||||
~KObject() {
|
|
||||||
if (!checked && valid) {
|
|
||||||
KernelPanic("KObject - Object not checked!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parentObject && close) {
|
|
||||||
CloseHandleToObject(parentObject, parentType, parentFlags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void *object, *parentObject;
|
|
||||||
uint32_t flags, parentFlags;
|
|
||||||
KernelObjectType type, parentType;
|
|
||||||
bool valid, checked, close, softFailure;
|
|
||||||
};
|
|
||||||
|
|
||||||
void InitialiseObjectManager();
|
void InitialiseObjectManager();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef IMPLEMENTATION
|
#ifdef IMPLEMENTATION
|
||||||
|
|
||||||
KObject::KObject(Process *process, EsHandle _handle, KernelObjectType _type) {
|
|
||||||
EsMemoryZero(this, sizeof(*this));
|
|
||||||
Initialise(&process->handleTable, _handle, _type);
|
|
||||||
}
|
|
||||||
|
|
||||||
KObject::KObject(HandleTable *handleTable, EsHandle _handle, KernelObjectType _type) {
|
|
||||||
EsMemoryZero(this, sizeof(*this));
|
|
||||||
Initialise(handleTable, _handle, _type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KObject::Initialise(HandleTable *handleTable, EsHandle _handle, KernelObjectType _type) {
|
|
||||||
type = _type;
|
|
||||||
|
|
||||||
handleTable->ResolveHandle(this, _handle);
|
|
||||||
parentObject = object, parentType = type, parentFlags = flags;
|
|
||||||
|
|
||||||
if (!valid) {
|
|
||||||
KernelLog(LOG_ERROR, "Object Manager", "invalid handle", "KObject::Initialise - Invalid handle %d for type mask %x.\n", _handle, _type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A lock used to change the handle count on several objects.
|
// A lock used to change the handle count on several objects.
|
||||||
// TODO Make changing handle count lockless wherever possible?
|
// TODO Make changing handle count lockless wherever possible?
|
||||||
KMutex objectHandleCountChange;
|
KMutex objectHandleCountChange;
|
||||||
|
@ -462,43 +421,48 @@ void HandleTable::ModifyFlags(EsHandle handle, uint32_t newFlags) {
|
||||||
_handle->flags = newFlags;
|
_handle->flags = newFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleTable::ResolveHandle(KObject *object, EsHandle handle) {
|
uint8_t HandleTable::ResolveHandle(Handle *outHandle, EsHandle inHandle, KernelObjectType typeMask) {
|
||||||
KernelObjectType requestedType = object->type;
|
|
||||||
object->type = COULD_NOT_RESOLVE_HANDLE;
|
|
||||||
|
|
||||||
// Special handles.
|
// Special handles.
|
||||||
if (handle == ES_CURRENT_THREAD && (requestedType & KERNEL_OBJECT_THREAD)) {
|
if (inHandle == ES_CURRENT_THREAD && (typeMask & KERNEL_OBJECT_THREAD)) {
|
||||||
object->type = KERNEL_OBJECT_THREAD, object->valid = true, object->object = GetCurrentThread();
|
outHandle->type = KERNEL_OBJECT_THREAD;
|
||||||
return;
|
outHandle->object = GetCurrentThread();
|
||||||
} else if (handle == ES_CURRENT_PROCESS && (requestedType & KERNEL_OBJECT_PROCESS)) {
|
outHandle->flags = 0;
|
||||||
object->type = KERNEL_OBJECT_PROCESS, object->valid = true, object->object = GetCurrentThread()->process;
|
return RESOLVE_HANDLE_NO_CLOSE;
|
||||||
return;
|
} else if (inHandle == ES_CURRENT_PROCESS && (typeMask & KERNEL_OBJECT_PROCESS)) {
|
||||||
} else if (handle == ES_INVALID_HANDLE && (requestedType & KERNEL_OBJECT_NONE)) {
|
outHandle->type = KERNEL_OBJECT_PROCESS;
|
||||||
object->type = KERNEL_OBJECT_NONE, object->valid = true;
|
outHandle->object = GetCurrentThread()->process;
|
||||||
return;
|
outHandle->flags = 0;
|
||||||
|
return RESOLVE_HANDLE_NO_CLOSE;
|
||||||
|
} else if (inHandle == ES_INVALID_HANDLE && (typeMask & KERNEL_OBJECT_NONE)) {
|
||||||
|
outHandle->type = KERNEL_OBJECT_NONE;
|
||||||
|
outHandle->object = nullptr;
|
||||||
|
outHandle->flags = 0;
|
||||||
|
return RESOLVE_HANDLE_NO_CLOSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the handle is within the correct bounds.
|
// Check that the handle is within the correct bounds.
|
||||||
if ((!handle) || handle >= HANDLE_TABLE_L1_ENTRIES * HANDLE_TABLE_L2_ENTRIES) {
|
if ((!inHandle) || inHandle >= HANDLE_TABLE_L1_ENTRIES * HANDLE_TABLE_L2_ENTRIES) {
|
||||||
return;
|
return RESOLVE_HANDLE_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
KMutexAcquire(&lock);
|
KMutexAcquire(&lock);
|
||||||
EsDefer(KMutexRelease(&lock));
|
EsDefer(KMutexRelease(&lock));
|
||||||
|
|
||||||
HandleTableL2 *l2 = l1r.t[handle / HANDLE_TABLE_L2_ENTRIES];
|
HandleTableL2 *l2 = l1r.t[inHandle / HANDLE_TABLE_L2_ENTRIES];
|
||||||
if (!l2) return;
|
if (!l2) return RESOLVE_HANDLE_FAILED;
|
||||||
|
|
||||||
Handle *_handle = l2->t + (handle % HANDLE_TABLE_L2_ENTRIES);
|
Handle *_handle = l2->t + (inHandle % HANDLE_TABLE_L2_ENTRIES);
|
||||||
|
|
||||||
if ((_handle->type & requestedType) && (_handle->object)) {
|
if ((_handle->type & typeMask) && (_handle->object)) {
|
||||||
// Open a handle to the object so that it can't be destroyed while the system call is still using it.
|
// Open a handle to the object so that it can't be destroyed while the system call is still using it.
|
||||||
// The handle is closed in the KObject's destructor.
|
// The handle is closed in the KObject's destructor.
|
||||||
if (OpenHandleToObject(_handle->object, _handle->type, _handle->flags)) {
|
if (OpenHandleToObject(_handle->object, _handle->type, _handle->flags)) {
|
||||||
object->type = _handle->type, object->object = _handle->object, object->flags = _handle->flags;
|
*outHandle = *_handle;
|
||||||
object->valid = object->close = true;
|
return RESOLVE_HANDLE_NORMAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return RESOLVE_HANDLE_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Switch the order of flags and type, so that the default value of flags can be 0.
|
// TODO Switch the order of flags and type, so that the default value of flags can be 0.
|
||||||
|
|
|
@ -115,7 +115,6 @@ bool MessageQueue::GetMessage(_EsMessageWithObject *_message) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHECK_OBJECT(x) if (!x.valid) SYSCALL_RETURN(ES_FATAL_ERROR_INVALID_HANDLE, !x.softFailure); else x.checked = true
|
|
||||||
#define SYSCALL_BUFFER_LIMIT (64 * 1024 * 1024) // To prevent overflow and DOS attacks.
|
#define SYSCALL_BUFFER_LIMIT (64 * 1024 * 1024) // To prevent overflow and DOS attacks.
|
||||||
#define SYSCALL_BUFFER(address, length, index, write) \
|
#define SYSCALL_BUFFER(address, length, index, write) \
|
||||||
MMRegion *_region ## index = MMFindAndPinRegion(currentVMM, (address), (length)); \
|
MMRegion *_region ## index = MMFindAndPinRegion(currentVMM, (address), (length)); \
|
||||||
|
@ -123,18 +122,18 @@ bool MessageQueue::GetMessage(_EsMessageWithObject *_message) {
|
||||||
EsDefer(if (_region ## index) MMUnpinRegion(currentVMM, _region ## index)); \
|
EsDefer(if (_region ## index) MMUnpinRegion(currentVMM, _region ## index)); \
|
||||||
if (write && (_region ## index->flags & MM_REGION_READ_ONLY) && (~_region ## index->flags & MM_REGION_COPY_ON_WRITE)) \
|
if (write && (_region ## index->flags & MM_REGION_READ_ONLY) && (~_region ## index->flags & MM_REGION_COPY_ON_WRITE)) \
|
||||||
SYSCALL_RETURN(ES_FATAL_ERROR_INVALID_BUFFER, true);
|
SYSCALL_RETURN(ES_FATAL_ERROR_INVALID_BUFFER, true);
|
||||||
#define SYSCALL_HANDLE(handle, type, __object, variableType) \
|
|
||||||
KObject ES_C_PREPROCESSOR_JOIN(_object, __LINE__)(currentProcess, handle, type); \
|
|
||||||
CHECK_OBJECT(ES_C_PREPROCESSOR_JOIN(_object, __LINE__)); \
|
|
||||||
variableType *const __object = (variableType *) (ES_C_PREPROCESSOR_JOIN(_object, __LINE__)).object
|
|
||||||
#define SYSCALL_HANDLE_2(handle, _type, out) \
|
#define SYSCALL_HANDLE_2(handle, _type, out) \
|
||||||
KObject ES_C_PREPROCESSOR_JOIN(_object, __LINE__)(currentProcess, handle, _type); \
|
Handle _ ## out; \
|
||||||
CHECK_OBJECT(ES_C_PREPROCESSOR_JOIN(_object, __LINE__)); \
|
uint8_t status_ ## out = currentProcess->handleTable.ResolveHandle(&_ ## out, handle, _type); \
|
||||||
const Handle out = { \
|
if (status_ ## out == RESOLVE_HANDLE_FAILED) SYSCALL_RETURN(ES_FATAL_ERROR_INVALID_HANDLE, true); \
|
||||||
.object = (ES_C_PREPROCESSOR_JOIN(_object, __LINE__)).object, \
|
EsDefer(if (status_ ## out == RESOLVE_HANDLE_NORMAL) CloseHandleToObject(_ ## out.object, _ ## out.type, _ ## out.flags)); \
|
||||||
.flags = (ES_C_PREPROCESSOR_JOIN(_object, __LINE__)).flags, \
|
const Handle out = _ ## out
|
||||||
.type = (ES_C_PREPROCESSOR_JOIN(_object, __LINE__)).type, \
|
#define SYSCALL_HANDLE(handle, _type, out, variableType) \
|
||||||
}
|
Handle _ ## out; \
|
||||||
|
uint8_t status_ ## out = currentProcess->handleTable.ResolveHandle(&_ ## out, handle, _type); \
|
||||||
|
if (status_ ## out == RESOLVE_HANDLE_FAILED) SYSCALL_RETURN(ES_FATAL_ERROR_INVALID_HANDLE, true); \
|
||||||
|
EsDefer(if (status_ ## out == RESOLVE_HANDLE_NORMAL) CloseHandleToObject(_ ## out.object, _ ## out.type, _ ## out.flags)); \
|
||||||
|
variableType *const out = (variableType *) _ ## out.object
|
||||||
#define SYSCALL_READ(destination, source, length) \
|
#define SYSCALL_READ(destination, source, length) \
|
||||||
if (!MMArchIsBufferInUserRange(source, length) || !MMArchSafeCopy((uintptr_t) (destination), source, length)) \
|
if (!MMArchIsBufferInUserRange(source, length) || !MMArchSafeCopy((uintptr_t) (destination), source, length)) \
|
||||||
SYSCALL_RETURN(ES_FATAL_ERROR_INVALID_BUFFER, true);
|
SYSCALL_RETURN(ES_FATAL_ERROR_INVALID_BUFFER, true);
|
||||||
|
@ -866,15 +865,22 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_WAIT) {
|
||||||
}
|
}
|
||||||
|
|
||||||
EsHandle handles[ES_MAX_WAIT_COUNT];
|
EsHandle handles[ES_MAX_WAIT_COUNT];
|
||||||
|
KEvent *events[ES_MAX_WAIT_COUNT];
|
||||||
|
Handle _objects[ES_MAX_WAIT_COUNT];
|
||||||
|
uint8_t status[ES_MAX_WAIT_COUNT];
|
||||||
|
bool handleErrors = false;
|
||||||
|
uintptr_t waitReturnValue;
|
||||||
|
|
||||||
SYSCALL_READ(handles, argument0, argument1 * sizeof(EsHandle));
|
SYSCALL_READ(handles, argument0, argument1 * sizeof(EsHandle));
|
||||||
|
|
||||||
KEvent *events[ES_MAX_WAIT_COUNT];
|
|
||||||
KObject _objects[ES_MAX_WAIT_COUNT] = {};
|
|
||||||
|
|
||||||
for (uintptr_t i = 0; i < argument1; i++) {
|
for (uintptr_t i = 0; i < argument1; i++) {
|
||||||
_objects[i].Initialise(¤tProcess->handleTable, handles[i],
|
KernelObjectType typeMask = KERNEL_OBJECT_PROCESS | KERNEL_OBJECT_THREAD | KERNEL_OBJECT_EVENT | KERNEL_OBJECT_EVENT_SINK;
|
||||||
KERNEL_OBJECT_PROCESS | KERNEL_OBJECT_THREAD | KERNEL_OBJECT_EVENT | KERNEL_OBJECT_EVENT_SINK);
|
status[i] = currentProcess->handleTable.ResolveHandle(&_objects[i], handles[i], typeMask);
|
||||||
CHECK_OBJECT(_objects[i]);
|
|
||||||
|
if (status[i] == RESOLVE_HANDLE_FAILED) {
|
||||||
|
handleErrors = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
void *object = _objects[i].object;
|
void *object = _objects[i].object;
|
||||||
|
|
||||||
|
@ -901,28 +907,39 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_WAIT) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t waitObjectCount = argument1;
|
if (!handleErrors) {
|
||||||
KTimer timer = {};
|
size_t waitObjectCount = argument1;
|
||||||
|
KTimer timer = {};
|
||||||
|
|
||||||
if (argument2 != (uintptr_t) ES_WAIT_NO_TIMEOUT) {
|
if (argument2 != (uintptr_t) ES_WAIT_NO_TIMEOUT) {
|
||||||
KTimerSet(&timer, argument2);
|
KTimerSet(&timer, argument2);
|
||||||
events[waitObjectCount++] = &timer.event;
|
events[waitObjectCount++] = &timer.event;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentThread->terminatableState = THREAD_USER_BLOCK_REQUEST;
|
||||||
|
waitReturnValue = scheduler.WaitEvents(events, waitObjectCount);
|
||||||
|
currentThread->terminatableState = THREAD_IN_SYSCALL;
|
||||||
|
|
||||||
|
if (waitReturnValue == argument1) {
|
||||||
|
waitReturnValue = ES_ERROR_TIMEOUT_REACHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argument2 != (uintptr_t) ES_WAIT_NO_TIMEOUT) {
|
||||||
|
KTimerRemove(&timer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t waitReturnValue;
|
for (uintptr_t i = 0; i < argument1; i++) {
|
||||||
currentThread->terminatableState = THREAD_USER_BLOCK_REQUEST;
|
if (status[i] == RESOLVE_HANDLE_NORMAL) {
|
||||||
waitReturnValue = scheduler.WaitEvents(events, waitObjectCount);
|
CloseHandleToObject(_objects[i].object, _objects[i].type, _objects[i].flags);
|
||||||
currentThread->terminatableState = THREAD_IN_SYSCALL;
|
}
|
||||||
|
|
||||||
if (waitReturnValue == argument1) {
|
|
||||||
waitReturnValue = ES_ERROR_TIMEOUT_REACHED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argument2 != (uintptr_t) ES_WAIT_NO_TIMEOUT) {
|
if (handleErrors) {
|
||||||
KTimerRemove(&timer);
|
SYSCALL_RETURN(ES_FATAL_ERROR_INVALID_HANDLE, true);
|
||||||
|
} else {
|
||||||
|
SYSCALL_RETURN(waitReturnValue, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_RETURN(waitReturnValue, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_IMPLEMENT(ES_SYSCALL_WINDOW_SET_CURSOR) {
|
SYSCALL_IMPLEMENT(ES_SYSCALL_WINDOW_SET_CURSOR) {
|
||||||
|
|
Loading…
Reference in New Issue