Ardour  8.12
cycles.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2006 Taybin Rutkin <taybin@taybin.com>
3  * Copyright (C) 2007-2008 Paul Davis <paul@linuxaudiosystems.com>
4  * Copyright (C) 2008-2011 David Robillard <d@drobilla.net>
5  * Copyright (C) 2012 Carl Hetherington <carl@carlh.net>
6  * Copyright (C) 2018-2019 Robin Gareus <robin@gareus.org>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22 
23 #ifndef __ardour_cycles_h__
24 #define __ardour_cycles_h__
25 
26 #include <stdint.h>
27 
28 #if defined(__i386__) || defined(__x86_64__)
29 
30 /*
31  * Standard way to access the cycle counter on i586+ CPUs.
32  * Currently only used on SMP.
33  *
34  * If you really have a SMP machine with i486 chips or older,
35  * compile for that, and this will just always return zero.
36  * That's ok, it just means that the nicer scheduling heuristics
37  * won't work for you.
38  *
39  * We only use the low 32 bits, and we'd simply better make sure
40  * that we reschedule before that wraps. Scheduling at least every
41  * four billion cycles just basically sounds like a good idea,
42  * regardless of how fast the machine is.
43  */
44 typedef uint64_t cycles_t;
45 
46 #if defined(__x86_64__)
47 
48 #define rdtscll(lo, hi) \
49  __asm__ __volatile__("rdtsc" : "=a" (lo), "=d" (hi))
50 
51 static inline cycles_t get_cycles (void)
52 {
53  cycles_t lo, hi;
54 
55  rdtscll(lo, hi);
56  return lo;
57 }
58 
59 #else
60 
61 #define rdtscll(val) \
62 __asm__ __volatile__("rdtsc" : "=A" (val))
63 
64 static inline cycles_t get_cycles (void)
65 {
66  cycles_t ret;
67 
68  rdtscll(ret);
69  return ret & 0xffffffff;
70 }
71 #endif
72 
73 #elif defined(__powerpc64__)
74 
75 #ifdef __linux__
76 #include <sys/platform/ppc.h>
77 typedef uint64_t cycles_t;
78 static inline cycles_t get_cycles(void)
79 {
80  return __ppc_get_timebase();
81 }
82 #elif defined(__FreeBSD__)
83 typedef uint64_t cycles_t;
84 static inline cycles_t get_cycles(void)
85 {
86  cycles_t tbr;
87  asm volatile("mfspr %0, 268" : "=r"(tbr));
88  return tbr;
89 }
90 #endif
91 
92 #elif defined(__powerpc__)
93 
94 #define CPU_FTR_601 0x00000100
95 
96 typedef uint32_t cycles_t;
97 
98 /*
99  * For the "cycle" counter we use the timebase lower half.
100  * Currently only used on SMP.
101  */
102 
103 static inline cycles_t get_cycles(void)
104 {
105  cycles_t ret = 0;
106 
107  __asm__ __volatile__(
108  "98: mftb %0\n"
109  "99:\n"
110  ".section __ftr_fixup,\"a\"\n"
111  " .long %1\n"
112  " .long 0\n"
113  " .long 98b\n"
114  " .long 99b\n"
115  ".previous"
116  : "=r" (ret) : "i" (CPU_FTR_601));
117  return ret;
118 }
119 
120 #elif defined(__ia64__)
121 /* ia64 */
122 
123 typedef uint32_t cycles_t;
124 static inline cycles_t
125 get_cycles (void)
126 {
127  cycles_t ret;
128  __asm__ __volatile__ ("mov %0=ar.itc" : "=r"(ret));
129  return ret;
130 }
131 
132 #elif defined(__alpha__)
133 /* alpha */
134 
135 /*
136  * Standard way to access the cycle counter.
137  * Currently only used on SMP for scheduling.
138  *
139  * Only the low 32 bits are available as a continuously counting entity.
140  * But this only means we'll force a reschedule every 8 seconds or so,
141  * which isn't an evil thing.
142  */
143 
144 typedef uint32_t cycles_t;
145 static inline cycles_t get_cycles (void)
146 {
147  cycles_t ret;
148  __asm__ __volatile__ ("rpcc %0" : "=r"(ret));
149  return ret;
150 }
151 
152 #elif defined(__s390__)
153 /* s390 */
154 
155 typedef uint32_t long cycles_t;
156 static inline cycles_t get_cycles(void)
157 {
158  cycles_t cycles;
159  __asm__("stck 0(%0)" : : "a" (&(cycles)) : "memory", "cc");
160  return cycles >> 2;
161 }
162 
163 #elif defined(__hppa__)
164 /* hppa/parisc */
165 
166 #define mfctl(reg) ({ \
167  uint32_t cr; \
168  __asm__ __volatile__( \
169  "mfctl " #reg ",%0" : \
170  "=r" (cr) \
171  ); \
172  cr; \
173 })
174 
175 typedef uint32_t cycles_t;
176 static inline cycles_t get_cycles (void)
177 {
178  return mfctl(16);
179 }
180 
181 #elif defined(__mips__)
182 /* mips/mipsel */
183 
184 /*
185  * Standard way to access the cycle counter.
186  * Currently only used on SMP for scheduling.
187  *
188  * Only the low 32 bits are available as a continuously counting entity.
189  * But this only means we'll force a reschedule every 8 seconds or so,
190  * which isn't an evil thing.
191  *
192  * We know that all SMP capable CPUs have cycle counters.
193  */
194 
195 #define __read_32bit_c0_register(source, sel) \
196 ({ int __res; \
197  if (sel == 0) \
198  __asm__ __volatile__( \
199  "mfc0\t%0, " #source "\n\t" \
200  : "=r" (__res)); \
201  else \
202  __asm__ __volatile__( \
203  ".set\tmips32\n\t" \
204  "mfc0\t%0, " #source ", " #sel "\n\t" \
205  ".set\tmips0\n\t" \
206  : "=r" (__res)); \
207  __res; \
208 })
209 
210 /* #define CP0_COUNT $9 */
211 #define read_c0_count() __read_32bit_c0_register($9, 0)
212 
213 typedef uint32_t cycles_t;
214 static inline cycles_t get_cycles (void)
215 {
216  return read_c0_count();
217 }
218 
219 /* begin mach */
220 #elif defined(__APPLE__)
221 
222 #include <CoreAudio/HostTime.h>
223 
224 typedef UInt64 cycles_t;
225 static inline cycles_t get_cycles (void)
226 {
227  UInt64 time = AudioGetCurrentHostTime();
228  return AudioConvertHostTimeToNanos(time);
229 }
230 /* end mach */
231 
232 #else
233 
234 /* debian: sparc, arm, m68k */
235 
236 #ifndef COMPILER_MSVC
237 /* GRRR... Annoyingly, #warning aborts the compilation for MSVC !! */
238 #warning You are compiling libardour on a platform for which ardour/cycles.h needs work
239 #endif
240 
241 #include <sys/time.h>
242 
243 typedef long cycles_t;
244 
245 static inline cycles_t get_cycles(void)
246 {
247  struct timeval tv;
248  gettimeofday (&tv, NULL);
249 
250  return tv.tv_usec;
251 }
252 
253 #endif
254 
255 #endif /* __ardour_cycles_h__ */
static cycles_t get_cycles(void)
Definition: cycles.h:245
long cycles_t
Definition: cycles.h:243