openblt

a hobby OS from the late 90s
git clone http://frotz.net/git/openblt.git
Log | Files | Refs | LICENSE

openblt.html (8887B)


      1 <HTML>
      2 <HEAD>
      3 <TITLE>OpenBLT Overview</TITLE>
      4 </HEAD>
      5 <BODY BGCOLOR="#ffffff">
      6 
      7 <CENTER>
      8 <TABLE WIDTH=600>
      9 <TR><TD>
     10 
     11 <H1>OpenBLT: An Overview</H1>
     12 <I>by Brian J. Swetland</I>
     13 
     14 <P>
     15 OpenBLT is a microkernel operating system for PC's based on the Intel
     16 80386 or later CPUs.  Some aspects of OpenBLT were inspired by Andy
     17 Valencia's VSTa OS, Mach, assorted UNIX variants, and the author's 
     18 deranged imagination.  The acronym BLT expands to "Brian's Lightweight
     19 Tasker" or "Bacon, Lettuce, and Threads".  The word Open was tacked on
     20 for no particular reason.  
     21 <P>
     22 The OpenBLT kernel is responsible for managing system memory, providing
     23 IPC facilities, and creation, destruction, and scheduling threads of control.
     24 <P>
     25 Below, we'll examine Tasks, Aspaces, and Ports (the basic objects managed
     26 by the OpenBLT kernel) in terms of their use in and appearance to userland
     27 programs.
     28 
     29 <P><B>Tasks</B><BR>
     30 Tasks in OpenBLT are single threads of control.  Each task is associated
     31 with an address space, within which it runs.  Tasks may terminate themselves
     32 using the 
     33 <PRE>void  os_terminate(int status);</PRE>
     34 system call.  A task may start another task (sharing the same address space)
     35 using the
     36 
     37 <PRE>int   os_thread(void *addr);</PRE>
     38 system call.  The new task begins execution at the specified address and
     39 a 4K stack is created for it.  <I>[ os_thread() will probably take a stack
     40 pointer address in the next revision ]</I>
     41 
     42 <P><B>Address Spaces</B><BR>
     43 Address spaces are currently not readily manipulated from userland.  
     44 In the near future, shared memory system calls should allow the creation
     45 of new address spaces and sharing memory between address spaces.  A
     46 thread may request that its address space be expanded using the <TT>os_brk()</TT> system call:
     47 <PRE>
     48 int   os_brk(int addr);
     49 </PRE>
     50 
     51 <P><B>Ports</B><BR>
     52 IPC (interprocess communication) in OpenBLT occurs when one task sends a
     53 message to another task via a port.  Ports are 'owned' by one task (the
     54 task that created them).  Messages are send from one port to another port
     55 (thus a port must exist for the sending task to send from).  A port may
     56 be restricted so that it can only receive messages from one specified
     57 other port <I>[ future versions will likely allow a list of allowed senders ]</I>.
     58 
     59 
     60 <P>
     61 All messages sent or received via an OpenBLT port are described with
     62 a message header.  The header indicates the source port, destination port,
     63 size of message, pointer to message data (or receive data buffer), and
     64 flags (to allow for future expansion -- non-blocking IO, scatter/gather
     65 IO, etc)
     66 <PRE>
     67 typedef struct {
     68     int flags;
     69     int src;
     70     int dst;
     71     int size;
     72     void *data;    
     73 } msg_hdr_t;
     74 </PRE>
     75 
     76 
     77 <P><TT>int <B>port_create</B>(uint32 restrict);</TT><BR>
     78 Create a new port owned by the running thread.  Only allow messages
     79 from port 'restrict' to be received.  If <TT>restrict</TT> is 0, messages
     80 from any source will be received.  Will return <TT>ERR_MEMORY</TT> if
     81 the system lacks the resources to create the port, otherwise the port
     82 number will be returned.
     83 
     84 <P><TT>int <B>port_destroy</B>(uint32 port);</TT><BR>
     85 Destroy an existing port.  Returns <TT>ERR_RESOURCE</TT> if <TT>port</TT> is
     86 not a valid port or if there are other ports slaved to this port.
     87 Returns <TT>ERR_PERMISSION</TT> if the running thread is not the owner
     88 of this port.  Returns <TT>ERR_NONE</TT> upon success/
     89 
     90 <P><TT>int <B>port_send</B>(msg_hdr_t *mh);</TT></BR>
     91 Send the message in <TT>mh->data</TT>, of length <TT>mh->size</TT>
     92 from port <T>mh->src</TT> to port <TT>mh->dst</TT>.  Returns
     93 <TT>mh->size</TT> upon success, <TT>ERR_MEMORY</TT> if there is a
     94 bounds error, <TT>ERR_RESOURCE</TT> if either the source or
     95 destination ports do not exist, <TT>ERR_PERMISSION</TT> if the source
     96 is not owned by the running thread or the destination is not sendable
     97 from the source port.
     98 
     99 <P><TT>int <B>port_recv</B>(msg_hdr_t *mh);</TT></BR>
    100 Receive a message (in buffer <TT>mh->data</TT>, max length
    101 <TT>mh->size</TT>) from port <TT>mh->dst</TT>.  Upon success,
    102 <TT>mh->src</TT> will be set to the sender, <TT>mh->dst</TT> will be
    103 set to the destination if it was a slaved port, and the number of
    104 received bytes will be returned.  If the data or header are out of
    105 bounds, <TT>ERR_MEMORY</TT> is returned.  If the destination port does
    106 not exist <TT>ERR_RESOURCE</TT> is returned.  If the running thread
    107 does not own the destination port, <TT>ERR_PERMISSION</TT> is
    108 returned.  This call will block if no messages are available, unless
    109 the port is set to NOWAIT, in which case <TT>ERR_WOULDBLOCK</TT> is
    110 returned.
    111 
    112 <P><TT>int <B>port_option</B>(uint32 port, int opt, int arg);</TT></BR>
    113 Modify port options.  The two functions below are wrappers around 
    114 <TT>port_option()</TT>
    115 
    116 <P><TT>int <B>port_slave</B>(uint32 master, uint32 slave);</TT><BR>
    117 Cause the master port to receive all messages sent to the slave port.
    118 If master is 0, the slave is released from bondage.  Returns ERR_NONE
    119 upon success, <TT>ERR_PERMISSION</TT> if the master and slave are not
    120 both owned by the running thread, or <TT>ERR_RESOURCE</TT> if the
    121 master or slave are not valid ports.
    122 
    123 <P><TT>int <B>port_set_restrict</B>(uint32 port, uint32 restrict);</TT><BR>
    124 Change the restriction on a port.  Returns <TT>ERR_NONE</TT> on
    125 success, <TT>ERR_RESOURCE</TT> if the port does not exits, or
    126 <TT>ERR_PERMISSION</TT> if the running thread does not own the port.
    127 A restriction of 0 allows any port to send to this port.
    128 
    129 <P><B>Finding other tasks to talk to</B><BR>
    130 Since port numbers are generated dynamically by the kernel and tend to
    131 be different depending on the order tasks are started, etc, there needs
    132 to be a mechanism for locating device drivers or just other tasks to 
    133 talk to.  The kernel automatically creates port 1 (the uberport) and gives
    134 ownership of this port to the first task created.  This task is the namer,
    135 a service that allows drivers to register ports under specific names and
    136 allows tasks that wish to find these drivers to look up the port that is
    137 associated with a specific name.
    138 <P>
    139 The utility functions listed below are part of the OpenBLT libc and provide
    140 convenient ways to access the namer.
    141 <PRE>
    142 int namer_newhandle(void);
    143 int namer_delhandle(int nh);
    144 int namer_register(int nh, int port, char *name);
    145 int namer_find(int nh, char *name);
    146 </PRE>
    147 
    148 <P><B>Connections between Connectionless ports</B><BR>
    149 Ports in OpenBLT are connectionless.  Each <TT>port_send()</TT> specifies
    150 a source and destination port.  Tasks may send from any port they own to
    151 any port they are allowed to write to.  Ports may be writable to be any
    152 other port or restricted to just one other port. <I>[ multiple port restrict
    153 lists will be in a later version ]</I>
    154 <P>
    155 The general procedure for providing a service in OpenBLT is
    156 <UL>
    157 <LI>Create an unrestricted port
    158 <LI>Register this port with the namer under a descriptive name (eg ne2000, console, etc)
    159 </UL>
    160 When one task (a client) wishes to connect to a service (the server), 
    161 the following occurs:
    162 <UL>
    163 <LI>The client looks up the servers unrestricted port using the namer
    164 <LI>The client creates a port that is restricted to the server's 
    165 unrestricted port
    166 <LI>The client sends a message to the servers unrestricted port 
    167 requesting a connection
    168 <LI>If the server accepts the connection, it will send a response back 
    169 to the client's port notifying it that the connection is accepted and
    170  possibly providing a different port than the unrestricted port that the
    171 client should send future messages too.
    172 </UL>
    173 <I>[ a toolkit in libc will streamline this process ]</I>
    174 
    175 <P><B>Handling Devices</B><BR>
    176 The security model in OpenBLT is still being designed.  Most likely
    177 there will be a task that is a "security manager" which will be able
    178 to give permissions (for accession IO devices, etc) to tasks that need them.
    179 The two syscalls described below are sufficient for simple device drivers
    180 in the initial (overly trusting) version of OpenBLT:
    181 
    182 <P><TT>void  <B>os_handle_irq</B>(int irq);</TT><BR>
    183 Ask the kernel to make this task eligible to process the specified IRQ.
    184 The kernel will also allow the task IO access.
    185 
    186 
    187 <P><TT>void  <B>os_sleep_irq</B>(void);</TT><BR>
    188 Suspend this task until the IRQ it is registered to handle is triggered.
    189 When that IRQ is triggered, the task will be scheduled (preempting the
    190 currently running task).  The IRQ will be ignored by the kernel when the
    191 task is no sleeping in <TT>os_sleep_irq()</TT>.
    192 
    193 <P><B>Startup</B><BR>
    194 On startup, OpenBLT creates initializes its internal memory and resource
    195 management, sets up kernel space at the 2gb line (0x8000000), creates
    196 an address space and task for each userland program that it can find.
    197 An idle task is created (to give the scheduler something to schedule, 
    198 should all other tasks be sleeping on something). The kernel schedules
    199 the first task in the run queue to execute and the fun starts.
    200 
    201 
    202 </TD></TR>
    203 </TABLE>
    204 </CENTER>
    205 
    206 </BODY>