1170431Spjd/*- 2170431Spjd * Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3170431Spjd * All rights reserved. 4170431Spjd * 5170431Spjd * Redistribution and use in source and binary forms, with or without 6170431Spjd * modification, are permitted provided that the following conditions 7170431Spjd * are met: 8170431Spjd * 1. Redistributions of source code must retain the above copyright 9170431Spjd * notice, this list of conditions and the following disclaimer. 10170431Spjd * 2. Redistributions in binary form must reproduce the above copyright 11170431Spjd * notice, this list of conditions and the following disclaimer in the 12170431Spjd * documentation and/or other materials provided with the distribution. 13170431Spjd * 14170431Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15170431Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16170431Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17170431Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18170431Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19170431Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20170431Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21170431Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22170431Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23170431Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24170431Spjd * SUCH DAMAGE. 25170431Spjd */ 26170431Spjd 27170431Spjd#include <sys/cdefs.h> 28170431Spjd__FBSDID("$FreeBSD$"); 29170431Spjd 30170431Spjd#include <sys/param.h> 31170431Spjd#include <sys/lock.h> 32170431Spjd#include <sys/mutex.h> 33170431Spjd#include <sys/atomic.h> 34170431Spjd 35170431Spjd#ifdef _KERNEL 36170431Spjd#include <sys/kernel.h> 37170431Spjd 38170431Spjdstruct mtx atomic_mtx; 39170431SpjdMTX_SYSINIT(atomic, &atomic_mtx, "atomic", MTX_DEF); 40170431Spjd#else 41170431Spjd#include <pthread.h> 42170431Spjd 43170431Spjd#define mtx_lock(lock) pthread_mutex_lock(lock) 44170431Spjd#define mtx_unlock(lock) pthread_mutex_unlock(lock) 45170431Spjd 46170431Spjdstatic pthread_mutex_t atomic_mtx; 47170431Spjd 48170431Spjdstatic __attribute__((constructor)) void 49170431Spjdatomic_init(void) 50170431Spjd{ 51170431Spjd pthread_mutex_init(&atomic_mtx, NULL); 52170431Spjd} 53170431Spjd#endif 54170431Spjd 55218007Sjchandra#if !defined(__LP64__) && !defined(__mips_n32) 56170431Spjdvoid 57170431Spjdatomic_add_64(volatile uint64_t *target, int64_t delta) 58170431Spjd{ 59170431Spjd 60170431Spjd mtx_lock(&atomic_mtx); 61170431Spjd *target += delta; 62170431Spjd mtx_unlock(&atomic_mtx); 63170431Spjd} 64185029Spjd 65185029Spjdvoid 66185029Spjdatomic_dec_64(volatile uint64_t *target) 67185029Spjd{ 68185029Spjd 69185029Spjd mtx_lock(&atomic_mtx); 70185029Spjd *target -= 1; 71185029Spjd mtx_unlock(&atomic_mtx); 72185029Spjd} 73170431Spjd#endif 74170431Spjd 75170431Spjduint64_t 76170431Spjdatomic_add_64_nv(volatile uint64_t *target, int64_t delta) 77170431Spjd{ 78170431Spjd uint64_t newval; 79170431Spjd 80170431Spjd mtx_lock(&atomic_mtx); 81170431Spjd newval = (*target += delta); 82170431Spjd mtx_unlock(&atomic_mtx); 83170431Spjd return (newval); 84170431Spjd} 85170431Spjd 86219089Spjd#if defined(__powerpc__) || defined(__arm__) || defined(__mips__) 87170431Spjdvoid 88170431Spjdatomic_or_8(volatile uint8_t *target, uint8_t value) 89170431Spjd{ 90170431Spjd mtx_lock(&atomic_mtx); 91170431Spjd *target |= value; 92170431Spjd mtx_unlock(&atomic_mtx); 93170431Spjd} 94170431Spjd#endif 95170431Spjd 96170431Spjduint8_t 97170431Spjdatomic_or_8_nv(volatile uint8_t *target, uint8_t value) 98170431Spjd{ 99170431Spjd uint8_t newval; 100170431Spjd 101170431Spjd mtx_lock(&atomic_mtx); 102170431Spjd newval = (*target |= value); 103170431Spjd mtx_unlock(&atomic_mtx); 104170431Spjd return (newval); 105170431Spjd} 106170431Spjd 107219089Spjduint64_t 108219089Spjdatomic_cas_64(volatile uint64_t *target, uint64_t cmp, uint64_t newval) 109170431Spjd{ 110219089Spjd uint64_t oldval; 111170431Spjd 112170431Spjd mtx_lock(&atomic_mtx); 113219089Spjd oldval = *target; 114170431Spjd if (oldval == cmp) 115219089Spjd *target = newval; 116170431Spjd mtx_unlock(&atomic_mtx); 117170431Spjd return (oldval); 118170431Spjd} 119170431Spjd 120219089Spjduint32_t 121219089Spjdatomic_cas_32(volatile uint32_t *target, uint32_t cmp, uint32_t newval) 122170431Spjd{ 123219089Spjd uint32_t oldval; 124170431Spjd 125170431Spjd mtx_lock(&atomic_mtx); 126170431Spjd oldval = *target; 127170431Spjd if (oldval == cmp) 128170431Spjd *target = newval; 129170431Spjd mtx_unlock(&atomic_mtx); 130170431Spjd return (oldval); 131170431Spjd} 132170431Spjd 133170431Spjdvoid 134170431Spjdmembar_producer(void) 135170431Spjd{ 136170431Spjd /* nothing */ 137170431Spjd} 138