| iMatix home page
| << | < | > | >>
SMT Logo SMT
Version 2.81

The SMT Kernel Architecture

Structure Of An SMT Application

An SMT application generally consists of a number of agents, connected to the SMT kernel:

                     .------------.
                     : SMT kernel |
                     `============"
                            |
     - -+------------+------+-----+------------+- -
        |            |            |            |
    .-------.    .-------.    .-------.    .-------.
    : Agent |    : Agent |    : Agent |    : Agent |
    `======="    `======="    `======="    `======="

Figure: Regular SMT application

We may also use an event driver to make an 'embedded application'. This is necessary when external events cannot be collected by a normal SMT agent program such as the socket i/o agent. An example of such an application is one designed for MS Windows.

                     .--------------.
                     : Event Driver |
                     `=============="
                            |
                     .------------.
                     : SMT kernel |
                     `============"
                            |
     - -+------------+------+-----+------------+- -
        |            |            |            |
    .-------.    .-------.    .-------.    .-------.
    : Agent |    : Agent |    : Agent |    : Agent |
    `======="    `======="    `======="    `======="

Figure: Embedded SMT application

There are many other types of SMT application. The SMT kernel defines a number of objects, and operations on those objects. These objects are arranged in a hierarchy: this is structural, not morphological (they do not inherit attributes from each other):

         Agent
           :            :  Method
         Queue
        /          Thread     Event

Figure: Main SMT Objects

The SMT holds these objects in a set of linked lists. Each thread, for instance, contains the reference of its parent queue; a queue refers to its parent agent.

                      .------------.
                      : SMT kernel |
                      `============"
                             |
       -+-------------+------+------+-------------+-
        |             |             |             |
                  .-------.
                  : Agent |
                  `======="
                      |
        +-------------+-------------+
        |             |             |
    .--------.    .--------.    .--------.
    : Queue  |    : Queue  |    : Queue  |
    `========"    `========"    `========"
        |             |             |
    .--------.    .--------.    .--------.
    : Thread |    : Thread |    : Thread |
    `========"    `========"    `========"

Figure: Agent Program With 3 Threads

Floating Event Queues

In normal cases, events are sent to a queue that is held by an agent program. Sometimes this is a limitation: we can see cases where non-agent programs also need to receive events. Any program can send an event: this is just a call to the SMT kernel API.

We therefore define the concept of a floating event queue; that is, an event queue that is managed by some program that is not constructed as an agent:

        Program
           :
         Queue
           :
         Event

Figure: Floating Event Queue

The designer of the application must also find a way to service the event queue, since the SMT kernel cannot schedule and execute such a program.

Routers

In most cases, one queue is served by one thread. Thus, when you send an event to a queue, you are effectively sending it to a specific thread. In some cases, it is better to share one queue among several threads. Imagine an agent that executes database requests coming from a set of clients. A thread takes an event, processes it, and returns a reply. Each event is independent, and may take some time to process. It makes sense to start several threads, so that several events can be processed in parallel. It would be wrong to allocate one queue per thread, however, for two reasons. Firstly, this implies that there are N queues which the clients must know about. Secondly, it implies that someone (client or agent) chooses a queue for each event. Consequently, events may be waiting in the queue for one thread while another thread is idle. By allocating just one queue, shared between all the agent threads, events are processed at full speed, in arrival order.

An agent is either defined as a router, or not. When an agent is a router, it is legal to create multiple threads with the same name. All threads in a router agent share a single event queue.

Internal and External Events

SMT agents are built as event-driven Libero programs. We define two kinds of event: an internal event (supplied by the program itself) and an external event (taken from the event queue). If we consider a normal Libero program, all events are internal. The SMT kernel adds the concept of external events.

When you design the program dialog, you do not distinguish internal and external events. Indeed, a name like "Ok" can be used for both types of event.

The SMT kernel delivers an external event when the program did not supply an internal event itself. This occurs at a state transition, i.e. after executing the action modules for an event. When an external event is delivered, it is converted into an appropriate internal event.

To put it another way: if none of the action modules put a value into the_next_event, then the SMT kernel will pull an event from the event queue, translate it into a suitable value, and put that into the_next_event instead.

The methods define the translation from external event to internal event. External events that do not match declared methods are rejected. This is usually a programming error, so an error message is sent to the console.

Event Management

The SMT kernel provides an level of event management. Firstly, it will destroy undelivered events after a specified expiry period. Secondly, it will automatically send return events to acknowledge receipt or non-receipt of an event. This works as follows: when you send an event, you may specify reply events for delivery, rejection, and expiry.

Priorities and Scheduling

The SMT kernel has a simple priority and scheduling mechanism. Agents run with a certain priority level (a number from 1 to 255). When the SMT kernel delivers events to threads, it schedules the threads for execution, by placing them in a queue (the active list). Threads with higher priorities are placed at the start of the active list. No account is taken of the time spent in the active list, so it is quite possible for a set of high-priority threads to take-up all execution time. This normally does not happen, since such threads will eventually wait for events from somewhere else, so become passive.

Events have a similar priority level, defined by the accepting program, in the event method. When the SMT kernel delivers an event, it chooses the event with the highest priority. One example of a high-priority event is shutdown, which is sent to all threads when the SMT kernel receives a 'kill' signal (i.e. when someone decides to stop the running program).

You can change agent and event priorities on the fly, although this may get a little complex to manage. You can also process the events in an event queue directly, without waiting for the SMT kernel to deliver each one.

In general we recommend that you leave agents and events with unspecified priority - i.e. the normal priority level - unless there are good reasons for doing otherwise.

Native Programs Vs. Foreign Programs

A native program is designed as a finite-state machine (FSM) and built using Libero and the smtschm.c schema. A native program can be multithreaded. It is tightly integrated with the SMT kernel: the kernel supplies events to the program, schedules and executes threads, etc.

A native program is also called a agent. The two terms are equivalent.

A foreign program is not based on the smtschm.c schema. It is always single threaded, and while it may call SMT kernel functions, it is not integrated with the kernel. Typically a foreign program calls the SMT kernel to send and receive events and manage floating event queues.

The SMT Kernel Meta-State-Machine

We can consider the application (an ensemble of agents, queues, threads, and events) as a meta-state-machine (i.e. a state machine that defines a set of state machines). The application has three states:

We do not usually define this as a Libero dialog, though it is possible to do so. What we must do is to write a foreign program, a stub, that implements the application meta-state- machine. This is the stub for an Internet ECHO daemon, showing the three states:

#include "sfl.h"                   /*  SFL library header file  */
#include "smtlib.h"                /*  SMT kernel functions     */

int main (int argc, char *argv [])
{
    /*  Application is latent - initialise it                   */
    smt init ();                   /*  Initialise SMT kernel    */
    smtecho init (NULL);           /*  Initialise ECHO agent    */

    /*  Application is active - execute it                      */
    smt exec full ();              /*  Run until completed      */

    /*  Application is halted - terminate it                    */
    smt term ();                   /*  Shut-down SMT kernel     */
    return (0);
}

This main code is the glue that joins the various pieces of the application.


| << | < | > | >> iMatix Copyright © 1996-99 iMatix Corporation