~james-page/ubuntu/saucy/openvswitch/1.12-snapshot

« back to all changes in this revision

Viewing changes to lib/ovs-atomic-pthreads.h

  • Committer: James Page
  • Date: 2013-08-21 10:16:57 UTC
  • mfrom: (1.1.20)
  • Revision ID: james.page@canonical.com-20130821101657-3o0z0qeiv5zkwlzi
New upstream snapshot

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2013 Nicira, Inc.
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * You may obtain a copy of the License at:
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
10
 * Unless required by applicable law or agreed to in writing, software
 
11
 * distributed under the License is distributed on an "AS IS" BASIS,
 
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
 * See the License for the specific language governing permissions and
 
14
 * limitations under the License.
 
15
 */
 
16
 
 
17
/* This header implements atomic operation primitives using pthreads. */
 
18
#ifndef IN_OVS_ATOMIC_H
 
19
#error "This header should only be included indirectly via ovs-atomic.h."
 
20
#endif
 
21
 
 
22
#define OVS_ATOMIC_PTHREADS_IMPL 1
 
23
 
 
24
#define DEFINE_PTHREAD_ATOMIC(TYPE, NAME)       \
 
25
    typedef struct {                            \
 
26
        TYPE value;                             \
 
27
        pthread_mutex_t mutex;                  \
 
28
    } NAME;
 
29
 
 
30
#define ATOMIC_BOOL_LOCK_FREE 0
 
31
DEFINE_PTHREAD_ATOMIC(bool, atomic_bool);
 
32
 
 
33
#define ATOMIC_CHAR_LOCK_FREE 0
 
34
DEFINE_PTHREAD_ATOMIC(char, atomic_char);
 
35
DEFINE_PTHREAD_ATOMIC(signed char, atomic_schar);
 
36
DEFINE_PTHREAD_ATOMIC(unsigned char, atomic_uchar);
 
37
 
 
38
#define ATOMIC_SHORT_LOCK_FREE 0
 
39
DEFINE_PTHREAD_ATOMIC(short, atomic_short);
 
40
DEFINE_PTHREAD_ATOMIC(unsigned short, atomic_ushort);
 
41
 
 
42
#define ATOMIC_INT_LOCK_FREE 0
 
43
DEFINE_PTHREAD_ATOMIC(int, atomic_int);
 
44
DEFINE_PTHREAD_ATOMIC(unsigned int, atomic_uint);
 
45
 
 
46
#define ATOMIC_LONG_LOCK_FREE 0
 
47
DEFINE_PTHREAD_ATOMIC(long, atomic_long);
 
48
DEFINE_PTHREAD_ATOMIC(unsigned long, atomic_ulong);
 
49
 
 
50
#define ATOMIC_LLONG_LOCK_FREE 0
 
51
DEFINE_PTHREAD_ATOMIC(long long, atomic_llong);
 
52
DEFINE_PTHREAD_ATOMIC(unsigned long long, atomic_ullong);
 
53
 
 
54
DEFINE_PTHREAD_ATOMIC(size_t, atomic_size_t);
 
55
DEFINE_PTHREAD_ATOMIC(ptrdiff_t, atomic_ptrdiff_t);
 
56
 
 
57
DEFINE_PTHREAD_ATOMIC(intmax_t, atomic_intmax_t);
 
58
DEFINE_PTHREAD_ATOMIC(uintmax_t, atomic_uintmax_t);
 
59
 
 
60
#define ATOMIC_POINTER_LOCK_FREE 0
 
61
DEFINE_PTHREAD_ATOMIC(intptr_t, atomic_intptr_t);
 
62
DEFINE_PTHREAD_ATOMIC(uintptr_t, atomic_uintptr_t);
 
63
 
 
64
/* Nonstandard atomic types. */
 
65
DEFINE_PTHREAD_ATOMIC(uint8_t,  atomic_uint8_t);
 
66
DEFINE_PTHREAD_ATOMIC(uint16_t, atomic_uint16_t);
 
67
DEFINE_PTHREAD_ATOMIC(uint32_t, atomic_uint32_t);
 
68
DEFINE_PTHREAD_ATOMIC(int8_t,   atomic_int8_t);
 
69
DEFINE_PTHREAD_ATOMIC(int16_t,  atomic_int16_t);
 
70
DEFINE_PTHREAD_ATOMIC(int32_t,  atomic_int32_t);
 
71
DEFINE_PTHREAD_ATOMIC(uint64_t, atomic_uint64_t);
 
72
DEFINE_PTHREAD_ATOMIC(int64_t,  atomic_int64_t);
 
73
 
 
74
typedef enum {
 
75
    memory_order_relaxed,
 
76
    memory_order_consume,
 
77
    memory_order_acquire,
 
78
    memory_order_release,
 
79
    memory_order_acq_rel,
 
80
    memory_order_seq_cst
 
81
} memory_order;
 
