2 * \file rtc/lib/client/librtc.cc
6 * \author Frank Mehnert <fm3@os.inf.tu-dresden.de> */
9 * (c) 2003-2009 Author(s)
10 * economic rights: Technische Universität Dresden (Germany)
12 * This file is part of TUD:OS and distributed under the terms of the
13 * GNU General Public License 2.
14 * Please see the COPYING-GPL-2 file for details.
17 #if defined(ARCH_x86) || defined(ARCH_amd64)
22 #include <l4/sys/err.h>
23 #include <l4/rtc/rtc.h>
24 #include <l4/sys/types.h>
26 #include <l4/re/namespace>
27 #include <l4/re/util/cap_alloc>
28 #include <l4/cxx/ipc_stream>
33 #include <l4/util/rdtsc.h>
36 //#include "rtc-client.h"
38 static l4_uint32_t s_offs_to_systime;
39 static l4_uint32_t linux_scaler;
41 /* We need to define this scaler here for use with l4_tsc_to_ns */
42 // l4_uint32_t l4_scaler_tsc_to_ns;
46 static int server_tried;
47 static L4::Cap<void> server(L4_INVALID_CAP);
50 * A fast and cheap way to calculate without violate the 32-bit range */
51 static inline l4_uint32_t
52 muldiv (l4_uint32_t val, l4_uint32_t mul, l4_uint32_t div)
56 asm volatile ("mull %3 ; divl %4\n\t"
57 :"=a" (val), "=d" (dummy)
58 : "0" (val), "d" (mul), "c" (div));
63 l4rtc_if_get_offset_call(L4::Cap<void> server, l4_uint32_t *offset)
65 L4::Ipc_iostream _(l4_utcb());
66 _ << l4_umword_t(L4RTC_OPCODE_get_offset);
67 l4_msgtag_t res = _.call(server.cap());
68 if (l4_ipc_error(res, l4_utcb()))
75 l4rtc_if_get_linux_tsc_scaler_call(L4::Cap<void> server, l4_uint32_t *scaler)
77 L4::Ipc_iostream _(l4_utcb());
78 _ << l4_umword_t(L4RTC_OPCODE_get_linux_tsc_scaler);
79 l4_msgtag_t res = _.call(server.cap());
80 if (l4_ipc_error(res, l4_utcb()))
87 * Connect to server and retreive general values */
93 server = L4Re::Env::env()->get_cap<void>("rtc");
94 if (!server.is_valid())
96 printf("rtc not found\n");
102 if (l4rtc_if_get_offset_call(server, &s_offs_to_systime))
105 if (l4rtc_if_get_linux_tsc_scaler_call(server, &linux_scaler))
108 l4_scaler_tsc_to_ns = muldiv(linux_scaler, 1000, 1<<5);
109 l4_scaler_tsc_to_us = linux_scaler;
110 l4_scaler_ns_to_tsc = muldiv(1U<<27, 1U<<29, 125*linux_scaler);
116 static inline void gettime(l4_uint32_t *s, l4_uint32_t *ns)
118 l4_tsc_to_s_and_ns(l4_rdtsc(), s, ns);
128 static inline void gettime(l4_uint32_t *s, l4_uint32_t *ns)
135 * Deliver the numbers of seconds elapsed since 01.01.1970. This value is
136 * needed by Linux. */
138 l4rtc_get_seconds_since_1970(l4_uint32_t *seconds)
146 *seconds = s + s_offs_to_systime;
151 * Deliver the offset between real time and system's uptime in seconds.
152 * Some applications want to compute their time in other ways as done
153 * in l4rtc_get_seconds_since_1970(). */
155 l4rtc_get_offset_to_realtime(l4_uint32_t *offset)
160 *offset = s_offs_to_systime;
165 * Deliver the scaler 2^32 / (tsc clocks per usec). This value is needed by
168 l4rtc_get_linux_tsc_scaler(l4_uint32_t *scaler)
173 *scaler = linux_scaler;