File: atomic.h

package info (click to toggle)
kernel-source-2.0.35 2.0.35-3
  • links: PTS
  • area: main
  • in suites: slink
  • size: 32,456 kB
  • ctags: 94,327
  • sloc: ansic: 587,014; asm: 26,388; makefile: 4,055; sh: 1,221; perl: 727; tcl: 408; cpp: 277; lisp: 211; awk: 134
file content (103 lines) | stat: -rw-r--r-- 2,233 bytes parent folder | download | duplicates (13)
1
2
3
4
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
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
95
96
97
98
99
100
101
102
103
#ifndef __ARCH_ALPHA_ATOMIC__
#define __ARCH_ALPHA_ATOMIC__

/*
 * Atomic operations that C can't guarantee us.  Useful for
 * resource counting etc...
 *
 * But use these as seldom as possible since they are much more slower
 * than regular operations.
 */

/*
 * Make sure gcc doesn't try to be clever and move things around
 * on us. We need to use _exactly_ the address the user gave us,
 * not some alias that contains the same information.
 */
#define __atomic_fool_gcc(x) (*(struct { int a[100]; } *)x)

typedef int atomic_t;

extern __inline__ void atomic_add(atomic_t i, atomic_t * v)
{
	unsigned long temp;
	__asm__ __volatile__(
		"\n1:\t"
		"ldl_l %0,%1\n\t"
		"addl %0,%2,%0\n\t"
		"stl_c %0,%1\n\t"
		"beq %0,1b\n"
		"2:"
		:"=&r" (temp),
		 "=m" (__atomic_fool_gcc(v))
		:"Ir" (i),
		 "m" (__atomic_fool_gcc(v)));
}

extern __inline__ void atomic_sub(atomic_t i, atomic_t * v)
{
	unsigned long temp;
	__asm__ __volatile__(
		"\n1:\t"
		"ldl_l %0,%1\n\t"
		"subl %0,%2,%0\n\t"
		"stl_c %0,%1\n\t"
		"beq %0,1b\n"
		"2:"
		:"=&r" (temp),
		 "=m" (__atomic_fool_gcc(v))
		:"Ir" (i),
		 "m" (__atomic_fool_gcc(v)));
}

/*
 * Same as above, but return the result value
 */
extern __inline__ long atomic_add_return(atomic_t i, atomic_t * v)
{
	long temp, result;
	__asm__ __volatile__(
		"\n1:\t"
		"ldl_l %0,%1\n\t"
		"addl %0,%3,%0\n\t"
		"bis %0,%0,%2\n\t"
		"stl_c %0,%1\n\t"
		"beq %0,1b\n"
		"2:"
		:"=&r" (temp),
		 "=m" (__atomic_fool_gcc(v)),
		 "=&r" (result)
		:"Ir" (i),
		 "m" (__atomic_fool_gcc(v)));
	return result;
}

extern __inline__ long atomic_sub_return(atomic_t i, atomic_t * v)
{
	long temp, result;
	__asm__ __volatile__(
		"\n1:\t"
		"ldl_l %0,%1\n\t"
		"subl %0,%3,%0\n\t"
		"bis %0,%0,%2\n\t"
		"stl_c %0,%1\n\t"
		"beq %0,1b\n"
		"2:"
		:"=&r" (temp),
		 "=m" (__atomic_fool_gcc(v)),
		 "=&r" (result)
		:"Ir" (i),
		 "m" (__atomic_fool_gcc(v)));
	return result;
}

#define atomic_dec_return(v) atomic_sub_return(1,(v))
#define atomic_inc_return(v) atomic_add_return(1,(v))

#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)

#define atomic_inc(v) atomic_add(1,(v))
#define atomic_dec(v) atomic_sub(1,(v))

#endif