82
 
 
83
#define ATOMIC_VAR_INIT(VALUE) { VALUE, PTHREAD_MUTEX_INITIALIZER }
 
84
#define atomic_init(OBJECT, VALUE)                      \
 
85
    ((OBJECT)->value = (VALUE),                         \
 
86
     pthread_mutex_init(&(OBJECT)->mutex, NULL),        \
 
87
     (void) 0)
 
88
 
 
89
static inline void
 
90
atomic_thread_fence(memory_order order OVS_UNUSED)
 
91
{
 
92
    /* Nothing to do. */
 
93
}
 
94
 
 
95
static inline void
 
96
atomic_signal_fence(memory_order order OVS_UNUSED)
 
97
{
 
98
    /* Nothing to do. */
 
99
}
 
100
 
 
101
#define atomic_is_lock_free(OBJ) false
 
102
 
 
103
#define atomic_store(DST, SRC)                  \
 
104
    (pthread_mutex_lock(&(DST)->mutex),         \
 
105
     (DST)->value = (SRC),                      \
 
106
     pthread_mutex_unlock(&(DST)->mutex),       \
 
107
     (void) 0)
 
108
#define atomic_store_explicit(DST, SRC, ORDER) \
 
109
    ((void) (ORDER), atomic_store(DST, SRC))
 
110
 
 
111
#define atomic_read(SRC, DST)                                           \
 
112
    (pthread_mutex_lock(CONST_CAST(pthread_mutex_t *, &(SRC)->mutex)),  \
 
113
     *(DST) = (SRC)->value,                                             \
 
114
     pthread_mutex_unlock(CONST_CAST(pthread_mutex_t *, &(SRC)->mutex)), \
 
115
     (void) 0)
 
116
#define atomic_read_explicit(SRC, DST, ORDER)   \
 
117
    ((void) (ORDER), atomic_read(SRC, DST))
 
118
 
 
119
#define atomic_op__(RMW, OPERATOR, OPERAND, ORIG)       \
 
120
    (pthread_mutex_lock(&(RMW)->mutex),                 \
 
121
     *(ORIG) = (RMW)->value,                            \
 
122
     (RMW)->value OPERATOR (OPERAND),                   \
 
123
     pthread_mutex_unlock(&(RMW)->mutex),               \
 
124
     (void) 0)
 
125
 
 
126
#define atomic_add(RMW, OPERAND, ORIG) atomic_op__(RMW, +=, OPERAND, ORIG)
 
127
#define atomic_sub(RMW, OPERAND, ORIG) atomic_op__(RMW, -=, OPERAND, ORIG)
 
128
#define atomic_or( RMW, OPERAND, ORIG) atomic_op__(RMW, |=, OPERAND, ORIG)
 
129
#define atomic_xor(RMW, OPERAND, ORIG) atomic_op__(RMW, ^=, OPERAND, ORIG)
 
130
#define atomic_and(RMW, OPERAND, ORIG) atomic_op__(RMW, &=, OPERAND, ORIG)
 
131
 
 
132
#define atomic_add_explicit(RMW, OPERAND, ORIG, ORDER)  \
 
133
    ((void) (ORDER), atomic_add(RMW, OPERAND, ORIG))
 
134
#define atomic_sub_explicit(RMW, OPERAND, ORIG, ORDER)  \
 
135
    ((void) (ORDER), atomic_sub(RMW, OPERAND, ORIG))
 
136
#define atomic_or_explicit(RMW, OPERAND, ORIG, ORDER)   \
 
137
    ((void) (ORDER), atomic_or(RMW, OPERAND, ORIG))
 
138
#define atomic_xor_explicit(RMW, OPERAND, ORIG, ORDER)  \
 
139
    ((void) (ORDER), atomic_xor(RMW, OPERAND, ORIG))
 
140
#define atomic_and_explicit(RMW, OPERAND, ORIG, ORDER)  \
 
141
    ((void) (ORDER), atomic_and(RMW, OPERAND, ORIG))
 
142
 
 
143
/* atomic_flag */
 
144
 
 
145
typedef struct {
 
146
    bool b;
 
147
    pthread_mutex_t mutex;
 
148
} atomic_flag;
 
149
#define ATOMIC_FLAG_INIT { false, PTHREAD_MUTEX_INITIALIZER }
 
150
 
 
151
bool atomic_flag_test_and_set(volatile atomic_flag *);
 
152
bool atomic_flag_test_and_set_explicit(volatile atomic_flag *, memory_order);
 
153
 
 
154
void atomic_flag_clear(volatile atomic_flag *);
 
155
void atomic_flag_clear_explicit(volatile atomic_flag *, memory_order);