From 748871578c3dd0077e1f1de246993c80424ab63b Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Wed, 17 Aug 2016 09:52:09 +0000 Subject: timecounter: Merge FreeBSD change r304285 Implement userspace gettimeofday(2) with HPET timecounter. Right now, userspace (fast) gettimeofday(2) on x86 only works for RDTSC. For older machines, like Core2, where RDTSC is not C2/C3 invariant, and which fall to HPET hardware, this means that the call has both the penalty of the syscall and of the uncached hw behind the QPI or PCIe connection to the sought bridge. Nothing can me done against the access latency, but the syscall overhead can be removed. System already provides mappable /dev/hpetX devices, which gives straight access to the HPET registers page. Add yet another algorithm to the x86 'vdso' timehands. Libc is updated to handle both RDTSC and HPET. For HPET, the index of the hpet device to mmap is passed from kernel to userspace, index might be changed and libc invalidates its mapping as needed. Remove cpu_fill_vdso_timehands() KPI, instead require that timecounters which can be used from userspace, to provide tc_fill_vdso_timehands{,32}() methods. Merge i386 and amd64 libc//sys/__vdso_gettc.c into one source file in the new libc/x86/sys location. __vdso_gettc() internal interface is changed to move timecounter algorithm detection into the MD code. Measurements show that RDTSC even with the syscall overhead is faster than userspace HPET access. But still, userspace HPET is three-four times faster than syscall HPET on several Core2 and SandyBridge machines. Tested by: Howard Su Sponsored by: The FreeBSD Foundation MFC after: 1 month Differential revision: https://reviews.freebsd.org/D7473 Update #3175. --- cpukit/score/include/sys/timetc.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'cpukit/score/include/sys') diff --git a/cpukit/score/include/sys/timetc.h b/cpukit/score/include/sys/timetc.h index 73e63f7333..361535c0c8 100644 --- a/cpukit/score/include/sys/timetc.h +++ b/cpukit/score/include/sys/timetc.h @@ -30,8 +30,18 @@ */ struct timecounter; +struct vdso_timehands; +struct vdso_timehands32; +#ifndef __rtems__ +typedef u_int timecounter_get_t(struct timecounter *); +#else /* __rtems__ */ typedef uint32_t timecounter_get_t(struct timecounter *); +#endif /* __rtems__ */ typedef void timecounter_pps_t(struct timecounter *); +typedef uint32_t timecounter_fill_vdso_timehands_t(struct vdso_timehands *, + struct timecounter *); +typedef uint32_t timecounter_fill_vdso_timehands32_t(struct vdso_timehands32 *, + struct timecounter *); struct timecounter { timecounter_get_t *tc_get_timecount; @@ -70,6 +80,10 @@ struct timecounter { /* Pointer to the timecounter's private parts. */ struct timecounter *tc_next; /* Pointer to the next timecounter. */ +#ifndef __rtems__ + timecounter_fill_vdso_timehands_t *tc_fill_vdso_timehands; + timecounter_fill_vdso_timehands32_t *tc_fill_vdso_timehands32; +#endif /* __rtems__ */ }; extern struct timecounter *timecounter; -- cgit v1.2.3