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 int64 34 atomic_set64(vint64 *value, int64 newValue) 35 { 36 SpinLocker locker(&atomic_lock); 37 38 int64 oldValue = *value; 39 *value = newValue; 40 return oldValue; 41 } 42 43 44 int64 45 atomic_test_and_set64(vint64 *value, int64 newValue, int64 testAgainst) 46 { 47 SpinLocker locker(&atomic_lock); 48 49 int64 oldValue = *value; 50 if (oldValue == testAgainst) 51 *value = newValue; 52 return oldValue; 53 } 54 55 56 int64 57 atomic_add64(vint64 *value, int64 addValue) 58 { 59 SpinLocker locker(&atomic_lock); 60 61 int64 oldValue = *value; 62 *value += addValue; 63 return oldValue; 64 } 65 66 67 int64 68 atomic_and64(vint64 *value, int64 andValue) 69 { 70 SpinLocker locker(&atomic_lock); 71 72 int64 oldValue = *value; 73 *value &= andValue; 74 return oldValue; 75 } 76 77 78 int64 79 atomic_or64(vint64 *value, int64 orValue) 80 { 81 SpinLocker locker(&atomic_lock); 82 83 int64 oldValue = *value; 84 *value |= orValue; 85 return oldValue; 86 } 87 88 89 int64 90 atomic_get64(vint64 *value) 91 { 92 SpinLocker locker(&atomic_lock); 93 return *value; 94 } 95 96 97 int64 98 _user_atomic_set64(vint64 *value, int64 newValue) 99 { 100 if (IS_USER_ADDRESS(value) 101 && lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) { 102 int64 oldValue = atomic_set64(value, newValue); 103 unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE); 104 return oldValue; 105 } 106 107 access_violation: 108 // XXX kill application 109 return -1; 110 } 111 112 113 int64 114 _user_atomic_test_and_set64(vint64 *value, int64 newValue, int64 testAgainst) 115 { 116 if (IS_USER_ADDRESS(value) 117 && lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) { 118 int64 oldValue = atomic_test_and_set64(value, newValue, testAgainst); 119 unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE); 120 return oldValue; 121 } 122 123 access_violation: 124 // XXX kill application 125 return -1; 126 } 127 128 129 int64 130 _user_atomic_add64(vint64 *value, int64 addValue) 131 { 132 if (IS_USER_ADDRESS(value) 133 && lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) { 134 int64 oldValue = atomic_add64(value, addValue); 135 unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE); 136 return oldValue; 137 } 138 139 access_violation: 140 // XXX kill application 141 return -1; 142 } 143 144 145 int64 146 _user_atomic_and64(vint64 *value, int64 andValue) 147 { 148 if (IS_USER_ADDRESS(value) 149 && lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) { 150 int64 oldValue = atomic_and64(value, andValue); 151 unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE); 152 return oldValue; 153 } 154 155 access_violation: 156 // XXX kill application 157 return -1; 158 } 159 160 161 int64 162 _user_atomic_or64(vint64 *value, int64 orValue) 163 { 164 if (IS_USER_ADDRESS(value) 165 && lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) { 166 int64 oldValue = atomic_or64(value, orValue); 167 unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE); 168 return oldValue; 169 } 170 171 access_violation: 172 // XXX kill application 173 return -1; 174 } 175 176 177 int64 178 _user_atomic_get64(vint64 *value) 179 { 180 if (IS_USER_ADDRESS(value) 181 && lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) { 182 int64 oldValue = atomic_get64(value); 183 unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE); 184 return oldValue; 185 } 186 187 access_violation: 188 // XXX kill application 189 return -1; 190 } 191 192 #endif /* ATOMIC64_FUNCS_ARE_SYSCALLS */ 193