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 27void 28atomic_set(int32 *value, int32 newValue) 29{ 30 InterruptsLocker locker; 31 *value = newValue; 32} 33 34int32 35atomic_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 43int32 44atomic_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 54int32 55atomic_add(int32 *value, int32 addValue) 56{ 57 InterruptsLocker locker; 58 59 int32 oldValue = *value; 60 *value += addValue; 61 return oldValue; 62} 63 64int32 65atomic_and(int32 *value, int32 andValue) 66{ 67 InterruptsLocker locker; 68 69 int32 oldValue = *value; 70 *value &= andValue; 71 return oldValue; 72} 73 74int32 75atomic_or(int32 *value, int32 orValue) 76{ 77 InterruptsLocker locker; 78 79 int32 oldValue = *value; 80 *value |= orValue; 81 return oldValue; 82} 83 84int32 85atomic_get(int32 *value) 86{ 87 InterruptsLocker locker; 88 89 int32 oldValue = *value; 90 return oldValue; 91} 92 93void 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 103access_violation: 104 // XXX kill application 105 return; 106} 107 108int32 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 118access_violation: 119 // XXX kill application 120 return -1; 121} 122 123int32 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 133access_violation: 134 // XXX kill application 135 return -1; 136} 137 138int32 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 148access_violation: 149 // XXX kill application 150 return -1; 151} 152 153int32 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 163access_violation: 164 // XXX kill application 165 return -1; 166} 167 168int32 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 178access_violation: 179 // XXX kill application 180 return -1; 181} 182 183int32 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 193access_violation: 194 // XXX kill application 195 return -1; 196} 197 198#endif /* ATOMIC_FUNCS_ARE_SYSCALLS */ 199