Remove linux/cycles.h
[jack2.git] / linux / JackLinuxTime.c
bloba5ece7650797616e95b7f3b45b57082dd19cf711
1 /*
2 Copyright (C) 2001-2003 Paul Davis
3 Copyright (C) 2005 Jussi Laako
4 Copyright (C) 2004-2008 Grame
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #include "JackConstants.h"
23 #include "JackTime.h"
24 #include "JackTypes.h"
25 #include "JackError.h"
27 #include <stdint.h>
28 #include <stdio.h>
29 #include <sys/mman.h>
30 #include <sys/time.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 #include <errno.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <stdlib.h>
38 #include <inttypes.h>
40 jack_time_t (*_jack_get_microseconds)(void) = 0;
42 #if defined(__gnu_linux__) && (defined(__i386__) || defined(__x86_64__))
43 #define HPET_SUPPORT
44 #define HPET_MMAP_SIZE 1024
45 #define HPET_CAPS 0x000
46 #define HPET_PERIOD 0x004
47 #define HPET_COUNTER 0x0f0
48 #define HPET_CAPS_COUNTER_64BIT (1 << 13)
49 #if defined(__x86_64__)
50 typedef uint64_t hpet_counter_t;
51 #else
52 typedef uint32_t hpet_counter_t;
53 #endif
54 static int hpet_fd;
55 static unsigned char *hpet_ptr;
56 static uint32_t hpet_period; /* period length in femto secs */
57 static uint64_t hpet_offset = 0;
58 static uint64_t hpet_wrap;
59 static hpet_counter_t hpet_previous = 0;
60 #endif /* defined(__gnu_linux__) && (__i386__ || __x86_64__) */
62 #ifdef HPET_SUPPORT
64 static int jack_hpet_init ()
66 uint32_t hpet_caps;
68 hpet_fd = open("/dev/hpet", O_RDONLY);
69 if (hpet_fd < 0) {
70 jack_error ("This system has no accessible HPET device (%s)", strerror (errno));
71 return -1;
74 hpet_ptr = (unsigned char *) mmap(NULL, HPET_MMAP_SIZE,
75 PROT_READ, MAP_SHARED, hpet_fd, 0);
76 if (hpet_ptr == MAP_FAILED) {
77 jack_error ("This system has no mappable HPET device (%s)", strerror (errno));
78 close (hpet_fd);
79 return -1;
82 /* this assumes period to be constant. if needed,
83 it can be moved to the clock access function
85 hpet_period = *((uint32_t *) (hpet_ptr + HPET_PERIOD));
86 hpet_caps = *((uint32_t *) (hpet_ptr + HPET_CAPS));
87 hpet_wrap = ((hpet_caps & HPET_CAPS_COUNTER_64BIT) &&
88 (sizeof(hpet_counter_t) == sizeof(uint64_t))) ?
89 0 : ((uint64_t) 1 << 32);
91 return 0;
94 static jack_time_t jack_get_microseconds_from_hpet (void)
96 hpet_counter_t hpet_counter;
97 long double hpet_time;
99 hpet_counter = *((hpet_counter_t *) (hpet_ptr + HPET_COUNTER));
100 if (hpet_counter < hpet_previous)
101 hpet_offset += hpet_wrap;
102 hpet_previous = hpet_counter;
103 hpet_time = (long double) (hpet_offset + hpet_counter) *
104 (long double) hpet_period * (long double) 1e-9;
105 return ((jack_time_t) (hpet_time + 0.5));
108 #else
110 static int jack_hpet_init ()
112 jack_error ("This version of JACK or this computer does not have HPET support.\n"
113 "Please choose a different clock source.");
114 return -1;
117 static jack_time_t jack_get_microseconds_from_hpet (void)
119 /* never called */
120 return 0;
123 #endif /* HPET_SUPPORT */
125 #define HAVE_CLOCK_GETTIME 1
127 #ifndef HAVE_CLOCK_GETTIME
129 static jack_time_t jack_get_microseconds_from_system (void)
131 jack_time_t jackTime;
132 struct timeval tv;
134 gettimeofday (&tv, NULL);
135 jackTime = (jack_time_t) tv.tv_sec * 1000000 + (jack_time_t) tv.tv_usec;
136 return jackTime;
139 #else
141 static jack_time_t jack_get_microseconds_from_system (void)
143 jack_time_t jackTime;
144 struct timespec time;
146 clock_gettime(CLOCK_MONOTONIC, &time);
147 jackTime = (jack_time_t) time.tv_sec * 1e6 +
148 (jack_time_t) time.tv_nsec / 1e3;
149 return jackTime;
152 #endif /* HAVE_CLOCK_GETTIME */
155 SERVER_EXPORT void JackSleep(long usec)
157 usleep(usec);
160 SERVER_EXPORT void InitTime()
162 /* nothing to do on a generic system - we use the system clock */
165 SERVER_EXPORT void EndTime()
168 void SetClockSource(jack_timer_type_t source)
170 jack_log("Clock source : %s", ClockSourceName(source));
172 switch (source)
174 case JACK_TIMER_HPET:
175 if (jack_hpet_init () == 0) {
176 _jack_get_microseconds = jack_get_microseconds_from_hpet;
177 } else {
178 _jack_get_microseconds = jack_get_microseconds_from_system;
180 break;
182 case JACK_TIMER_SYSTEM_CLOCK:
183 default:
184 _jack_get_microseconds = jack_get_microseconds_from_system;
185 break;
189 const char* ClockSourceName(jack_timer_type_t source)
191 switch (source) {
192 case JACK_TIMER_HPET:
193 return "hpet";
194 case JACK_TIMER_SYSTEM_CLOCK:
195 #ifdef HAVE_CLOCK_GETTIME
196 return "system clock via clock_gettime";
197 #else
198 return "system clock via gettimeofday";
199 #endif
202 /* what is wrong with gcc ? */
203 return "unknown";
206 SERVER_EXPORT jack_time_t GetMicroSeconds()
208 return _jack_get_microseconds();
211 SERVER_EXPORT jack_time_t jack_get_microseconds()
213 return _jack_get_microseconds();