nullplan wrote:
rdos wrote:
Octocontrabass wrote:
I don't see why it wouldn't work. Actually, it should be easier than other devices since they're always edge-triggered and can't raise a new IRQ until the driver acknowledges them.
When a new one is raised (because another character arrives), the old one is lost if the port has no FIFO. So, the issue is that with high enough baudrate, and no (or small) FIFO, characters will be lost if not handled fast enough. The fastest handling of course is buffering characters in an IRQ written in assembly.
The highest baud rate of the ISA serial port is 115200. With the typical settings of 8/N/1, you require 10 bit times to transmit a single character, meaning a single character takes 1/11520 seconds to transmit (which comes out at roughly 85µs). A 1GHz CPU (bear in mind those are 20 years old now) has 85000 cycles in that time. That really is more than enough to take the interrupt, handle it, unblock the serial port driver, switch to it, and read out the character. Unless the serial driver were somehow not the most important thing to run in that situation, in which case I would question the design choices in the scheduler that lead to that being the case.
So I highly doubt that the kernel thread method is too slow for any device of any relevance today.
You forgot several factors above.
First, you need to add the longest time interrupts can be disabled (interrupt latency). In a real-time kernel this is an important parameter, but in many more normal kernels, this time can be very long. For instance, if you implement spinlocks with cli, then the CPU can spin a spinlock for a long time. The scheduler & task switcher is almost guaranteed to need to disable interrupts at last part of the time it switches tasks. Some IRQs might run with interrupts disabled (and if you enable interrupts in the IRQ, then you need to protect against scheduling). How you handle exceptions can further delay the response. For instance, does the pagefault handle run with interrupts disabled? A poorly designed SMP scheduler can further increase interrupt responses if it needs many spinlocks or have too many resources under contention, like shared task queues. A poor design could also have the IRQ happen on one core while the server thread runs on another, needing an IPI to activate the server.
Second, the BIOS might use SMI to emulate devices, and if this is poorly done, it can "kill" interrupt latency, This can be minimzed by not using emulated devices like keyboard emulation, but other than that, it's just an unknown that can create problems
Third, I don't think serial port server threads should have the highest priority in the system. Things like playing sound must have higher priority to avoid click sounds in the playback. I think network server threads are additional candidates for high priority, particularly if the chip turns off on buffer overrun (like RTL does).
Forth, my lower end CPUs run only at a few 100 MHz, so I'd divide the time by 5 or so. The original 386 only run at 25 MHz or so.
In fact, even if I think I have farily good interrupt latency, handling 115000 baud is a problem even when the IRQ buffers characters and there is no FIFO.
So, if you want to prove that your kernel can handle 115200 baud with no FIFO, you first need to subtract the worse case interrupt response time from 85us. If you know the interrupt latency, you probably have a realtime kernel, and otherwise you probably don't know it and you need to resort to statistics that you will lose a character with some probability.
Also, a cycle doesn't mean an instruction. For instance, if the IRQ happens in user mode, it can take hundreds of cycles before the processor has switched to kernel and is executing the IRQ code.