~ubuntu-branches/ubuntu/utopic/ardour3/utopic

« back to all changes in this revision

Viewing changes to libs/ardour/ardour/cycles.h

  • Committer: Package Import Robot
  • Author(s): Felipe Sateler
  • Date: 2013-09-21 19:05:02 UTC
  • Revision ID: package-import@ubuntu.com-20130921190502-8gsftrku6jnzhd7v
Tags: upstream-3.4~dfsg
ImportĀ upstreamĀ versionĀ 3.4~dfsg

Show diffs side-by-side

added added

removed removed

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