[comp.os.xinu] Xinu port to Omnibyte OB68k1a

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