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 42static isc_int32_t 43isc_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 61static isc_int64_t 62isc_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 80static void 81isc_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 98static isc_int32_t 99isc_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