From: compudj Date: Fri, 20 Jan 2006 18:10:51 +0000 (+0000) Subject: LTTV 0.8.6 : support for architecture without TSC X-Git-Tag: v0.12.20~2005 X-Git-Url: http://git.lttng.org/?a=commitdiff_plain;h=cb310b57eb65bb2c6a29bf69cf85cb0d4480e280;p=lttv.git LTTV 0.8.6 : support for architecture without TSC git-svn-id: http://ltt.polymtl.ca/svn@1484 04897980-b3bd-0310-b5e0-8ef037075253 --- diff --git a/ltt/branches/poly/configure.in b/ltt/branches/poly/configure.in index 171331a4..5ecb494f 100644 --- a/ltt/branches/poly/configure.in +++ b/ltt/branches/poly/configure.in @@ -23,7 +23,7 @@ AC_PREREQ(2.57) AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS) #AC_WITH_LTDL # not needed ? -AM_INIT_AUTOMAKE(LinuxTraceToolkitViewer,0.8.5-17012006) +AM_INIT_AUTOMAKE(LinuxTraceToolkitViewer,0.8.6-20012006) AM_CONFIG_HEADER(config.h) AM_PROG_LIBTOOL diff --git a/ltt/branches/poly/doc/developer/format.html b/ltt/branches/poly/doc/developer/format.html index ee98fc20..a211ace1 100644 --- a/ltt/branches/poly/doc/developer/format.html +++ b/ltt/branches/poly/doc/developer/format.html @@ -125,20 +125,12 @@ The block start/end header

 begin
 	* the beginning of buffer information
-	timestamp
-		* Used only when no TSC is available.
-		uint32 seconds
-		uint32 microseconds
 	uint64 cycle_count
 		* TSC at the beginning of the buffer
 	uint64 freq
 		* frequency of the CPUs at the beginning of the buffer.
 end
 	* the end of buffer information
-	timestamp
-		* Used only when no TSC is available.
-		uint32 seconds
-		uint32 microseconds
 	uint64 cycle_count
 		* TSC at the beginning of the buffer
 	uint64 freq
@@ -181,15 +173,9 @@ uint8 has_alignment
 	* Is the information in this trace aligned ?
 		Yes (1) -> aligned on min(arch size, atomic data size).
 		No (0) -> data is packed.
-uint8 has_tsc
-	* Does the traced machine has a working TSC ?
-		Yes (1) -> event time is calculated from :
-			trace_start_time + ((event_tsc - trace_start_tsc) * freq)
-		No (0) -> event time is calculated from :
-			trace_start_time 
-			+ (buffer start timestamp - trace start_monotonic) 
-			+ (event_time_delta)
-			(not supported)
+uint328 freq_scale
+		event time is always calculated from :
+			trace_start_time + ((event_tsc - trace_start_tsc) * (freq / freq_scale))
 uint64 start_freq
 	* CPUs clock frequency at the beginnig of the trace.
 uint64 start_tsc
@@ -222,9 +208,6 @@ Event header :
 	uint64 timestamp }
 	* if has_heartbeat : 32 LSB of the cycle counter at the event record time.
 	* else : 64 bits complete cycle counter.
-	* note : if there is no working TSC (has_tsc == 0), then this field contains
-	  either the complete monotonically increasing time or the time delta from the
-		previous heartbeat event. (unsupported)
 uint8 facility_id
 	* Numerical ID of the facility corresponding to the event. See the facility
 	  tracefile to know which facility ID matches which facility name and
