Ardour  9.0-pre0-582-g084a23a80d
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 #pragma once
24 
25 #include <stdint.h>
26 
27 #if defined(__i386__) || defined(__x86_64__)
28 
29 /*
30  * Standard way to access the cycle counter on i586+ CPUs.
31  * Currently only used on SMP.
32  *
33  * If you really have a SMP machine with i486 chips or older,
34  * compile for that, and this will just always return zero.
35  * That's ok, it just means that the nicer scheduling heuristics
36  * won't work for you.
37  *
38  * We only use the low 32 bits, and we'd simply better make sure
39  * that we reschedule before that wraps. Scheduling at least every
40  * four billion cycles just basically sounds like a good idea,
41  * regardless of how fast the machine is.
42  */
43 typedef uint64_t cycles_t;
44 
45 #if defined(__x86_64__)
46 
47 #define rdtscll(lo, hi) \
48  __asm__ __volatile__("rdtsc" : "=a" (lo), "=d" (hi))
49 
50 static inline cycles_t get_cycles (void)
51 {
52  cycles_t lo, hi;
53 
54  rdtscll(lo, hi);
55  return lo;
56 }
57 
58 #else
59 
60 #define rdtscll(val) \
61 __asm__ __volatile__("rdtsc" : "=A" (val))
62 
63 static inline cycles_t get_cycles (void)
64 {
65  cycles_t ret;
66 
67  rdtscll(ret);
68  return ret & 0xffffffff;
69 }
70 #endif
71 
72 #elif defined(__powerpc64__)
73 
74 #ifdef __linux__
75 #include <sys/platform/ppc.h>
76 typedef uint64_t cycles_t;
77 static inline cycles_t get_cycles(void)
78 {
79  return __ppc_get_timebase();
80 }
81 #elif defined(__FreeBSD__)
82 typedef uint64_t cycles_t;
83 static inline cycles_t get_cycles(void)
84 {
85  cycles_t tbr;
86  asm volatile("mfspr %0, 268" : "=r"(tbr));
87  return tbr;
88 }
89 #endif
90 
91 #elif defined(__powerpc__)
92 
93 #define CPU_FTR_601 0x00000100
94 
95 typedef uint32_t cycles_t;
96 
97 /*
98  * For the "cycle" counter we use the timebase lower half.
99  * Currently only used on SMP.
100  */
101 
102 static inline cycles_t get_cycles(void)
103 {
104  cycles_t ret = 0;
105 
106  __asm__ __volatile__(
107  "98: mftb %0\n"
108  "99:\n"
109  ".section __ftr_fixup,\"a\"\n"
110  " .long %1\n"
111  " .long 0\n"
112  " .long 98b\n"
113  " .long 99b\n"
114  ".previous"
115  : "=r" (ret) : "i" (CPU_FTR_601));
116  return ret;
117 }
118 
119 #elif defined(__ia64__)
120 /* ia64 */
121 
122 typedef uint32_t cycles_t;
123 static inline cycles_t
124 get_cycles (void)
125 {
126  cycles_t ret;
127  __asm__ __volatile__ ("mov %0=ar.itc" : "=r"(ret));
128  return ret;
129 }
130 
131 #elif defined(__alpha__)
132 /* alpha */
133 
134 /*
135  * Standard way to access the cycle counter.
136  * Currently only used on SMP for scheduling.
137  *
138  * Only the low 32 bits are available as a continuously counting entity.
139  * But this only means we'll force a reschedule every 8 seconds or so,
140  * which isn't an evil thing.
141  */
142 
143 typedef uint32_t cycles_t;
144 static inline cycles_t get_cycles (void)
145 {
146  cycles_t ret;
147  __asm__ __volatile__ ("rpcc %0" : "=r"(ret));
148  return ret;
149 }
150 
151 #elif defined(__s390__)
152 /* s390 */
153 
154 typedef uint32_t long cycles_t;
155 static inline cycles_t get_cycles(void)
156 {
157  cycles_t cycles;
158  __asm__("stck 0(%0)" : : "a" (&(cycles)) : "memory", "cc");
159  return cycles >> 2;
160 }
161 
162 #elif defined(__hppa__)
163 /* hppa/parisc */
164 
165 #define mfctl(reg) ({ \
166  uint32_t cr; \
167  __asm__ __volatile__( \
168  "mfctl " #reg ",%0" : \
169  "=r" (cr) \
170  ); \
171  cr; \
172 })
173 
174 typedef uint32_t cycles_t;
175 static inline cycles_t get_cycles (void)
176 {
177  return mfctl(16);
178 }
179 
180 #elif defined(__mips__)
181 /* mips/mipsel */
182 
183 /*
184  * Standard way to access the cycle counter.
185  * Currently only used on SMP for scheduling.
186  *
187  * Only the low 32 bits are available as a continuously counting entity.
188  * But this only means we'll force a reschedule every 8 seconds or so,
189  * which isn't an evil thing.
190  *
191  * We know that all SMP capable CPUs have cycle counters.
192  */
193 
194 #define __read_32bit_c0_register(source, sel) \
195 ({ int __res; \
196  if (sel == 0) \
197  __asm__ __volatile__( \
198  "mfc0\t%0, " #source "\n\t" \
199  : "=r" (__res)); \
200  else \
201  __asm__ __volatile__( \
202  ".set\tmips32\n\t" \
203  "mfc0\t%0, " #source ", " #sel "\n\t" \
204  ".set\tmips0\n\t" \
205  : "=r" (__res)); \
206  __res; \
207 })
208 
209 /* #define CP0_COUNT $9 */
210 #define read_c0_count() __read_32bit_c0_register($9, 0)
211 
212 typedef uint32_t cycles_t;
213 static inline cycles_t get_cycles (void)
214 {
215  return read_c0_count();
216 }
217 
218 /* begin mach */
219 #elif defined(__APPLE__)
220 
221 #include <CoreAudio/HostTime.h>
222 
223 typedef UInt64 cycles_t;
224 static inline cycles_t get_cycles (void)
225 {
226  UInt64 time = AudioGetCurrentHostTime();
227  return AudioConvertHostTimeToNanos(time);
228 }
229 /* end mach */
230 
231 #else
232 
233 /* debian: sparc, arm, m68k */
234 
235 #ifndef COMPILER_MSVC
236 /* GRRR... Annoyingly, #warning aborts the compilation for MSVC !! */
237 #warning You are compiling libardour on a platform for which ardour/cycles.h needs work
238 #endif
239 
240 #include <sys/time.h>
241 
242 typedef long cycles_t;
243 
244 static inline cycles_t get_cycles(void)
245 {
246  struct timeval tv;
247  gettimeofday (&tv, NULL);
248 
249  return tv.tv_usec;
250 }
251 
252 #endif
253 
static cycles_t get_cycles(void)
Definition: cycles.h:244
long cycles_t
Definition: cycles.h:242