Merge tag 'locks-v3.16-2' of git://git.samba.org/jlayton/linux
[linux/fpc-iii.git] / arch / tile / kernel / vdso / vgettimeofday.c
blob51ec8e46f5f90667faef2bef6b195a70bd6a1e3b
1 /*
2 * Copyright 2012 Tilera Corporation. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11 * NON INFRINGEMENT. See the GNU General Public License for
12 * more details.
15 #define VDSO_BUILD /* avoid some shift warnings for -m32 in <asm/page.h> */
16 #include <linux/time.h>
17 #include <asm/timex.h>
18 #include <asm/vdso.h>
20 #if CHIP_HAS_SPLIT_CYCLE()
21 static inline cycles_t get_cycles_inline(void)
23 unsigned int high = __insn_mfspr(SPR_CYCLE_HIGH);
24 unsigned int low = __insn_mfspr(SPR_CYCLE_LOW);
25 unsigned int high2 = __insn_mfspr(SPR_CYCLE_HIGH);
27 while (unlikely(high != high2)) {
28 low = __insn_mfspr(SPR_CYCLE_LOW);
29 high = high2;
30 high2 = __insn_mfspr(SPR_CYCLE_HIGH);
33 return (((cycles_t)high) << 32) | low;
35 #define get_cycles get_cycles_inline
36 #endif
39 * Find out the vDSO data page address in the process address space.
41 inline unsigned long get_datapage(void)
43 unsigned long ret;
45 /* vdso data page located in the 2nd vDSO page. */
46 asm volatile ("lnk %0" : "=r"(ret));
47 ret &= ~(PAGE_SIZE - 1);
48 ret += PAGE_SIZE;
50 return ret;
53 int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
55 cycles_t cycles;
56 unsigned long count, sec, ns;
57 volatile struct vdso_data *vdso_data;
59 vdso_data = (struct vdso_data *)get_datapage();
60 /* The use of the timezone is obsolete, normally tz is NULL. */
61 if (unlikely(tz != NULL)) {
62 while (1) {
63 /* Spin until the update finish. */
64 count = vdso_data->tz_update_count;
65 if (count & 1)
66 continue;
68 tz->tz_minuteswest = vdso_data->tz_minuteswest;
69 tz->tz_dsttime = vdso_data->tz_dsttime;
71 /* Check whether updated, read again if so. */
72 if (count == vdso_data->tz_update_count)
73 break;
77 if (unlikely(tv == NULL))
78 return 0;
80 while (1) {
81 /* Spin until the update finish. */
82 count = vdso_data->tb_update_count;
83 if (count & 1)
84 continue;
86 cycles = (get_cycles() - vdso_data->xtime_tod_stamp);
87 ns = (cycles * vdso_data->mult) >> vdso_data->shift;
88 sec = vdso_data->xtime_clock_sec;
89 ns += vdso_data->xtime_clock_nsec;
90 if (ns >= NSEC_PER_SEC) {
91 ns -= NSEC_PER_SEC;
92 sec += 1;
95 /* Check whether updated, read again if so. */
96 if (count == vdso_data->tb_update_count)
97 break;
100 tv->tv_sec = sec;
101 tv->tv_usec = ns / 1000;
103 return 0;
106 int gettimeofday(struct timeval *tv, struct timezone *tz)
107 __attribute__((weak, alias("__vdso_gettimeofday")));