johnr@systech.uucp (John Reed) (10/14/89)
I have been working on a Xinu port to an Omnibyte 68000 based computer on and off for awhile, and I have finally got it to work. I ported from the Version 7.1 Sun3 code which we obtained from Purdue. Along the way I uncovered some bugs, and I made some additions which may be useful to somebody. The Omnibyte is a very basic 68000 based Multibus board. It has 512K ram, 2 6850 serial chips, a 6840 timer, and a couple of parallel ports. We use these boards at Systech for test fixtures. For my port, I stripped out all of the networking code, and all of the file system stuff. I was interested in getting a bare-bones system up and running. The port went pretty fast, and in the beginning the most difficult thing for me was getting the code compiled and running under our Microtec 'C' development tools. The shell came up quickly, and after a few tweaks of my tty driver, Xinu was up and running. The difficult part of the port was when I attempted to get a shell session going on both of the serial ports. The Xinu code, as I got it, assumes that there will only be a console port and thats it. I needed to make many additions in order to get 2 login sessions going simultaneously. If anyone is interested in the details involved with this, please E-mail me. So I finally got 2 shells going at the same time, and the next logical step was to blast output on both channels to see how the OS performed. This was where I really got into the nitty-gritty debug stuff. I had a login session enabled on both the console and "ttyb". And I added a very simple shell command which blasted output to "stdout". The program was an endless loop of 26 "writes", and each write was for 50 characters. So I would log on to the console then log on to ttyb, and start things going. I started up "ptest" (the blast output program) on the console and output blasted at 19.2kbaud on the terminal. I typed in "ptest" on ttyb and nothing happened--it just kind of hung there. After messing around with it for awhile I discovered something very surpising. If I hit the return key on ttyb where output was hung up, about 20 characters would pop out. And if the return key was held down long enough, output would begin to flow constantly. It was almost like "priming the pump": you had to hold the return key down for awhile to get it going. The kicker though, was that once it got going the output rate was severely decreased. Both terminals were configured for 19.2kbaud and the output looked like about 4800 baud. Something was definitely wrong! Typing a ^S on one of the terminals would allow the output on the other terminal to blast at 19.2k, but when ^Q was hit, the output rate went to pot again. Sometimes the output would not start back up, and the return key had to be used again to "prime the pump". It took me a good 2 days to debug this problem, and I uncovered a nasty little bug. The bug is in the transmit interupt routine "ttyoin". Here is the section of code at fault: if ((ct=iptr->ocnt) > 0) { zptr->zscc_data = iptr->obuff[iptr->otail++]; --iptr->ocnt; if (iptr->otail >= OBUFLEN) iptr->otail = 0; if (ct > OBMINSP) signal(iptr->osem); else if ( ++(iptr->odsend) == OBMINSP) { iptr->odsend = 0; signaln(iptr->osem, OBMINSP); } } else ttyostop(iptr); The statement: if (ct > OBMINSP) signal(iptr->osem); is the one in error. When a process is doing heavy output, the output buffer will fill up quickly and the process will be taken off of the ready queue. iptr->ocnt will increase very quickly (the upper-half code increments it for every character put into the buffer) and will approach the value of OBUFLEN. It will certainly be greater than OBMINSP (the low water mark), so the signal statement will be executed for every character that is transmitted. This will happen as long as the process keeps filling the output buffer, which in my test case, it will do endlessly. What we end up with is a process taking itself off of the ready queue for every (single) character that it stuffs in the output buffer, then waking back up for every character that is transmitted. That is some pretty serious thrashing going on there DUDE! The solution is straightforward: if (ct < OBMINSP) signal(iptr->osem); Which was the intended behavior. After further investigation and trial runs, I could find no real use for iptr->ocnt. I got rid of the references to ocnt and modified the code further to look like this: if ((ct=semaph[iptr->osem].semcnt) < OBUFLEN) { aptr->trdr = iptr->obuff[iptr->otail++]; if (iptr->otail >= OBUFLEN) iptr->otail = 0; if (ct > OBMINSP) signal(iptr->osem); else if ( ++(iptr->odsend) == OBMINSP) { iptr->odsend = 0; signaln(iptr->osem, OBMINSP); } } else ttyostop(iptr); This version of the code is more in line with the code found in the LSI version of Comer's book. So all in all, I am pleased with the Xinu port. It is a neat little system to work with. I plan to port next to one of Systech's cluster controllers. Each cluster controller has an arcnet chip set, a very high performance 8 channel octart, 128k of ram, and a 68000 to run the show. I am especially anxious to get the networking code implemented and running under arcnet. What'dya say there Vern? Please mail me if anybody out there has any questions about my work. John Reed Systech Corp. San Diego, CA {uunet,ucsd}!systech!johnr johnr%systech.uucp@ucsd