diff --git a/ltt/branches/poly/doc/developer/lttng-lttv-compatibility.html b/ltt/branches/poly/doc/developer/lttng-lttv-compatibility.html
index 6cdd6d63..2ae961db 100644
--- a/ltt/branches/poly/doc/developer/lttng-lttv-compatibility.html
+++ b/ltt/branches/poly/doc/developer/lttng-lttv-compatibility.html
@@ -193,6 +193,30 @@ Use atomic_cmpxchg()
+ + +0.8.6
+ + +0.5.7
+ +0.4
+ + +0.7
+ +0.6
+ + +2.6.15-i386 (git)
+2.6.15-i386 (tarball)
+ + +Support for architectures without TSC.
+
+ + + diff --git a/ltt/branches/poly/doc/developer/lttng-userspace-tracing.txt b/ltt/branches/poly/doc/developer/lttng-userspace-tracing.txt index 85a31b3d..4bf221c3 100644 --- a/ltt/branches/poly/doc/developer/lttng-userspace-tracing.txt +++ b/ltt/branches/poly/doc/developer/lttng-userspace-tracing.txt @@ -48,8 +48,13 @@ status. My suggestion is to go for a system call, but only call it : -- when the process starts -- when receiving a SIG_UPDTRACING +- when the thread starts +- when receiving a SIG_UPDTRACING (multithread ?) + +Note : save the thread ID (process ID) in the logging function and the update +handler. Use it as a comparison to check if we are a forked child thread. +Start a brand new buffer list in that case. + Two possibilities : @@ -66,7 +71,9 @@ I would tend to adopt : syscall get_tracing_info -first parameter : active traces mask (32 bits : 32 traces). +parameter 1 : trace buffer map address. (id) + +parameter 2 : active ? (int) Concurrency @@ -79,15 +86,15 @@ that) and removes false sharing. Multiple traces By having the number of active traces, we can allocate as much buffers as we -need. The only thing is that the buffers will only be allocated when receiving -the signal/starting the process and getting the number of traces actives. +need. Allocation is done in the kernel with relay_open. User space mapping is +done when receiving the signal/starting the process and getting the number of +traces actives. It means that we must make sure to only update the data structures used by tracing functions once the buffers are created. -When adding a new buffer, we should call the set_tracing_info syscall and give -the new buffers array to the kernel. It's an array of 32 pointers to user pages. -They will be used by the kernel to get the last pages when the thread dies. +We could have a syscall "get_next_buffer" that would basically mmap the next +unmmapped buffer, or return NULL is all buffers are mapped. If we remove a trace, the kernel should stop the tracing, and then get the last buffer for this trace. What is important is to make sure no writers are still @@ -115,8 +122,7 @@ We could do that trace removal in two operations : accessing this memory area. When the control comes back to the writer, at the end of the write in a trace, if the trace is marked for switch/delete and the tracing_level is 0 (after the decrement of the writer itself), then the - writer must buffer switch, set_tracing_info to NULL and then delete the - memory area. + writer must buffer switch, and then delete the memory area. Filter @@ -124,9 +130,7 @@ Filter The update tracing info signal will make the thread get the new filter information. Getting this information will also happen upon process creation. -parameter 2 for the get tracing info : array of 32 ints (32 bits). -Each integer is the filter mask for a trace. As there are up to 32 active -traces, we have 32 integers for filter. +parameter 3 for the get tracing info : a integer containing the 32 bits mask. Buffer switch @@ -142,15 +146,10 @@ The kernel should be aware of the current pages used for tracing in each thread. If a thread dies unexpectedly, we want the kernel to get the last bits of information before the thread crashes. -syscall set_tracing_info - -parameter 1 : array of 32 user space pointers to current pages or NULL. - - Memory protection -We want each process to be usable to make a trace unreadable, and each process -to have its own memory space. +If a process corrupt its own mmaped buffers, the rest of the trace will be +readable, and each process have its own memory space. Two possibilities : @@ -189,6 +188,34 @@ trace, per process. +API : + +syscall 1 : + +int update_tracing_info(void *buffer, int *active, int *filter); + + +syscall 2 : + +int tracing_buffer_switch(void *buffer); + + +Signal : + +UPD_TRACING +Default : SIG IGNORE +(like hardware fault and expiring timer : to the thread, see p. 413 of Advances +prog. in the UNIX env.) + +Will update for itself only : it will remove unnecessary concurrency. + + + + + + + + diff --git a/ltt/branches/poly/ltt/ltt-private.h b/ltt/branches/poly/ltt/ltt-private.h index 57f0063e..6d51afbb 100644 --- a/ltt/branches/poly/ltt/ltt-private.h +++ b/ltt/branches/poly/ltt/ltt-private.h @@ -160,7 +160,7 @@ struct ltt_trace_header_any { uint8_t flight_recorder; uint8_t has_heartbeat; uint8_t has_alignment; /* Event header alignment */ - uint8_t has_tsc; + uint32_t freq_scale; } LTT_PACKED_STRUCT; @@ -177,12 +177,12 @@ struct ltt_trace_header_0_3 { uint8_t flight_recorder; uint8_t has_heartbeat; uint8_t has_alignment; /* Event header alignment */ - uint8_t has_tsc; + uint32_t freq_scale; } LTT_PACKED_STRUCT; -/* For version 0.6 */ +/* For version 0.7 */ -struct ltt_trace_header_0_6 { +struct ltt_trace_header_0_7 { uint32_t magic_number; uint32_t arch_type; uint32_t arch_variant; @@ -193,11 +193,10 @@ struct ltt_trace_header_0_6 { uint8_t flight_recorder; uint8_t has_heartbeat; uint8_t has_alignment; /* Event header alignment */ - uint8_t has_tsc; + uint32_t freq_scale; uint64_t start_freq; uint64_t start_tsc; uint64_t start_monotonic; - //struct timespec start_time; // not portable uint64_t start_time_sec; uint64_t start_time_usec; } LTT_PACKED_STRUCT; @@ -205,16 +204,10 @@ struct ltt_trace_header_0_6 { struct ltt_block_start_header { struct { - //struct timeval timestamp; - uint64_t timestamp_sec; - uint64_t timestamp_usec; uint64_t cycle_count; uint64_t freq; } begin; struct { - //struct timeval timestamp; - uint64_t timestamp_sec; - uint64_t timestamp_usec; uint64_t cycle_count; uint64_t freq; } end; @@ -258,10 +251,7 @@ struct _LttEvent{ /* End of LttEventPosition fields */ - union { /* choice by trace has_tsc */ - guint32 timestamp; /* truncated timestamp */ - LttTime delta; - } time; + guint32 timestamp; /* truncated timestamp */ unsigned char facility_id; /* facility ID are never reused. */ unsigned char event_id; @@ -406,7 +396,7 @@ struct _LttTrace{ guint8 ltt_minor_version; guint8 flight_recorder; guint8 has_heartbeat; - guint8 has_tsc; + guint32 freq_scale; uint64_t start_freq; uint64_t start_tsc; uint64_t start_monotonic; diff --git a/ltt/branches/poly/ltt/tracefile.c b/ltt/branches/poly/ltt/tracefile.c index af99a23c..5feb97f5 100644 --- a/ltt/branches/poly/ltt/tracefile.c +++ b/ltt/branches/poly/ltt/tracefile.c @@ -232,7 +232,7 @@ int parse_trace_header(void *header, LttTracefile *tf, LttTrace *t) t->ltt_minor_version = any->minor_version; t->flight_recorder = any->flight_recorder; t->has_heartbeat = any->has_heartbeat; - t->has_tsc = any->has_tsc; + t->freq_scale = any->freq_scale; } @@ -250,13 +250,13 @@ int parse_trace_header(void *header, LttTracefile *tf, LttTrace *t) return 1; } break; - case 6: + case 7: { - struct ltt_trace_header_0_6 *vheader = - (struct ltt_trace_header_0_6 *)header; + struct ltt_trace_header_0_7 *vheader = + (struct ltt_trace_header_0_7 *)header; tf->buffer_header_size = sizeof(struct ltt_block_start_header) - + sizeof(struct ltt_trace_header_0_6); + + sizeof(struct ltt_trace_header_0_7); if(t) { t->start_freq = ltt_get_uint64(LTT_GET_BO(tf), &vheader->start_freq); @@ -1598,12 +1598,11 @@ LttTime ltt_interpolate_time(LttTracefile *tf, LttEvent *event) { LttTime time; - g_assert(tf->trace->has_tsc); - // time = ltt_time_from_uint64( // cycles_2_ns(tf, (guint64)(tf->buffer.tsc - tf->buffer.begin.cycle_count))); time = ltt_time_from_uint64( - (double)(tf->buffer.tsc - tf->trace->start_tsc) * 1000000.0 + (double)(tf->buffer.tsc - tf->trace->start_tsc) + * (1000000000.0 / tf->trace->freq_scale) / (double)tf->trace->start_freq); //time = ltt_time_add(tf->buffer.begin.timestamp, time); time = ltt_time_add(tf->trace->start_time_from_tsc, time); @@ -1719,43 +1718,30 @@ int ltt_tracefile_read_update_event(LttTracefile *tf) /* Align the head */ pos += ltt_align((size_t)pos, tf->trace->arch_size, tf->has_alignment); - if(tf->trace->has_tsc) { - if(tf->trace->has_heartbeat) { - event->time.timestamp = ltt_get_uint32(LTT_GET_BO(tf), - pos); - /* 32 bits -> 64 bits tsc */ - /* note : still works for seek and non seek cases. */ - if(event->time.timestamp < (0xFFFFFFFFULL&tf->buffer.tsc)) { - tf->buffer.tsc = ((tf->buffer.tsc&0xFFFFFFFF00000000ULL) - + 0x100000000ULL) - | (guint64)event->time.timestamp; - event->tsc = tf->buffer.tsc; - } else { - /* no overflow */ - tf->buffer.tsc = (tf->buffer.tsc&0xFFFFFFFF00000000ULL) - | (guint64)event->time.timestamp; - event->tsc = tf->buffer.tsc; - } - pos += sizeof(guint32); - } else { - event->tsc = ltt_get_uint64(LTT_GET_BO(tf), pos); - tf->buffer.tsc = event->tsc; - pos += sizeof(guint64); - } - - event->event_time = ltt_interpolate_time(tf, event); - } else { - event->time.delta.tv_sec = 0; - event->time.delta.tv_nsec = ltt_get_uint32(LTT_GET_BO(tf), - pos) * NSEC_PER_USEC; - tf->buffer.tsc = 0; - event->tsc = tf->buffer.tsc; - - event->event_time = ltt_time_add(tf->buffer.begin.timestamp, - event->time.delta); - pos += sizeof(guint32); - } - + if(tf->trace->has_heartbeat) { + event->timestamp = ltt_get_uint32(LTT_GET_BO(tf), + pos); + /* 32 bits -> 64 bits tsc */ + /* note : still works for seek and non seek cases. */ + if(event->timestamp < (0xFFFFFFFFULL&tf->buffer.tsc)) { + tf->buffer.tsc = ((tf->buffer.tsc&0xFFFFFFFF00000000ULL) + + 0x100000000ULL) + | (guint64)event->timestamp; + event->tsc = tf->buffer.tsc; + } else { + /* no overflow */ + tf->buffer.tsc = (tf->buffer.tsc&0xFFFFFFFF00000000ULL) + | (guint64)event->timestamp; + event->tsc = tf->buffer.tsc; + } + pos += sizeof(guint32); + } else { + event->tsc = ltt_get_uint64(LTT_GET_BO(tf), pos); + tf->buffer.tsc = event->tsc; + pos += sizeof(guint64); + } + + event->event_time = ltt_interpolate_time(tf, event); event->facility_id = *(guint8*)pos; pos += sizeof(guint8);