1/* 2 * Copyright 2013 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Ithamar R. Adema, ithamar@upgrade-android.com 7 */ 8 9#include <KernelExport.h> 10 11#include <kernel.h> 12#include <user_atomic.h> 13 14#include <util/AutoLock.h> 15 16#ifdef ATOMIC64_FUNCS_ARE_SYSCALLS 17 18/* 19 * NOTE: Unlike their 32-bit counterparts, these functions can use 20 * spinlocks safely currently, as no atomic 64-bit operations are 21 * done in the spinlock code. If this ever changes, this code will 22 * have to change. 23 * 24 * This code is here for ARMv6, which cannot do proper 64-bit atomic 25 * operations. Anything newer is capable, and does therefore not 26 * depend on this code. 27 */ 28 29 30static spinlock atomic_lock = B_SPINLOCK_INITIALIZER; 31 32 33void 34atomic_set64(int64 *value, int64 newValue) 35{ 36 SpinLocker locker(&atomic_lock); 37 38 *value = newValue; 39} 40 41 42int64 43atomic_get_and_set64(int64 *value, int64 newValue) 44{ 45 SpinLocker locker(&atomic_lock); 46 47 int64 oldValue = *value; 48 *value = newValue; 49 return oldValue; 50} 51 52 53int64 54atomic_test_and_set64(int64 *value, int64 newValue, int64 testAgainst) 55{ 56 SpinLocker locker(&atomic_lock); 57 58 int64 oldValue = *value; 59 if (oldValue == testAgainst) 60 *value = newValue; 61 return oldValue; 62} 63 64 65int64 66atomic_add64(int64 *value, int64 addValue) 67{ 68 SpinLocker locker(&atomic_lock); 69 70 int64 oldValue = *value; 71 *value += addValue; 72 return oldValue; 73} 74 75 76int64 77atomic_and64(int64 *value, int64 andValue) 78{ 79 SpinLocker locker(&atomic_lock); 80 81 int64 oldValue = *value; 82 *value &= andValue; 83 return oldValue; 84} 85 86 87int64 88atomic_or64(int64 *value, int64 orValue) 89{ 90 SpinLocker locker(&atomic_lock); 91 92 int64 oldValue = *value; 93 *value |= orValue; 94 return oldValue; 95} 96 97 98int64 99atomic_get64(int64 *value) 100{ 101 SpinLocker locker(&atomic_lock); 102 return *value; 103} 104 105 106int64 107_user_atomic_get_and_set64(int64 *value, int64 newValue) 108{ 109 if (IS_USER_ADDRESS(value) 110 && lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) { 111 int64 oldValue = atomic_get_and_set64(value, newValue); 112 unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE); 113 return oldValue; 114 } 115 116access_violation: 117 // XXX kill application 118 return -1; 119} 120 121 122void 123_user_atomic_set64(int64 *value, int64 newValue) 124{ 125 if (IS_USER_ADDRESS(value) 126 && lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) { 127 atomic_set64(value, newValue); 128 unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE); 129 return; 130 } 131 132access_violation: 133 // XXX kill application 134 return; 135} 136 137 138int64 139_user_atomic_test_and_set64(int64 *value, int64 newValue, int64 testAgainst) 140{ 141 if (IS_USER_ADDRESS(value) 142 && lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) { 143 int64 oldValue = atomic_test_and_set64(value, newValue, testAgainst); 144 unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE); 145 return oldValue; 146 } 147 148access_violation: 149 // XXX kill application 150 return -1; 151} 152 153 154int64 155_user_atomic_add64(int64 *value, int64 addValue) 156{ 157 if (IS_USER_ADDRESS(value) 158 && lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) { 159 int64 oldValue = atomic_add64(value, addValue); 160 unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE); 161 return oldValue; 162 } 163 164access_violation: 165 // XXX kill application 166 return -1; 167} 168 169 170int64 171_user_atomic_and64(int64 *value, int64 andValue) 172{ 173 if (IS_USER_ADDRESS(value) 174 && lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) { 175 int64 oldValue = atomic_and64(value, andValue); 176 unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE); 177 return oldValue; 178 } 179 180access_violation: 181 // XXX kill application 182 return -1; 183} 184 185 186int64 187_user_atomic_or64(int64 *value, int64 orValue) 188{ 189 if (IS_USER_ADDRESS(value) 190 && lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) { 191 int64 oldValue = atomic_or64(value, orValue); 192 unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE); 193 return oldValue; 194 } 195 196access_violation: 197 // XXX kill application 198 return -1; 199} 200 201 202int64 203_user_atomic_get64(int64 *value) 204{ 205 if (IS_USER_ADDRESS(value) 206 && lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) { 207 int64 oldValue = atomic_get64(value); 208 unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE); 209 return oldValue; 210 } 211 212access_violation: 213 // XXX kill application 214 return -1; 215} 216 217#endif /* ATOMIC64_FUNCS_ARE_SYSCALLS */ 218