OpenVMS Utility Routines Manual
18.1.7.1 Synchronous Versus Asynchronous Delivery of Requests
When you initialize your symbiont/job controller interface, the
symbiont has the option of accepting requests from the job controller
sychronously or asynchronously.
Synchronous Environment
The address of an AST routine is an optional argument to the
SMB$INITIALIZE routine; if it is not specified, the symbiont receives
messages from the job controller synchronously. A symbiont that
receives messages synchronously must call SMB$CHECK_FOR_MESSAGE
periodically during the processing of tasks in order to ensure the
timely delivery of STOP_TASK, PAUSE_TASK, and RESET_STREAM requests.
SMB$CHECK_FOR_MESSAGE checks to see if a message from the job
controller is waiting. If a message is waiting, SMB$CHECK_FOR_MESSAGE
returns a success code. The caller of SMB$CHECK_FOR_MESSAGE can then
call SMB$READ_MESSAGE to read the message and take the appropriate
action.
If no message is waiting, SMB$CHECK_FOR_MESSAGE returns a zero in R0.
The caller of SMB$CHECK_FOR_MESSAGE can continue to process the task at
hand.
Figure 18-2 is a flowchart for a synchronous, single-threaded
symbiont. The flowchart does not show all the details of the logic the
symbiont needs and does not show how the symbiont handles PAUSE_TASK,
RESUME_TASK, or RESET_STREAM requests.
Figure 18-2 Flowchart for a Single-Threaded, Synchronous
Symbiont
Asynchronous Environment
To receive messages asynchronously, a symbiont specifies a
message-handling AST routine as the second argument to the
SMB$INITIALIZE routine. In this scheme, whenever the job controller
sends messages to the symbiont, the AST routine is called.
The AST routine is called with no arguments and returns no value. You
have the option of having the AST routine read the message within the
context of its execution or of having the AST routine wake a suspended
process to read the message outside the context of the execution of the
AST routine.
Be aware that an AST can be delivered only while the symbiont is not
executing within the context of an AST routine. Thus, in order to
ensure delivery of messages from the job controller, the symbiont
should not perform lengthy operations at the AST level.
This is particularly important to the execution of STOP_TASK,
PAUSE_TASK, and RESET_STREAM requests. If a STOP_TASK request cannot be
delivered during the processing of a task, for example, it is useless.
One technique that ensures delivery of STOP and PAUSE requests in an
asynchronous environment is to have the AST routine set a flag if it
reads a PAUSE_TASK, STOP_TASK, or a RESET_STREAM request and to have
the symbiont's main routine periodically check the flag.
Figure 18-3 and Figure 18-4 show flowcharts for a single-threaded,
asynchronous symbiont. The figures do not show many details that your
symbiont might include, such as a call to the $QIO system service.
Note that the broken lines in Figure 18-3 that connect the calls to
$HIBER with the AST routine's calls to $WAKE show that the next action
to take place is the call to $WAKE. They do not accurately represent
the flow of control within the symbiont but represent the action of the
job controller in causing the AST routine to execute.
Figure 18-3 Flowchart for a Single-Threaded, Asynchronous
Symbiont (MAIN Routine)
Figure 18-4 Flowchart for a Single-Threaded, Asynchronous
Symbiont (AST Routine)
18.1.7.2 Single-Streaming Versus Multistreaming
A single-stream (or thread) is a logical link between a queue and a
symbiont process. When a symbiont process is linked to more than one
queue and serves those queues simultaneously, it is called a
multithreaded symbiont.
The argument to the SMB$READ_MESSAGE routine provides a way for a
multithreaded symbiont to keep track of the stream referred to by a
request. Writing your own multithreaded symbiont, however, can be a
complex undertaking.
18.1.8 Reading Job Controller Requests
The seven general functions that the job controller can request of the
symbiont are as follows:
- SMBMSG$K_START_STREAM
- SMBMSG$K_STOP_STREAM
- SMBMSG$K_START_TASK
- SMBMSG$K_PAUSE_TASK
- SMBMSG$K_RESUME_TASK
- SMBMSG$K_STOP_TASK
- SMBMSG$K_RESET_STREAM
The job controller passes these requests to the symbiont in a structure
that contains: (1) a code that identifies the requested function and
(2) optional items of information that the symbiont might need to
perform the requested function.
By calling SMB$READ_MESSAGE, the symbiont reads the function code and
writes the associated items of information, if any, into a buffer. The
symbiont then parses the message items stored in the buffer by calling
the SMB$READ_MESSAGE_ITEM routine. SMB$READ_MESSAGE_ITEM reads one
message item each time it is called.
Each message item consists of a code that identifies the type of
information the item contains, and the information itself. For example,
the SMBMSG$K_JOB_NAME code tells the symbiont that the item contains a
string, which is the name of a job.
The number of message items in a request message varies with each type
of request. Therefore, to ensure that all message items are read,
SMB$READ_MESSAGE_ITEM must be called repeatedly for each request.
SMB$READ_MESSAGE_ITEM returns status SMB$_NOMOREITEMS after it has read
the last message item in a given request.
Typically, a symbiont checks the code of a message item against a case
table and stores the message string in an appropriate variable until
all the message items are read and the processing of the request can
begin.
See the description of the SMB$READ_MESSAGE_ITEM routine for a table
that shows the message items that make up each type of request.
18.1.9 Processing Job Controller Requests
After a request is read, it must be processed. The way a request is
processed depends on the type of request. The following section lists,
for each request that the job controller sends to the print symbiont,
the actions that the standard symbiont (PRTSMB) takes when the message
is received. These actions are oriented toward print symbionts in
particular but can serve as a guideline for other kinds of symbionts as
well.
The symbiont you write can respond to requests in a similar way or in a
different way appropriate to the function of your symbiont. Compaq
suggests that your routines follow the guidelines described in this
document. (Note that the behavior of the standard symbiont is subject
to change without notice in future versions of the operating system.)
SMBMSG$K_START_STREAM
- Reset all stream-specific information that might have been altered
by previous START_STREAM requests on this stream (for multithreaded
symbionts).
- Read and store the message items associated with the request.
- Allocate the device specified by the SMBMSG$K_DEVICE_NAME item.
- Assign a channel to the device.
- Obtain the device characteristics.
- If the device is neither a terminal nor a printer, then abort
processing and return an error to the job controller by means of the
SMB$SEND_TO_JOBCTL routine. Note that, even though an error has
occurred, the stream is still considered started. The job controller
detects the error and sends a STOP_STREAM request to the symbiont.
- Set temporary device characteristics suited to the way the symbiont
will use the device.
- For remote devices (devices connected to the system by means of a
modem), establish an AST to report loss of the carrier signal.
- Report to the job controller that the request has been completed
and that the stream is started, by specifying SMBMSG$K_START_STREAM in
the call to SMB$SEND_TO_JOBCTL.
SMBMSG$K_START_TASK
- Reset all task-specific information that might have been altered by
previous START_TASK requests on this stream number.
- Read and store the message items associated with the request.
- Open the main input file.
- Report to the job controller that the task has been started by
specifying SMBMSG$K_START_TASK in the call to the SMB$SEND_TO_JOBCTL
routine.
- Begin processing the task.
- When the task is complete, notify the job controller by specifying
SMBMSG$K_TASK_COMPLETE in the call to the SMB$SEND_TO_JOBCTL routine.
SMBMSG$K_PAUSE_TASK
- Read and store the message items associated with the request.
- Set a flag that will cause the main processing routine to pause at
the beginning of the next output page.
- When the main routine pauses, notify the job controller by
specifying SMBMSG$K_PAUSE_TASK in the call to the SMB$SEND_TO_JOBCTL
routine.
SMBMSG$K_RESUME_TASK
- Read and store the message items associated with the request.
- Perform any positioning functions specified by the message items.
- Clear the flag that causes the main input routine to pause, and
resume processing the task.
- Notify the job controller that the task has been resumed by
specifying SMBMSG$K_RESUME_TASK in the call to the SMB$SEND_TO_JOBCTL
routine.
SMBMSG$K_STOP_TASK
- Read and store the message items associated with the request.
- If processing of the current task has paused, then resume it.
- Cancel any outstanding I/O operations.
- Close the input file.
- If the job controller specified, in the START_TASK message, that a
trailer page should be printed when the task is stopped or if it
specified that the device should be reset when the task is stopped,
then perform those functions.
- Notify the job controller that the task has been stopped abnormally
by specifying SMBMSG$K_STOP_TASK and by specifying an error vector in
the call to SMB$SEND_TO_JOBCTL. PRTSMB specifies the value passed by
the job controller in the SMBMSG$K_STOP_CONDITION item as the error
condition in the error vector.
SMBMSG$K_STOP_STREAM
- Read and store the message items associated with the request.
- Release any stream-specific resources: (1) deassign the channel to
the device, and (2) deallocate the device.
- Notify the job controller that the stream has been stopped by
specifying SMBMSG$K_STOP_STREAM in the call to SMB$SEND_TO_JOBCTL.
- If this is a single-threaded symbiont or if this is a multithreaded
symbiont but all other streams are currently stopped, then call the
$EXIT system service with the condition code SS$_NORMAL.
SMBMSG$K_RESET_STREAM
- Read and store the message items associated with the request.
- Abort any task in progress---you do not need to notify the job
controller that the task has been aborted, but you may do so if you
want.
- If the job controller specified, in the START_TASK message, that a
trailer page should be printed when the task is stopped or if it
specified that the device should be reset when the task is stopped,
then suppress those functions.
The job controller sends the
symbiont a RESET_STREAM request to regain control of a queue or a
device that has failed to respond to a STOP_TASK request. The
RESET_STREAM request should avoid any further I/O activity if possible.
The printer might be disabled, for example, and requests for output on
that device will never be completed.
- Continue as if this were a STOP_STREAM request.
Note
A STOP_STREAM request and a RESET_STREAM request each stop the queue;
but a RESET_STREAM request is an emergency stop and is used, for
example, when the device has failed. A RESET_STREAM request should
prevent any further I/O activity because the printer might not be able
to complete it.
|
18.1.10 Responding to Job Controller Requests
The symbiont uses the SMB$SEND_TO_JOBCTL routine to send messages to
the job controller.
Most messages that the symbiont sends to the job controller are
responses to requests made by the job controller. Such messages inform
the job controller that the request has been completed successfully or
unsuccessfully. The function code that the symbiont returns to the
controller in the call to SMB$SEND_TO_JOBCTL indicates what request has
been completed.
For example, if the job controller sends a START_TASK request using the
SMBMSG$K_START_TASK code, the symbiont responds by calling
SMB$SEND_TO_JOBCTL using SMBMSG$K_START_TASK as the
request argument to indicate that task processing has
begun. Until the symbiont responds, the DCL command SHOW QUEUE
indicates that the queue is starting.
The responses to some requests use additional arguments to send more
information than just the request code. See the SMB$SEND_TO_JOBCTL
routine for a table showing the additional arguments allowed in
response to each request.
In addition to sending messages in response to requests, the symbiont
can send other messages to the job controller. In these messages the
symbiont sends either the SMBMSG$K_TASK_COMPLETE code, indicating that
it has completed a task, or SMBMSG$K_TASK_STATUS, indicating that the
message contains information on the status of a task.
Note that, when a START_TASK request is delivered, the symbiont
responds with a SMB$SEND_TO_JOBCTL message with the SMBMSG$K_START_TASK
code. This response means the task has been started. It does not mean
the task has been completed. When the symbiont completes the task, it
calls SMB$SEND_TO_JOBCTL with the SMBMSG$K_TASK_COMPLETE code.
18.2 SMB Routines
This section describes the individual SMB routines.
SMB$CHECK_FOR_MESSAGE
The SMB$CHECK_FOR_MESSAGE routine determines whether a message sent
from the job controller to the symbiont is waiting to be read.
Format
SMB$CHECK_FOR_MESSAGE
RETURNS
OpenVMS usage: |
cond_value |
type: |
longword (unsigned) |
access: |
write only |
mechanism: |
by value |
Longword condition value. Most utility routines return a condition
value in R0. Condition values that this routine can return are listed
under Condition Values Returned.
Arguments
None.
Description
When your symbiont calls the SMB$INITIALIZE routine to initialize the
interface between the symbiont and the job controller, you can choose
to have requests from the job controller delivered by means of an AST.
If you choose not to use ASTs, your symbiont must call
SMB$CHECK_FOR_MESSAGE during the processing of tasks in order to see if
a message from the job controller is waiting to be read. If a message
is waiting, SMB$CHECK_FOR_MESSAGE returns a success code; if not, it
returns a zero.
If a message is waiting, the symbiont should call SMB$READ_MESSAGE to
read it to determine if immediate action should be taken (as in the
case of STOP_TASK, RESET_STREAM or PAUSE_TASK).
If a message is not waiting, SMB$CHECK_MESSAGE returns a zero. If this
condition is detected, the symbiont should continue processing the
request at hand.
Condition Values Returned
SS$_NORMAL
|
One or more messages waiting.
|
0
|
No messages waiting.
|
SMB$INITIALIZE
The SMB$INITIALIZE routine initializes the user-written symbiont and
the interface between the symbiont and the job controller. It allocates
and initializes the internal databases of the interface and sets up the
mechanism that is to wake up the symbiont when a message is received.
Format
SMB$INITIALIZE structure_level [,ast_routine] [,streams]
RETURNS
OpenVMS usage: |
cond_value |
type: |
longword (unsigned) |
access: |
write only |
mechanism: |
by value |
Longword condition value. Most utility routines return a condition
value in R0. Condition values that this routine can return are listed
under Condition Values Returned.
Arguments
structure_level
OpenVMS usage: |
longword_unsigned |
type: |
longword (unsigned) |
access: |
read only |
mechanism: |
by reference |
Version of the symbiont/job controller interface. The
structure_level argument is the address of a longword
containing the version of the symbiont/job controller interface used
when the symbiont was compiled. Always place the value of the symbol
SMBMSG$K_STRUCTURE_LEVEL in the longword addressed by this argument.
Each programming language provides an appropriate mechanism for
defining symbols.
ast_routine
OpenVMS usage: |
ast_procedure |
type: |
procedure value |
access: |
read only |
mechanism: |
by reference |
Message-handling routine called at AST level. The
ast_routine argument is the address of the entry point
of the message-handling routine to be called at AST level when the
symbiont receives a message from the job controller. The AST routine is
called with no parameters and returns no value. If an AST routine is
specified, the routine is called once each time the symbiont receives a
message from the job controller.
The AST routine typically reads the message and determines if immediate
action must be taken. Be aware that an AST can be delivered only while
the symbiont is operating at non-AST level. Thus, to ensure delivery of
messages from the job controller, the symbiont should not perform
lengthy operations at AST level.
If you do not specify the ast_routine argument, the
symbiont must call the SMB$CHECK_FOR_MESSAGE routine to check for
waiting messages.
streams
OpenVMS usage: |
longword_unsigned |
type: |
longword (unsigned) |
access: |
read only |
mechanism: |
by reference |
Maximum number of streams the symbiont is to support. The
streams argument is the address of a longword
containing the number of streams that the symbiont is to support. The
number must be in the range of 1 to 32.
If you do not specify this argument, a default value of 1 is
used. Thus, by default, a symbiont supports one stream. Such a symbiont
is called a single-threaded symbiont.
A stream (or thread) is a logical link between a queue and a symbiont.
When a symbiont is linked to more than one queue, and serves those
queues simultaneously, it is called a multithreaded symbiont.
Description
Your symbiont must call SMB$INITIALIZE before calling any other SMB
routines. It calls SMB$INITIALIZE in order to do the following:
- Allocate and initialize the SMB facility's internal database.
- Establish the interface between the job controller and the symbiont.
- Determine the threading scheme of the symbiont.
- Set up the mechanism to wake your symbiont when a message is
received.
After the symbiont calls SMB$INITIALIZE, it can communicate with the
job controller using the other SMB routines.
Condition Values Returned
SS$_NORMAL
|
Normal successful completion.
|
SMB$_INVSTRLEV
|
Invalid structure level.
|
This routine also returns any codes returned by $ASSIGN and LIB$GET_VM.
SMB$READ_MESSAGE
The SMB$READ_MESSAGE routine copies a message that the job controller
has sent into the caller's specified buffer.
Format
SMB$READ_MESSAGE stream ,buffer ,request
RETURNS
OpenVMS usage: |
cond_value |
type: |
longword (unsigned) |
access: |
write only |
mechanism: |
by value |
Longword condition value. Most utility routines return a condition
value in R0. Condition values that this routine can return are listed
under Condition Values Returned.
Arguments
stream
OpenVMS usage: |
longword_unsigned |
type: |
longword (unsigned) |
access: |
write only |
mechanism: |
by reference |
Stream number specifying the stream to which the message refers. The
stream argument is the address of a longword into
which the job controller writes the number of the stream referred to by
the message. In single-threaded symbionts, the stream number is always
0.
buffer
OpenVMS usage: |
char_string |
type: |
character string |
access: |
write only |
mechanism: |
by descriptor |
Address of the descriptor that points to the buffer into which the job
controller writes the message. SMB$READ_MESSAGE uses the Run-Time
Library string-handling (STR$) routines to copy the message into the
buffer you supply. The buffer should be specified by a dynamic string
descriptor.
request
OpenVMS usage: |
identifier |
type: |
longword (unsigned) |
access: |
write only |
mechanism: |
by reference |
Code that identifies the request. The request argument
is the address of a longword into which SMB$READ_MESSAGE writes the
code that identifies the request.
There are seven request codes. Each code is interpreted as a message by
the symbiont. The codes and their descriptions follow:
SMBMSG$K_START_STREAM
|
Initiates processing on an inactive symbiont stream. The job controller
sends this message when a START/QUEUE or an INITIALIZE/QUEUE/START
command is issued on a stopped queue.
|
SMBMSG$K_STOP_STREAM
|
Stops processing on a started queue. The job controller sends this
message when a STOP/QUEUE/NEXT command is issued, after the symbiont
completes any currently active task.
|
SMBMSG$K_RESET_STREAM
|
Aborts all processing on a started stream and requeues the current job.
The job controller sends this message when a STOP/QUEUE/RESET command
is issued.
|
SMBMSG$K_START_TASK
|
Requests that the symbiont begin processing a task. The job controller
sends this message when a file is pending on an idle, started queue.
|
SMBMSG$K_STOP_TASK
|
Requests that the symbiont abort the processing of a task. The job
controller sends this message when a STOP/QUEUE/ABORT or
STOP/QUEUE/REQUEUE command is issued. The item SMBMSG$K_STOP_CONDITION
identifies whether this is an abort or a requeue request.
|
SMBMSG$K_PAUSE_TASK
|
Requests that the symbiont pause in the processing of a task but retain
the resources necessary to continue. The job controller sends this
message when a STOP/QUEUE command is issued without the /ABORT, /ENTRY,
/REQUEUE, or /NEXT qualifier for a queue that is currently printing a
job.
|
SMBMSG$K_RESUME_TASK
|
Requests that the symbiont continue processing a task that has been
stopped with a PAUSE_TASK request. This message is sent when a
START/QUEUE command is issued for a queue served by a symbiont that has
paused in processing the current task.
|
Description
Your symbiont calls SMB$READ_MESSAGE to read a message that the job
controller has sent to the symbiont.
Each message from the job controller consists of a code identifying the
function the symbiont is to perform and a number of message items.
There are seven codes. Message items are pieces of information that the
symbiont needs to carry out the requested function.
For example, when you enter the DCL command PRINT, the job controller
sends a message containing a START_TASK code and a message item
containing the specification of the file to be printed.
SMB$READ_MESSAGE writes the code into a longword (specified by the
request argument) and writes the accompanying message
items, if any, into a buffer (specified by the buffer
argument).
See the description of the SMB$READ_MESSAGE_ITEM routine for
information about processing the individual message items.
Condition Values Returned
SS$_NORMAL
|
Normal successful completion.
|
LIB$_INVARG
|
Routine completed unsuccessfully because of an invalid argument.
|
This routine also returns any of the condition codes returned by the
Run-Time Library string-handling (STR$) routines.
|