[an error occurred while processing this directive]
![]() |
![]() HP OpenVMS Systems Documentation |
![]() |
HP OpenVMS System Analysis Tools Manual
Chapter 10
|
$cc mbx$sda + sys$library:sys$lib_c /library $link /share - mbx$sda.obj, - sys$library:vms$volatile_private_interfaces /library, - sys$input /option symbol_vector = (sda$extend=procedure) symbol_vector = (sda$extend_version=data) |
1. You can include the qualifier /INSTRUCTION=NOFLOAT on the compile command line if floating-point instructions are not needed. 2. The + SYS$LIBRARY:SYS$LIB_C /LIBRARY is not needed on the compile command line if the logical name DECC$TEXT_LIBRARY is defined and translates to SYS$LIBRARY:SYS$LIB_C.TLB. 3. If the user-written extension needs to signal SDA condition codes, or output their text with $PUTMSG, you should add the qualifier /INCLUDE=SDAMSG to the parameter SYS$LIBRARY:VMS$VOLATILE_PRIVATE_INTERFACES /LIBRARY . |
You can invoke the SDA extension as follows:
$define mbx$sda sys$disk:[]mbx$sda $analyze /system SDA>mbx summary SDA>mbx <address> |
At a minimum, the user-written module must contain:
int sda$extend_version = SDA_FLAGS$K_VERSION; |
Optionally, the user-written module may also contain the statement:
#define __NEW_STARLET |
You should use this option because it provides type checking of function arguments and gives consistency in casing and naming conventions.
The entry point in the user-written module, SDA$EXTEND, is called as a routine with three arguments and no return value. The declaration is as follows:
void sda$extend ( int *transfer_table, struct dsc$descriptor_s *cmd_line, SDA_FLAGS sda_flags) |
The arguments in this code example have the following meanings:
Line of Code | Meaning | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
transfer_table | Address of the vector table in the base image. The user-written routine SDA$EXTEND must copy this to SDA$VECTOR_TABLE (declared in SDA_ROUTINES.H) before any SDA routines can be called. | ||||||||||||||||
cmd_line | Address of the descriptor of the command line as entered by the user, less the name of the extension. So, if you enter "SDA> MBX" or "SDA> DO MBX", the command line is a zero length string. If you enter the command "SDA> MBX 80102030", the command line is " 80102030" (the separating space is not stripped). | ||||||||||||||||
sda_flags |
Definition for the following four bits in this structure:
|
The first executable statement of the routine must be to copy TRANSFER_TABLE to SDA$VECTOR_TABLE (which is declared in SDA_ROUTINES.H):
sda$vector_table = transfer_table; |
If this is not done, you cannot call any of the routines described below. Any attempts to call the routines receive a status return of SDA$_VECNOTINIT. (For routines defined not to return a status, this value can be found only by examining the return value directly.)
The next statement should be one to establish a condition handler, as it is often difficult to track down errors in extensions such as access violations because the extension is activated dynamically with LIB$FIND_IMAGE_SYMBOL. A default condition handler, SDA$COND_HANDLER, is provided that outputs the following information in the event of an error:
You can establish this condition handler as follows:
lib$establish (sda$cond_handler); |
The error condition, signal array, and register dump are output directly to SYS$OUTPUT and/or SYS$ERROR, and are not affected by the use of the SDA commands SET OUTPUT and SET LOG. |
Thus, a minimal extension would be:
#define __NEW_STARLET 1 #include <descrip.h> #include <sda_routines.h> int sda$extend_version = SDA_FLAGS$K_VERSION; void sda$extend (int *transfer_table, struct dsc$descriptor_s *cmd_line, SDA_FLAGS sda_flags) { sda$vector_table = transfer_table; lib$establish (sda$cond_handler); sda$print ("hello, world"); return; } |
In addition to the "after-the-fact" information provided by the condition handler, you can debug SDA extensions using the OpenVMS Debugger. A second copy of the SDA image, SDA_DEBUG.EXE, is provided in SYS$SYSTEM. By defining the logical name SDA to reference this image, you can debug SDA extensions as follows:
An example of the preceding steps is as follows:
$ cc /debug /noopt mbx$sda + sys$library:sys$lib_c /library $ link /debug /share - mbx$sda.obj, - sys$library:vms$volatile_private_interfaces /library, - sys$input /option symbol_vector = (sda$extend=procedure) symbol_vector = (sda$extend_version=data) $ ! $ define mbx$sda sys$disk:[]mbx$sda $ define sda sda_debug $ analyze /system ... DBG> set break start_extension DBG> go ... SDA> mbx break at routine START\START_EXTENSION ... DBG> set image mbx$sda DBG> set language c DBG> set break /exception DBG> go MBX commands: 'MBX SUMMARY' and 'MBX <address>' SDA> mbx summary ... SDA> mbx <address> ... %DEBUG-I-DYNMODSET, setting module MBX$SDA %SYSTEM-E-INVARG, invalid argument ... DBG> |
The user-written routine may call SDA routines to accomplish any of the following tasks:
Note the following points before using the callable routines described here:
VOID_PQ start /* 64-bit pointer */ |
void *dest /* 32-bit pointer */ |
The following sections describe the SDA extension callable routines.
Adds a symbol to SDA's local symbol table.
void sda$add_symbol (char *symbol_name, uint64 symbol_value);
symbol_name
OpenVMS usage char_string type character string access read only mechanism by reference
Address of symbol name string (zero-terminated).symbol_value
OpenVMS usage quadword_unsigned type quadword (unsigned) access read only mechanism by value
The symbol value.
SDA maintains a list of symbols and the corresponding values. SDA$ADD_SYMBOL is used to insert additional symbols into this list, so that they can be used in expressions and during symbolization.
None
sda$add_symbol ("MBX", 0xFFFFFFFF80102030); |
This call defines the symbol MBX to the hexadecimal value FFFFFFFF80102030.
Allocates dynamic memory.
void sda$allocate (uint32 size, void **ptr_block);
size
OpenVMS usage longword_unsigned type longword (unsigned) access read only mechanism by value
Size of block to allocate (in bytes).ptr_block
OpenVMS usage address type longword (unsigned) access write only mechanism by reference
Address of longword to receive address of block.
The requested memory is allocated and the address returned. Note that this is the only supported mechanism for allocation of dynamic memory.SDA$DEALLOCATE
None
If no memory is available, the error is signaled and the SDA session aborted.
PCB *local_pcb; ... sda$allocate (PCB$C_LENGTH, (void *)&local_pcb); |
This call allocates a block of heap storage for a copy of a PCB, and stores its address in the pointer LOCAL_PCB.
Performs a Boolean operation on a pair of CBBs.
int sda$cbb_boolean_oper (CBB_PQ input_cbb, CBB_PQ output_cbb, int operation);
input_cbb
OpenVMS usage address type CBB structure access read only mechanism by reference
The address of the first (input) CBB structure.output_cbb
OpenVMS usage address type CBB structure access read/write mechanism by reference
The address of the second (output) CBB structure.operation
OpenVMS usage longword type longword (unsigned) access read only mechanism by value
The desired operation from the following list:
CBB$C_OR The logical sum of the two CBBs is performed and the result (B = A | B) is written to the output CBB. CBB$C_BIC The logical product with complement of the two CBBs is performed and the result (B = B & ~A) is written to the output CBB.
The desired Boolean operation is performed on the two CBB structures, and the result is written to the second (output) structure.
SS$_BADPARAM The number of valid bits in the input and output CBBs is different. SS$_WASCLR All bits in the resulting output CBB are clear. SS$_WASSET At least one bit in the resulting output CBB is set.
int status; extern CBB active_set, configure_set; CBB inactive_set; sda$cbb_copy (&configure_set, &inactive_set); status = sda$cbb_boolean_oper (&active_set, &inactive_set, CBB$C_BIC); if (status == SS$_WASSET) sda$print ("There are inactive CPUs in the system"); |
This example shows how the set of active CPUs and the set of configured CPUs can be manipulated to create a set of inactive CPUs.
Clears the specified bit in a CBB.
int sda$cbb_clear_bit (CBB_PQ cbb, int bit);
cbb
OpenVMS usage address type CBB structure access read/write mechanism by reference
The address of the CBB structure to be modified.bit
OpenVMS usage longword type longword (unsigned) access read only mechanism by value
The bit in the CBB to be cleared. If the bit number is -1, clears all bits.
The specified bit (or all bits) in the CBB is cleared.
SS$NORMAL Successful completion SS$BADPARAM The bit number is out of range
int status; extern int next; extern CBB active_set; status = sda$cbb_clear_bit (&active_set, next); if (!(status & 1)) sda$print ("Bad CPU specified: !XL", next); |
This example shows how a bit in a CBB is cleared.
Copies the contents of one CBB to another.
int sda$cbb_copy (CBB_PQ input_cbb, CBB_PQ output_cbb);
input_cbb
OpenVMS usage address type CBB structure access read only mechanism by reference
The address of the CBB structure to be copied.output_cbb
OpenVMS usage address type CBB structure access write only mechanism by reference
The address of the CBB structure to receive the copy.
The specified CBB is copied.
None
Locates the first clear bit in a CBB.
int sda$cbb_ffc (CBB_PQ cbb, int start_bit);
cbb
OpenVMS usage address type CBB structure access read only mechanism by reference
The address of the CBB structure to be searched.start_bit
OpenVMS usage longword type longword (unsigned) access read only mechanism by value
The first bit in the CBB to be checked.
The CBB structure is searched, starting at the specified bit, for a clear bit.
bit_number If a clear bit is found, its bit number is returned. If no clear bit is found (all bits from start_bit to cbb->cbb$l_valid_bits are set), then the number of valid bits is returned.
int bit; extern int start; extern CBB active_set; bit = sda$cbb_ffc (&active_set, start); if (bit >= active_set.cbb$l_valid_bits) sda$print ("No clear bits in active set"); else sda$print ("First clear bit in active set = !XL", bit); |
This example shows how the next clear bit in a CBB can be located.
Locates the first set bit in a CBB.
int sda$cbb_ffs (CBB_PQ cbb, int start_bit);
cbb
OpenVMS usage address type CBB structure access read only mechanism by reference
The address of the CBB structure to be searched.start_bit
OpenVMS usage longword type longword (unsigned) access read only mechanism by value
The first bit in the CBB to be checked.
The CBB structure is searched for a set bit, starting at the specified bit.
bit_number If a set bit is found, its bit number is returned. If no set bit is found (all bits from start_bit to cbb->cbb$l_valid_bits are clear), then the number of valid bits is returned.
int bit; extern int start; extern CBB active_set; bit = sda$cbb_ffs (&active_set, start); if (bit >= active_set.cbb$l_valid_bits) sda$print ("No set bits in active set"); else sda$print ("First set bit in active set = !XL", bit); |
This example shows how the next set bit in a CBB can be located.
Initializes a CBB structure to a known state.
void sda$cbb_init (CBB_PQ cbb);
cbb
OpenVMS usage address type CBB structure access read only mechanism by reference
The address of the CBB structure to be initialized.
The fields of the CBB that describe its layout are initialized as necessary for a CPU CBB. The actual bitmask is zeroed.
None
Sets the specified bit in a CBB.
int sda$cbb_set_bit (CBB_PQ cbb,int bit);
cbb
OpenVMS usage address type CBB structure access read/write mechanism by reference
The address of the CBB structure to be modified.bit
OpenVMS usage longword type longword (unsigned) access read only mechanism by value
The bit in the CBB to be set. If the bit number is -1, set all bits.
The specified bit (or all bits) in the CBB is set.
SS$NORMAL Successful completion. SS$BADPARAM The bit number is out of range.
int status; extern int next; extern CBB active_set; status = sda$cbb_set_bit (&active_set, next); if (!(status & 1)) sda$print ("Bad CPU specified: !XL", next); |
This example shows how a bit in a CBB is set.
Tests the specified bit in a CBB.
int sda$cbb_test_bit (CBB_PQ cbb,int bit);
cbb
OpenVMS usage address type CBB structure access read only mechanism by reference
The address of the CBB structure to be tested.bit
OpenVMS usage longword type longword (unsigned) access read only mechanism by value
The bit in the CBB to be tested.
The specified bit in the CBB is tested and its value returned.
SS$_WASSET The specified bit was set. SS$_WASCLR The specified bit was clear. SS$_BADPARAM The bit number is out of range.
int status; extern int next; extern CBB active_set; status = sda$cbb_test_bit (&active_set, next); if (!(status & 1)) sda$print ("Bad CPU specified: !XL", next); else if (status == SS$_WASSET) sda$print ("CPU !XL was set", next); else sda$print ("CPU !XL was clear", next); |
This example shows how a bit in a CBB is tested.
Previous | Next | Contents | Index |