• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

ink_atomic.h

Go to the documentation of this file.
00001 /** @file
00002 
00003   A brief file description
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 
00024 /****************************************************************************
00025 
00026   ink_atomic.h
00027 
00028   This file defines atomic memory operations.
00029 
00030   On a Sparc V9, ink_atomic.c must be compiled with gcc and requires
00031   the argument "-Wa,-xarch=v8plus" to get the assembler to emit V9
00032   instructions.
00033 
00034 
00035  ****************************************************************************/
00036 
00037 #ifndef _ink_atomic_h_
00038 #define _ink_atomic_h_
00039 
00040 #include <stdio.h>
00041 #include <string.h>
00042 #include <stdint.h>
00043 #include <assert.h>
00044 #include "ink_defs.h"
00045 
00046 #include "ink_apidefs.h"
00047 #include "ink_mutex.h"
00048 
00049 typedef volatile int8_t vint8;
00050 typedef volatile int16_t vint16;
00051 typedef volatile int32_t vint32;
00052 typedef volatile int64_t vint64;
00053 typedef volatile uint64_t vuint64;
00054 typedef volatile long vlong;
00055 typedef volatile void *vvoidp;
00056 
00057 typedef vint8 *pvint8;
00058 typedef vint16 *pvint16;
00059 typedef vint32 *pvint32;
00060 typedef vint64 *pvint64;
00061 typedef vuint64 *pvuint64;
00062 typedef vlong *pvlong;
00063 typedef vvoidp *pvvoidp;
00064 
00065 /* GCC compiler >= 4.1 */
00066 #if defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
00067 
00068 /* see http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html */
00069 
00070 // ink_atomic_swap(ptr, value)
00071 // Writes @value into @ptr, returning the previous value.
00072 template <typename T> static inline T
00073 ink_atomic_swap(volatile T * mem, T value) {
00074   return __sync_lock_test_and_set(mem, value);
00075 }
00076 
00077 // ink_atomic_cas(mem, prev, next)
00078 // Atomically store the value @next into the pointer @mem, but only if the current value at @mem is @prev.
00079 // Returns true if @next was successfully stored.
00080 template <typename T> static inline bool
00081 ink_atomic_cas(volatile T * mem, T prev, T next) {
00082   return __sync_bool_compare_and_swap(mem, prev, next);
00083 }
00084 
00085 // ink_atomic_increment(ptr, count)
00086 // Increment @ptr by @count, returning the previous value.
00087 template <typename Type, typename Amount> static inline Type
00088 ink_atomic_increment(volatile Type * mem, Amount count) {
00089   return __sync_fetch_and_add(mem, (Type)count);
00090 }
00091 
00092 // ink_atomic_decrement(ptr, count)
00093 // Decrement @ptr by @count, returning the previous value.
00094 template <typename Type, typename Amount> static inline Type
00095 ink_atomic_decrement(volatile Type * mem, Amount count) {
00096   return __sync_fetch_and_sub(mem, (Type)count);
00097 }
00098 
00099 // Special hacks for ARM 32-bit
00100 #if (defined(__arm__) || defined(__mips__)) && (SIZEOF_VOIDP == 4)
00101 extern ink_mutex __global_death;
00102 
00103 template<>
00104 inline int64_t
00105 ink_atomic_swap<int64_t>(pvint64 mem, int64_t value) {
00106   int64_t old;
00107   ink_mutex_acquire(&__global_death);
00108   old = *mem;
00109   *mem = value;
00110   ink_mutex_release(&__global_death);
00111   return old;
00112 }
00113 
00114 template<>
00115 inline bool
00116 ink_atomic_cas<int64_t>(pvint64 mem, int64_t old, int64_t new_value) {
00117   int64_t curr;
00118   ink_mutex_acquire(&__global_death);
00119   curr = *mem;
00120   if(old == curr) *mem = new_value;
00121   ink_mutex_release(&__global_death);
00122   if(old == curr) return 1;
00123   return 0;
00124 }
00125 
00126 template<typename Amount> static inline int64_t
00127 ink_atomic_increment(pvint64 mem, Amount value) {
00128   int64_t curr;
00129   ink_mutex_acquire(&__global_death);
00130   curr = *mem;
00131   *mem = curr + value;
00132   ink_mutex_release(&__global_death);
00133   return curr;
00134 }
00135 
00136 template<typename Amount> static inline int64_t
00137 ink_atomic_decrement(pvint64 mem, Amount value) {
00138   int64_t curr;
00139   ink_mutex_acquire(&__global_death);
00140   curr = *mem;
00141   *mem = curr - value;
00142   ink_mutex_release(&__global_death);
00143   return curr;
00144 }
00145 
00146 template<typename Amount> static inline uint64_t
00147 ink_atomic_increment(pvuint64 mem, Amount value) {
00148   uint64_t curr;
00149   ink_mutex_acquire(&__global_death);
00150   curr = *mem;
00151   *mem = curr + value;
00152   ink_mutex_release(&__global_death);
00153   return curr;
00154 }
00155 
00156 template<typename Amount> static inline uint64_t
00157 ink_atomic_decrement(pvuint64 mem, Amount value) {
00158   uint64_t curr;
00159   ink_mutex_acquire(&__global_death);
00160   curr = *mem;
00161   *mem = curr - value;
00162   ink_mutex_release(&__global_death);
00163   return curr;
00164 }
00165 
00166 #endif /* Special hacks for ARM 32-bit */
00167 
00168 /* not used for Intel Processors which have sequential(esque) consistency */
00169 #define INK_WRITE_MEMORY_BARRIER
00170 #define INK_MEMORY_BARRIER
00171 
00172 
00173 #else /* not gcc > v4.1.2 */
00174 #error Need a compiler / libc that supports atomic operations, e.g. gcc v4.1.2 or later
00175 #endif
00176 
00177 #endif                          /* _ink_atomic_h_ */

Generated by  doxygen 1.7.1