diff --git a/src/include/hlib.h b/src/include/hlib.h index 6b27b81..fa51e95 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -26,7 +26,7 @@ extern uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, uint32_t parameter2, uint32_t parameter3); -extern void fireEvent(uint32_t eventId); +extern void fireEvent(uint32_t eventId, uint32_t data); extern void subscribeEvent(uint32_t service, uint32_t event, void(handler)(void *, uint32_t)); extern uint32_t getEvent(uint32_t service, char *name); @@ -48,6 +48,8 @@ extern bool stackContains(uint32_t serviceId); +extern uint32_t await(uint32_t service, uint32_t event); + #define MAX(x, y) (x > y ? (x) : (y)) #endif diff --git a/src/include/hlib.h b/src/include/hlib.h index 6b27b81..fa51e95 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -26,7 +26,7 @@ extern uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, uint32_t parameter2, uint32_t parameter3); -extern void fireEvent(uint32_t eventId); +extern void fireEvent(uint32_t eventId, uint32_t data); extern void subscribeEvent(uint32_t service, uint32_t event, void(handler)(void *, uint32_t)); extern uint32_t getEvent(uint32_t service, char *name); @@ -48,6 +48,8 @@ extern bool stackContains(uint32_t serviceId); +extern uint32_t await(uint32_t service, uint32_t event); + #define MAX(x, y) (x > y ? (x) : (y)) #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 8395e6c..bf22f17 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -28,6 +28,7 @@ typedef struct { char *name; ListElement *subscriptions; + ListElement *waitingSyscalls; } Event; extern ListElement *services; diff --git a/src/include/hlib.h b/src/include/hlib.h index 6b27b81..fa51e95 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -26,7 +26,7 @@ extern uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, uint32_t parameter2, uint32_t parameter3); -extern void fireEvent(uint32_t eventId); +extern void fireEvent(uint32_t eventId, uint32_t data); extern void subscribeEvent(uint32_t service, uint32_t event, void(handler)(void *, uint32_t)); extern uint32_t getEvent(uint32_t service, char *name); @@ -48,6 +48,8 @@ extern bool stackContains(uint32_t serviceId); +extern uint32_t await(uint32_t service, uint32_t event); + #define MAX(x, y) (x > y ? (x) : (y)) #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 8395e6c..bf22f17 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -28,6 +28,7 @@ typedef struct { char *name; ListElement *subscriptions; + ListElement *waitingSyscalls; } Event; extern ListElement *services; diff --git a/src/kernel/service/eventSyscalls.c b/src/kernel/service/eventSyscalls.c index 1219142..28a4c51 100644 --- a/src/kernel/service/eventSyscalls.c +++ b/src/kernel/service/eventSyscalls.c @@ -40,7 +40,7 @@ void handleFireEventSyscall(Syscall *call) { Service *service = call->service; Event *event = listGet(service->events, call->parameters[0]); - fireEvent(event, 0); + fireEvent(event, call->parameters[1]); } void handleSubscribeEventSyscall(Syscall *call) { @@ -58,3 +58,15 @@ provider->address = PTR(call->parameters[2]); listAdd(&event->subscriptions, provider); } + +void handleAwaitSyscall(Syscall *call) { + call->avoidReschedule = true; + ListElement *list = kernelEvents; + if (call->parameters[0]) { + // given another service as the target + Service *eventService = listGet(services, call->parameters[0]); + list = eventService->events; + } + Event *event = listGet(list, call->parameters[1]); + listAdd(&event->waitingSyscalls, call); +} diff --git a/src/include/hlib.h b/src/include/hlib.h index 6b27b81..fa51e95 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -26,7 +26,7 @@ extern uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, uint32_t parameter2, uint32_t parameter3); -extern void fireEvent(uint32_t eventId); +extern void fireEvent(uint32_t eventId, uint32_t data); extern void subscribeEvent(uint32_t service, uint32_t event, void(handler)(void *, uint32_t)); extern uint32_t getEvent(uint32_t service, char *name); @@ -48,6 +48,8 @@ extern bool stackContains(uint32_t serviceId); +extern uint32_t await(uint32_t service, uint32_t event); + #define MAX(x, y) (x > y ? (x) : (y)) #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 8395e6c..bf22f17 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -28,6 +28,7 @@ typedef struct { char *name; ListElement *subscriptions; + ListElement *waitingSyscalls; } Event; extern ListElement *services; diff --git a/src/kernel/service/eventSyscalls.c b/src/kernel/service/eventSyscalls.c index 1219142..28a4c51 100644 --- a/src/kernel/service/eventSyscalls.c +++ b/src/kernel/service/eventSyscalls.c @@ -40,7 +40,7 @@ void handleFireEventSyscall(Syscall *call) { Service *service = call->service; Event *event = listGet(service->events, call->parameters[0]); - fireEvent(event, 0); + fireEvent(event, call->parameters[1]); } void handleSubscribeEventSyscall(Syscall *call) { @@ -58,3 +58,15 @@ provider->address = PTR(call->parameters[2]); listAdd(&event->subscriptions, provider); } + +void handleAwaitSyscall(Syscall *call) { + call->avoidReschedule = true; + ListElement *list = kernelEvents; + if (call->parameters[0]) { + // given another service as the target + Service *eventService = listGet(services, call->parameters[0]); + list = eventService->events; + } + Event *event = listGet(list, call->parameters[1]); + listAdd(&event->waitingSyscalls, call); +} diff --git a/src/kernel/service/events.c b/src/kernel/service/events.c index 35f5827..618f152 100644 --- a/src/kernel/service/events.c +++ b/src/kernel/service/events.c @@ -13,10 +13,21 @@ return event; } +extern ListElement *callsToProcess; + void fireEvent(Event *event, uint32_t data) { foreach (event->subscriptions, ServiceFunction *, function, { scheduleFunction(function, NULL, data); }) ; + for (ListElement *current = event->waitingSyscalls; current;) { + Syscall *call = current->data; + call->returnValue = data; + listAdd(&callsToProcess, call); + ListElement *old = current; + current = current->next; + free(old); + } + event->waitingSyscalls = NULL; } void installKernelEvents() { diff --git a/src/include/hlib.h b/src/include/hlib.h index 6b27b81..fa51e95 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -26,7 +26,7 @@ extern uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, uint32_t parameter2, uint32_t parameter3); -extern void fireEvent(uint32_t eventId); +extern void fireEvent(uint32_t eventId, uint32_t data); extern void subscribeEvent(uint32_t service, uint32_t event, void(handler)(void *, uint32_t)); extern uint32_t getEvent(uint32_t service, char *name); @@ -48,6 +48,8 @@ extern bool stackContains(uint32_t serviceId); +extern uint32_t await(uint32_t service, uint32_t event); + #define MAX(x, y) (x > y ? (x) : (y)) #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 8395e6c..bf22f17 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -28,6 +28,7 @@ typedef struct { char *name; ListElement *subscriptions; + ListElement *waitingSyscalls; } Event; extern ListElement *services; diff --git a/src/kernel/service/eventSyscalls.c b/src/kernel/service/eventSyscalls.c index 1219142..28a4c51 100644 --- a/src/kernel/service/eventSyscalls.c +++ b/src/kernel/service/eventSyscalls.c @@ -40,7 +40,7 @@ void handleFireEventSyscall(Syscall *call) { Service *service = call->service; Event *event = listGet(service->events, call->parameters[0]); - fireEvent(event, 0); + fireEvent(event, call->parameters[1]); } void handleSubscribeEventSyscall(Syscall *call) { @@ -58,3 +58,15 @@ provider->address = PTR(call->parameters[2]); listAdd(&event->subscriptions, provider); } + +void handleAwaitSyscall(Syscall *call) { + call->avoidReschedule = true; + ListElement *list = kernelEvents; + if (call->parameters[0]) { + // given another service as the target + Service *eventService = listGet(services, call->parameters[0]); + list = eventService->events; + } + Event *event = listGet(list, call->parameters[1]); + listAdd(&event->waitingSyscalls, call); +} diff --git a/src/kernel/service/events.c b/src/kernel/service/events.c index 35f5827..618f152 100644 --- a/src/kernel/service/events.c +++ b/src/kernel/service/events.c @@ -13,10 +13,21 @@ return event; } +extern ListElement *callsToProcess; + void fireEvent(Event *event, uint32_t data) { foreach (event->subscriptions, ServiceFunction *, function, { scheduleFunction(function, NULL, data); }) ; + for (ListElement *current = event->waitingSyscalls; current;) { + Syscall *call = current->data; + call->returnValue = data; + listAdd(&callsToProcess, call); + ListElement *old = current; + current = current->next; + free(old); + } + event->waitingSyscalls = NULL; } void installKernelEvents() { diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index 5133cde..4b1dce0 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -70,6 +70,7 @@ extern uintptr_t handleRequestMemorySyscall; extern uintptr_t handleLookupSymbolSyscall; extern uintptr_t handleStackContainsSyscall; +extern uintptr_t handleAwaitSyscall; void (*syscallHandlers[])(Syscall *) = { 0, @@ -93,6 +94,10 @@ (void *)&handleRequestMemorySyscall, (void *)&handleLookupSymbolSyscall, (void *)&handleStackContainsSyscall, + (void *)&handleAwaitSyscall, + 0, + 0, + 0, }; void processSyscall(Syscall *call) { diff --git a/src/include/hlib.h b/src/include/hlib.h index 6b27b81..fa51e95 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -26,7 +26,7 @@ extern uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, uint32_t parameter2, uint32_t parameter3); -extern void fireEvent(uint32_t eventId); +extern void fireEvent(uint32_t eventId, uint32_t data); extern void subscribeEvent(uint32_t service, uint32_t event, void(handler)(void *, uint32_t)); extern uint32_t getEvent(uint32_t service, char *name); @@ -48,6 +48,8 @@ extern bool stackContains(uint32_t serviceId); +extern uint32_t await(uint32_t service, uint32_t event); + #define MAX(x, y) (x > y ? (x) : (y)) #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 8395e6c..bf22f17 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -28,6 +28,7 @@ typedef struct { char *name; ListElement *subscriptions; + ListElement *waitingSyscalls; } Event; extern ListElement *services; diff --git a/src/kernel/service/eventSyscalls.c b/src/kernel/service/eventSyscalls.c index 1219142..28a4c51 100644 --- a/src/kernel/service/eventSyscalls.c +++ b/src/kernel/service/eventSyscalls.c @@ -40,7 +40,7 @@ void handleFireEventSyscall(Syscall *call) { Service *service = call->service; Event *event = listGet(service->events, call->parameters[0]); - fireEvent(event, 0); + fireEvent(event, call->parameters[1]); } void handleSubscribeEventSyscall(Syscall *call) { @@ -58,3 +58,15 @@ provider->address = PTR(call->parameters[2]); listAdd(&event->subscriptions, provider); } + +void handleAwaitSyscall(Syscall *call) { + call->avoidReschedule = true; + ListElement *list = kernelEvents; + if (call->parameters[0]) { + // given another service as the target + Service *eventService = listGet(services, call->parameters[0]); + list = eventService->events; + } + Event *event = listGet(list, call->parameters[1]); + listAdd(&event->waitingSyscalls, call); +} diff --git a/src/kernel/service/events.c b/src/kernel/service/events.c index 35f5827..618f152 100644 --- a/src/kernel/service/events.c +++ b/src/kernel/service/events.c @@ -13,10 +13,21 @@ return event; } +extern ListElement *callsToProcess; + void fireEvent(Event *event, uint32_t data) { foreach (event->subscriptions, ServiceFunction *, function, { scheduleFunction(function, NULL, data); }) ; + for (ListElement *current = event->waitingSyscalls; current;) { + Syscall *call = current->data; + call->returnValue = data; + listAdd(&callsToProcess, call); + ListElement *old = current; + current = current->next; + free(old); + } + event->waitingSyscalls = NULL; } void installKernelEvents() { diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index 5133cde..4b1dce0 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -70,6 +70,7 @@ extern uintptr_t handleRequestMemorySyscall; extern uintptr_t handleLookupSymbolSyscall; extern uintptr_t handleStackContainsSyscall; +extern uintptr_t handleAwaitSyscall; void (*syscallHandlers[])(Syscall *) = { 0, @@ -93,6 +94,10 @@ (void *)&handleRequestMemorySyscall, (void *)&handleLookupSymbolSyscall, (void *)&handleStackContainsSyscall, + (void *)&handleAwaitSyscall, + 0, + 0, + 0, }; void processSyscall(Syscall *call) { diff --git a/src/userland/crashTest/main.c b/src/userland/crashTest/main.c index 375b198..7142285 100644 --- a/src/userland/crashTest/main.c +++ b/src/userland/crashTest/main.c @@ -6,7 +6,9 @@ void testFunction() { printf("0/0 = %i\n", 0 / 0); } int32_t main() { - printf("trying to divide by zero now . . .\n"); + printf("trying to divide by zero whenever you press a key...\n"); + uint32_t ioManager = getService("ioManager"); + await(ioManager, getEvent(ioManager, "keyPress")); testFunction(); return 0; } diff --git a/src/include/hlib.h b/src/include/hlib.h index 6b27b81..fa51e95 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -26,7 +26,7 @@ extern uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, uint32_t parameter2, uint32_t parameter3); -extern void fireEvent(uint32_t eventId); +extern void fireEvent(uint32_t eventId, uint32_t data); extern void subscribeEvent(uint32_t service, uint32_t event, void(handler)(void *, uint32_t)); extern uint32_t getEvent(uint32_t service, char *name); @@ -48,6 +48,8 @@ extern bool stackContains(uint32_t serviceId); +extern uint32_t await(uint32_t service, uint32_t event); + #define MAX(x, y) (x > y ? (x) : (y)) #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 8395e6c..bf22f17 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -28,6 +28,7 @@ typedef struct { char *name; ListElement *subscriptions; + ListElement *waitingSyscalls; } Event; extern ListElement *services; diff --git a/src/kernel/service/eventSyscalls.c b/src/kernel/service/eventSyscalls.c index 1219142..28a4c51 100644 --- a/src/kernel/service/eventSyscalls.c +++ b/src/kernel/service/eventSyscalls.c @@ -40,7 +40,7 @@ void handleFireEventSyscall(Syscall *call) { Service *service = call->service; Event *event = listGet(service->events, call->parameters[0]); - fireEvent(event, 0); + fireEvent(event, call->parameters[1]); } void handleSubscribeEventSyscall(Syscall *call) { @@ -58,3 +58,15 @@ provider->address = PTR(call->parameters[2]); listAdd(&event->subscriptions, provider); } + +void handleAwaitSyscall(Syscall *call) { + call->avoidReschedule = true; + ListElement *list = kernelEvents; + if (call->parameters[0]) { + // given another service as the target + Service *eventService = listGet(services, call->parameters[0]); + list = eventService->events; + } + Event *event = listGet(list, call->parameters[1]); + listAdd(&event->waitingSyscalls, call); +} diff --git a/src/kernel/service/events.c b/src/kernel/service/events.c index 35f5827..618f152 100644 --- a/src/kernel/service/events.c +++ b/src/kernel/service/events.c @@ -13,10 +13,21 @@ return event; } +extern ListElement *callsToProcess; + void fireEvent(Event *event, uint32_t data) { foreach (event->subscriptions, ServiceFunction *, function, { scheduleFunction(function, NULL, data); }) ; + for (ListElement *current = event->waitingSyscalls; current;) { + Syscall *call = current->data; + call->returnValue = data; + listAdd(&callsToProcess, call); + ListElement *old = current; + current = current->next; + free(old); + } + event->waitingSyscalls = NULL; } void installKernelEvents() { diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index 5133cde..4b1dce0 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -70,6 +70,7 @@ extern uintptr_t handleRequestMemorySyscall; extern uintptr_t handleLookupSymbolSyscall; extern uintptr_t handleStackContainsSyscall; +extern uintptr_t handleAwaitSyscall; void (*syscallHandlers[])(Syscall *) = { 0, @@ -93,6 +94,10 @@ (void *)&handleRequestMemorySyscall, (void *)&handleLookupSymbolSyscall, (void *)&handleStackContainsSyscall, + (void *)&handleAwaitSyscall, + 0, + 0, + 0, }; void processSyscall(Syscall *call) { diff --git a/src/userland/crashTest/main.c b/src/userland/crashTest/main.c index 375b198..7142285 100644 --- a/src/userland/crashTest/main.c +++ b/src/userland/crashTest/main.c @@ -6,7 +6,9 @@ void testFunction() { printf("0/0 = %i\n", 0 / 0); } int32_t main() { - printf("trying to divide by zero now . . .\n"); + printf("trying to divide by zero whenever you press a key...\n"); + uint32_t ioManager = getService("ioManager"); + await(ioManager, getEvent(ioManager, "keyPress")); testFunction(); return 0; } diff --git a/src/userland/hlib/include/syscalls.h b/src/userland/hlib/include/syscalls.h index 9d72a54..c872d37 100644 --- a/src/userland/hlib/include/syscalls.h +++ b/src/userland/hlib/include/syscalls.h @@ -26,6 +26,7 @@ SYS_REQUEST_MEMORY = 18, SYS_LOOKUP_SYMBOL = 19, SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, } SyscallIds; extern uint32_t getFunction(uint32_t module, char *name); diff --git a/src/include/hlib.h b/src/include/hlib.h index 6b27b81..fa51e95 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -26,7 +26,7 @@ extern uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, uint32_t parameter2, uint32_t parameter3); -extern void fireEvent(uint32_t eventId); +extern void fireEvent(uint32_t eventId, uint32_t data); extern void subscribeEvent(uint32_t service, uint32_t event, void(handler)(void *, uint32_t)); extern uint32_t getEvent(uint32_t service, char *name); @@ -48,6 +48,8 @@ extern bool stackContains(uint32_t serviceId); +extern uint32_t await(uint32_t service, uint32_t event); + #define MAX(x, y) (x > y ? (x) : (y)) #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 8395e6c..bf22f17 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -28,6 +28,7 @@ typedef struct { char *name; ListElement *subscriptions; + ListElement *waitingSyscalls; } Event; extern ListElement *services; diff --git a/src/kernel/service/eventSyscalls.c b/src/kernel/service/eventSyscalls.c index 1219142..28a4c51 100644 --- a/src/kernel/service/eventSyscalls.c +++ b/src/kernel/service/eventSyscalls.c @@ -40,7 +40,7 @@ void handleFireEventSyscall(Syscall *call) { Service *service = call->service; Event *event = listGet(service->events, call->parameters[0]); - fireEvent(event, 0); + fireEvent(event, call->parameters[1]); } void handleSubscribeEventSyscall(Syscall *call) { @@ -58,3 +58,15 @@ provider->address = PTR(call->parameters[2]); listAdd(&event->subscriptions, provider); } + +void handleAwaitSyscall(Syscall *call) { + call->avoidReschedule = true; + ListElement *list = kernelEvents; + if (call->parameters[0]) { + // given another service as the target + Service *eventService = listGet(services, call->parameters[0]); + list = eventService->events; + } + Event *event = listGet(list, call->parameters[1]); + listAdd(&event->waitingSyscalls, call); +} diff --git a/src/kernel/service/events.c b/src/kernel/service/events.c index 35f5827..618f152 100644 --- a/src/kernel/service/events.c +++ b/src/kernel/service/events.c @@ -13,10 +13,21 @@ return event; } +extern ListElement *callsToProcess; + void fireEvent(Event *event, uint32_t data) { foreach (event->subscriptions, ServiceFunction *, function, { scheduleFunction(function, NULL, data); }) ; + for (ListElement *current = event->waitingSyscalls; current;) { + Syscall *call = current->data; + call->returnValue = data; + listAdd(&callsToProcess, call); + ListElement *old = current; + current = current->next; + free(old); + } + event->waitingSyscalls = NULL; } void installKernelEvents() { diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index 5133cde..4b1dce0 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -70,6 +70,7 @@ extern uintptr_t handleRequestMemorySyscall; extern uintptr_t handleLookupSymbolSyscall; extern uintptr_t handleStackContainsSyscall; +extern uintptr_t handleAwaitSyscall; void (*syscallHandlers[])(Syscall *) = { 0, @@ -93,6 +94,10 @@ (void *)&handleRequestMemorySyscall, (void *)&handleLookupSymbolSyscall, (void *)&handleStackContainsSyscall, + (void *)&handleAwaitSyscall, + 0, + 0, + 0, }; void processSyscall(Syscall *call) { diff --git a/src/userland/crashTest/main.c b/src/userland/crashTest/main.c index 375b198..7142285 100644 --- a/src/userland/crashTest/main.c +++ b/src/userland/crashTest/main.c @@ -6,7 +6,9 @@ void testFunction() { printf("0/0 = %i\n", 0 / 0); } int32_t main() { - printf("trying to divide by zero now . . .\n"); + printf("trying to divide by zero whenever you press a key...\n"); + uint32_t ioManager = getService("ioManager"); + await(ioManager, getEvent(ioManager, "keyPress")); testFunction(); return 0; } diff --git a/src/userland/hlib/include/syscalls.h b/src/userland/hlib/include/syscalls.h index 9d72a54..c872d37 100644 --- a/src/userland/hlib/include/syscalls.h +++ b/src/userland/hlib/include/syscalls.h @@ -26,6 +26,7 @@ SYS_REQUEST_MEMORY = 18, SYS_LOOKUP_SYMBOL = 19, SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, } SyscallIds; extern uint32_t getFunction(uint32_t module, char *name); diff --git a/src/userland/hlib/service/events.c b/src/userland/hlib/service/events.c index 8b2ed97..38c527b 100644 --- a/src/userland/hlib/service/events.c +++ b/src/userland/hlib/service/events.c @@ -20,11 +20,15 @@ return syscall(SYS_GET_EVENT, service, id, 0, 0); } -void fireEvent(uint32_t eventNumber) { - syscall(SYS_FIRE_EVENT, eventNumber, 0, 0, 0); +void fireEvent(uint32_t eventNumber, uint32_t data) { + syscall(SYS_FIRE_EVENT, eventNumber, data, 0, 0); } void subscribeEvent(uint32_t service, uint32_t event, void(handler)(void *, uint32_t)) { syscall(SYS_SUBSCRIBE_EVENT, service, event, U32(handler), 0); } + +uint32_t await(uint32_t service, uint32_t event) { + return syscall(SYS_AWAIT, service, event, 0, 0); +} diff --git a/src/include/hlib.h b/src/include/hlib.h index 6b27b81..fa51e95 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -26,7 +26,7 @@ extern uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, uint32_t parameter2, uint32_t parameter3); -extern void fireEvent(uint32_t eventId); +extern void fireEvent(uint32_t eventId, uint32_t data); extern void subscribeEvent(uint32_t service, uint32_t event, void(handler)(void *, uint32_t)); extern uint32_t getEvent(uint32_t service, char *name); @@ -48,6 +48,8 @@ extern bool stackContains(uint32_t serviceId); +extern uint32_t await(uint32_t service, uint32_t event); + #define MAX(x, y) (x > y ? (x) : (y)) #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 8395e6c..bf22f17 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -28,6 +28,7 @@ typedef struct { char *name; ListElement *subscriptions; + ListElement *waitingSyscalls; } Event; extern ListElement *services; diff --git a/src/kernel/service/eventSyscalls.c b/src/kernel/service/eventSyscalls.c index 1219142..28a4c51 100644 --- a/src/kernel/service/eventSyscalls.c +++ b/src/kernel/service/eventSyscalls.c @@ -40,7 +40,7 @@ void handleFireEventSyscall(Syscall *call) { Service *service = call->service; Event *event = listGet(service->events, call->parameters[0]); - fireEvent(event, 0); + fireEvent(event, call->parameters[1]); } void handleSubscribeEventSyscall(Syscall *call) { @@ -58,3 +58,15 @@ provider->address = PTR(call->parameters[2]); listAdd(&event->subscriptions, provider); } + +void handleAwaitSyscall(Syscall *call) { + call->avoidReschedule = true; + ListElement *list = kernelEvents; + if (call->parameters[0]) { + // given another service as the target + Service *eventService = listGet(services, call->parameters[0]); + list = eventService->events; + } + Event *event = listGet(list, call->parameters[1]); + listAdd(&event->waitingSyscalls, call); +} diff --git a/src/kernel/service/events.c b/src/kernel/service/events.c index 35f5827..618f152 100644 --- a/src/kernel/service/events.c +++ b/src/kernel/service/events.c @@ -13,10 +13,21 @@ return event; } +extern ListElement *callsToProcess; + void fireEvent(Event *event, uint32_t data) { foreach (event->subscriptions, ServiceFunction *, function, { scheduleFunction(function, NULL, data); }) ; + for (ListElement *current = event->waitingSyscalls; current;) { + Syscall *call = current->data; + call->returnValue = data; + listAdd(&callsToProcess, call); + ListElement *old = current; + current = current->next; + free(old); + } + event->waitingSyscalls = NULL; } void installKernelEvents() { diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index 5133cde..4b1dce0 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -70,6 +70,7 @@ extern uintptr_t handleRequestMemorySyscall; extern uintptr_t handleLookupSymbolSyscall; extern uintptr_t handleStackContainsSyscall; +extern uintptr_t handleAwaitSyscall; void (*syscallHandlers[])(Syscall *) = { 0, @@ -93,6 +94,10 @@ (void *)&handleRequestMemorySyscall, (void *)&handleLookupSymbolSyscall, (void *)&handleStackContainsSyscall, + (void *)&handleAwaitSyscall, + 0, + 0, + 0, }; void processSyscall(Syscall *call) { diff --git a/src/userland/crashTest/main.c b/src/userland/crashTest/main.c index 375b198..7142285 100644 --- a/src/userland/crashTest/main.c +++ b/src/userland/crashTest/main.c @@ -6,7 +6,9 @@ void testFunction() { printf("0/0 = %i\n", 0 / 0); } int32_t main() { - printf("trying to divide by zero now . . .\n"); + printf("trying to divide by zero whenever you press a key...\n"); + uint32_t ioManager = getService("ioManager"); + await(ioManager, getEvent(ioManager, "keyPress")); testFunction(); return 0; } diff --git a/src/userland/hlib/include/syscalls.h b/src/userland/hlib/include/syscalls.h index 9d72a54..c872d37 100644 --- a/src/userland/hlib/include/syscalls.h +++ b/src/userland/hlib/include/syscalls.h @@ -26,6 +26,7 @@ SYS_REQUEST_MEMORY = 18, SYS_LOOKUP_SYMBOL = 19, SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, } SyscallIds; extern uint32_t getFunction(uint32_t module, char *name); diff --git a/src/userland/hlib/service/events.c b/src/userland/hlib/service/events.c index 8b2ed97..38c527b 100644 --- a/src/userland/hlib/service/events.c +++ b/src/userland/hlib/service/events.c @@ -20,11 +20,15 @@ return syscall(SYS_GET_EVENT, service, id, 0, 0); } -void fireEvent(uint32_t eventNumber) { - syscall(SYS_FIRE_EVENT, eventNumber, 0, 0, 0); +void fireEvent(uint32_t eventNumber, uint32_t data) { + syscall(SYS_FIRE_EVENT, eventNumber, data, 0, 0); } void subscribeEvent(uint32_t service, uint32_t event, void(handler)(void *, uint32_t)) { syscall(SYS_SUBSCRIBE_EVENT, service, event, U32(handler), 0); } + +uint32_t await(uint32_t service, uint32_t event) { + return syscall(SYS_AWAIT, service, event, 0, 0); +} diff --git a/src/userland/ioManager/main.c b/src/userland/ioManager/main.c index 81f8184..db1a0d9 100644 --- a/src/userland/ioManager/main.c +++ b/src/userland/ioManager/main.c @@ -61,9 +61,12 @@ focusServiceKeyHandler = 0; } +uint32_t keyEvent; + void handleKey(uint32_t keycode, uint32_t stringId) { focusServiceKeyHandler = getFunction(focusService, "onKey"); request(focusService, focusServiceKeyHandler, keycode, stringId); + fireEvent(keyEvent, keycode); } int32_t main() { @@ -78,4 +81,5 @@ loadFromInitrd("pic"); loadFromInitrd("keyboard"); createFunction("setForeground", (void *)setForeground); + keyEvent = createEvent("keyPress"); }