atomic-long.h revision 337896
1142425Snectar/*- 2160814Ssimon * Copyright (c) 2010 Isilon Systems, Inc. 3142425Snectar * Copyright (c) 2010 iX Systems, Inc. 4142425Snectar * Copyright (c) 2010 Panasas, Inc. 5142425Snectar * Copyright (c) 2013-2017 Mellanox Technologies, Ltd. 6142425Snectar * All rights reserved. 7142425Snectar * 8142425Snectar * Redistribution and use in source and binary forms, with or without 9142425Snectar * modification, are permitted provided that the following conditions 10142425Snectar * are met: 11142425Snectar * 1. Redistributions of source code must retain the above copyright 12142425Snectar * notice unmodified, this list of conditions, and the following 13142425Snectar * disclaimer. 14142425Snectar * 2. Redistributions in binary form must reproduce the above copyright 15142425Snectar * notice, this list of conditions and the following disclaimer in the 16142425Snectar * documentation and/or other materials provided with the distribution. 17142425Snectar * 18142425Snectar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19142425Snectar * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20194206Ssimon * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21194206Ssimon * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22142425Snectar * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23142425Snectar * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24142425Snectar * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25142425Snectar * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26142425Snectar * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27142425Snectar * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28142425Snectar * 29142425Snectar * $FreeBSD: stable/11/sys/compat/linuxkpi/common/include/asm/atomic-long.h 337896 2018-08-16 08:10:11Z hselasky $ 30142425Snectar */ 31142425Snectar#ifndef _ATOMIC_LONG_H_ 32142425Snectar#define _ATOMIC_LONG_H_ 33142425Snectar 34142425Snectar#include <linux/compiler.h> 35142425Snectar#include <sys/types.h> 36238405Sjkim#include <machine/atomic.h> 37142425Snectar 38142425Snectar#define ATOMIC_LONG_INIT(x) { .counter = (x) } 39142425Snectar 40142425Snectartypedef struct { 41142425Snectar volatile long counter; 42142425Snectar} atomic_long_t; 43142425Snectar 44142425Snectar#define atomic_long_add(i, v) atomic_long_add_return((i), (v)) 45142425Snectar#define atomic_long_inc_return(v) atomic_long_add_return(1, (v)) 46142425Snectar#define atomic_long_inc_not_zero(v) atomic_long_add_unless((v), 1, 0) 47142425Snectar 48142425Snectarstatic inline long 49160814Ssimonatomic_long_add_return(long i, atomic_long_t *v) 50160814Ssimon{ 51142425Snectar return i + atomic_fetchadd_long(&v->counter, i); 52142425Snectar} 53142425Snectar 54142425Snectarstatic inline void 55142425Snectaratomic_long_set(atomic_long_t *v, long i) 56142425Snectar{ 57142425Snectar WRITE_ONCE(v->counter, i); 58142425Snectar} 59142425Snectar 60142425Snectarstatic inline long 61142425Snectaratomic_long_read(atomic_long_t *v) 62142425Snectar{ 63142425Snectar return READ_ONCE(v->counter); 64284283Sjkim} 65284283Sjkim 66142425Snectarstatic inline long 67160814Ssimonatomic_long_inc(atomic_long_t *v) 68142425Snectar{ 69142425Snectar return atomic_fetchadd_long(&v->counter, 1) + 1; 70142425Snectar} 71142425Snectar 72142425Snectarstatic inline long 73142425Snectaratomic_long_dec(atomic_long_t *v) 74142425Snectar{ 75142425Snectar return atomic_fetchadd_long(&v->counter, -1) - 1; 76142425Snectar} 77142425Snectar 78142425Snectarstatic inline long 79142425Snectaratomic_long_xchg(atomic_long_t *v, long val) 80142425Snectar{ 81142425Snectar return atomic_swap_long(&v->counter, val); 82142425Snectar} 83160814Ssimon 84160814Ssimonstatic inline long 85160814Ssimonatomic_long_cmpxchg(atomic_long_t *v, long old, long new) 86194206Ssimon{ 87194206Ssimon long ret = old; 88194206Ssimon 89194206Ssimon for (;;) { 90194206Ssimon if (atomic_cmpset_long(&v->counter, old, new)) 91194206Ssimon break; 92194206Ssimon ret = READ_ONCE(v->counter); 93142425Snectar if (ret != old) 94142425Snectar break; 95142425Snectar } 96142425Snectar return (ret); 97160814Ssimon} 98160814Ssimon 99160814Ssimonstatic inline int 100atomic_long_add_unless(atomic_long_t *v, long a, long u) 101{ 102 long c; 103 104 for (;;) { 105 c = atomic_long_read(v); 106 if (unlikely(c == u)) 107 break; 108 if (likely(atomic_cmpset_long(&v->counter, c, c + a))) 109 break; 110 } 111 return (c != u); 112} 113 114static inline long 115atomic_long_dec_and_test(atomic_long_t *v) 116{ 117 long i = atomic_long_add(-1, v); 118 return i == 0 ; 119} 120 121#endif /* _ATOMIC_LONG_H_ */ 122