cycles.h 3.41 KB
Newer Older
sletz's avatar
sletz committed
1
2
3
/*
  Copyright (C) 2001 Paul Davis
  Code derived from various headers from the Linux kernel
sletz's avatar
sletz committed
4

sletz's avatar
sletz committed
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

  $Id: cycles.h,v 1.4.2.1 2006/06/20 14:44:00 letz Exp $
*/

#ifndef __jack_cycles_h__
#define __jack_cycles_h__

/*
 * Standard way to access the cycle counter on i586+ CPUs.
 * Currently only used on SMP.
 *
 * If you really have a SMP machine with i486 chips or older,
 * compile for that, and this will just always return zero.
 * That's ok, it just means that the nicer scheduling heuristics
 * won't work for you.
 *
 * We only use the low 32 bits, and we'd simply better make sure
 * that we reschedule before that wraps. Scheduling at least every
 * four billion cycles just basically sounds like a good idea,
sletz's avatar
sletz committed
37
 * regardless of how fast the machine is.
sletz's avatar
sletz committed
38
39
40
41
 */

#ifdef __linux__

sletz's avatar
sletz committed
42
43
44
45
46
47
48
49
50
51
52
53
#ifdef __x86_64__

typedef unsigned long cycles_t;
extern cycles_t cacheflush_time;

static inline unsigned long get_cycles(void)
{
    unsigned int hi, lo;
    __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
    return (((unsigned long)hi)<<32) | ((unsigned long)lo);
}

sletz's avatar
sletz committed
54
55
56
57
58
59
60
61
62
63
64
#endif /* __x86_64__ */

#ifdef __sparc_v9__
/* rd is V9 only */
static inline unsigned long long get_cycles(void)
{
	unsigned long long res;
	__asm__ __volatile__("rd %%tick, %0" : "=r"(res));
	return res;
}
#endif /* __sparc_v9__ */
sletz's avatar
sletz committed
65

sletz's avatar
sletz committed
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#ifdef __PPC__

/* PowerPC */

#define CPU_FTR_601			0x00000100

typedef unsigned long cycles_t;

/* For the "cycle" counter we use the timebase lower half. */

extern cycles_t cacheflush_time;

static inline cycles_t get_cycles(void)
{
    cycles_t ret = 0;

    __asm__ __volatile__(
        "98:	mftb %0\n"
        "99:\n"
        ".section __ftr_fixup,\"a\"\n"
        "	.long %1\n"
        "	.long 0\n"
        "	.long 98b\n"
        "	.long 99b\n"
        ".previous"
    : "=r" (ret) : "i" (CPU_FTR_601));
    return ret;
}

sletz's avatar
sletz committed
95
#endif /* __PPC__ */
sletz's avatar
sletz committed
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113

#ifdef __i386__

typedef unsigned long long cycles_t;

extern cycles_t cacheflush_time;

#define rdtscll(val) \
     __asm__ __volatile__("rdtsc" : "=A" (val))

static inline cycles_t get_cycles (void)
{
    unsigned long long ret;

    rdtscll(ret);
    return ret;
}

sletz's avatar
sletz committed
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#endif /* __i386__ */

/* everything else but x86, amd64, sparcv9 or ppc */
#if !defined (__PPC__) && !defined (__x86_64__) && !defined (__i386__) && !defined (__sparc_v9__)

#warning No suitable get_cycles() implementation. Returning 0 instead

typedef unsigned long long cycles_t;

static inline cycles_t get_cycles(void)
{
    return 0;
}

#endif /* everything else but x86, amd64, sparcv9 or ppc */

#endif /* __linux__ */

sletz's avatar
sletz committed
132

sletz's avatar
sletz committed
133
#if defined(__FreeBSD_kernel__)
sletz's avatar
sletz committed
134
135
136
137
138
139
140
141
142
143

#warning No suitable get_cycles() implementation. Returning 0 instead

typedef unsigned long long cycles_t;

static inline cycles_t get_cycles(void)
{
    return 0;
}

sletz's avatar
sletz committed
144
#endif /* __FreeBSD_kernel__ */
sletz's avatar
sletz committed
145

sletz's avatar
sletz committed
146
147

#endif /* __jack_cycles_h__ */