1/* 2 * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25// 26// threading_internal - internal support classes and functions for threading implementation 27// 28#ifndef _H_THREADING_INTERNAL 29#define _H_THREADING_INTERNAL 30 31#include <security_utilities/utilities.h> 32#include <libkern/OSAtomic.h> 33 34 35namespace Security { 36 37 38// 39// Do we have 64-bit atomic operations? 40// 41#define _HAVE_64BIT_ATOMIC (defined(__ppc64__) || defined(__i386__) || defined(__x86_64__)) 42 43 44// 45// The AtomicTypes class is an implementation detail. 46// Do not use it. 47// 48template <unsigned wordsize> 49struct AtomicTypes { 50 // unsupported word size (this will cause compilation errors if used) 51}; 52 53template <> 54struct AtomicTypes<32> { 55 typedef int32_t Integer; 56 57 static Integer add(int delta, Integer &base) 58 { return OSAtomicAdd32(delta, &base); } 59 static Integer addb(int delta, Integer &base) { return OSAtomicAdd32Barrier(delta, &base); } 60 61 static bool cas(Integer oldValue, Integer newValue, Integer &base) 62 { return OSAtomicCompareAndSwap32(oldValue, newValue, &base); } 63 static bool casb(Integer oldValue, Integer newValue, Integer &base) 64 { return OSAtomicCompareAndSwap32Barrier(oldValue, newValue, &base); } 65}; 66 67#if _HAVE_64BIT_ATOMIC 68 69template <> 70struct AtomicTypes<64> { 71 typedef int64_t Integer; 72 73 static Integer add(int delta, Integer &base) { return OSAtomicAdd64(delta, &base); } 74 static Integer addb(int delta, Integer &base) { return OSAtomicAdd64Barrier(delta, &base); } 75 76 static bool cas(Integer oldValue, Integer newValue, Integer &base) 77 { return OSAtomicCompareAndSwap64(oldValue, newValue, &base); } 78 static bool casb(Integer oldValue, Integer newValue, Integer &base) 79 { return OSAtomicCompareAndSwap64Barrier(oldValue, newValue, &base); } 80}; 81 82#endif //_HAVE_64BIT_ATOMIC 83 84 85// 86// Atomic<Type> is a set of (static) operations that can atomically access memory. 87// This is not a wrapper object. Think of it as a generator class that produces 88// the proper atomic memory operations for arbitrary data types. 89// If the underlying system does not support atomicity for a particular type 90// (e.g. 64 bits on ppc, or 16 bits anywhere), you will get compilation errors. 91// 92template <class Type> 93class Atomic { 94 typedef AtomicTypes<sizeof(Type) * 8> _Ops; 95 typedef typename _Ops::Integer _Type; 96 97public: 98 static Type add(int delta, Type &store) 99 { return Type(_Ops::add(delta, (_Type &)store)); } 100 static Type addb(int delta, Type &store) 101 { return Type(_Ops::addb(delta, (_Type &)store)); } 102 103 static bool cas(Type oldValue, Type newValue, Type &store) 104 { return _Ops::cas(_Type(oldValue), _Type(newValue), (_Type &)store); } 105 static bool casb(Type oldValue, Type newValue, Type &store) 106 { return _Ops::casb(_Type(oldValue), _Type(newValue), (_Type &)store); } 107 108 static void barrier() { OSMemoryBarrier(); } 109 static void readBarrier() { OSMemoryBarrier(); } 110 static void writeBarrier() { OSMemoryBarrier(); } 111 112 // convenience additions (expressed in terms above) 113 114 static Type increment(Type &store) { return add(1, store); } 115 static Type decrement(Type &store) { return add(-1, store); } 116 117 static Type load(const Type &store) { readBarrier(); return store; } 118 static Type store(Type value, Type &store) 119 { while (!casb(store, value, store)) {}; return value; } 120}; 121 122 123} // end namespace Security 124 125#endif //_H_THREADING_INTERNAL 126