ast@cs.vu.nl (Andy Tanenbaum) (12/20/88)
After a certain about of effort, I now have MINIX-Kermit running on my AT and talking to Kermit on a Sun over a 1200 baud line. I seem to be able to get an effective bandwidth of 1100 baud out of this combination. This is not bad at all considering that the Kermit packets are only 90 bytes, of which 5 are packet overhead. Under these conditions the theoretical user bandwidth is 1133 baud, so I am getting 97% efficiency. I think it is fairly safe to say that at 1200 baud, the MINIX RS232 driver is adequate for an AT. It would be interesting to hear statistics about over combinations of hardware/speeds. Andy Tanenbaum (ast@cs.vu.nl)
brucee@runx.ips.oz (Bruce Evans) (12/27/88)
In <1835@ast.cs.vu.nl> ast@cs.vu.nl (Andy Tanenbaum) writes: >is 1133 baud, so I am getting 97% efficiency. I think it is fairly safe to >say that at 1200 baud, the MINIX RS232 driver is adequate for an AT. It would >be interesting to hear statistics about over combinations of hardware/speeds. I have rewritten the RS232 driver (3rd iteration this year), so that it works at 9600 baud on a 5Mhz PC. The best throughput achieved was 901 chars/sec using zmodem, sending from a 386 running DSZ.COM under DOS to the PC. Zmodem under Minix from the 386 to the PC only achieves 580 chars/sec. Minix kermits on each side reported 8630 baud on a 33K text file and 5560 baud on a 102K binary. Kermit had compression on. This inflated the rate for the text file. The changes required for this are extensive. The basic problem in Minix 1.3 is that too many things turn off interrupts for long periods. On the PC at 5MHz, you get only 200-300 instructions per millisec, so locking more than this causes dropped characters at 9600 baud. My code mostly avoids locks for more than 100 instructions, with a maximum of about 200. Approximate numbers are: save() handler interrupt() restart() latency RS232 interrupt avoided 50 avoided avoided 50 RS232 output completion 34 50 50 17 151 clock interrupt 34 80 50 17 181 disk interrupt 34 none 50 17 101 keyboard interrupt 34 116 avoided 17 167 system call (switch) 26 not locked not used 22 26 Note that these numbers rule out reliable operation at 19200 baud, but small bursts should get through, consistent with what my system actually does. In Minix 1.3, the corresponding numbers are about 70 for save() + restart(), and (from distant memory) over 500 for handling a sendrec() system call, 200 to 300 for interrupt() in the best case, and several thousand for interrupt() in the worst case (because of a loop). Any inadequacies in the RS232 driver are just another straw. Of course my faster system call handler and interrupt() improve system performance generally, but not signifigantly except in the case of programs doing single character i/o. But having a low level clock handler is worth 15% on a PC. Summary of changes: rs232.c: Rewritten (dates from before the Minix rs232.c). It is almost independendent of tty.c and has been used in a real-time application with a throughput of 1700 chars/sec. The interrupt handlers are now in assembler. The interface to tty.c consists of functions rs_read(), rs_write(), etc., which pass buffer pointers back and forth without requiring any copying (even locally). The clock interrupt is used to wakeup TTY after RS232 activity. tty.c: The interface to rs232.c is changed. Numerous bugs are fixed. Many inner loops are rewritten. Calls to get_byte() are replaced by block calls to phys_copy(), since get_byte() is not portable and was getting in the way of my 386 port. Locks around loops are eliminated. Several Kbytes of buffer space are reclaimed. console.c: I tried not to get involved with it, but had to simplify the keyboard interrupt handler (it was taking 2 millisec), and changed the keyboard buffering method to the same as in rs232.c at the same time. get_byte() also had to go, and some of the initialisation code was relocated. Eventually, I want to split console.c into keyboard.c and screen.c (coordinated by tty.c) and deny access to the tty structure to both. clock.c: rs_flush() is called at _every_ clock tick to let RS232 decide whether to wake up TTY. This is best done independent of switching to the clock task. proc.c: Rewritten. Interrupt() was just too slow. Locking had to be done locally and more carefully since there was no longer a global lock. These changes are sufficient for fast RS232, but I also hid all the magic process numbers using macros and reduced dynamic instruction counts wherever possible. mpx88.s: Rewritten. Small modifications allow sys_call() to run unlocked. Everything was changed to reduce instruction counts. *.h, *.c: magic process numbers are hidden. I plan to post rs232.c, tty.c, console.c.cdif and a couple of other small cdiffs early in January. If there is enough interest, I will see about posting proc.c and its supporting changes. Bruce Evans Internet: brucee@runx.ips.oz.au UUCP: uunet!runx.ips.oz.au!brucee