The maintenance of statistics such as "packets transmitted" for a network interface can greatly assist the system administrator (or user) in a variety of circumstances.
Traditionally, support for such statistics gathering has been irregular and generally limited to direct screen printing. This specification provides a more controlled method of presenting statistics to the user, and permits a single generic display program to cope with all compliant modules.
The following characterise the intentions of this interface specification:
Plus points
Minus points
A piece of software that wishes to offer statistics is termed a "supplier". A piece of software that obtains statistics from a supplier and presents them to the user is termed a "gatherer", and the operation it performs is often referred to as "enumerating the statistics". There are typically more suppliers than gatherers in a system.
As part of its normal operations, a supplier maintains a set of statistics. A gatherer, typically upon user invocation, enumerates the available suppliers, enumerates the statistics supplied by each supplier and then presents this information to the user. More dynamic presentation is also possible. A supplier is passive (other than its normal operations), whilst the gatherer actively seeks out the information to be presented.
The first stage of enumeration (determining what suppliers are present) is performed with a service call (Service_StatisticEnumerate), and the second stage (determining what statistics are available and their values) is performed through a SWI whose SWI number is obtained during the first stage of enumeration (StatisticsProvider_Statistics). This SWI number is used for all stages of operation apart from enumeration itself.
Each statistic has a number of different pieces of information associated with it, forming its description, and a value. The description provides the necessary information to access and manipulate the value, including the number of bytes of storage required for the value, it's type, format and desired presentation. The data types supported are boolean, integer and string. An unused data type also provides for padding.
Descriptions and statistics are read in ranges from a lower statistic number to an upper statistic number, inclusive. The first statistic of any supplier is zero. The highest statistic number of a supplier is obtained when the SWI number for a supplier is obtained. A range is always processed atomically by the supplier, ensuring consistent values and presentation to a gatherer when so required. A supplier indicates the volatility of its statistics and typically attempts to group statistics into ranges of the same volatility.
The list of available suppliers is determined with a single service call, Service_StatisticEnumerate.
On receiving this service, each supplier allocates a small structure from the RMA, initializes it and links it into the linked list whose head is pointed to by R0. Whether the supplier adds an entry at the head or tail of the list does not matter, although it is recommended that the entries be added to the head for simplicity. If a gatherer requires any specific order, then it should explicitly sort the suppliers list itself. A gatherer should not cache SWI values across invocations of suppliers, as a module might choose a dynamic SWI numbering scheme if it offers multiple effective suppliers.
In C, this structure is defined as follows:
typedef struct spctl
{
struct spctl *next; /* Next structure in list */
unsigned int i_version; /* Interface version */
unsigned long features; /* Combination of SF_ values */
unsigned int swinumber; /* The SWI SA_DESCRIBE/SA_READ use */
unsigned int max_stat; /* Highest stat number (inclusive) */
unsigned int type; /* Acorn assigned supplier type */
unsigned int s_version; /* Supplier version */
char *module; /* Module name (short one) */
char *title; /* Title string - short */
char *description; /* Descriptive string - long */
unsigned char reset[8]; /* Unique for each invocation */
} dci4_spctl;
| Offset | Name | Contents | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| +0 | next | This field is used to construct the linked list of suppliers for the enumeration operation. A value of zero indicates the end of the list. | |||||||||||||||
| +4 | i_version | The DCI4 Statistic Interface version that the supplier is implemented against. | |||||||||||||||
| +8 | features | A bitset of flags defining optional aspects of a supplier. No features are currently defined and the the value must be set to 0. | |||||||||||||||
| +12 | swinumber | The SWI number through which all other communication with the supplier is performed. | |||||||||||||||
| +16 | max_stat | The highest statistic number, inclusive, that the supplier provides. This implies a supplier must always supply at least one statistic. | |||||||||||||||
| +20 | type | This field is available to provide some classification of suppliers. It is the only centrally administered resource in this specification, and its use is optional. The currently defined values are as follows:
| |||||||||||||||
| +24 | s_version | This is the version number of the supplier module itself (as opposed to the version number of an interface it conforms to). It is provided for the convenience of the user. | |||||||||||||||
| +28 | module | This is the supplier's module title (as opposed to its help string). | |||||||||||||||
| +32 | title | This is a short descriptive string to identify the supplier to the user. The gatherer only contracts to print at least the first twenty characters of this string. | |||||||||||||||
| +36 | description | This is a longer description of the supplier that should convey it's purpose to the user. The gatherer only contracts to print at least the first fifty characters of this string. | |||||||||||||||
| +40 | reset | This 8 byte field is initialised with a unique value each time the supplier is initialised. It permits the gatherer to spot a supplier that has just re-initialised. The time and date at which the supplier initialises are recommended values to write here. The gatherer performs an 8 byte equality test and otherwise assumes no further format information about these bytes. |
When a gatherer has finished interacting with a supplier, it should free the allocated structures back into the RMA.
Apart from the enumeration phase, all communication with a supplier is performed through the single SWI number obtained during the enumeration phase (described as StatisticsProvider_Statistics).
SA_DESCRIBE (0) obtains descriptions of statistics, whilst SA_READ (1) obtains the actual values of statistics. It is necessary for first obtain the description of a statistic before reading it, as the description is the only way the gatherer can obtain the size of the statistic value and know how much buffer space to allocate.
In essence, both these actions enumerate information about a range of statistics into the buffer supplied. This is performed atomically, where necessary, by the supplier. In both cases, the operation starts from the first statistic and proceeds in steps of one and stops once the last statistic has been processed. Output is placed into the buffer supplied. If this buffer is not big enough for the requested range of statistics, then processing will stop when it is no longer possible to write all the necessary information for a statistic (i.e. if the buffer supplied is not big enough, the number of unused bytes will be less than the size of a statistic description). Return values of the number of statistics processed and the number of bytes of the buffer used are returned. The buffer must be word aligned in memory.
Each statistic is described with a fixed sized buffer, described in C as follows:
typedef struct stdesc
{
unsigned int type; /* ST_ series */
unsigned int format; /* SxF_ series */
unsigned int presentation; /* SxP_ series */
unsigned int size; /* Measured in bytes */
unsigned int volatility; /* SV_ series */
char *name; /* String is static */
unsigned int name_tag; /* See specification */
unsigned int spare; /* Unused. Always zero */
} dci4_stdesc;
| Offset | Name | Contents | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| +0 | type | This defines the type of statistic. Possible values are:
| ||||||||||||||||||||||||||||||
| +4 | format | This field contains a value indicating the format of the value. The range of values is specific to each type (all the integer types share a common set of formats and presentations for convenience). Depending upon the type in question, this value may be an enumeration, a bitset of flags or a combination of both (none of the currently defined formats mix enumeration and flag bitsets). See below for the meanings of the formats, | ||||||||||||||||||||||||||||||
| +8 | presentation | This field dictates how the supplier would like the value to be presented. A gatherer may choose to ignore this value, but only at the risk of presenting the user with incoherent information. See below for the meaning of the presentations. | ||||||||||||||||||||||||||||||
| +12 | size | This is the number of bytes the statistic wishes reserved in the buffer for an SA_READ operation. It is always a multiple of four bytes. It is sometimes larger than the actual value necessary. | ||||||||||||||||||||||||||||||
| +16 | volatility |
This field indicates how volatile a statistic is. The three possible values are:
| ||||||||||||||||||||||||||||||
| +20 | name | This fields points at the name of the statistic. It is a short descriptive string that the gatherer contracts to display at least the first twenty characters of. The string itself is static, zero byte terminated and contained with the supplier module. | ||||||||||||||||||||||||||||||
| +24 | name_tag |
This value, together with the information contained in the dci4_spctl structure and a ISV/IHV supplied data file permit the gatherer to obtain a description of a statistic. The precise mechanism has yet to be determined. Must be zero. | ||||||||||||||||||||||||||||||
| +28 | spare | This field is reserved for future use and must be zero. |
The format and presentation vary with the statistic types.
| Statistic type | Name | Format and presentation | |||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | ST_UNUSED | There is no format or presentation defined for the ST_UNUSED type. | |||||||||||||||||||||||||||||||||||
| 1 | ST_BOOLEAN |
Format:
Presentation:
| |||||||||||||||||||||||||||||||||||
| 2 | ST_STRING |
Format:
Presentation:
| |||||||||||||||||||||||||||||||||||
| 3-6 | ST_INTEGER# |
Format:
Presentation:
| |||||||||||||||||||||||||||||||||||
| 7 | ST_ADDRESS |
Format:
Presentation:
| |||||||||||||||||||||||||||||||||||
| 7 | ST_TIME |
Format:
Presentation:
| |||||||||||||||||||||||||||||||||||
The supplier is required to perform each read request atomically. This means a gatherer can rely upon a read operation producing consistent statistics, but it cannot be certain quite when in time these statistics apply to: in some cases, statistics are virtually always out of date by the time the gatherer obtains and uses them.
The simplistic approach to ensuring an atomic read operation is to perform the entire action with interrupts disabled. This, however, has an undesirable effect on interrupt latency for suppliers with many or complex statistics and is not recommended.
The suggested method is a three buffer scheme. One buffer holds the accumulated statistics, the second holds the increments (deltas) being generated "live", and the third is either entirely full of zero values, or there is an active read operation in progress and it holds a previous set of increments that are currently being added (merged) into the accumulated values.
Two pointers are maintained. One for the "live" buffer and the other for the "merge" buffer. The operation that is necessary to perform atomically is the swapping of these two pointer values.
The overall structure suggested is as follows:
start thread of control (ie SWI)
enter mutex (eg disable interrupts)
temp := buffer pointer 1
buffer pointer 1 := buffer pointer 2
buffer pointer 2 := temp
exit mutex (and ensure interrupts enabled)
add values from buffer pointer 2 into the accumulated values
zero the memory described by buffer pointer 2
end thread of control (ie SWI)
This maximises the usefulness of the non re-entrancy requirement and requires ONLY the swapping of the buffer pointers to be performed atomically. All other operations can proceed with interrupts enabled. This minimal critical region is the prime motivation behind this scheme.
Some applications of the statistic interface will require a single RISC OS module to behave as multiple suppliers. For example, a device driver module that controls multiple interfaces might well wish to provide an overall set of statistics, and then an instance of a set of statistics per interface controlled.
A separate SWI number is required for each 'effective supplier'. This is not normally a problem, as very few modules approach the limit of the 64 separate SWIs allocated. Gatherers are expected to obtain SWI numbers through the enumeration method supplied, and should be capable of handling dynamic SWI number assignment. For example, a device driver may choose SWIs 63, 62 and 61 for units 0, 1 and 2, respectively. If a gatherer were to attempt to 'cache' these SWI numbers across invocations of the device driver, then it might not correctly cater for the addition or removal of interfaces.
| R0 | = | Pointer to the head of the enumeration chain |
| R1 | = | Reason code (&A1) |
| R0 | = | New pointer to the head of the enumeration chain containing all the statistic providers |
This service call is used to enumerate the statistic providers which are currently active. Each supplier should allocate a block in the RMA containing the Statistics Provider Structure and fill in the details of its provider. It should then update the next pointer to point to the supplied head of the chain, and return the new pointer in R1. It must not claim the service.
Statistics gatherers will use this information to decide what to display, and call the supplied SWI number as appropriate. Initially the statistics provider will supply the pointer in R0 as 0 when the service is issued.
| R0 | = | SA_DESCRIBE (0) or SA_READ (1) depending on the operation required |
| R1 | = | First statistic, inclusive |
| R2 | = | Last statistic, inclusive |
| R3 | = | First byte of buffer in memory |
| R4 | = | Number of bytes in buffer |
| R0-4 | preserved | |
| R5 | = | Number of statistics processed |
| R6 | = | Number of bytes of buffer used |
This SWI is used to obtain a description of the statistics provided by a supplier, or the actual values of those statitics. It is expected that it be called at least twice, once to read the descriptions of the statistics, and then future times to read the values of those statistics.
When the operation requested is SA_DESCRIBE (0), the statistics buffer supplied in R1 should be filled with structures as described in Statistic Description Structure.
When the operation requested is SA_READ (1), the statistics buffer supplied in R1 should be filled with the values corresponding to those that would be described if SA_DESCRIBE (0) had been requested. Each statistics has a length as defined by the Statistic Description Structure.
If the buffer is filled before all statistics are written, the SWI should exit with as much data as would fit into the buffer written and appropriate values in R5 and R6 on exit. Statistics gatherers may recognise this condition and provide extended buffers.
| Maintainer(s): | Charles Ferguson <gerph@gerph.org> | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| History: |
| ||||||||||||||||||||||||||||
| Disclaimer: |
Copyright (C) 1994 ANT Limited., PO BOX 300, Cambridge, England.
All rights reserved. Redistribution and use in source code and executable binary forms are permitted provided that: (1) source distributions retain this entire copyright notice and comment, and (2) distributions including executable binaries contain the following acknowledgement: ``This product includes software developed by ANT Limited and its contributors. Copyright (C) ANT Limited 1994.'' and also in the documentation and other materials provided with the distribution and in all advertising materials mentioning features or use of this software. Neither the name of ANT Limited nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. NOT INTENDED FOR USE IN LIFE CRITICAL APPLICATIONS. |