At 11:30 AM 3/21/00 -0500, "Todd L. Miller" <[EMAIL PROTECTED]> wrote:
>       Okay, so there's another of level indirection in here that I
>missed.  That is, Controller.getObject() may well return itself, but the
>Controller for a Device is the only object in the system which keeps a
>driver reference?)

So, there are two things going on here at the same time. As you point out,
we misses a step. Indirection -- between a user process and a low-level
device -- might be required because of class loaders and threads.

Both class and class loader are significant in casting and using the
instanceof operator. Carefullly consider the following snippet:

  public void example() {
    String s = "org.jos.device.Port";
    Object o = Factory.getObject( s );
    if ( !o instanceof Port ) {
      return;
    }
    Port p = (Port) o;
    :
  }

If two class loaders are involved, this snippet will never work. A user
process always has a custom class loader, so that classes used by a user
process can be garbage collected when a process dies. The device factory is
system-wide with its own custom class loader. A low-level device is
guaranteed *not* to be on the same class loader as a user process.

A user process always has its own thread, so that its bytecode can be
interpreted asynchronously from all other threads. The device factory is
part of the system process. A system process has its own thread. Each
device might need to have its own private thread for double-buffered I/O. A
high-level device runs off the user process thread.

A high-level device communicates with a low-level device through
inter-process communication (IPC). Inter-process communication is required
to break through the persistence barrier that makes all processes independent.

A low-level Port is created in a system process. The low-level device
manager must make sure that only one low-level Port at a time for each port
in hardware.

An IPC channel is opened between this object and a high-level Modem created
in a user process. A user process can do whatever it wants with the
low-level Port through an IPC channel.

In fact, the low-level port is a JVM-specific class. Any modem that uses a
port is not a JVM-specific class. Therefore, there must be at least two
packages for our JOS device project: decaf.device and org.jos.device

Starting with org.jos.device, we should build generic device drivers that
work with any distribution of JOS. Any JOS-specific application uses these
generic device drivers. We would have a Port interface, etc.

For the decaf virtual machine only, we would have decaf.device. A BCNI
factory for decaf would return an instance of GenericPort when asked for a
Port.

When any device needs to use a serial port, it uses a serial port. Any
device can use a serial port. Here is what a port and port listener might
look like:

// Port.java
package org.jos.device;
public interface Port {
  public int getID();
  public PortListener getListener();
  public void setListener( PortListener v );
  public void run();
  public void write( byte[] v );
  public void close();
}

// PortListener.java
package org.jos.device;
public interface PortListener {
  public void onRead( byte[] v );
  public void onClose();
}

Since a byte array passes easily through a persistence barrier, a generic
port can be used by all kinds of devices. This is must better than anything
I've seen from other operating systems. Here is my first attempt at a
generic port:

// GenericPort.java
package decaf.device;
public class GenericPort
    implements Port {
  GenericPort( int v ) {
    id = v;
  }
  public PortListener getListener() {
    return listener;
  }
  public void setListener( PortListener v ) {
    listener = v;
  }
  public void run() {
    synchronized( flag ) {
      flag = Flag.RUNNING;
    }

    for (;;) {
      synchronized( flag ) {
        if ( flag == Flag.CLOSED ) {
          break;
        }
      }

      for ( int i = 0; i < SIZE; i++ ) {
         int b = queue.read();
         if ( b < 0 ) {
           if ( i == 0 ) {
             Thread.yeild();
             break;
           }

           byte[] temp = new byte[ i ];
           System.arraycopy( buffer, 0, temp, 0, i );
           listener.onRead( temp );
           break;
         }

         buffer[ i ] = (byte) i;
      }
    }
  }
  public void write( byte[] v ) {
    int iMax = v.length;
    for ( int i = 0; i < iMax; i++ ) {
      queue.write( v[ i ] );
    }
  }
  public void close() {
    synchronized( flag ) {
      flag = Flag.CLOSED;
    }
  }
  private Flag flag = Flag.IDLE;
  private int id;
  private PortListener listener;
  private byte[] buffer = new byte[ SIZE ];
  private EventQueue queue;
}


_______________________________________________
Kernel maillist  -  [EMAIL PROTECTED]
http://jos.org/mailman/listinfo/kernel

Reply via email to