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 int32 28 atomic_set(vint32 *value, int32 newValue) 29 { 30 InterruptsLocker locker; 31 32 int32 oldValue = *value; 33 *value = newValue; 34 return oldValue; 35 } 36 37 int32 38 atomic_test_and_set(vint32 *value, int32 newValue, int32 testAgainst) 39 { 40 InterruptsLocker locker; 41 42 int32 oldValue = *value; 43 if (oldValue == testAgainst) 44 *value = newValue; 45 return oldValue; 46 } 47 48 int32 49 atomic_add(vint32 *value, int32 addValue) 50 { 51 InterruptsLocker locker; 52 53 int32 oldValue = *value; 54 *value += addValue; 55 return oldValue; 56 } 57 58 int32 59 atomic_and(vint32 *value, int32 andValue) 60 { 61 InterruptsLocker locker; 62 63 int32 oldValue = *value; 64 *value &= andValue; 65 return oldValue; 66 } 67 68 int32 69 atomic_or(vint32 *value, int32 orValue) 70 { 71 InterruptsLocker locker; 72 73 int32 oldValue = *value; 74 *value |= orValue; 75 return oldValue; 76 } 77 78 int32 79 atomic_get(vint32 *value) 80 { 81 InterruptsLocker locker; 82 83 int32 oldValue = *value; 84 return oldValue; 85 } 86 87 int32 88 _user_atomic_set(vint32 *value, int32 newValue) 89 { 90 if (IS_USER_ADDRESS(value) 91 && lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) { 92 int32 oldValue = atomic_set(value, newValue); 93 unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE); 94 return oldValue; 95 } 96 97 access_violation: 98 // XXX kill application 99 return -1; 100 } 101 102 int32 103 _user_atomic_test_and_set(vint32 *value, int32 newValue, int32 testAgainst) 104 { 105 if (IS_USER_ADDRESS(value) 106 && lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) { 107 int32 oldValue = atomic_test_and_set(value, newValue, testAgainst); 108 unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE); 109 return oldValue; 110 } 111 112 access_violation: 113 // XXX kill application 114 return -1; 115 } 116 117 int32 118 _user_atomic_add(vint32 *value, int32 addValue) 119 { 120 if (IS_USER_ADDRESS(value) 121 && lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) { 122 int32 oldValue = atomic_add(value, addValue); 123 unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE); 124 return oldValue; 125 } 126 127 access_violation: 128 // XXX kill application 129 return -1; 130 } 131 132 int32 133 _user_atomic_and(vint32 *value, int32 andValue) 134 { 135 if (IS_USER_ADDRESS(value) 136 && lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) { 137 int32 oldValue = atomic_and(value, andValue); 138 unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE); 139 return oldValue; 140 } 141 142 access_violation: 143 // XXX kill application 144 return -1; 145 } 146 147 int32 148 _user_atomic_or(vint32 *value, int32 orValue) 149 { 150 if (IS_USER_ADDRESS(value) 151 && lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) { 152 int32 oldValue = atomic_or(value, orValue); 153 unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE); 154 return oldValue; 155 } 156 157 access_violation: 158 // XXX kill application 159 return -1; 160 } 161 162 int32 163 _user_atomic_get(vint32 *value) 164 { 165 if (IS_USER_ADDRESS(value) 166 && lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) { 167 int32 oldValue = atomic_get(value); 168 unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE); 169 return oldValue; 170 } 171 172 access_violation: 173 // XXX kill application 174 return -1; 175 } 176 177 #endif /* ATOMIC_FUNCS_ARE_SYSCALLS */ 178