[ltt-dev] [RFC PATCH v2] Add TRACE_CLOCK option to clock_gettime vDSO

Mathieu Desnoyers mathieu.desnoyers at efficios.com
Thu Nov 4 17:23:34 EDT 2010


* Julien Desfossez (julien.desfossez at polymtl.ca) wrote:
> This option allows the user to fetch the current time in sec.nsec based
> on the current TSC using the LTTng infrastructure.
> If the TSC is not synchronized we return an error to the user.
> 
> The main change from the previous version of this patch is the
> conversion of the TSC in sec.nsec instead of encoding it in the timespec
> struct. Also now we check if the TSC is synchronized and we export this
> information along with the CPU frequency in the vDSO shared structure.
> 
> The next step is to make this code work even if vDSOs are not available and
> then to find a way to call {get,put}_trace_clock from inside the vDSO to
> activate the archtitecture specific debug infrastructure if necessary, but this
> should probably come in a different patch.

Yes, you are right. Please keep this as a separate patch.

> 
> Signed-off-by: Julien Desfossez <julien.desfossez at polymtl.ca>
> ---
>  arch/x86/include/asm/trace-clock.h |    1 +
>  arch/x86/include/asm/vgtod.h       |    2 ++
>  arch/x86/kernel/vsyscall_64.c      |    5 +++++
>  arch/x86/vdso/vclock_gettime.c     |   36 ++++++++++++++++++++++++++++++++++++
>  include/linux/time.h               |    1 +
>  5 files changed, 45 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/x86/include/asm/trace-clock.h b/arch/x86/include/asm/trace-clock.h
> index 01bc2f5..c1fd160 100644
> --- a/arch/x86/include/asm/trace-clock.h
> +++ b/arch/x86/include/asm/trace-clock.h
> @@ -14,6 +14,7 @@
>  #include <asm/system.h>
>  #include <asm/processor.h>
>  #include <asm/atomic.h>
> +#include <asm/vgtod.h>
>  
>  /* Minimum duration of a probe, in cycles */
>  #define TRACE_CLOCK_MIN_PROBE_DURATION 200
> diff --git a/arch/x86/include/asm/vgtod.h b/arch/x86/include/asm/vgtod.h
> index 3d61e20..7b6f50b 100644
> --- a/arch/x86/include/asm/vgtod.h
> +++ b/arch/x86/include/asm/vgtod.h
> @@ -12,6 +12,8 @@ struct vsyscall_gtod_data {
>  	u32		wall_time_nsec;
>  
>  	int		sysctl_enabled;
> +	int		trace_clock_is_sync;
> +	u64		scaled_cpu_khz;
>  	struct timezone sys_tz;
>  	struct { /* extract of a clocksource struct */
>  		cycle_t (*vread)(void);
> diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
> index dcbb28c..b5d52ab 100644
> --- a/arch/x86/kernel/vsyscall_64.c
> +++ b/arch/x86/kernel/vsyscall_64.c
> @@ -44,6 +44,8 @@
>  #include <asm/desc.h>
>  #include <asm/topology.h>
>  #include <asm/vgtod.h>
> +#include <asm/trace-clock.h>
> +#include <asm/timer.h>
>  
>  #define __vsyscall(nr) \
>  		__attribute__ ((unused, __section__(".vsyscall_" #nr))) notrace
> @@ -61,6 +63,7 @@ struct vsyscall_gtod_data __vsyscall_gtod_data __section_vsyscall_gtod_data =
>  {
>  	.lock = SEQLOCK_UNLOCKED,
>  	.sysctl_enabled = 1,
> +	.trace_clock_is_sync = 0,
>  };
>  
>  void update_vsyscall_tz(void)
> @@ -89,6 +92,8 @@ void update_vsyscall(struct timespec *wall_time, struct timespec *wtm,
>  	vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec;
>  	vsyscall_gtod_data.wall_to_monotonic = *wtm;
>  	vsyscall_gtod_data.wall_time_coarse = __current_kernel_time();
> +	vsyscall_gtod_data.scaled_cpu_khz = (u64)cpu_khz >> CYC2NS_SCALE_FACTOR;
> +	vsyscall_gtod_data.trace_clock_is_sync = _trace_clock_is_sync;
>  	write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags);
>  }
>  
> diff --git a/arch/x86/vdso/vclock_gettime.c b/arch/x86/vdso/vclock_gettime.c
> index ee55754..8574ba6 100644
> --- a/arch/x86/vdso/vclock_gettime.c
> +++ b/arch/x86/vdso/vclock_gettime.c
> @@ -22,6 +22,8 @@
>  #include <asm/hpet.h>
>  #include <asm/unistd.h>
>  #include <asm/io.h>
> +#include <asm/trace-clock.h>
> +#include <asm/timer.h>
>  #include "vextern.h"
>  
>  #define gtod vdso_vsyscall_gtod_data
> @@ -69,6 +71,7 @@ vset_normalized_timespec(struct timespec *ts, long sec, long nsec)
>  		--sec;
>  	}
>  	ts->tv_sec = sec;
> +

whitespace.

>  	ts->tv_nsec = nsec;
>  }
>  
> @@ -111,6 +114,33 @@ notrace static noinline int do_monotonic_coarse(struct timespec *ts)
>  	return 0;
>  }
>  
> +#ifdef CONFIG_X86
> +notrace static noinline int do_trace_clock(struct timespec *ts)
> +{
> +	cycle_t cycles;
> +	unsigned long tmp;
> +
> +	if (!gtod->trace_clock_is_sync)
> +		return -EPERM;
> +
> +	/* Copy of the version in kernel/tsc.c which we cannot directly access
> +	 *
> +	 * Surround the RDTSC by barriers, to make sure it's not
> +	 * speculated to outside the seqlock critical section and
> +	 * does not cause time warps:
> +	 */
> +	rdtsc_barrier();
> +	cycles = (cycle_t)vget_cycles();
> +	rdtsc_barrier();
> +
> +	tmp = cycles*(USEC_PER_SEC / gtod->scaled_cpu_khz) >> CYC2NS_SCALE_FACTOR;

Is it me or the seqlock is missing ?

Thanks,

Mathieu


> +	ts->tv_nsec = do_div(tmp, NSEC_PER_SEC);
> +	ts->tv_sec = tmp;
> +
> +	return 0;
> +}
> +#endif /* CONFIG_X86 */
> +
>  notrace int __vdso_clock_gettime(clockid_t clock, struct timespec *ts)
>  {
>  	if (likely(gtod->sysctl_enabled))
> @@ -127,6 +157,12 @@ notrace int __vdso_clock_gettime(clockid_t clock, struct timespec *ts)
>  			return do_realtime_coarse(ts);
>  		case CLOCK_MONOTONIC_COARSE:
>  			return do_monotonic_coarse(ts);
> +#ifdef CONFIG_X86
> +		case CLOCK_TRACE:
> +			return do_trace_clock(ts);
> +#endif
> +		default:
> +			return -EINVAL;
>  		}
>  	return vdso_fallback_gettime(clock, ts);
>  }
> diff --git a/include/linux/time.h b/include/linux/time.h
> index 9f15ac7..bf638ff 100644
> --- a/include/linux/time.h
> +++ b/include/linux/time.h
> @@ -290,6 +290,7 @@ struct itimerval {
>  #define CLOCK_MONOTONIC_RAW		4
>  #define CLOCK_REALTIME_COARSE		5
>  #define CLOCK_MONOTONIC_COARSE		6
> +#define CLOCK_TRACE					7
>  
>  /*
>   * The IDs of various hardware clocks:
> -- 
> 1.7.0.4
> 

-- 
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com




More information about the lttng-dev mailing list