1170222Sdougb/* 2245163Serwin * Copyright (C) 2006, 2007, 2009, 2012 Internet Systems Consortium, Inc. ("ISC") 3170222Sdougb * 4193149Sdougb * Permission to use, copy, modify, and/or distribute this software for any 5170222Sdougb * purpose with or without fee is hereby granted, provided that the above 6170222Sdougb * copyright notice and this permission notice appear in all copies. 7170222Sdougb * 8170222Sdougb * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9170222Sdougb * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10170222Sdougb * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11170222Sdougb * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12170222Sdougb * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13170222Sdougb * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14170222Sdougb * PERFORMANCE OF THIS SOFTWARE. 15170222Sdougb */ 16170222Sdougb 17234010Sdougb/* $Id: atomic.h,v 1.7 2009/06/24 02:22:50 marka Exp $ */ 18170222Sdougb 19170222Sdougb#ifndef ISC_ATOMIC_H 20170222Sdougb#define ISC_ATOMIC_H 1 21170222Sdougb 22170222Sdougb#include <isc/platform.h> 23170222Sdougb#include <isc/types.h> 24170222Sdougb 25170222Sdougb#ifdef ISC_PLATFORM_USEGCCASM 26170222Sdougb/* 27170222Sdougb * This routine atomically increments the value stored in 'p' by 'val', and 28170222Sdougb * returns the previous value. 29170222Sdougb * 30170222Sdougb * Open issue: can 'fetchadd' make the code faster for some particular values 31170222Sdougb * (e.g., 1 and -1)? 32170222Sdougb */ 33170222Sdougbstatic inline isc_int32_t 34195000Sdougb#ifdef __GNUC__ 35195000Sdougb__attribute__ ((unused)) 36195000Sdougb#endif 37193149Sdougbisc_atomic_xadd(isc_int32_t *p, isc_int32_t val) 38193149Sdougb{ 39170222Sdougb isc_int32_t prev, swapped; 40170222Sdougb 41170222Sdougb for (prev = *(volatile isc_int32_t *)p; ; prev = swapped) { 42170222Sdougb swapped = prev + val; 43170222Sdougb __asm__ volatile( 44200202Smarcel "mov ar.ccv=%2;;" 45170222Sdougb "cmpxchg4.acq %0=%4,%3,ar.ccv" 46170222Sdougb : "=r" (swapped), "=m" (*p) 47170222Sdougb : "r" (prev), "r" (swapped), "m" (*p) 48170222Sdougb : "memory"); 49170222Sdougb if (swapped == prev) 50170222Sdougb break; 51170222Sdougb } 52170222Sdougb 53170222Sdougb return (prev); 54170222Sdougb} 55170222Sdougb 56170222Sdougb/* 57170222Sdougb * This routine atomically stores the value 'val' in 'p'. 58170222Sdougb */ 59170222Sdougbstatic inline void 60195000Sdougb#ifdef __GNUC__ 61195000Sdougb__attribute__ ((unused)) 62195000Sdougb#endif 63193149Sdougbisc_atomic_store(isc_int32_t *p, isc_int32_t val) 64193149Sdougb{ 65170222Sdougb __asm__ volatile( 66170222Sdougb "st4.rel %0=%1" 67170222Sdougb : "=m" (*p) 68170222Sdougb : "r" (val) 69170222Sdougb : "memory" 70170222Sdougb ); 71170222Sdougb} 72170222Sdougb 73170222Sdougb/* 74170222Sdougb * This routine atomically replaces the value in 'p' with 'val', if the 75170222Sdougb * original value is equal to 'cmpval'. The original value is returned in any 76170222Sdougb * case. 77170222Sdougb */ 78170222Sdougbstatic inline isc_int32_t 79195000Sdougb#ifdef __GNUC__ 80195000Sdougb__attribute__ ((unused)) 81195000Sdougb#endif 82193149Sdougbisc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) 83193149Sdougb{ 84170222Sdougb isc_int32_t ret; 85170222Sdougb 86170222Sdougb __asm__ volatile( 87200202Smarcel "mov ar.ccv=%2;;" 88170222Sdougb "cmpxchg4.acq %0=%4,%3,ar.ccv" 89170222Sdougb : "=r" (ret), "=m" (*p) 90170222Sdougb : "r" (cmpval), "r" (val), "m" (*p) 91170222Sdougb : "memory"); 92170222Sdougb 93170222Sdougb return (ret); 94170222Sdougb} 95170222Sdougb#else /* !ISC_PLATFORM_USEGCCASM */ 96170222Sdougb 97170222Sdougb#error "unsupported compiler. disable atomic ops by --disable-atomic" 98170222Sdougb 99170222Sdougb#endif 100170222Sdougb#endif /* ISC_ATOMIC_H */ 101