7.3.1 Lexical Scope
7.3.2 Static and Dynamic Scopes
7.4 TSDL Examples
+8. Clocks
1. Preliminary definitions
possess a field name, which is a unique identifier within the structure.
The identifier is not allowed to use any reserved keyword
(see Section C.1.2). Replacing reserved keywords with
-underscore-prefixed field names is recommended.
+underscore-prefixed field names is recommended. Fields starting with an
+underscore should have their leading underscore removed by the CTF trace
+readers.
A nameless structure can be declared as a field type or as part of a typedef:
Each variant type selector possess a field name, which is a unique
identifier within the variant. The identifier is not allowed to use any
reserved keyword (see Section C.1.2). Replacing reserved keywords with
-underscore-prefixed field names is recommended.
+underscore-prefixed field names is recommended. Fields starting with an
+underscore should have their leading underscore removed by the CTF trace
+readers.
+
A named variant declaration followed by its definition within a structure
declaration:
7.3.1 Lexical Scope
-Each of "trace", "stream", "event", "struct" and "variant" have their own
-nestable declaration scope, within which types can be declared using "typedef"
-and "typealias". A root declaration scope also contains all declarations
-located outside of any of the aforementioned declarations. An inner
-declaration scope can refer to type declared within its container
-lexical scope prior to the inner declaration scope. Redefinition of a
-typedef or typealias is not valid, although hiding an upper scope
-typedef or typealias is allowed within a sub-scope.
+Each of "trace", "env", "stream", "event", "struct" and "variant" have
+their own nestable declaration scope, within which types can be declared
+using "typedef" and "typealias". A root declaration scope also contains
+all declarations located outside of any of the aforementioned
+declarations. An inner declaration scope can refer to type declared
+within its container lexical scope prior to the inner declaration scope.
+Redefinition of a typedef or typealias is not valid, although hiding an
+upper scope typedef or typealias is allowed within a sub-scope.
7.3.2 Static and Dynamic Scopes
The dynamic scope prefixes are thus:
+ - Trace Environment: <env. >,
- Trace Packet Header: <trace.packet.header. >,
- Stream Packet Context: <stream.packet.context. >,
- Event Header: <stream.event.header. >,
not permitted as field names. It is recommended that field names
clashing with CTF and C99 reserved keywords use an underscore prefix to
eliminate the risk of generating a description containing an invalid
-field name.
+field name. Consequently, fields starting with an underscore should have
+their leading underscore removed by the CTF trace readers.
+
The information available in the dynamic scopes can be thought of as the
current tracing context. At trace production, information about the
in a stream.
trace {
- major = value; /* Trace format version */
- minor = value;
+ major = value; /* CTF spec version major number */
+ minor = value; /* CTF spec version minor number */
uuid = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"; /* Trace UUID */
byte_order = be OR le; /* Endianness (required) */
packet.header := struct {
};
};
+/*
+ * The "env" (environment) scope contains assignment expressions. The
+ * field names and content are implementation-defined.
+ */
+env {
+ pid = value; /* example */
+ proc_name = "name"; /* example */
+ ...
+};
+
stream {
id = stream_id;
/* Type 1 - Few event IDs; Type 2 - Many event IDs. See section 6.1. */
name = "event_name";
id = value; /* Numeric identifier within the stream */
stream_id = stream_id;
- loglevel.identifier = "loglevel_identifier";
- loglevel.value = value;
+ loglevel = value;
context := struct {
...
};
}
+8. Clocks
+
+Clock metadata allows to describe the clock topology of the system, as
+well as to detail each clock parameter. In absence of clock description,
+it is assumed that all fields named "timestamp" use the same clock
+source, which increments once per nanosecond.
+
+Describing a clock and how it is used by streams is threefold: first,
+the clock and clock topology should be described in a "clock"
+description block, e.g.:
+
+clock {
+ name = cycle_counter_sync;
+ uuid = "62189bee-96dc-11e0-91a8-cfa3d89f3923";
+ description = "Cycle counter synchronized across CPUs";
+ freq = 1000000000; /* frequency, in Hz */
+ /* precision in seconds is: 1000 * (1/freq) */
+ precision = 1000;
+ /*
+ * clock value offset from Epoch is:
+ * offset_s + (offset * (1/freq))
+ */
+ offset_s = 1326476837;
+ offset = 897235420;
+ absolute = FALSE;
+};
+
+The mandatory "name" field specifies the name of the clock identifier,
+which can later be used as a reference. The optional field "uuid" is the
+unique identifier of the clock. It can be used to correlate different
+traces that use the same clock. An optional textual description string
+can be added with the "description" field. The "freq" field is the
+initial frequency of the clock, in Hz. If the "freq" field is not
+present, the frequency is assumed to be 1000000000 (providing clock
+increment of 1 ns). The optional "precision" field details the
+uncertainty on the clock measurements, in (1/freq) units. The "offset_s"
+and "offset" fields indicate the offset from POSIX.1 Epoch, 1970-01-01
+00:00:00 +0000 (UTC), to the zero of value of the clock. The "offset_s"
+field is in seconds. The "offset" field is in (1/freq) units. If any of
+the "offset_s" or "offset" field is not present, it is assigned the 0
+value. The field "absolute" is TRUE if the clock is a global reference
+across different clock uuid (e.g. NTP time). Otherwise, "absolute" is
+FALSE, and the clock can be considered as synchronized only with other
+clocks that have the same uuid.
+
+
+Secondly, a reference to this clock should be added within an integer
+type:
+
+typealias integer {
+ size = 64; align = 1; signed = false;
+ map = clock.cycle_counter_sync.value;
+} := uint64_ccnt_t;
+
+Thirdly, stream declarations can reference the clock they use as a
+time-stamp source:
+
+struct packet_context {
+ uint64_ccnt_t ccnt_begin;
+ uint64_ccnt_t ccnt_end;
+ /* ... */
+};
+
+stream {
+ /* ... */
+ event.header := struct {
+ uint64_ccnt_t timestamp;
+ /* ... */
+ }
+ packet.context := struct packet_context;
+};
+
+For a N-bit integer type referring to a clock, if the integer overflows
+compared to the N low order bits of the clock prior value, then it is
+assumed that one, and only one, overflow occurred. It is therefore
+important that events encoding time on a small number of bits happen
+frequently enough to detect when more than one N-bit overflow occurs.
+
+In a packet context, clock field names ending with "_begin" and "_end"
+have a special meaning: this refers to the time-stamps at, respectively,
+the beginning and the end of each packet.
+
+
A. Helper macros
The two following macros keep track of the size of a GNU/C structure without
align
const
char
+clock
double
enum
+env
event
floating_point
float
ctf-specifier:
event { ctf-assignment-expression-list-opt }
stream { ctf-assignment-expression-list-opt }
+ env { ctf-assignment-expression-list-opt }
trace { ctf-assignment-expression-list-opt }
typealias declaration-specifiers abstract-declarator-list type-assignment-operator declaration-specifiers abstract-declarator-list
typealias declaration-specifiers abstract-declarator-list type-assignment-operator declarator-list