Changeset 74887157 in rtems


Ignore:
Timestamp:
Aug 17, 2016, 9:52:09 AM (3 years ago)
Author:
Konstantin Belousov <kib@…>
Branches:
master
Children:
a9219e7
Parents:
c382cc83
git-author:
Konstantin Belousov <kib@…> (08/17/16 09:52:09)
git-committer:
Sebastian Huber <sebastian.huber@…> (10/12/17 05:04:11)
Message:

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/<arch>/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 <howard0su@…>
Sponsored by: The FreeBSD Foundation
MFC after: 1 month
Differential revision: https://reviews.freebsd.org/D7473

Update #3175.

Location:
cpukit/score
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • cpukit/score/include/sys/timetc.h

    rc382cc83 r74887157  
    3131
    3232struct timecounter;
     33struct vdso_timehands;
     34struct vdso_timehands32;
     35#ifndef __rtems__
     36typedef u_int timecounter_get_t(struct timecounter *);
     37#else /* __rtems__ */
    3338typedef uint32_t timecounter_get_t(struct timecounter *);
     39#endif /* __rtems__ */
    3440typedef void timecounter_pps_t(struct timecounter *);
     41typedef uint32_t timecounter_fill_vdso_timehands_t(struct vdso_timehands *,
     42    struct timecounter *);
     43typedef uint32_t timecounter_fill_vdso_timehands32_t(struct vdso_timehands32 *,
     44    struct timecounter *);
    3545
    3646struct timecounter {
     
    7181        struct timecounter      *tc_next;
    7282                /* Pointer to the next timecounter. */
     83#ifndef __rtems__
     84        timecounter_fill_vdso_timehands_t *tc_fill_vdso_timehands;
     85        timecounter_fill_vdso_timehands32_t *tc_fill_vdso_timehands32;
     86#endif /* __rtems__ */
    7387};
    7488
  • cpukit/score/src/kern_tc.c

    rc382cc83 r74887157  
    77 * ----------------------------------------------------------------------------
    88 *
    9  * Copyright (c) 2011 The FreeBSD Foundation
     9 * Copyright (c) 2011, 2015, 2016 The FreeBSD Foundation
    1010 * All rights reserved.
    1111 *
    1212 * Portions of this software were developed by Julien Ridoux at the University
    1313 * of Melbourne under sponsorship from the FreeBSD Foundation.
     14 *
     15 * Portions of this software were developed by Konstantin Belousov
     16 * under sponsorship from the FreeBSD Foundation.
    1417 */
    1518
     
    23892392
    23902393        th = timehands;
    2391         vdso_th->th_algo = VDSO_TH_ALGO_1;
    23922394        vdso_th->th_scale = th->th_scale;
    23932395        vdso_th->th_offset_count = th->th_offset_count;
     
    23952397        vdso_th->th_offset = th->th_offset;
    23962398        vdso_th->th_boottime = th->th_boottime;
    2397         enabled = cpu_fill_vdso_timehands(vdso_th, th->th_counter);
     2399        if (th->th_counter->tc_fill_vdso_timehands != NULL) {
     2400                enabled = th->th_counter->tc_fill_vdso_timehands(vdso_th,
     2401                    th->th_counter);
     2402        } else
     2403                enabled = 0;
    23982404        if (!vdso_th_enable)
    23992405                enabled = 0;
     
    24102416
    24112417        th = timehands;
    2412         vdso_th32->th_algo = VDSO_TH_ALGO_1;
    24132418        *(uint64_t *)&vdso_th32->th_scale[0] = th->th_scale;
    24142419        vdso_th32->th_offset_count = th->th_offset_count;
     
    24182423        vdso_th32->th_boottime.sec = th->th_boottime.sec;
    24192424        *(uint64_t *)&vdso_th32->th_boottime.frac[0] = th->th_boottime.frac;
    2420         enabled = cpu_fill_vdso_timehands32(vdso_th32, th->th_counter);
     2425        if (th->th_counter->tc_fill_vdso_timehands32 != NULL) {
     2426                enabled = th->th_counter->tc_fill_vdso_timehands32(vdso_th32,
     2427                    th->th_counter);
     2428        } else
     2429                enabled = 0;
    24212430        if (!vdso_th_enable)
    24222431                enabled = 0;
Note: See TracChangeset for help on using the changeset viewer.