nullplan wrote:AndrewAPrice wrote:We could implement "this program is unresponsive" and terminate if the queue gets full.
Wrong layer of abstraction. This is only about input devices and how to read them out, it has nothing to do with process management. What you are talking about is more like an application in a windowing system not responding to events fast enough. Which is fine if the windowing system wants to implement this, but this is already twice removed from reading the input device (Device --> Windowing system --> Application). I suppose, the best thing you can do is inject an "overflow occurred" message into the event stream when the buffer is full. You save somewhere in the kernel/driver that an overflow occurred, and next time the message queue is read, after removing a message from the queue, an overflow event is injected at the end of the stream and reset the overflow flag. That way, the userland driver can reset state or explicitly ask for the current state if appropriate, to make sure at the very least it has the most up-to-date picture of what is going on.
Sorry, I meant having a full queue is one possible signal that the kernel could use to identify that a program (be it a user program, service, or driver) could be unresponsive. This could alert the process manager to say, hey this process got stuck, perhaps we should try restarting it? (With some limits in place - if a driver crashes <1 per day, log it because there's a bug somewhere, but you could probably restart the driver and continue business as usual. If a driver crashes >1 per minute, this driver is a dud and it should stay dead.)
nullplan wrote:I do not think a high-load situation is going to be improved massively by killing processes that are too slow. And your users probably won't appreciate their browser being killed for a bad website, either.
Fair enough. For a user program, I'd rather my web browser or word processor to occasionally lag than to randomly die.
If this logic is in the process manager (a userland process in my microkernel), it could keep track of what should reset (it's probably fine if to reset a network driver or video card driver - user programs will have to be implemented in a way that they can reupload textures and reopen connections if this happens), whereas you wouldn't want to kill the user's word processor (perhaps alert the window manager to show a busy cursor or gray out the title bar or something.)
nullplan wrote:AndrewAPrice wrote:How would you implement this in a fast, generic way in the context of a microkernel that doesn't have any concept of a mouse?
The mouse driver has a concept of a mouse. The queue between mouse driver and event consumer must be such that the mouse driver can inspect at least the latest event in it. Then you can update that even in-place if it happens to be of the right type. You only want to merge mouse-move events that are consecutive. If a mouse-button event is in there, you do not want to update the pointer position before the click with moves that happened later. There, that is O(1), doesn't get much faster, conceptually.
Would this need a FIFO queue per sender/receiver pair? Having one incoming queue per process would be a security risk (and also a race risk) if anybody could see and modify it.
OSwhatever wrote:Now there are interrupts that don't have this possibility. One suggestion here is to have several but limited amount of bottom half queue items. If there are too many interrupts than you can process you have lost the game anyway.
Having a priority queue would be interesting. Give processes a priority (0 = kernel, 1000 = drivers, 2000 = services, 3000 = programs - the lower the number the higher the priority) and you can send messages at a priority number that is equal to or higher than your process's priority (so a driver could send a low priority message, but a program can't send a driver-priority message)?
Still, a priority queue is still a queue and we have finite space and computation power.
So some approaches we could take:
a) Let every message be a unique message (so it's fine if there are 20 "mouse moved" or "interrupt fired" events) and if the queue gets full we just ignore messages.
b) Have some kernel support for combining messages. In my OS, message IDs are unique to the receiver, and the messages themselves are small, fixed sized (small enough to fit in registers). I wonder if I could possibly register with the kernel the "combine" conditions of each register, with combine conditions such as "SUM" (mouse movement), "REPLACE" (window focus state, timestamp of the message, etc), "IGNORE" (the interrupt fired, don't really care about the parameters.)
c) Move the above logic to userland. Expect user processes to have a message processing thread (that's at a higher priority than the process's other threads), whos job is to process messages (combining together messages for the worker thread.) This feels like the purest option for a microkernel and would be super flexible, but would require additional syscalls (the wake the worker thread and sleep the messaging thread) + thread switch to get to the actual that would do something with the message.