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"
24 #include "JackTypes.h"
25 #include "JackError.h"
31 #include <sys/types.h>
40 jack_time_t (*_jack_get_microseconds
)(void) = 0;
42 #if defined(__gnu_linux__) && (defined(__i386__) || defined(__x86_64__))
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
;
52 typedef uint32_t hpet_counter_t
;
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__) */
64 static int jack_hpet_init ()
68 hpet_fd
= open("/dev/hpet", O_RDONLY
);
70 jack_error ("This system has no accessible HPET device (%s)", strerror (errno
));
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
));
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);
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));
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.");
117 static jack_time_t
jack_get_microseconds_from_hpet (void)
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
;
134 gettimeofday (&tv
, NULL
);
135 jackTime
= (jack_time_t
) tv
.tv_sec
* 1000000 + (jack_time_t
) tv
.tv_usec
;
141 static jack_time_t
jack_get_microseconds_from_system (void)
143 jack_time_t jackTime
;
144 struct timespec time
;
146 #ifdef CLOCK_MONOTONIC_RAW
147 clock_gettime(CLOCK_MONOTONIC_RAW
, &time
);
149 clock_gettime(CLOCK_MONOTONIC
, &time
);
151 jackTime
= (jack_time_t
) time
.tv_sec
* 1e6
+
152 (jack_time_t
) time
.tv_nsec
/ 1e3
;
156 #endif /* HAVE_CLOCK_GETTIME */
159 SERVER_EXPORT
void JackSleep(long usec
)
164 SERVER_EXPORT
void InitTime()
166 /* nothing to do on a generic system - we use the system clock */
169 SERVER_EXPORT
void EndTime()
172 void SetClockSource(jack_timer_type_t source
)
174 jack_log("Clock source : %s", ClockSourceName(source
));
178 case JACK_TIMER_HPET
:
179 if (jack_hpet_init () == 0) {
180 _jack_get_microseconds
= jack_get_microseconds_from_hpet
;
182 _jack_get_microseconds
= jack_get_microseconds_from_system
;
186 case JACK_TIMER_SYSTEM_CLOCK
:
188 _jack_get_microseconds
= jack_get_microseconds_from_system
;
193 const char* ClockSourceName(jack_timer_type_t source
)
196 case JACK_TIMER_HPET
:
198 case JACK_TIMER_SYSTEM_CLOCK
:
199 #ifdef HAVE_CLOCK_GETTIME
200 return "system clock via clock_gettime";
202 return "system clock via gettimeofday";
206 /* what is wrong with gcc ? */
210 SERVER_EXPORT jack_time_t
GetMicroSeconds()
212 return _jack_get_microseconds();
215 SERVER_EXPORT jack_time_t
jack_get_microseconds()
217 return _jack_get_microseconds();