|
|
Calling Sequence and Naming Conventions
7.1 Overview
This chapter defines naming and calling conventions that apply to UDI environment interfaces in general. All calls of certain general types have common properties.
This chapter also defines conventions for metalanguage-specific interfaces. Some of these conventions are specified as strict requirements for all metalanguages; others are simply recommendations that may be overridden by metalanguage designers.
Generally, conventions covering required function parameters and types are strict requirements, while conventions covering function, parameter, and macro naming are recommendations. Metalanguage designers are free to use different naming conventions as long as the interface requirements defined below are met and the resulting names would be considered unique within the UDI interface namespace (at least as unique as the recommended conventions described in this chapter).
There are two function call categories to which these conventions apply: channel operations and asynchronous service calls. For more details on function call categorization see Section 4.8, "Function Call Classifications".
In addition, conventions apply to the naming of metalanguage-specific channel ops vector types and control block group numbers.
7.2 Channel Operations
Channel operations are invoked by a driver or by the environment and result in a procedure call to an operation entry point in another region. The calling sequence for the invocation of a channel operation (caller-side interface) is identical to the calling sequence for the corresponding entry point (callee-side interface). Caller-side functions have specific names, such as udi_gio_xfer_req. Callee-side functions have the same prototype as the caller-side equivalent, but will have names private to the driver, such as my_gio_xfer_req, and should be static symbols.
7.2.1 Channel Operation Invocations
Channel operations are metalanguage-specific. The invocation calls have declarations with the following form:
void <<meta>>_<<op>> ( <<meta>>_<<cbtype>>_cb_t *cb, ...<<call-dependent parms>>... );<<meta>> is a distinct prefix identifying the metalanguage, usually beginning with the prefix, "udi_". <<op>> identifies the particular channel operation within the metalanguage. <<cbtype>> identifies the particular control block type within the metalanguage. cb is a pointer to the semi-opaque metalanguage-specific control block, of type <<meta>>_<<cbtype>>_cb_t, for this operation. <<call-dependent parms>> are the zero or more metalanguage-dependent parameters for this particular channel operation.Channel operation invocation calls are required to begin with an argument with the semantics described above for cb. The name of this argument and the naming of <<meta>>, <<op>>, and <<cbtype>> are up to the metalanguage designer, but the above naming conventions are recommended.
The target channel over which to send the operation is determined by the value of cb->gcb.channel. The particular channel type to use for the operation is specified in the TARGET CHANNEL section of the reference page defining the operation.
7.2.2 Channel Operation Entry Points
The corresponding operation entry point in the target driver can have any name, but by convention has the same name as the invocation call with the initial "udi" prefix replaced by a driver-specific prefix, "ddd." In any case, the arguments will be as shown in the following declaration:
static void ddd_<<meta>>_<<op>> ( <<meta>>_<<cbtype>>_cb_t *cb, ...<<call-dependent parms>>... );This is the same as the calling sequence for the corresponding channel operation invocation.
For example, one driver may call:
udi_intr_event_ind(intr_event_cb, flags);This would result in an invocation of the target driver's entry point routine for the target channel for this operation:
udi_intr_event_ind_op_t my_intr_event_ind; : my_intr_event_ind(intr_event_cb, flags);For convenience in the declaration of ops vector types and operation entry point forward declarations, a standard typedef shall be defined by the metalanguage header files for each operation type, in the form:
typedef void <<meta>>_<<op>>_op_t ( <<meta>>_<<cbtype>>_cb_t *cb, ...<<call-dependent parms>>... );7.3 Asynchronous Service Calls
Asynchronous service calls are calls to the environment in which the result may not be immediately available and is therefore supplied via a callback routine rather than as a direct return value of the service call itself (see Section 4.8.1.2). These types of calls are a core mechanism of the non-blocking UDI model of execution.
7.3.1 Asynchronous Service Call Invocations
Asynchronous service calls all have declarations with the following form:
void udi_<<category>>_<<service>> ( udi_<<category>>_<<service>>_call_t *callback, udi_cb_t *gcb, ...<<call-dependent parms>>... );<<category>> is a distinct prefix identifying the service category, such as "buf" for buffer management. <<service>> identifies the particular service within the category. callback is a pointer to the driver's callback routine, of type udi_<<category>>_<<service>>_call_t. gcb is a pointer to a generic control block. <<call-dependent parms>> are the zero or more specific additional parameters for this service call.7.3.2 Associated Callback Functions
Callback functions are called upon completion of the service request. The declaration for each callback type appears on the reference page along with the associated service call, in the following form:
typedef void udi_<<category>>_<<service>>_call_t ( udi_cb_t *gcb, ...<<callback-dependent parms>>... );<<callback-dependent parms>> are zero or more additional parameters specific to this callback type.In the driver's code, the callback routine would appear as:
static void ddd_<<category>>_<<service>>_callback ( udi_cb_t *gcb, ...<<callback-dependent parms>>... ) { ... }For example, a driver may call the environment as follows to obtain a new control block:
udi_cb_alloc(&my_cb_alloc_callback, gcb, my_cb_idx, chan);which will result in calling the following callback when the allocation is complete:
udi_cb_alloc_call_t my_cb_alloc_callback; : my_cb_alloc_callback(gcb, new_cb);7.3.3 Control Block Type Conversion
Although the asynchronous service calls are defined to use a "generic control block", the driver may use any control block for this purpose because all control blocks are a superset of the generic control block definition. The control block passed to a driver via a channel operation entry point is typically used for all asynchronous service calls and the subsequent channel operation made while processing that operation.
The UDI_GCB() macro (defined on page 11-11) is provided for convenience in converting a specific control block pointer to a generic control block pointer, in order to pass it to a service call. Using this macro, a typical asynchronous service call invocation becomes:
udi_<<category>>_<<service>>(callback, UDI_GCB(cb), ...);The UDI_MCB() macro (defined on page 11-12) is provided for convenience in converting a generic control block pointer back to a specific control block type. Using this macro, a callback routine typically begins with:
<<meta>>_<<cbtype>>_cb_t *cb = UDI_MCB(gcb, <<meta>>_<<cbtype>>_cb_t);7.4 Channel Operations Vectors
The channel operations vector structure ("ops vector") used with each type of channel endpoint is defined in each metalanguage. These structures generally have declarations of the following form:1
typedef struct { udi_channel_event_ind_op_t *channel_event_ind_op; <<meta>>_<<op_1>>_op_t *<<op_1>>_op; ... <<meta>>_<<op_N>>_op_t *<<op_N>>_op; } <<meta>>_<<role>>_ops_t;<<meta>> and <<role>> are defined as above in the "ops_init" calling sequence. <<op_1>>..<<op_N>> identifies one or more channel operation entry point types that belong to this ops vector. These have the callee-side calling sequences defined in Section 7.2.2, "Channel Operation Entry Points".Each entry in the ops vector is the driver's entry point for the corresponding channel operation.
Associated with each ops vector definition is a metalanguage-defined number that identifies this ops vector type with respect to others in the same metalanguage. Metalanguages must define both the numeric value and a mnemonic to use for that value. The mnemonic is typically named:
<<meta>>_<<role>>_OPS_NUM<<meta>> and <<role>> are upper-case versions of those used in the above type definition.7.5 Control Block Groups
Associated with each control block group is a metalanguage-defined number that identifies this control block group with respect to others in the same metalanguage. Metalanguages must define both the numeric value and a mnemonic to use for that value. The mnemonic is typically named:
<<meta>>_<<cbgroup>>_CB_NUM1The Management Metalanguage deviates from this form in that it doesn't have a channel_event_ind_op as the first member; all other metalanguages must have the first member of type udi_channel_event_ind_op_t as shown here.