aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern B. Brandenburg <bbb@cs.unc.edu>2008-05-21 12:27:45 -0400
committerBjoern B. Brandenburg <bbb@cs.unc.edu>2008-05-21 12:27:45 -0400
commit99631b2b256687a6ab97c095f4094ea873a1e702 (patch)
tree1609d47fc9939c4352353448fa9be861631c3e9d
parent19fdd6f62388ed4373d28ca55b1c63e2fd62bb2f (diff)
add more sparc assembly, and platform indepenent get_cycles()
-rw-r--r--include/asm_i386.h60
-rw-r--r--include/asm_sparc.h77
-rw-r--r--include/cycles.h36
3 files changed, 170 insertions, 3 deletions
diff --git a/include/asm_i386.h b/include/asm_i386.h
index 51ba501..e077ddc 100644
--- a/include/asm_i386.h
+++ b/include/asm_i386.h
@@ -1,8 +1,68 @@
1/* Intel ia32 assembly. 1/* Intel ia32 assembly.
2 * Don't include directly, use asm.h instead. 2 * Don't include directly, use asm.h instead.
3 *
4 * Most of this code comes straight out of the Linux kernel.
5 *
6 * The terms of the GPL v2 apply.
3 */ 7 */
4 8
5static inline void barrier(void) 9static inline void barrier(void)
6{ 10{
7 __asm__ __volatile__("sfence": : :"memory"); 11 __asm__ __volatile__("sfence": : :"memory");
8} 12}
13
14static __inline__ void cpu_relax(void)
15{
16 __asm__ __volatile("pause");
17}
18
19typedef struct { int counter; } atomic_t;
20
21#define ATOMIC_INIT(i) { (i) }
22
23/**
24 * atomic_read - read atomic variable
25 * @v: pointer of type atomic_t
26 *
27 * Atomically reads the value of @v.
28 */
29#define atomic_read(v) ((v)->counter)
30
31/**
32 * atomic_set - set atomic variable
33 * @v: pointer of type atomic_t
34 * @i: required value
35 *
36 * Atomically sets the value of @v to @i.
37 */
38#define atomic_set(v,i) (((v)->counter) = (i))
39
40static __inline__ void atomic_add(int i, atomic_t *v)
41{
42 __asm__ __volatile__(
43 "lock; addl %1,%0"
44 :"+m" (v->counter)
45 :"ir" (i));
46}
47
48/**
49 * atomic_add_return - add and return
50 * @v: pointer of type atomic_t
51 * @i: integer value to add
52 *
53 * Atomically adds @i to @v and returns @i + @v
54 */
55static __inline__ int atomic_add_return(int i, atomic_t *v)
56{
57 int __i;
58 __i = i;
59 __asm__ __volatile__(
60 "lock; xaddl %0, %1"
61 :"+r" (i), "+m" (v->counter)
62 : : "memory");
63 return i + __i;
64}
65
66#define atomic_inc_return(v) (atomic_add_return(1,v))
67
68
diff --git a/include/asm_sparc.h b/include/asm_sparc.h
index 0e0ca78..96c8049 100644
--- a/include/asm_sparc.h
+++ b/include/asm_sparc.h
@@ -1,9 +1,12 @@
1/* sparc64 assembly. 1/* sparc64 assembly.
2 * Don't include directly, use asm.h instead. 2 * Don't include directly, use asm.h instead.
3 *
4 * Most of this code comes straight out of the Linux kernel.
5 *
6 * The terms of the GPL v2 apply.
7 *
3 */ 8 */
4 9
5/* From Linux:
6 <<snip>>*/
7#define membar_safe(type) \ 10#define membar_safe(type) \
8do { __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" \ 11do { __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" \
9 " membar " type "\n" \ 12 " membar " type "\n" \
@@ -13,9 +16,77 @@ do { __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" \
13 16
14#define mb() \ 17#define mb() \
15 membar_safe("#LoadLoad | #LoadStore | #StoreStore | #StoreLoad") 18 membar_safe("#LoadLoad | #LoadStore | #StoreStore | #StoreLoad")
16/* <<snap>> */
17 19
18static inline void barrier(void) 20static inline void barrier(void)
19{ 21{
20 mb(); 22 mb();
21} 23}
24
25
26#define cpu_relax() barrier()
27
28static inline int
29cmpxchg(volatile int *m, int old, int new)
30{
31 __asm__ __volatile__("membar #StoreLoad | #LoadLoad\n"
32 "cas [%2], %3, %0\n\t"
33 "membar #StoreLoad | #StoreStore"
34 : "=&r" (new)
35 : "0" (new), "r" (m), "r" (old)
36 : "memory");
37
38 return new;
39}
40
41
42typedef struct { int counter; } atomic_t;
43
44#define ATOMIC_INIT(i) { (i) }
45
46/**
47 * atomic_read - read atomic variable
48 * @v: pointer of type atomic_t
49 *
50 * Atomically reads the value of @v.
51 */
52#define atomic_read(v) ((v)->counter)
53
54/**
55 * atomic_set - set atomic variable
56 * @v: pointer of type atomic_t
57 * @i: required value
58 *
59 * Atomically sets the value of @v to @i.
60 */
61#define atomic_set(v,i) (((v)->counter) = (i))
62
63
64/**
65 * atomic_add_return - add and return
66 * @v: pointer of type atomic_t
67 * @i: integer value to add
68 *
69 * Atomically adds @i to @v and returns @i + @v
70 */
71static __inline__ int atomic_add_return(int i, atomic_t *v)
72{
73 int old;
74 int ret;
75 goto first;
76 do {
77 cpu_relax();
78 first:
79 old = atomic_read(v);
80 ret = cmpxchg(&v->counter, old, old + i);
81 } while (ret != old);
82 return old + i;
83}
84
85static __inline__ void atomic_add(int i, atomic_t *v)
86{
87 atomic_add_return(i, v);
88}
89
90#define atomic_inc_return(v) (atomic_add_return(1,v))
91
92
diff --git a/include/cycles.h b/include/cycles.h
new file mode 100644
index 0000000..01f36a9
--- /dev/null
+++ b/include/cycles.h
@@ -0,0 +1,36 @@
1#ifndef CYCLES_H
2#define CYCLES_H
3
4#ifdef __i386__
5
6typedef unsigned long long cycles_t;
7
8#define CYCLES_FMT "llu"
9
10static inline cycles_t get_cycles(void)
11{
12 unsigned long long ret;
13 __asm__ __volatile__("rdtsc" : "=A" (ret));
14 return ret;
15}
16
17#endif
18
19
20#ifdef __sparc__
21
22#define NPT_BIT 63
23
24typedef unsigned long cycles_t;
25
26#define CYCLES_FMT "lu"
27
28static inline cycles_t get_cycles(void) {
29 unsigned long cycles = 0;
30 __asm__ __volatile__("rd %%asr24, %0" : "=r" (cycles));
31 return cycles & ~(1UL << NPT_BIT);
32}
33
34#endif
35
36#endif