Hi Matthew,

> clocks: well though out IMO, looks like it would support a large
> veriety of clocks. On a hardware side, would a jitter/drift be
> interesting? also would scaling clocks (such as the turbo button 
> on 286s ) be interesting?

We have thought a fair bit about how frequency scaling could be handled.  It is 
quite important for use cases beyond turbo buttons :-)  An increasing amount of 
embedded systems now-a-days (e.g. an Android phone) consist of many cores with 
power management that are doing a lot of voltage and frequency scaling in order 
to squeeze every little bit out of the battery.  This of course can create 
discontinuities in the clocks.  Clocks speeding up, slowing down, stopping 
altogether, getting reset.  There is even the possibility of the clock for a 
trace event stream completely changing to a different clock mid-stream.  Of 
course if you do not have a way to know that it happened you are in trouble, 
but the hope is to be able to record these as events in the stream (which means 
instrumenting the power management, or doing it in hardware). 

Section 8 of the CTF spec details how clock values are set/referenced through 
the type system:

typealias integer {
        size = 64; align = 1; signed = false;
        map = clock.cycle_counter_sync.value;
} := uint64_ccnt_t;

This declares that a field that contains a value of this type is setting the 
VALUE (the count) of this clock.

So then it is possible to declare a stream in which every event sets the 
current value of the clock:

stream {
        /* ... */
        event.header := struct {
                uint64_ccnt_t timestamp;
                /* ... */
        }
        packet.context := struct packet_context;
};

So then every time an event occurs, it is in effect setting the current value 
of the clock.  The value of the clock is not necessarily the only thing that 
can be adjusted in this way though.  It could also be possible to adjust the 
frequency in the same way.  Say you had another type declared like this:

typealias integer {
        size = 64; align = 1; signed = false;
        map = clock.cycle_counter_sync.freq;
} := uint64_ccnt_freq_t;

So this declares a type that when referenced sets the FREQUENCY of the clock as 
opposed to the current count value.  Say for example that you had a power 
management event that changes the current count and frequency at the same time. 
 In the TDSL, that CTF defines, this event might look like this:

event {
        name = ccnt_change_event;
        id = 1;
      
        fields := {
            uint64_ccnt_t      ccnt_value;
            uint64_ccnt_freq_t ccnt_freq;
        ];
};

so when this occurs it changes the frequency and count.

* Yes, it is true that this sort of thing happening in the trace stream has 
implications for algorithms that are trying to go through gigabytes of trace 
events with a binary search and that sort of thing.  I think that in general 
you would have to know that there were events in the stream that changed the 
frequency and have to find them all in order to really maintain accurate 
timekeeping, at least if you cared about correlation with other cores.

hope this helps,
Aaron Spear

_______________________________________________
lttng-dev mailing list
[email protected]
http://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev

Reply via email to