File: ink_atomic.h

package info (click to toggle)
trafficserver 6.2.0-1~bpo8%2B1
  • links: PTS, VCS
  • area: main
  • in suites: jessie-backports
  • size: 45,456 kB
  • sloc: cpp: 271,894; ansic: 80,740; sh: 6,032; makefile: 3,364; python: 2,135; perl: 2,040; java: 277; lex: 128; sql: 94; yacc: 68; sed: 8
file content (196 lines) | stat: -rw-r--r-- 5,095 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/** @file

  A brief file description

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
 */

/****************************************************************************

  ink_atomic.h

  This file defines atomic memory operations.

  On a Sparc V9, ink_atomic.c must be compiled with gcc and requires
  the argument "-Wa,-xarch=v8plus" to get the assembler to emit V9
  instructions.


 ****************************************************************************/

#ifndef _ink_atomic_h_
#define _ink_atomic_h_

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <assert.h>

#include "ts/ink_defs.h"
#include "ts/ink_apidefs.h"
#include "ts/ink_mutex.h"

typedef volatile int8_t vint8;
typedef volatile int16_t vint16;
typedef volatile int32_t vint32;
typedef volatile int64_t vint64;
typedef volatile uint64_t vuint64;
typedef volatile long vlong;
typedef volatile void *vvoidp;

typedef vint8 *pvint8;
typedef vint16 *pvint16;
typedef vint32 *pvint32;
typedef vint64 *pvint64;
typedef vuint64 *pvuint64;
typedef vlong *pvlong;
typedef vvoidp *pvvoidp;

/* GCC compiler >= 4.1 */
#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1)) || (__GNUC__ >= 5))

/* see http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html */

// ink_atomic_swap(ptr, value)
// Writes @value into @ptr, returning the previous value.
template <typename T>
static inline T
ink_atomic_swap(volatile T *mem, T value)
{
  return __sync_lock_test_and_set(mem, value);
}

// ink_atomic_cas(mem, prev, next)
// Atomically store the value @next into the pointer @mem, but only if the current value at @mem is @prev.
// Returns true if @next was successfully stored.
template <typename T>
static inline bool
ink_atomic_cas(volatile T *mem, T prev, T next)
{
  return __sync_bool_compare_and_swap(mem, prev, next);
}

// ink_atomic_increment(ptr, count)
// Increment @ptr by @count, returning the previous value.
template <typename Type, typename Amount>
static inline Type
ink_atomic_increment(volatile Type *mem, Amount count)
{
  return __sync_fetch_and_add(mem, (Type)count);
}

// ink_atomic_decrement(ptr, count)
// Decrement @ptr by @count, returning the previous value.
template <typename Type, typename Amount>
static inline Type
ink_atomic_decrement(volatile Type *mem, Amount count)
{
  return __sync_fetch_and_sub(mem, (Type)count);
}

// Special hacks for ARM 32-bit
#if (defined(__arm__) || defined(__mips__)) && (SIZEOF_VOIDP == 4)
extern ink_mutex __global_death;

template <>
inline int64_t
ink_atomic_swap<int64_t>(pvint64 mem, int64_t value)
{
  int64_t old;
  ink_mutex_acquire(&__global_death);
  old  = *mem;
  *mem = value;
  ink_mutex_release(&__global_death);
  return old;
}

template <>
inline bool
ink_atomic_cas<int64_t>(pvint64 mem, int64_t old, int64_t new_value)
{
  int64_t curr;
  ink_mutex_acquire(&__global_death);
  curr = *mem;
  if (old == curr)
    *mem = new_value;
  ink_mutex_release(&__global_death);
  if (old == curr)
    return 1;
  return 0;
}

template <typename Amount>
static inline int64_t
ink_atomic_increment(pvint64 mem, Amount value)
{
  int64_t curr;
  ink_mutex_acquire(&__global_death);
  curr = *mem;
  *mem = curr + value;
  ink_mutex_release(&__global_death);
  return curr;
}

template <typename Amount>
static inline int64_t
ink_atomic_decrement(pvint64 mem, Amount value)
{
  int64_t curr;
  ink_mutex_acquire(&__global_death);
  curr = *mem;
  *mem = curr - value;
  ink_mutex_release(&__global_death);
  return curr;
}

template <typename Amount>
static inline uint64_t
ink_atomic_increment(pvuint64 mem, Amount value)
{
  uint64_t curr;
  ink_mutex_acquire(&__global_death);
  curr = *mem;
  *mem = curr + value;
  ink_mutex_release(&__global_death);
  return curr;
}

template <typename Amount>
static inline uint64_t
ink_atomic_decrement(pvuint64 mem, Amount value)
{
  uint64_t curr;
  ink_mutex_acquire(&__global_death);
  curr = *mem;
  *mem = curr - value;
  ink_mutex_release(&__global_death);
  return curr;
}

#endif /* Special hacks for ARM 32-bit */

/* not used for Intel Processors which have sequential(esque) consistency */
#define INK_WRITE_MEMORY_BARRIER
#define INK_MEMORY_BARRIER

#else /* not gcc > v4.1.2 */
#error Need a compiler / libc that supports atomic operations, e.g. gcc v4.1.2 or later
#endif

#endif /* _ink_atomic_h_ */