1 /*	$NetBSD: atomic.h,v 1.1.1.1 2009/12/13 16:54:48 kardel Exp $	*/
2 
3 /*
4  * Copyright (C) 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /* Id: atomic.h,v 1.6 2008/01/24 23:47:00 tbox Exp */
20 
21 #ifndef ISC_ATOMIC_H
22 #define ISC_ATOMIC_H 1
23 
24 #include <isc/platform.h>
25 #include <isc/types.h>
26 
27 #ifdef ISC_PLATFORM_USEGCCASM
28 
29 /* We share the gcc-version with x86_32 */
30 #error "impossible case.  check build configuration"
31 
32 #elif defined(ISC_PLATFORM_USESTDASM)
33 /*
34  * The followings are "generic" assembly code which implements the same
35  * functionality in case the gcc extension cannot be used.  It should be
36  * better to avoid inlining below, since we directly refer to specific
37  * registers for arguments, which would not actually correspond to the
38  * intended address or value in the embedded mnemonic.
39  */
40 #include <isc/util.h>		/* for 'UNUSED' macro */
41 
42 static isc_int32_t
43 isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
44 	UNUSED(p);
45 	UNUSED(val);
46 
47 	__asm (
48 		"movq %rdi, %rdx\n"
49 		"movl %esi, %eax\n"
50 #ifdef ISC_PLATFORM_USETHREADS
51 		"lock;"
52 #endif
53 		"xadd %eax, (%rdx)\n"
54 		/*
55 		 * XXX: assume %eax will be used as the return value.
56 		 */
57 		);
58 }
59 
60 #ifdef ISC_PLATFORM_HAVEXADDQ
61 static isc_int64_t
62 isc_atomic_xaddq(isc_int64_t *p, isc_int64_t val) {
63 	UNUSED(p);
64 	UNUSED(val);
65 
66 	__asm (
67 		"movq %rdi, %rdx\n"
68 		"movq %rsi, %rax\n"
69 #ifdef ISC_PLATFORM_USETHREADS
70 		"lock;"
71 #endif
72 		"xaddq %rax, (%rdx)\n"
73 		/*
74 		 * XXX: assume %rax will be used as the return value.
75 		 */
76 		);
77 }
78 #endif
79 
80 static void
81 isc_atomic_store(isc_int32_t *p, isc_int32_t val) {
82 	UNUSED(p);
83 	UNUSED(val);
84 
85 	__asm (
86 		"movq %rdi, %rax\n"
87 		"movl %esi, %edx\n"
88 #ifdef ISC_PLATFORM_USETHREADS
89 		"lock;"
90 #endif
91 		"xchgl (%rax), %edx\n"
92 		/*
93 		 * XXX: assume %rax will be used as the return value.
94 		 */
95 		);
96 }
97 
98 static isc_int32_t
99 isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
100 	UNUSED(p);
101 	UNUSED(cmpval);
102 	UNUSED(val);
103 
104 	__asm (
105 		"movl %edx, %ecx\n"
106 		"movl %esi, %eax\n"
107 		"movq %rdi, %rdx\n"
108 
109 #ifdef ISC_PLATFORM_USETHREADS
110 		"lock;"
111 #endif
112 		/*
113 		 * If (%rdi) == %eax then (%rdi) := %edx.
114 		 * %eax is set to old (%ecx), which will be the return value.
115 		 */
116 		"cmpxchgl %ecx, (%rdx)"
117 		);
118 }
119 
120 #else /* !ISC_PLATFORM_USEGCCASM && !ISC_PLATFORM_USESTDASM */
121 
122 #error "unsupported compiler.  disable atomic ops by --disable-atomic"
123 
124 #endif
125 #endif /* ISC_ATOMIC_H */
126