libardour added.
[ardour.git] / libs / ardour / ardour / cycles.h
1 /*
2     Copyright (C) 2001 Paul Davis
3     Code derived from various headers from the Linux kernel
4     
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19     $Id$
20 */
21
22 #ifndef __ardour_cycles_h__
23 #define __ardour_cycles_h__
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 extern cycles_t cacheflush_time;
46
47 #define rdtscll(val) \
48      __asm__ __volatile__("rdtsc" : "=A" (val))
49
50 static inline cycles_t get_cycles (void)
51 {
52         uint32_t long ret;
53
54         rdtscll(ret);
55         return ret;
56 }
57
58 #elif defined(__powerpc__)
59
60 #define CPU_FTR_601                     0x00000100
61
62 typedef uint32_t cycles_t;
63
64 /*
65  * For the "cycle" counter we use the timebase lower half.
66  * Currently only used on SMP.
67  */
68
69 extern cycles_t cacheflush_time;
70
71 static inline cycles_t get_cycles(void)
72 {
73         cycles_t ret = 0;
74
75         __asm__ __volatile__(
76                 "98:    mftb %0\n"
77                 "99:\n"
78                 ".section __ftr_fixup,\"a\"\n"
79                 "       .long %1\n"
80                 "       .long 0\n"
81                 "       .long 98b\n"
82                 "       .long 99b\n"
83                 ".previous"
84                 : "=r" (ret) : "i" (CPU_FTR_601));
85         return ret;
86 }
87
88 #elif defined(__ia64__)
89 /* ia64 */
90
91 typedef uint32_t cycles_t;
92 static inline cycles_t
93 get_cycles (void)
94 {
95         cycles_t ret;
96         __asm__ __volatile__ ("mov %0=ar.itc" : "=r"(ret));
97         return ret;
98 }
99
100 #elif defined(__alpha__)
101 /* alpha */
102
103 /*
104  * Standard way to access the cycle counter.
105  * Currently only used on SMP for scheduling.
106  *
107  * Only the low 32 bits are available as a continuously counting entity. 
108  * But this only means we'll force a reschedule every 8 seconds or so,
109  * which isn't an evil thing.
110  */
111
112 typedef uint32_t cycles_t;
113 static inline cycles_t get_cycles (void)
114 {
115         cycles_t ret;
116         __asm__ __volatile__ ("rpcc %0" : "=r"(ret));
117         return ret;
118 }
119
120 #elif defined(__s390__)
121 /* s390 */
122
123 typedef uint32_t long cycles_t;
124 static inline cycles_t get_cycles(void)
125 {
126         cycles_t cycles;
127         __asm__("stck 0(%0)" : : "a" (&(cycles)) : "memory", "cc");
128         return cycles >> 2;
129 }
130
131 #elif defined(__hppa__)
132 /* hppa/parisc */
133
134 #define mfctl(reg)      ({              \
135         uint32_t cr;               \
136         __asm__ __volatile__(           \
137                 "mfctl " #reg ",%0" :   \
138                  "=r" (cr)              \
139         );                              \
140         cr;                             \
141 })
142
143 typedef uint32_t cycles_t;
144 static inline cycles_t get_cycles (void)
145 {
146         return mfctl(16);
147 }
148
149 #elif defined(__mips__)
150 /* mips/mipsel */
151
152 /*
153  * Standard way to access the cycle counter.
154  * Currently only used on SMP for scheduling.
155  *
156  * Only the low 32 bits are available as a continuously counting entity.
157  * But this only means we'll force a reschedule every 8 seconds or so,
158  * which isn't an evil thing.
159  *
160  * We know that all SMP capable CPUs have cycle counters.
161  */
162
163 #define __read_32bit_c0_register(source, sel)                           \
164 ({ int __res;                                                           \
165         if (sel == 0)                                                   \
166                 __asm__ __volatile__(                                   \
167                         "mfc0\t%0, " #source "\n\t"                     \
168                         : "=r" (__res));                                \
169         else                                                            \
170                 __asm__ __volatile__(                                   \
171                         ".set\tmips32\n\t"                              \
172                         "mfc0\t%0, " #source ", " #sel "\n\t"           \
173                         ".set\tmips0\n\t"                               \
174                         : "=r" (__res));                                \
175         __res;                                                          \
176 })
177
178 /* #define CP0_COUNT $9 */
179 #define read_c0_count()         __read_32bit_c0_register($9, 0)
180
181 typedef uint32_t cycles_t;
182 static inline cycles_t get_cycles (void)
183 {
184         return read_c0_count();
185 }
186
187 /* begin mach */
188 #elif defined(__APPLE__)
189 #include <CoreAudio/CoreAudioTypes.h>
190 #include <CoreAudio/HostTime.h>
191 typedef UInt64 cycles_t;
192 static inline cycles_t get_cycles (void)
193 {
194        UInt64 time = AudioGetCurrentHostTime();
195        return AudioConvertHostTimeToNanos(time);
196 }
197 /* end mach  */
198
199 #else
200
201 /* debian: sparc, arm, m68k */
202
203 #warning You are compiling libardour on a platform for which ardour/cycles.h needs work
204
205 #include <sys/time.h>
206
207 typedef long cycles_t;
208
209 extern cycles_t cacheflush_time;
210
211 static inline cycles_t get_cycles(void)
212 {
213        struct timeval tv;
214        gettimeofday (&tv, NULL);
215
216        return tv.tv_usec;
217 }
218
219 #endif
220
221 #endif /* __ardour_cycles_h__ */