|
|
Inter-Module Communication
16.1 Overview
The Inter-Module Communication (IMC) services allow drivers to create new channels, to anchor channels within a region, to dynamically set the channel context, and to close a channel. This chapter also defines the channel event indication operation, which is used to send channel-related events from the environment to a driver. See Chapter 4, "Execution Model", for an introduction to regions and channels.
16.2 Service Calls
This section defines service calls that allow drivers to create and anchor channels, dynamically set a channel's context, close a channel, abort outstanding channel operations, and process channel-related events.
Note that the primary region and management channel for each driver instance are provided to the driver automatically by the Management Agent when the driver instance is created based on information provided by the driver in its udi_init_info variable. If the driver has indicated that it requires static secondary regions, they will also be created at this time, along with an internal bind channel between the primary region and each such secondary region. If the driver has requested dynamic secondary regions, additional secondary regions and corresponding internal bind channels will be created later, when appropriate child or parent instances are being bound to this driver instance.
Drivers can spawn new channels at any time, but it is the driver's responsibility to allocate, track and return these objects back to the environment in a responsible manner. Drivers must not free any channels not explicitly spawned by the driver, via calls to the services in this chapter.
NAME udi_channel_anchor
Anchor a channel to the current region
#include <udi.h>void udi_channel_anchor ( udi_channel_anchor_call_t *callback, udi_cb_t *gcb, udi_channel_t channel, udi_index_t ops_idx, void *channel_context ); typedef void udi_channel_anchor_call_t ( udi_cb_t *gcb, udi_channel_t anchored_channel );ARGUMENTS callback, gcb are standard arguments described in the "Asynchronous Service Calls" section of "Calling Sequence and Naming Conventions".
channel is the channel handle for the loose end to be anchored. Once udi_channel_anchor is called, the driver may no longer use this handle.
ops_idx is an ops index for the ops vector that the driver wants to associate with the specified channel, as indicated by the appropriate udi_ops_init_t in udi_init_info. ops_idx must be non-zero.
channel_context is a channel context pointer to be associated with the anchored channel endpoint.
anchored_channel is the new channel handle for the now-anchored channel endpoint. This handle must subsequently be used to access the channel, rather than the original handle passed to udi_channel_anchor.
WARNINGS Control block usage must follow the rules described in the "Asynchronous Service Calls" section of "Calling Sequence and Naming Conventions".
DESCRIPTION udi_channel_anchor is used to anchor a loose channel end to the current region. Loose ends may be passed to a driver from another region, or as the result of a udi_channel_spawn request. Management channels, external bind channels between driver instances, and internal bind channels between primary and secondary regions are always pre-anchored.
Once anchored, the channel endpoint is permanently associated with the current region, and has an associated ops vector and channel context. Loose ends may be anchored, but anchored ends may not be made loose.
Loose ends may be passed between regions as parameters to channel operations. Anchored ends may not.
When the anchoring is complete, the UDI environment will invoke the callback to notify the requestor of the completion, and return ownership of the control block (gcb) to the driver.
Once both ends of the channel are anchored, the channel may be used for communication, by invoking channel operations. Drivers must ensure that both ends are anchored and ready to go before invoking any operations on the channel. This is typically done via metalanguage-specific handshaking on another channel.
REFERENCES udi_init_info, udi_cancel, udi_channel_spawn
NAME udi_channel_spawn
Spawn a new channel
#include <udi.h>void udi_channel_spawn ( udi_channel_spawn_call_t *callback, udi_cb_t *gcb, udi_channel_t channel, udi_index_t spawn_idx, udi_index_t ops_idx, void *channel_context ); typedef void udi_channel_spawn_call_t ( udi_cb_t *gcb, udi_channel_t new_channel );ARGUMENTS callback, gcb are standard arguments described in the "Asynchronous Service Calls" section of "Calling Sequence and Naming Conventions"
channel is the channel handle for an existing anchored channel. The new channel will be spawned relative to this channel.
spawn_idx is a small integer which allows the environment to match two spawn requests (one from each end of the channel) together.
ops_idx is an ops index for the ops vector that the driver wants to associate with the specified channel, as indicated by the appropriate udi_ops_init_t in udi_init_info, or zero.
channel_context is a channel context pointer to be associated with the new anchored channel endpoint.
new_channel is the channel handle for the new channel's local endpoint, which will be a loose end. This handle must subsequently be passed to udi_channel_anchor, either in this region, or after passing it to another region via a channel operation.
WARNINGS Control block usage must follow the rules described in the "Asynchronous Service Calls" section of "Calling Sequence and Naming Conventions".
DESCRIPTION udi_channel_spawn is used to create a new channel (initially) between the same two regions as an existing channel. Both ends must be created separately by their own calls to udi_channel_spawn.
If ops_idx is zero, the channel endpoint is created as a loose end, which must be anchored before it can be used. Loose ends may be passed between regions, and even between drivers, before being anchored.
The pair of the original channel handle and the spawn index uniquely identify an in-progress spawn operation. The callback routine is called once the local end of the channel has been created and, if specified, anchored. The other region may or may not yet have completed its end of the spawn.
Drivers must ensure that both ends have completed spawning and are anchored and ready to go before invoking any operations on the channel. This is typically done via metalanguage-specific handshaking on the original channel.
REFERENCES udi_init_info, udi_cancel, udi_channel_anchor
NAME udi_channel_set_context
Attach a new context to a channel endpoint
#include <udi.h>void udi_channel_set_context ( udi_channel_t target_channel, void *channel_context );ARGUMENTS target_channel is a channel handle for the channel endpoint to be modified.
channel_context is a generic pointer that will be returned as-is by UDI in any channel operations related to this channel.
DESCRIPTION udi_channel_set_context attaches a new context pointer to the local end of a target channel. The new context pointer will be attached to the referenced channel (target_channel) by the time this call returns. It will then be passed to the driver with each channel operation in the gcb.channel_context member of the control block.
WARNINGS udi_channel_set_context must be called from the region containing the channel endpoint. This endpoint must already be anchored.
NAME udi_channel_op_abort
Abort a previously issued channel operation
#include <udi.h>void udi_channel_op_abort ( udi_channel_t target_channel, udi_cb_t *orig_cb );ARGUMENTS target_channel is a channel handle for the channel to which the previously issued operation was sent.
orig_cb is a control block pointer for the control block that was sent with the original operation. Even though the driver no longer owns that control block, it is allowed to use the otherwise stale pointer only with this service call.
DESCRIPTION udi_channel_op_abort delivers a UDI_CHANNEL_OP_ABORTED event via udi_channel_event_ind to the other end of the target channel, in order to request that a previously sent request, using orig_cb as its control block, be aborted.
The original operation must be of an operation type defined to be abortable by the relevant metalanguage definition. Metalanguage libraries indicate that operations are abortable by using the UDI_MEI_OP_ABORTABLE flag in the corresponding udi_mei_op_template_t.
The original control block, identified by orig_cb, must previously have been sent on the target channel using an abortable operation, and must not yet have been returned (via a metalanguage-specific operation) to the initiating region. The control block is aborted and returned to the current driver via the normal metalanguage completion operation with a status of UDI_STAT_ABORTED to indicate that the operation was aborted; operations that have already completed will be passed back to the current module in the normal fashion without the abort status indication.
Even if the control block was originally sent as part of a chain of control blocks sent with one operation, only the specific control block indicated by orig_cb is aborted.
Drivers receiving abortable control blocks must not free them but must (eventually) return them over the same channel on which they were received.
references udi_channel_event_cb_t, udi_channel_event_ind, udi_mei_op_template_t
NAME udi_channel_close
Close a channel
#include <udi.h>void udi_channel_close ( udi_channel_t channel );ARGUMENTS channel is a channel handle for the channel endpoint being closed.
DESCRIPTION udi_channel_close deallocates and returns any channel-related resources to the UDI environment. Normally a driver calls this routine only as a result of receiving a channel_event_ind operation of type UDI_CHANNEL_CLOSED, to close its end of the channel.
The result of this routine is immediate: the channel endpoint will be closed and freed when this call returns. It is the responsibility of the driver to clean up all channel-related state and resources first, so as to maintain architectural integrity before destroying a channel. This must include the processing of all outstanding operations related to the channel. The driver should ensure, via proper channel operation handling, that all operations directed to this channel have been completed and that no more will be generated. Any operations previously sent to this channel but not yet delivered at the time this routine is called will be treated as having been initiated after the channel was closed.
When one end of a channel is closed, either by the driver explicitly calling udi_channel_close or by the environment if a driver is killed, the other end receives a udi_channel_event_ind operation of type UDI_CHANNEL_CLOSED. This tells the driver at the other end that one of its neighbors has gone away unexpectedly. (See page 16-13 for the definition of the udi_channel_event_ind operation).
udi_channel_close may be used on loose ends, as well as anchored channel endpoints.
If a driver calls udi_channel_close on a channel whose other end is loose, the udi_channel_event_ind operation will be delivered if and when that other end is anchored.
If a driver invokes an operation on a channel whose other end is closed, it will be ignored and any associated control blocks and data objects will be freed.
Once both ends of a channel are closed, all environment resources associated with the channel are released. Calling udi_channel_close on the single end of a half-spawned channel has this effect as well.
udi_channel_close acts as a no-op if channel is a null handle, but must not be called for a channel that has already been closed with a previous call to udi_channel_close.
WARNINGS udi_channel_close must not be used with a channel handle that has been passed to another region. udi_channel_close must not be used on management channels.
REFERENCES udi_channel_event_ind, udi_channel_anchor, udi_channel_spawn
16.3 Channel Event Indication Operation
The one channel operation common to all metalanguages (except the Management Metalanguage) is the udi_channel_event_ind operation. It is always the first operation in any channel ops vector. It is automatically invoked by the environment whenever one of several channel-related events occurs:
- A udi_channel_event_ind operation of type UDI_CHANNEL_CLOSED is passed to the other end of a channel whenever a channel is closed. This can occur as a result of an explicit udi_channel_close (see page 16-8) or as a result of the region being prematurely terminated by the environment.
- A udi_channel_event_ind operation of type UDI_CHANNEL_BOUND is passed to the initiator end of a newly created bind channel after it has been anchored (by the environment) on both ends. The initiator, as opposed to responder, is the driver (or environment entity) that generally initiates requests to the responder (see the description of relationship on page 28-4 for more details on these metalanguage roles). This allows the initiator to acquire the channel handle for its end of the channel (via the channel member of the control block), so it can send the first request. The responder acquires its channel handle as a result of this first request.
- A udi_channel_event_ind operation of type UDI_CHANNEL_OP_ABORTED is passed to the other end of a channel whenever a driver calls udi_channel_op_abort (see page 16-7), in order to abort a previously sent channel operation.
The udi_channel_event_ind operation is used in all metalanguages except the Management Metalanguage, but is defined only once, here in this chapter in the reference pages that follow.
NAME udi_channel_event_cb_t
Channel event control block
#include <udi.h>typedef struct { udi_cb_t gcb; udi_ubit8_t event; union { struct { udi_cb_t *bind_cb; } internal_bound; struct { udi_cb_t *bind_cb; udi_ubit8_t parent_ID; udi_buf_path_t *path_handles; } parent_bound; udi_cb_t *orig_cb; } params; } udi_channel_event_cb_t; /* Channel event types */#define UDI_CHANNEL_CLOSED 0 #define UDI_CHANNEL_BOUND 1 #define UDI_CHANNEL_OP_ABORTED 2MEMBERS gcb is the standard control block section providing scratch space and context information.
event is the type of event that is being indicated:
UDI_CHANNEL_CLOSED indicates that the remote end of the channel has been closed. The driver receiving this event must clean up any channel-related resources and call udi_channel_close on its end of the channel after calling udi_channel_event_complete.
UDI_CHANNEL_BOUND indicates that another region has been bound to this region as a result of a "parent_bind_ops" or "internal_bind_ops" declaration from this driver's static driver properties (see Chapter 30, "Static Driver Properties"), and that this channel was created as a result of that binding. The driver receiving this event may now begin using the channel for normal operations, usually beginning with a metalanguage-specific bind request. (For internal bindings, only the region using the initiator role in the corresponding metalanguage receives the UDI_CHANNEL_BOUND indication.)
For parent bindings, the parent_ID field will contain an environment-assigned parent ID that identifies the particular parent instance. The parent_ID value will never be zero; zero is reserved for environment use. Single-parent drivers can ignore this field.
The driver must not call udi_channel_event_complete for this event until its entire bind sequence has completed.
See Chapter 24, "Management Metalanguage", for more details on the bind sequence.
UDI_CHANNEL_OP_ABORTED indicates that an abort request has been generated (using udi_channel_op_abort) by the driver on the other end of the channel, with respect to a previous metalanguage-specific abortable request (the original request). The driver receiving this event must abort any outstanding processing for the original request and fail it with a status code of UDI_STAT_ABORTED; it may do this before or after calling udi_channel_event_complete. The orig_cb field will point to the control block for the original request, which is guaranteed to be an abortable control block currently owned by this region (though it may be in use with an environment service call on behalf of this region). Drivers receiving abortable control blocks must not free them but must (eventually) return them over the same channel on which they were received.
orig_cb is a pointer to the control block for the original request being aborted by a UDI_CHANNEL_OP_ABORTED channel event. For all other channel events, the value of orig_cb is unspecified and must not be used by the driver.
bind_cb is a pointer to the pre-allocated control block for the metalanguage-specific bind request that the driver will issue as a result of the UDI_CHANNEL_BOUND event. This control block type is indicated by the <bind_cb_idx> value of the corresponding "parent_bind_ops" declaration (see Section 30.6.3) or "internal_bind_ops" declaration (see Section 30.6.4). For all other channel events or if <bind_cb_idx> was zero then no control block will be allocated and the value of bind_cb is unspecified and must not be used by the driver.
parent_ID is a unique non-zero value supplied by the MA during a UDI_CHANNEL_BOUND event on a parent bind channel, to explicitly identify the parent driver instance being bound. Drivers that have multiple parents will be assigned a unique parent_ID value for each parent. This parent_ID is used for any operations that need to identify a specific parent to which those operations are related (e.g. the enumeration and device management operations of the Management Metalanguage). If the event was not for a parent binding, this member's value is unspecified and must be ignored.
The MA may assign parent IDs in any order.
path_handles is a pointer to an array of udi_buf_path_t handles that may be used by the driver when allocating buffers on behalf of the parent being bound. These handles are maintained in an inline array associated with the channel event control block and must be copied to instance-internal storage before the control block is passed to udi_channel_event_complete. If the event was not for a parent binding, this member's value is unspecified and must be ignored.
DESCRIPTION The udi_channel_event_cb_t control block is a semi-opaque object used between the environment and the driver in channel event indication operations. When passed to the target driver, this control block provides a context for the operation and must be returned to the environment by calling udi_channel_event_complete.
Unlike with other control blocks, the value of gcb.channel for a channel event control block is unspecified and must not be modified.
Unlike with other control blocks, there is no way to list attributes of a udi_channel_event_cb_t in a udi_cb_init_t initialization structure, so the scratch space size for udi_channel_event_cb_t control blocks is always zero.
Drivers cannot allocate udi_channel_event_cb_t control blocks.
REFERENCES udi_channel_event_complete, udi_channel_close, udi_channel_op_aborted, udi_constraints_propagate, udi_layout_t
NAME udi_channel_event_ind
Channel event notification (env-to-driver)
#include <udi.h>void udi_channel_event_ind ( udi_channel_event_cb_t *cb ); typedef void udi_channel_event_ind_op_t ( udi_channel_event_cb_t *cb );ARGUMENTS cb is a channel event control block allocated by the environment and used to hold details of the specific channel event.
TARGET CHANNEL The channel over which the event is to be delivered.
DESCRIPTION This channel operation is used by the environment to signal that a generic event has occured on the other end of the channel. The type of event that has occured, and additional parameters for the event, are contained in the udi_channel_event_cb_t control block.
If a driver receives an unexpected UDI_CHANNEL_CLOSED event indication on a parent or child channel, it must treat it as an "abrupt unbind", as described in Section 24.6, "Device Management Operations".
If a driver closes its end of the channel itself (with udi_channel_close) before the other end is closed or before a udi_channel_event_ind of type UDI_CHANNEL_CLOSED is serviced, it will not receive a UDI_CHANNEL_CLOSED indication.
Once a UDI_CHANNEL_CLOSED indication has been received on a given channel, no other operations will be received on that channel.
Once the driver has completed processing the channel event, it must return the control block to the environment using udi_channel_event_complete. Drivers must not directly free channel event control blocks.
WARNINGs Drivers must not invoke this operation.
Drivers handling UDI_CHANNEL_OP_ABORTED events should be careful to abort the referenced control block (or at least mark it as having an abort in progress) before returning from the udi_channel_event_ind operation, to avoid race conditions with normal completions.
references udi_channel_event_cb_t, udi_channel_event_complete
NAME udi_channel_event_complete
Complete a channel event (driver-to-env)
#include <udi.h>void udi_channel_event_complete ( udi_channel_event_cb_t *cb, udi_status_t status );ARGUMENTS cb is a channel event control block from udi_channel_event_ind.
status is a UDI status code used to indicate the success or failure of some event types. Unless otherwise specified, drivers must set status to UDI_OK.
DESCRIPTION udi_channel_event_complete is called by a driver that has previously received a udi_channel_event_ind notification from the environment after that driver has processed the event. Drivers must not directly free channel event control blocks.
status values UDI_OK The event was processed successfully.
UDI_STAT_CANNOT_BIND A parent binding triggered by a UDI_CHANNEL_BOUND event failed because the metalanguage specific bind process was rejected by the parent, or was otherwise unsuccessful.
UDI_STAT_TOO_MANY_PARENTS A parent binding triggered by a UDI_CHANNEL_BOUND event failed because this driver instance is already bound to the maximum number of parents that it can support.
UDI_STAT_BAD_PARENT_TYPE A parent binding triggered by a UDI_CHANNEL_BOUND event failed because the parent metalanguage or device properties (as determined by the parent-specified enumeration attributes) for the binding cannot be supported by this driver instance in its current state.
UDI_STAT_ATTR_MISMATCH A parent binding triggered by a UDI_CHANNEL_BOUND event failed because the child could not comply with one or more of the custom attribute settings already specified for the newly-created child instance.
warnings The control block must be the same control block as passed to the driver in the corresponding udi_channel_event_ind operation.