ia64/xen-unstable

view extras/mini-os/time.c @ 2743:df9ad701dbce

bitkeeper revision 1.1159.1.282 (417e5b60oXUOPTWl81d5zD6oq1tOTQ)

Clean up docs dir layout.
author kaf24@freefall.cl.cam.ac.uk
date Tue Oct 26 14:12:48 2004 +0000 (2004-10-26)
parents 3a610b209872
children 189c87adf876 1883ec07708b
line source
1 /* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
2 ****************************************************************************
3 * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
4 * (C) 2002-2003 - Keir Fraser - University of Cambridge
5 ****************************************************************************
6 *
7 * File: time.c
8 * Author: Rolf Neugebauer and Keir Fraser
9 *
10 * Description: Simple time and timer functions
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a copy
13 * of this software and associated documentation files (the "Software"), to
14 * deal in the Software without restriction, including without limitation the
15 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16 * sell copies of the Software, and to permit persons to whom the Software is
17 * furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 * DEALINGS IN THE SOFTWARE.
29 */
32 #include <os.h>
33 #include <types.h>
34 #include <hypervisor.h>
35 #include <events.h>
36 #include <time.h>
37 #include <lib.h>
39 /************************************************************************
40 * Time functions
41 *************************************************************************/
43 static unsigned int rdtsc_bitshift;
44 static u32 st_scale_f; /* convert ticks -> usecs */
45 static u32 st_scale_i; /* convert ticks -> usecs */
47 /* These are peridically updated in shared_info, and then copied here. */
48 static u32 shadow_tsc_stamp;
49 static s64 shadow_system_time;
50 static u32 shadow_time_version;
51 static struct timeval shadow_tv;
53 #ifndef rmb
54 #define rmb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
55 #endif
57 #define HANDLE_USEC_OVERFLOW(_tv) \
58 do { \
59 while ( (_tv).tv_usec >= 1000000 ) \
60 { \
61 (_tv).tv_usec -= 1000000; \
62 (_tv).tv_sec++; \
63 } \
64 } while ( 0 )
66 static void get_time_values_from_xen(void)
67 {
68 do {
69 shadow_time_version = HYPERVISOR_shared_info->time_version2;
70 rmb();
71 shadow_tv.tv_sec = HYPERVISOR_shared_info->wc_sec;
72 shadow_tv.tv_usec = HYPERVISOR_shared_info->wc_usec;
73 shadow_tsc_stamp = HYPERVISOR_shared_info->tsc_timestamp.tsc_bits;
74 shadow_system_time = HYPERVISOR_shared_info->system_time;
75 rmb();
76 }
77 while ( shadow_time_version != HYPERVISOR_shared_info->time_version1 );
78 }
81 #define TIME_VALUES_UP_TO_DATE \
82 (shadow_time_version == HYPERVISOR_shared_info->time_version2)
85 static __inline__ unsigned long get_time_delta_usecs(void)
86 {
87 s32 delta_tsc;
88 u32 low;
89 u64 delta, tsc;
91 rdtscll(tsc);
92 low = (u32)(tsc >> rdtsc_bitshift);
93 delta_tsc = (s32)(low - shadow_tsc_stamp);
94 if ( unlikely(delta_tsc < 0) ) delta_tsc = 0;
95 delta = ((u64)delta_tsc * st_scale_f);
96 delta >>= 32;
97 delta += ((u64)delta_tsc * st_scale_i);
99 return (unsigned long)delta;
100 }
102 s64 get_s_time (void)
103 {
104 u64 u_delta;
105 s64 ret;
107 again:
109 u_delta = get_time_delta_usecs();
110 ret = shadow_system_time + (1000 * u_delta);
112 if ( unlikely(!TIME_VALUES_UP_TO_DATE) )
113 {
114 /*
115 * We may have blocked for a long time, rendering our calculations
116 * invalid (e.g. the time delta may have overflowed). Detect that
117 * and recalculate with fresh values.
118 */
119 get_time_values_from_xen();
120 goto again;
121 }
123 return ret;
124 }
126 void gettimeofday(struct timeval *tv)
127 {
128 struct timeval _tv;
130 do {
131 get_time_values_from_xen();
132 _tv.tv_usec = get_time_delta_usecs();
133 _tv.tv_sec = shadow_tv.tv_sec;
134 _tv.tv_usec += shadow_tv.tv_usec;
135 }
136 while ( unlikely(!TIME_VALUES_UP_TO_DATE) );
138 HANDLE_USEC_OVERFLOW(_tv);
139 *tv = _tv;
140 }
143 /*
144 * Just a dummy
145 */
146 static void timer_handler(int ev, struct pt_regs *regs)
147 {
148 static int i;
149 struct timeval tv;
151 get_time_values_from_xen();
153 i++;
154 if (i >= 1000) {
155 gettimeofday(&tv);
156 printf("T(s=%ld us=%ld)\n", tv.tv_sec, tv.tv_usec);
157 i = 0;
158 }
159 }
162 void init_time(void)
163 {
164 u64 __cpu_khz, cpu_freq, scale;
165 unsigned long cpu_khz;
167 __cpu_khz = HYPERVISOR_shared_info->cpu_freq;
168 cpu_khz = (u32) (__cpu_khz/1000);
170 rdtsc_bitshift = HYPERVISOR_shared_info->tsc_timestamp.tsc_bitshift;
171 cpu_freq = HYPERVISOR_shared_info->cpu_freq;
173 scale = 1000000LL << (32 + rdtsc_bitshift);
174 scale /= cpu_freq;
176 st_scale_f = scale & 0xffffffff;
177 st_scale_i = scale >> 32;
179 printk("Xen reported: %lu.%03lu MHz processor.\n",
180 cpu_khz / 1000, cpu_khz % 1000);
182 add_ev_action(EV_TIMER, &timer_handler);
183 enable_ev_action(EV_TIMER);
184 enable_hypervisor_event(EV_TIMER);
186 }