viratomic.h 3.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
 * viratomic.h: atomic integer operations
 *
 * Copyright (C) 2012 IBM Corporation
 *
 * Authors:
 *     Stefan Berger <stefanb@linux.vnet.ibm.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
O
Osier Yang 已提交
20 21
 * License along with this library;  If not, see
 * <http://www.gnu.org/licenses/>.
22 23 24 25 26 27 28 29 30 31 32
 *
 */

#ifndef __VIR_ATOMIC_H__
# define __VIR_ATOMIC_H__

# include "threads.h"

typedef struct _virAtomicInt virAtomicInt;
typedef virAtomicInt *virAtomicIntPtr;

33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
# define __VIR_ATOMIC_USES_LOCK

# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1)) || (__GNUC__ > 4)
#  undef __VIR_ATOMIC_USES_LOCK
# endif

static inline int virAtomicIntInit(virAtomicIntPtr vaip)
    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
static inline int virAtomicIntRead(virAtomicIntPtr vaip)
    ATTRIBUTE_NONNULL(1);
static inline void virAtomicIntSet(virAtomicIntPtr vaip, int val)
    ATTRIBUTE_NONNULL(1);
static inline int virAtomicIntAdd(virAtomicIntPtr vaip, int add)
    ATTRIBUTE_NONNULL(1);
static inline int virAtomicIntSub(virAtomicIntPtr vaip, int add)
    ATTRIBUTE_NONNULL(1);
static inline int virAtomicIntInc(virAtomicIntPtr vaip)
    ATTRIBUTE_NONNULL(1);
static inline int virAtomicIntDec(virAtomicIntPtr vaip)
    ATTRIBUTE_NONNULL(1);

# ifdef __VIR_ATOMIC_USES_LOCK

56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
struct _virAtomicInt {
    virMutex lock;
    int value;
};

static inline int
virAtomicIntInit(virAtomicIntPtr vaip)
{
    vaip->value = 0;
    return virMutexInit(&vaip->lock);
}

static inline int
virAtomicIntAdd(virAtomicIntPtr vaip, int add)
{
    int ret;

    virMutexLock(&vaip->lock);

    vaip->value += add;
    ret = vaip->value;

    virMutexUnlock(&vaip->lock);

    return ret;
}

static inline int
virAtomicIntSub(virAtomicIntPtr vaip, int sub)
{
    int ret;

    virMutexLock(&vaip->lock);

    vaip->value -= sub;
    ret = vaip->value;

    virMutexUnlock(&vaip->lock);

    return ret;
}

98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
# else /* __VIR_ATOMIC_USES_LOCK */

struct _virAtomicInt {
    int value;
};

static inline int
virAtomicIntInit(virAtomicIntPtr vaip)
{
    vaip->value = 0;
    return 0;
}

static inline int
virAtomicIntAdd(virAtomicIntPtr vaip, int add)
{
    return __sync_add_and_fetch(&vaip->value, add);
}

static inline int
virAtomicIntSub(virAtomicIntPtr vaip, int sub)
{
    return __sync_sub_and_fetch(&vaip->value, sub);
}

# endif /* __VIR_ATOMIC_USES_LOCK */



/* common operations that need no locking or build on others */


static inline void
virAtomicIntSet(virAtomicIntPtr vaip, int value)
{
     vaip->value = value;
}

static inline int
virAtomicIntRead(virAtomicIntPtr vaip)
{
     return *(volatile int *)&vaip->value;
}

static inline int
virAtomicIntInc(virAtomicIntPtr vaip)
{
    return virAtomicIntAdd(vaip, 1);
}

static inline int
virAtomicIntDec(virAtomicIntPtr vaip)
{
    return virAtomicIntSub(vaip, 1);
}

154
#endif /* __VIR_ATOMIC_H */