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 ATOMIC_FUNCS_ARE_SYSCALLS 17 18 /* 19 * NOTE: These functions are _intentionally_ not using spinlocks, unlike 20 * the 64 bit versions. The reason for this is that they are used by the 21 * spinlock code itself, and therefore would deadlock. 22 * 23 * Since these are only really needed for ARMv5, which is not SMP anyway, 24 * this is an acceptable compromise. 25 */ 26 27 void 28 atomic_set(int32 *value, int32 newValue) 29 { 30 InterruptsLocker locker; 31 *value = newValue; 32 } 33 34 int32 35 atomic_get_and_set(int32 *value, int32 newValue) 36 { 37 InterruptsLocker locker; 38 int32 oldValue = *value; 39 atomic_set(value, newValue); 40 return oldValue; 41 } 42 43 int32 44 atomic_test_and_set(int32 *value, int32 newValue, int32 testAgainst) 45 { 46 InterruptsLocker locker; 47 48 int32 oldValue = *value; 49 if (oldValue == testAgainst) 50 *value = newValue; 51 return oldValue; 52 } 53 54 int32 55 atomic_add(int32 *value, int32 addValue) 56 { 57 InterruptsLocker locker; 58 59 int32 oldValue = *value; 60 *value += addValue; 61 return oldValue; 62 } 63 64 int32 65 atomic_and(int32 *value, int32 andValue) 66 { 67 InterruptsLocker locker; 68 69 int32 oldValue = *value; 70 *value &= andValue; 71 return oldValue; 72 } 73 74 int32 75 atomic_or(int32 *value, int32 orValue) 76 { 77 InterruptsLocker locker; 78 79 int32 oldValue = *value; 80 *value |= orValue; 81 return oldValue; 82 } 83 84 int32 85 atomic_get(int32 *value) 86 { 87 InterruptsLocker locker; 88 89 int32 oldValue = *value; 90 return oldValue; 91 } 92 93 void 94 _user_atomic_set(int32 *value, int32 newValue) 95 { 96 if (IS_USER_ADDRESS(value) 97 && lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) { 98 atomic_set(value, newValue); 99 unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE); 100 return; 101 } 102 103 access_violation: 104 // XXX kill application 105 return; 106 } 107 108 int32 109 _user_atomic_get_and_set(int32 *value, int32 newValue) 110 { 111 if (IS_USER_ADDRESS(value) 112 && lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) { 113 int32 oldValue = atomic_get_and_set(value, newValue); 114 unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE); 115 return oldValue; 116 } 117 118 access_violation: 119 // XXX kill application 120 return -1; 121 } 122 123 int32 124 _user_atomic_test_and_set(int32 *value, int32 newValue, int32 testAgainst) 125 { 126 if (IS_USER_ADDRESS(value) 127 && lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) { 128 int32 oldValue = atomic_test_and_set((int32*)value, newValue, testAgainst); 129 unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE); 130 return oldValue; 131 } 132 133 access_violation: 134 // XXX kill application 135 return -1; 136 } 137 138 int32 139 _user_atomic_add(int32 *value, int32 addValue) 140 { 141 if (IS_USER_ADDRESS(value) 142 && lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) { 143 int32 oldValue = atomic_add(value, addValue); 144 unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE); 145 return oldValue; 146 } 147 148 access_violation: 149 // XXX kill application 150 return -1; 151 } 152 153 int32 154 _user_atomic_and(int32 *value, int32 andValue) 155 { 156 if (IS_USER_ADDRESS(value) 157 && lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) { 158 int32 oldValue = atomic_and(value, andValue); 159 unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE); 160 return oldValue; 161 } 162 163 access_violation: 164 // XXX kill application 165 return -1; 166 } 167 168 int32 169 _user_atomic_or(int32 *value, int32 orValue) 170 { 171 if (IS_USER_ADDRESS(value) 172 && lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) { 173 int32 oldValue = atomic_or(value, orValue); 174 unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE); 175 return oldValue; 176 } 177 178 access_violation: 179 // XXX kill application 180 return -1; 181 } 182 183 int32 184 _user_atomic_get(int32 *value) 185 { 186 if (IS_USER_ADDRESS(value) 187 && lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) { 188 int32 oldValue = atomic_get(value); 189 unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE); 190 return oldValue; 191 } 192 193 access_violation: 194 // XXX kill application 195 return -1; 196 } 197 198 #endif /* ATOMIC_FUNCS_ARE_SYSCALLS */ 199