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 30 static spinlock atomic_lock = B_SPINLOCK_INITIALIZER; 31 32 33 void 34 atomic_set64(int64 *value, int64 newValue) 35 { 36 SpinLocker locker(&atomic_lock); 37 38 *value = newValue; 39 } 40 41 42 int64 43 atomic_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 53 int64 54 atomic_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 65 int64 66 atomic_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 76 int64 77 atomic_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 87 int64 88 atomic_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 98 int64 99 atomic_get64(int64 *value) 100 { 101 SpinLocker locker(&atomic_lock); 102 return *value; 103 } 104 105 106 int64 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 116 access_violation: 117 // XXX kill application 118 return -1; 119 } 120 121 122 void 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 132 access_violation: 133 // XXX kill application 134 return; 135 } 136 137 138 int64 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 148 access_violation: 149 // XXX kill application 150 return -1; 151 } 152 153 154 int64 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 164 access_violation: 165 // XXX kill application 166 return -1; 167 } 168 169 170 int64 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 180 access_violation: 181 // XXX kill application 182 return -1; 183 } 184 185 186 int64 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 196 access_violation: 197 // XXX kill application 198 return -1; 199 } 200 201 202 int64 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 212 access_violation: 213 // XXX kill application 214 return -1; 215 } 216 217 #endif /* ATOMIC64_FUNCS_ARE_SYSCALLS */ 218