4e7e5eab74
In the last few years the kernel gained quite some architecture specific vdso implementations which contain very similar code. Introduce a generic VDSO implementation of gettimeofday() which will be shareable between architectures once they are converted over. The implementation is based on the current x86 VDSO code. [ tglx: Massaged changelog and made the kernel doc tabular ] Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Shijith Thotton <sthotton@marvell.com> Tested-by: Andre Przywara <andre.przywara@arm.com> Cc: linux-arch@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-mips@vger.kernel.org Cc: linux-kselftest@vger.kernel.org Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Will Deacon <will.deacon@arm.com> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Russell King <linux@armlinux.org.uk> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: Paul Burton <paul.burton@mips.com> Cc: Daniel Lezcano <daniel.lezcano@linaro.org> Cc: Mark Salyzyn <salyzyn@android.com> Cc: Peter Collingbourne <pcc@google.com> Cc: Shuah Khan <shuah@kernel.org> Cc: Dmitry Safonov <0x7f454c46@gmail.com> Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk> Cc: Huw Davies <huw@codeweavers.com> Link: https://lkml.kernel.org/r/20190621095252.32307-3-vincenzo.frascino@arm.com (cherry picked from commit 00b26474c2f1613d7ab894c525f775c67c8a9e8f) Signed-off-by: Mark Salyzyn <salyzyn@google.com> Bug: 154668398 Change-Id: I6d3031546e60ea5a883ea34198999a3fd0f34351
56 lines
1.3 KiB
C
56 lines
1.3 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef __VDSO_HELPERS_H
|
|
#define __VDSO_HELPERS_H
|
|
|
|
#ifndef __ASSEMBLY__
|
|
|
|
#include <vdso/datapage.h>
|
|
|
|
static __always_inline u32 vdso_read_begin(const struct vdso_data *vd)
|
|
{
|
|
u32 seq;
|
|
|
|
while ((seq = READ_ONCE(vd->seq)) & 1)
|
|
cpu_relax();
|
|
|
|
smp_rmb();
|
|
return seq;
|
|
}
|
|
|
|
static __always_inline u32 vdso_read_retry(const struct vdso_data *vd,
|
|
u32 start)
|
|
{
|
|
u32 seq;
|
|
|
|
smp_rmb();
|
|
seq = READ_ONCE(vd->seq);
|
|
return seq != start;
|
|
}
|
|
|
|
static __always_inline void vdso_write_begin(struct vdso_data *vd)
|
|
{
|
|
/*
|
|
* WRITE_ONCE it is required otherwise the compiler can validly tear
|
|
* updates to vd[x].seq and it is possible that the value seen by the
|
|
* reader it is inconsistent.
|
|
*/
|
|
WRITE_ONCE(vd[CS_HRES_COARSE].seq, vd[CS_HRES_COARSE].seq + 1);
|
|
WRITE_ONCE(vd[CS_RAW].seq, vd[CS_RAW].seq + 1);
|
|
smp_wmb();
|
|
}
|
|
|
|
static __always_inline void vdso_write_end(struct vdso_data *vd)
|
|
{
|
|
smp_wmb();
|
|
/*
|
|
* WRITE_ONCE it is required otherwise the compiler can validly tear
|
|
* updates to vd[x].seq and it is possible that the value seen by the
|
|
* reader it is inconsistent.
|
|
*/
|
|
WRITE_ONCE(vd[CS_HRES_COARSE].seq, vd[CS_HRES_COARSE].seq + 1);
|
|
WRITE_ONCE(vd[CS_RAW].seq, vd[CS_RAW].seq + 1);
|
|
}
|
|
|
|
#endif /* !__ASSEMBLY__ */
|
|
|
|
#endif /* __VDSO_HELPERS_H */
|