DOC HOME SITE MAP MAN PAGES GNU INFO SEARCH PRINT BOOK
 
TOC PREV NEXT INDEX

Execution Model

4

4.1 Introduction

UDI drivers are prepared for execution in a target environment by compiling driver source code for a target system, either directly on the target system or by separate compilation into relocatable object files. The result is one or more independent executable modules, called driver modules where each module is comprised of a set of object files (as defined by the driver's static driver properties file, see Chapter 30).

4.2 Driver Object Modules

A driver's executable is composed of one or more UDI driver modules, each of which can be separately loaded and executed (e.g., into separate addressing domains or protection/privilege domains). Driver writers need to consider the partitioning of their driver into modules in conjunction with the partitioning of driver instances into regions, as described in "Multi-Module Drivers". Each driver module handles some (mutually-exclusive) subset of the driver's region types. Each driver has one module, called the primary module, which handles the driver's primary region. Additional modules, called secondary modules, may be defined by the driver. The driver specifies its modules via the "module" property declaration in the driver's udiprops.txt configuration file (see Chapter 30).

Each UDI driver module has a single well-known global variable, named udi_init_info that describes the module's entry points and size requirements. (See udi_init_info.) There are no global entry points into UDI drivers; all entries are through function pointers in udi_init_info.

4.3 Driver Instances

In general, an instance refers to a specific occurrence of a generic item. An instance of a device, or device instance, refers to a specific occurrence of that device in a system. An instance of a driver, or driver instance, refers to the driver code attached to a particular device or pseudo-device combined with a set of driver state (control values, queues, control memory, etc.) that serve that device. The driver state associated with a particular device is often referred to as per-instance state. Even though driver instance are logically separate, environment implementations may use a single copy of the driver code for multiple instances of the same driver.

4.4 Regions

A driver instance is composed of one or more well-defined sub-divisions called regions. A region is implicitly serialized by the UDI environment, and thus defines the unit of concurrent execution. There is no shared memory between regions. This allows driver regions to be separately replaceable and locatable (e.g., in different address or protection domains), supporting the instance-independence and location-independence of UDI drivers. (See Chapter 5, "Data Model" for a discussion of instance-independence, and Section 4.9 for a discussion of location-independence).

4.4.1 Driver Partitioning

Driver writers need to consider the partitioning of their driver into regions when designing the driver. A simple driver may be composed of a single region; more complex drivers may be composed of multiple regions. The former is called a single-region driver; the latter a multi-region driver; but in either case it must be emphasized that regions are sub-divisions of a driver instance.

Many driver instances are composed of multiple state machines, roles, or cooperating functions. For example, a driver may have a somewhat distinct state machine that handles outbound packets, another to handle inbound packets, a third to handle timeouts, etc. When a driver is designed, such separable pieces of the driver may be defined to run in separate regions.

When a driver is instantiated, an initial region is created by the environment; this is called the driver's primary region. If requested by the driver, additional regions, called secondary regions, are also created.

4.5 Multi-Module Drivers

Each module in a multi-module driver contains the code and static data for one or more mutually-exclusive region types. Each module contains its own udi_init_info structure.

The primary module must contain all of the code and static data for the primary region and may contain the code and static data for one or more secondary regions as well. Other modules ("secondary modules") must not specify a primary_init_info structure in their udi_init_info initialization structures.

4.6 Channels

A channel is a point-to-point communication and connection mechanism between two regions. This point-to-point design allows for simplicity of connection build-up and tear-down and low-overhead of the communication path. Attached to each end of a channel (a channel endpoint) is a set of driver entry points called a channel operations vector or ops vector. The definition of the channel operations implemented by these entry points (along with associated service routines, attribute bindings, etc.) for a particular type of channel is referred to as a metalanguage.

Channels form the basis of all communication between regions, since regions cannot share data directly. Channels are also used to communicate with the Management Agent and other logical entities within the environment that act as though they were executing in UDI driver regions. (The Management Agent manages driver and device instance configuration, and is described in more detail in Chapter 24, "Management Metalanguage".)

4.7 Driver Execution Environments

All execution of driver code within UDI is done on a per-instance basis. Each instance is said to execute in the context of a region or in region context, and has access to driver and environment state associated with the particular region for which it was invoked.

Note - The UDI Physical I/O Specification defines a special type of region, called an interrupt region, that has additional restrictions in its execution environment.

4.7.1 Non-Blocking Model

While executing in the context of a region, UDI drivers are non-blocking; i.e. any service call that may require access to external resources or delayed completion is defined with a callback function so that the UDI environment does not have to block the thread from which the driver was called while waiting for resources. See the discussion of asynchronous service calls below for additional details.

4.8 Function Call Classifications

Function calls used by UDI drivers can be categorized as either calls into the driver (driver entry points), calls from the driver to the environment to request environment services (environment service calls), or calls over channels between driver or environment regions (metalanguage-specific channel operations). Channel operations are specified in terms of both the caller side (channel operation invocation) and callee side (channel operation entry point). Some service calls complete asynchronously and re-enter the driver via callback functions.

A UDI driver executes within the context of a region at all times and all driver entry points (channel operation entry points and callbacks from service calls) are called with region context. All channel operation invocations and service calls are called within the context of a region.

UDI environments also provide a set of utility functions, which are convenience functions defined for the driver. These convenience functions do not perform any operations that the driver could not do directly via its code and therefore do not set or test any environment state. These utilities may be implemented as environment function calls or as macros that result in inline code in the driver itself.

The following figure illustrates these function call categories.


4.8.1 Service Calls

UDI drivers request services of the UDI environment by calling environment service calls. These are functions provided by the environment and exported to all UDI drivers.

Service calls are common to all types of drivers. They are not metalanguage-specific.

4.8.1.1 Synchronous Service Calls

Service calls that can reasonably be expected to complete "immediately" (or at least in a small, finite amount of time) on all environment implementations are specified in the form of synchronous service calls. Synchronous service calls run entirely in the context of the calling region and complete all processing required to satisfy the request before returning to the calling driver.

Synchronous service calls are identifiable by the lack of a callback argument.

4.8.1.2 Asynchronous Service Calls

Service calls that might not complete "immediately" are specified in the form of asynchronous service calls. These need to operate asynchronously, returning results and/or completion status via callbacks (calls "back" into the driver) rather than as output parameters or return values from the service call itself. Any service call that might require allocation, access to external resources, or delayed completion shall be asynchronous. (This is required by UDI's non-blocking model-drivers executing in a region context cannot block the calling thread in order to wait for resources or I/O events.)

When an asynchronous service call returns to the calling driver, the service may or may not be complete. The associated callback may happen immediately, before the service call returns to the driver, or later, after the driver itself returns to its caller and the resource subsequently becomes available. The only restriction on callbacks is that they must not violate the region execution model and therefore delayed callbacks (ie. callbacks that occur after the service call has returned to the driver) must wait for any current execution in the region to complete before being scheduled to execute in that region (also see Section 5.5, "Implicit MP Synchronization"). Immediate callbacks may execute immediately before returning from the service call without violating region synchronization because only one thread of execution remains active in the region.

In the case of a delayed callback, the environment needs to be able to queue the pending request or callback and the driver must be able to continue the operational context that indicated the asynchronous call. In order to provide space for queuing the request (if needed) and maintaining the driver context a control block is passed to each asynchronous service call.

Control blocks are a finite resource that are provided to or allocated by the driver. Between the time that the service call is made and the time that the callback is called, the control block is under the control of the environment and must not be used in any way by the driver, except to cancel the service call (see udi_cancel). Only one allocation request must be pending on a given control block at a time. Any attempt to start another request using a control block that is already in use will produce indeterminate results.

Any type of control block can be used for this purpose. Because of this, the service calls are defined in terms of a least-common-denominator control block, which is itself part of every actual control block. This generic control block is denoted with the data type, udi_cb_t (see page 11-3).

4.8.2 Channel Operations

Channel operations are invoked by a driver or by the environment on one end of a channel and result in a procedure call to an operation entry point in another region at the other end of the channel.

Like asynchronous service calls, channel operations require control blocks, so the environment can queue them if the target region is busy. Control blocks used with channel operations can also be used by the environment to marshal and unmarshal1 other parameters and data passed to the operations if they need to be queued or transferred between separate domains.

Any channel operations queued by the environment will be delivered in FIFO order to the region; the region is unaware of the queueing. The environment must ensure that operations queued to a region are delivered in FIFO order relative to the channel on which they are queued, but there is no ordering between channels, therefore requests arriving to a region on different channels may be presented to the region in any order as long as they order preserves the FIFO ordering of the individual channels. There are also no ordering requirements imposed on callbacks which enter the region as a result of asynchronous call completions. If a metalanguage requires that the driver process operations in the order received, the metalanguage specification will indicate this requirement and the driver must insure that ordering is maintained with regards to forwarding or responding to those operations.

4.9 Location Independence

The UDI execution model also provides for location independence, which is the ability to instantiate and execute a driver's code without requiring that code to be run in a particular domain (e.g. kernel, user, etc) or even on the same node in a cluster. Within UDI the fundamental unit of execution is defined as the region (see Section 4.4) and this is therefore the level at which location independence can be applied. Two regions within the same driver may be located independently since there is no shared memory or other external access by either region outside of the UDI specified interfaces (which are expressly designed to allow for location independence).

The location of a region instantiation is determined by the environment implementation and may be affected by a number of considerations, including environment architecture, resource availability or utilization, and driver-specified region attributes (see Section 30.6.8, "Region Declaration").

4.10 Driver Faults/Recovery

Any improper usage of the UDI service calls or illegal usage of UDI control blocks or other illegal actions on the part of a UDI driver (see the definition of "illegal" in Section 3.2.1, "Directive Terms") will lead to implementation-dependent and, in some environments, indeterminate results. Since the driver cannot in general be expected to recover from its own misbehavior, it's left to the environment to determine appropriate actions in such cases. One such action, which has been defined and enabled in various parts of the UDI Specifications, is to abruptly terminate the corresponding driver instance. Such abrupt termination is sometimes referred to as being "region-killed" or "instance-killed", the latter referring to region-kills of all the regions in an instance.

4.10.1 Overview of Region-Kill

When an illegal action is detected by the UDI environment that results in an abrupt termination (region-kill) of the offending region, the region will typically be exited immediately and will be marked to disallow any further entries into the region. If the offending region is part of a Physical I/O Driver that has registered a "PIO Abort Sequence" handle via a udi_pio_abort_sequence then the associated PIO sequence will be executed to shut down the corresponding device. All channels attached to the region will then be closed, notifying any neighbors that the region has abruptly terminated. Any control blocks marked "recoverable" (via UDI_MEI_OP_RECOVERABLE) will be returned to the initiating region via the corresponding response operation, where applicable, along with associated transferable objects. Lastly, all other data objects owned by that region, including control blocks, allocated memory, and buffers, will be freed and the region destroyed. As a result of the channel closes, any neighboring regions must cease operation on channels to that region.

4.10.2 Improper Channel Operation Usage

UDI channel operations involve the source region, the associated metalanguage library, environment support code, and the target region. Illegal actions detected by the environment while between regions doing a channel operation may result in a region-kill of the source region. Illegal actions detected by the metalanguage library (considered to be a portable metalanguage library for purposes of this discussion, since a non-portable metalanguage library can be considered to be part of the environment) should result in a call to udi_mei_driver_error by the metalanguage library code. This may result in either an immediate error response operation back to the source region with status UDI_STAT_NOT_UNDERSTOOD or a region-kill operation by the environment.

Illegal actions by the source driver that end up being detected in the target driver must result in an appropriate status such as UDI_STAT_NOT_UNDERSTOOD being sent back in the corresponding response operation, when applicable, to the offending source region, and as defined in UDI Tracing and Logging, a call to udi_log_write.

4.11 Metalanguage Model

4.11.1 Metalanguage Roles

Each metalanguage defined in the UDI environment is typically bilaterally asymetric. In other words, the region at one end of the channel will typically initiate operations and the region at the other end of the channel will typically respond to operations. This is exemplified by the metalanguage-specific bind operation where one side initiates the metalanguage-specific binding and the other side responds to that binding.

In this context, each end of the channel is referred to as playing a role in the overall metalanguage design. This role is often referred to as either the "parent" role or the "child" role based on the typical device node tree representation of the device drivers, but this sense of orientation does not always apply.

Each metalanguage will therefore define the role for each end of the channel and will typically define the metalanguage operations and states in terms of those roles.

Example metalanguage roles:

4.11.1.1 Management Metalanguage Roles

The Management Metalanguage is somewhat unusual in that there are three parties rather than the usual two: the Management Agent (MA), the Parent, and the Child. There are also three channels involved:

  1. MA--Parent channel (a.k.a. the parent's management channel)
  2. MA--Child channel (a.k.a. the child's management channel)
  3. Parent--Child channel (a.k.a. the child's bind channel)

In this configuration the Management Metalanguage accordingly defines three roles: the "MA", the "parent", and the "child". For more information, see Chapter 24, "Management Metalanguage".

1Marshalling is the activity of identifying and possibly collecting all of the information related to the request so that the information may be moved to a different domain (via an unspecified mechanism) where it will be unmarshalled back into operational form to deliver to the recipient.


TOC PREV NEXT INDEX