remove event sinks

This commit is contained in:
nakst 2021-11-06 16:52:36 +00:00
parent d8906e84ab
commit 751b4652c1
7 changed files with 2 additions and 253 deletions

View File

@ -317,8 +317,6 @@ define ES_ERROR_FILE_TOO_FRAGMENTED (-54)
define ES_ERROR_DRIVE_FULL (-55)
define ES_ERROR_COULD_NOT_RESOLVE_SYMBOL (-56)
define ES_ERROR_ALREADY_EMBEDDED (-57)
define ES_ERROR_EVENT_SINK_OVERFLOW (-58)
define ES_ERROR_EVENT_SINK_DUPLICATE (-59)
define ES_ERROR_UNSUPPORTED_CONVERSION (-60)
define ES_ERROR_SOURCE_EMPTY (-61)
define ES_ERROR_UNSUPPORTED_EXECUTABLE (-62)
@ -342,8 +340,6 @@ define ES_CURRENT_PROCESS ((EsHandle) (0x11))
define ES_WAIT_NO_TIMEOUT (-1)
define ES_MAX_WAIT_COUNT (8)
define ES_MAX_EVENT_FORWARD_COUNT (4) // The maximum number of event sinks an event can be forwarded to.
define ES_MAX_EVENT_SINK_BUFFER_SIZE (256) // The maximum number of events an event sink can capture. TODO Make this configurable in EsEventSinkCreate?
define ES_MAX_DIRECTORY_CHILD_NAME_LENGTH (256)
@ -779,12 +775,8 @@ private enum EsSyscallType {
// Processing.
ES_SYSCALL_EVENT_CREATE
ES_SYSCALL_EVENT_FORWARD
ES_SYSCALL_EVENT_RESET
ES_SYSCALL_EVENT_SET
ES_SYSCALL_EVENT_SINK_CREATE
ES_SYSCALL_EVENT_SINK_POP
ES_SYSCALL_EVENT_SINK_PUSH
ES_SYSCALL_PROCESS_CRASH
ES_SYSCALL_PROCESS_CREATE
ES_SYSCALL_PROCESS_GET_STATE
@ -2218,14 +2210,9 @@ function size_t EsPipeWrite(EsHandle pipe, const void *buffer, size_t bytes);
// Synchronisation and timing.
function EsHandle EsEventCreate(bool autoReset);
function void EsEventForward(EsHandle event, EsHandle eventSink, EsGeneric data); // TODO Forwarding process/thread killed events.
function void EsEventReset(EsHandle event);
function void EsEventSet(EsHandle event);
function EsHandle EsEventSinkCreate(bool ignoreDuplicates);
function EsError EsEventSinkPop(EsHandle eventSink, EsGeneric *data); // Returns ES_ERROR_EVENT_NOT_SET if empty, and ES_ERROR_EVENT_SINK_OVERFLOW if data lost.
function EsError EsEventSinkPush(EsHandle eventSink, EsGeneric data); // Returns ES_ERROR_EVENT_SINK_DUPLICATE if duplicate, and ES_ERROR_EVENT_SINK_OVERFLOW if data lost.
function void EsMutexAcquire(EsMutex *mutex);
function void EsMutexDestroy(EsMutex *mutex);
function void EsMutexRelease(EsMutex *mutex);

View File

@ -737,23 +737,6 @@ EsError EsConnectionRead(EsConnection *connection, void *_buffer, size_t bufferB
return ES_SUCCESS;
}
void EsEventForward(EsHandle event, EsHandle eventSink, EsGeneric data) {
EsSyscall(ES_SYSCALL_EVENT_FORWARD, event, eventSink, data.u, 0);
}
EsHandle EsEventSinkCreate(bool ignoreDuplicates) {
return EsSyscall(ES_SYSCALL_EVENT_SINK_CREATE, ignoreDuplicates, 0, 0, 0);
}
EsError EsEventSinkPop(EsHandle eventSink, EsGeneric *data) {
EsGeneric unused; if (!data) data = &unused;
return EsSyscall(ES_SYSCALL_EVENT_SINK_POP, eventSink, (uintptr_t) data, 0, 0);
}
EsError EsEventSinkPush(EsHandle eventSink, EsGeneric data) {
return EsSyscall(ES_SYSCALL_EVENT_SINK_PUSH, eventSink, data.u, 0, 0);
}
size_t EsGameControllerStatePoll(EsGameControllerState *buffer) {
return EsSyscall(ES_SYSCALL_GAME_CONTROLLER_STATE_POLL, (uintptr_t) buffer, 0, 0, 0);
}

View File

@ -190,7 +190,6 @@ enum KernelObjectType : uint32_t {
#endif
KERNEL_OBJECT_PIPE = 0x00000200, // A pipe through which data can be sent between processes, blocking when full or empty.
KERNEL_OBJECT_EMBEDDED_WINDOW = 0x00000400, // An embedded window object, referencing its container Window.
KERNEL_OBJECT_EVENT_SINK = 0x00002000, // An event sink. Events can be forwarded to it, allowing waiting on many objects.
KERNEL_OBJECT_CONNECTION = 0x00004000, // A network connection.
KERNEL_OBJECT_DEVICE = 0x00008000, // A device.
};
@ -267,15 +266,11 @@ void KMutexRelease(KMutex *mutex);
void KMutexAssertLocked(KMutex *mutex);
struct KEvent { // Waiting and notifying. Can wait on multiple at once. Can be set and reset with interrupts disabled.
volatile bool autoReset; // This should be first field in the structure,
// so that the type of KEvent can be easily declared with {autoReset}.
volatile bool autoReset; // This should be first field in the structure, so that the type of KEvent can be easily declared with {autoReset}.
volatile uintptr_t state;
K_PRIVATE
LinkedList<Thread> blockedThreads;
volatile size_t handles;
struct EventSinkTable *sinkTable;
};
bool KEventSet(KEvent *event, bool schedulerAlreadyLocked = false, bool maybeAlreadySet = false);

View File

@ -34,23 +34,6 @@ struct Pipe {
size_t Access(void *buffer, size_t bytes, bool write, bool userBlockRequest);
};
struct EventSink {
KEvent available;
KSpinlock spinlock; // Take after the scheduler's spinlock.
volatile size_t handles;
uintptr_t queuePosition;
size_t queueCount;
bool overflow, ignoreDuplicates;
EsGeneric queue[ES_MAX_EVENT_SINK_BUFFER_SIZE];
EsError Push(EsGeneric data);
};
struct EventSinkTable {
EventSink *sink;
EsGeneric data;
};
struct MessageQueue {
bool SendMessage(void *target, EsMessage *message); // Returns false if the message queue is full.
bool SendMessage(_EsMessageWithObject *message); // Returns false if the message queue is full.
@ -210,14 +193,6 @@ bool OpenHandleToObject(void *object, KernelObjectType type, uint32_t flags, boo
KMutexRelease(&pipe->mutex);
} break;
case KERNEL_OBJECT_EVENT_SINK: {
EventSink *sink = (EventSink *) object;
KSpinlockAcquire(&sink->spinlock);
if (!sink->handles) hadNoHandles = true;
else sink->handles++;
KSpinlockRelease(&sink->spinlock);
} break;
case KERNEL_OBJECT_CONNECTION: {
NetConnection *connection = (NetConnection *) object;
hadNoHandles = 0 == __sync_fetch_and_add(&connection->handles, 1);
@ -275,16 +250,6 @@ void CloseHandleToObject(void *object, KernelObjectType type, uint32_t flags) {
KMutexRelease(&objectHandleCountChange);
if (destroy) {
if (event->sinkTable) {
for (uintptr_t i = 0; i < ES_MAX_EVENT_FORWARD_COUNT; i++) {
if (event->sinkTable[i].sink) {
CloseHandleToObject(event->sinkTable[i].sink, KERNEL_OBJECT_EVENT_SINK, 0);
}
}
EsHeapFree(event->sinkTable, sizeof(EventSinkTable) * ES_MAX_EVENT_FORWARD_COUNT, K_FIXED);
}
EsHeapFree(event, sizeof(KEvent), K_FIXED);
}
} break;
@ -386,18 +351,6 @@ void CloseHandleToObject(void *object, KernelObjectType type, uint32_t flags) {
}
} break;
case KERNEL_OBJECT_EVENT_SINK: {
EventSink *sink = (EventSink *) object;
KSpinlockAcquire(&sink->spinlock);
bool destroy = sink->handles == 1;
sink->handles--;
KSpinlockRelease(&sink->spinlock);
if (destroy) {
EsHeapFree(sink, sizeof(EventSink), K_FIXED);
}
} break;
case KERNEL_OBJECT_CONNECTION: {
NetConnection *connection = (NetConnection *) object;
unsigned previous = __sync_fetch_and_sub(&connection->handles, 1);

View File

@ -314,55 +314,6 @@ void KSemaphoreSet(KSemaphore *semaphore, uintptr_t u) {
KMutexRelease(&semaphore->mutex);
}
EsError EventSink::Push(EsGeneric data) {
EsError result = ES_SUCCESS;
KSpinlockAssertLocked(&scheduler.lock);
KSpinlockAcquire(&spinlock);
if (queueCount == ES_MAX_EVENT_SINK_BUFFER_SIZE) {
overflow = true;
result = ES_ERROR_EVENT_SINK_OVERFLOW;
KernelLog(LOG_VERBOSE, "Event Sinks", "push overflow", "Push %d into %x.\n", data.i, this);
} else {
bool ignored = false;
if (ignoreDuplicates) {
uintptr_t index = queuePosition;
for (uintptr_t i = 0; i < queueCount; i++) {
if (queue[index] == data) {
ignored = true;
result = ES_ERROR_EVENT_SINK_DUPLICATE;
KernelLog(LOG_VERBOSE, "Event Sinks", "push ignored", "Push %d into %x.\n", data.i, this);
break;
}
index++;
if (index == ES_MAX_EVENT_SINK_BUFFER_SIZE) {
index = 0;
}
}
}
if (!ignored) {
uintptr_t writeIndex = queuePosition + queueCount;
if (writeIndex >= ES_MAX_EVENT_SINK_BUFFER_SIZE) writeIndex -= ES_MAX_EVENT_SINK_BUFFER_SIZE;
if (writeIndex >= ES_MAX_EVENT_SINK_BUFFER_SIZE) KernelPanic("EventSink::Push - Invalid event sink (%x) queue.\n", this);
KernelLog(LOG_VERBOSE, "Event Sinks", "push", "Push %d into %x at %d (%d/%d).\n", data.i, this, writeIndex, queuePosition, queueCount);
queue[writeIndex] = data;
queueCount++;
KEventSet(&available, true, true);
}
}
KSpinlockRelease(&spinlock);
return result;
}
bool KEventSet(KEvent *event, bool schedulerAlreadyLocked, bool maybeAlreadySet) {
if (event->state && !maybeAlreadySet) {
KernelLog(LOG_ERROR, "Synchronisation", "event already set", "KEvent::Set - Attempt to set a event that had already been set\n");
@ -377,13 +328,6 @@ bool KEventSet(KEvent *event, bool schedulerAlreadyLocked, bool maybeAlreadySet)
volatile bool unblockedThreads = false;
if (!event->state) {
if (event->sinkTable) {
for (uintptr_t i = 0; i < ES_MAX_EVENT_FORWARD_COUNT; i++) {
if (!event->sinkTable[i].sink) continue;
event->sinkTable[i].sink->Push(event->sinkTable[i].data);
}
}
event->state = true;
if (scheduler.started) {

View File

@ -806,7 +806,7 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_WAIT) {
SYSCALL_READ(handles, argument0, argument1 * sizeof(EsHandle));
for (uintptr_t i = 0; i < argument1; i++) {
KernelObjectType typeMask = KERNEL_OBJECT_PROCESS | KERNEL_OBJECT_THREAD | KERNEL_OBJECT_EVENT | KERNEL_OBJECT_EVENT_SINK;
KernelObjectType typeMask = KERNEL_OBJECT_PROCESS | KERNEL_OBJECT_THREAD | KERNEL_OBJECT_EVENT;
status[i] = currentProcess->handleTable.ResolveHandle(&_objects[i], handles[i], typeMask);
if (status[i] == RESOLVE_HANDLE_FAILED) {
@ -825,10 +825,6 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_WAIT) {
events[i] = &((Thread *) object)->killedEvent;
} break;
case KERNEL_OBJECT_EVENT_SINK: {
events[i] = &((EventSink *) object)->available;
} break;
case KERNEL_OBJECT_EVENT: {
events[i] = (KEvent *) object;
} break;
@ -1464,111 +1460,6 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_PIPE_WRITE) {
SYSCALL_RETURN(pipe->Access((void *) argument1, argument2, true, true), false);
}
SYSCALL_IMPLEMENT(ES_SYSCALL_EVENT_SINK_CREATE) {
EventSink *sink = (EventSink *) EsHeapAllocate(sizeof(EventSink), true, K_FIXED);
if (!sink) {
SYSCALL_RETURN(ES_ERROR_INSUFFICIENT_RESOURCES, false);
}
sink->ignoreDuplicates = argument0;
sink->handles = 1;
SYSCALL_RETURN(currentProcess->handleTable.OpenHandle(sink, 0, KERNEL_OBJECT_EVENT_SINK), false);
}
SYSCALL_IMPLEMENT(ES_SYSCALL_EVENT_FORWARD) {
SYSCALL_HANDLE(argument0, KERNEL_OBJECT_EVENT, event, KEvent);
SYSCALL_HANDLE(argument1, KERNEL_OBJECT_EVENT_SINK, sink, EventSink);
EsGeneric data = argument2;
bool error = false, limitExceeded = false;
KMutexAcquire(&eventForwardMutex);
if (!event->sinkTable) {
event->sinkTable = (EventSinkTable *) EsHeapAllocate(sizeof(EventSinkTable) * ES_MAX_EVENT_FORWARD_COUNT, true, K_FIXED);
if (!event->sinkTable) {
error = true;
}
}
if (!error) {
limitExceeded = true;
for (uintptr_t i = 0; i < ES_MAX_EVENT_FORWARD_COUNT; i++) {
if (!event->sinkTable[i].sink) {
if (!OpenHandleToObject(sink, KERNEL_OBJECT_EVENT_SINK, 0, false)) {
error = true;
break;
}
KSpinlockAcquire(&scheduler.lock);
event->sinkTable[i].sink = sink;
event->sinkTable[i].data = data;
KSpinlockRelease(&scheduler.lock);
limitExceeded = false;
break;
}
}
}
KMutexRelease(&eventForwardMutex);
if (limitExceeded) {
SYSCALL_RETURN(ES_FATAL_ERROR_OUT_OF_RANGE, true);
} else if (error) {
SYSCALL_RETURN(ES_ERROR_INSUFFICIENT_RESOURCES, false);
} else {
SYSCALL_RETURN(0, false);
}
}
SYSCALL_IMPLEMENT(ES_SYSCALL_EVENT_SINK_POP) {
SYSCALL_HANDLE(argument0, KERNEL_OBJECT_EVENT_SINK, sink, EventSink);
bool empty = false, overflow = false;
EsGeneric data = {};
KSpinlockAcquire(&sink->spinlock);
if (!sink->queueCount) {
if (sink->overflow) {
overflow = true;
sink->overflow = false;
} else {
empty = true;
}
} else {
data = sink->queue[sink->queuePosition];
sink->queuePosition++;
sink->queueCount--;
if (sink->queuePosition == ES_MAX_EVENT_SINK_BUFFER_SIZE) {
sink->queuePosition = 0;
}
}
if (!sink->queueCount && !sink->overflow) {
KEventReset(&sink->available); // KEvent::Reset doesn't take the scheduler lock, so this won't deadlock!
}
KSpinlockRelease(&sink->spinlock);
SYSCALL_WRITE(argument1, &data, sizeof(EsGeneric));
SYSCALL_RETURN(overflow ? ES_ERROR_EVENT_SINK_OVERFLOW : empty ? ES_ERROR_EVENT_NOT_SET : ES_SUCCESS, false);
}
SYSCALL_IMPLEMENT(ES_SYSCALL_EVENT_SINK_PUSH) {
SYSCALL_HANDLE(argument0, KERNEL_OBJECT_EVENT_SINK, sink, EventSink);
KSpinlockAcquire(&scheduler.lock);
EsError result = sink->Push(argument1);
KSpinlockRelease(&scheduler.lock);
SYSCALL_RETURN(result, false);
}
SYSCALL_IMPLEMENT(ES_SYSCALL_DOMAIN_NAME_RESOLVE) {
SYSCALL_PERMISSION(ES_PERMISSION_NETWORKING);

View File

@ -131,13 +131,9 @@ EsPipeRead=129
EsListViewInsert=130
EsListViewRemove=131
EsEventCreate=132
EsEventForward=133
EsBufferFormat=134
EsEventReset=135
EsEventSet=136
EsEventSinkCreate=137
EsEventSinkPop=138
EsEventSinkPush=139
EsMutexAcquire=140
EsMutexDestroy=141
EsMutexRelease=142