From 751b4652c168441d7fbe93b9429ad257779bc037 Mon Sep 17 00:00:00 2001
From: nakst <>
Date: Sat, 6 Nov 2021 16:52:36 +0000
Subject: [PATCH] remove event sinks

---
 desktop/os.header          |  13 -----
 desktop/syscall.cpp        |  17 ------
 kernel/module.h            |   7 +--
 kernel/objects.cpp         |  47 ----------------
 kernel/synchronisation.cpp |  56 -------------------
 kernel/syscall.cpp         | 111 +------------------------------------
 util/api_table.ini         |   4 --
 7 files changed, 2 insertions(+), 253 deletions(-)

diff --git a/desktop/os.header b/desktop/os.header
index 1954fab..6ef1a39 100644
--- a/desktop/os.header
+++ b/desktop/os.header
@@ -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); 
diff --git a/desktop/syscall.cpp b/desktop/syscall.cpp
index ab9d991..78182d2 100644
--- a/desktop/syscall.cpp
+++ b/desktop/syscall.cpp
@@ -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);
 }
diff --git a/kernel/module.h b/kernel/module.h
index e4e1600..461380b 100644
--- a/kernel/module.h
+++ b/kernel/module.h
@@ -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);
diff --git a/kernel/objects.cpp b/kernel/objects.cpp
index b00d16d..5be0e58 100644
--- a/kernel/objects.cpp
+++ b/kernel/objects.cpp
@@ -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);
diff --git a/kernel/synchronisation.cpp b/kernel/synchronisation.cpp
index f2ef8d4..19889d9 100644
--- a/kernel/synchronisation.cpp
+++ b/kernel/synchronisation.cpp
@@ -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) {
diff --git a/kernel/syscall.cpp b/kernel/syscall.cpp
index 4e32edb..9e0d002 100644
--- a/kernel/syscall.cpp
+++ b/kernel/syscall.cpp
@@ -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);
 
diff --git a/util/api_table.ini b/util/api_table.ini
index 5f52703..5ad7a8c 100644
--- a/util/api_table.ini
+++ b/util/api_table.ini
@@ -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