1 /* 2 * Copyright 2007, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * François Revol <revol@free.fr> 7 * 8 * Copyright 2003, Marcus Overhagen. All rights reserved. 9 * Distributed under the terms of the MIT License. 10 */ 11 12 #include <KernelExport.h> 13 14 #include <kernel.h> 15 #include <user_atomic.h> 16 17 /* 18 * Emulation of 64 bit atomic functions. 19 * Slow, using spinlocks... 20 */ 21 22 #warning M68K: detect 060 here 23 #if 0 24 25 static spinlock atomic_lock = 0; 26 27 int64 28 atomic_set64(vint64 *value, int64 newValue) 29 { 30 cpu_status status; 31 int64 oldValue; 32 status = disable_interrupts(); 33 acquire_spinlock(&atomic_lock); 34 oldValue = *value; 35 *value = newValue; 36 release_spinlock(&atomic_lock); 37 restore_interrupts(status); 38 return oldValue; 39 } 40 41 int64 42 atomic_test_and_set64(vint64 *value, int64 newValue, int64 testAgainst) 43 { 44 cpu_status status; 45 int64 oldValue; 46 status = disable_interrupts(); 47 acquire_spinlock(&atomic_lock); 48 oldValue = *value; 49 if (oldValue == testAgainst) 50 *value = newValue; 51 release_spinlock(&atomic_lock); 52 restore_interrupts(status); 53 return oldValue; 54 } 55 56 int64 57 atomic_add64(vint64 *value, int64 addValue) 58 { 59 cpu_status status; 60 int64 oldValue; 61 status = disable_interrupts(); 62 acquire_spinlock(&atomic_lock); 63 oldValue = *value; 64 *value += addValue; 65 release_spinlock(&atomic_lock); 66 restore_interrupts(status); 67 return oldValue; 68 } 69 70 int64 71 atomic_and64(vint64 *value, int64 andValue) 72 { 73 cpu_status status; 74 int64 oldValue; 75 status = disable_interrupts(); 76 acquire_spinlock(&atomic_lock); 77 oldValue = *value; 78 *value &= andValue; 79 release_spinlock(&atomic_lock); 80 restore_interrupts(status); 81 return oldValue; 82 } 83 84 int64 85 atomic_or64(vint64 *value, int64 orValue) 86 { 87 cpu_status status; 88 int64 oldValue; 89 status = disable_interrupts(); 90 acquire_spinlock(&atomic_lock); 91 oldValue = *value; 92 *value |= orValue; 93 release_spinlock(&atomic_lock); 94 restore_interrupts(status); 95 return oldValue; 96 } 97 98 int64 99 atomic_get64(vint64 *value) 100 { 101 cpu_status status; 102 int64 oldValue; 103 status = disable_interrupts(); 104 acquire_spinlock(&atomic_lock); 105 oldValue = *value; 106 release_spinlock(&atomic_lock); 107 restore_interrupts(status); 108 return oldValue; 109 } 110 111 int64 112 _user_atomic_set64(vint64 *value, int64 newValue) 113 { 114 cpu_status status; 115 int64 oldValue; 116 if (!IS_USER_ADDRESS(value) 117 || lock_memory((void *)value, 8, B_READ_DEVICE) != B_OK) 118 goto access_violation; 119 120 status = disable_interrupts(); 121 acquire_spinlock(&atomic_lock); 122 oldValue = *value; 123 *value = newValue; 124 release_spinlock(&atomic_lock); 125 restore_interrupts(status); 126 unlock_memory((void *)value, 8, B_READ_DEVICE); 127 return oldValue; 128 129 access_violation: 130 // XXX kill application 131 return -1; 132 } 133 134 int64 135 _user_atomic_test_and_set64(vint64 *value, int64 newValue, int64 testAgainst) 136 { 137 cpu_status status; 138 int64 oldValue; 139 if (!IS_USER_ADDRESS(value) 140 || lock_memory((void *)value, 8, B_READ_DEVICE) != B_OK) 141 goto access_violation; 142 143 status = disable_interrupts(); 144 acquire_spinlock(&atomic_lock); 145 oldValue = *value; 146 if (oldValue == testAgainst) 147 *value = newValue; 148 release_spinlock(&atomic_lock); 149 restore_interrupts(status); 150 unlock_memory((void *)value, 8, B_READ_DEVICE); 151 return oldValue; 152 153 access_violation: 154 // XXX kill application 155 return -1; 156 } 157 158 int64 159 _user_atomic_add64(vint64 *value, int64 addValue) 160 { 161 cpu_status status; 162 int64 oldValue; 163 if (!IS_USER_ADDRESS(value) 164 || lock_memory((void *)value, 8, B_READ_DEVICE) != B_OK) 165 goto access_violation; 166 167 status = disable_interrupts(); 168 acquire_spinlock(&atomic_lock); 169 oldValue = *value; 170 *value += addValue; 171 release_spinlock(&atomic_lock); 172 restore_interrupts(status); 173 unlock_memory((void *)value, 8, B_READ_DEVICE); 174 return oldValue; 175 176 access_violation: 177 // XXX kill application 178 return -1; 179 } 180 181 int64 182 _user_atomic_and64(vint64 *value, int64 andValue) 183 { 184 cpu_status status; 185 int64 oldValue; 186 if (!IS_USER_ADDRESS(value) 187 || lock_memory((void *)value, 8, B_READ_DEVICE) != B_OK) 188 goto access_violation; 189 190 status = disable_interrupts(); 191 acquire_spinlock(&atomic_lock); 192 oldValue = *value; 193 *value &= andValue; 194 release_spinlock(&atomic_lock); 195 restore_interrupts(status); 196 unlock_memory((void *)value, 8, B_READ_DEVICE); 197 return oldValue; 198 199 access_violation: 200 // XXX kill application 201 return -1; 202 } 203 204 int64 205 _user_atomic_or64(vint64 *value, int64 orValue) 206 { 207 cpu_status status; 208 int64 oldValue; 209 if (!IS_USER_ADDRESS(value) 210 || lock_memory((void *)value, 8, B_READ_DEVICE) != B_OK) 211 goto access_violation; 212 213 status = disable_interrupts(); 214 acquire_spinlock(&atomic_lock); 215 oldValue = *value; 216 *value |= orValue; 217 release_spinlock(&atomic_lock); 218 restore_interrupts(status); 219 unlock_memory((void *)value, 8, B_READ_DEVICE); 220 return oldValue; 221 access_violation: 222 // XXX kill application 223 return -1; 224 } 225 226 int64 227 _user_atomic_get64(vint64 *value) 228 { 229 cpu_status status; 230 int64 oldValue; 231 if (!IS_USER_ADDRESS(value) 232 || lock_memory((void *)value, 8, B_READ_DEVICE) != B_OK) 233 goto access_violation; 234 235 status = disable_interrupts(); 236 acquire_spinlock(&atomic_lock); 237 oldValue = *value; 238 release_spinlock(&atomic_lock); 239 restore_interrupts(status); 240 unlock_memory((void *)value, 8, B_READ_DEVICE); 241 return oldValue; 242 243 access_violation: 244 // XXX kill application 245 return -1; 246 } 247 #endif 248