Changes in kernel/generic/src/synch/spinlock.c [4777e02:95d45482] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/synch/spinlock.c
r4777e02 r95d45482 1 1 /* 2 2 * Copyright (c) 2001-2004 Jakub Jermar 3 * Copyright (c) 2023 Jiří Zárevúcky4 3 * All rights reserved. 5 4 * … … 37 36 */ 38 37 39 #ifdef CONFIG_SMP40 41 #include <arch/asm.h>42 38 #include <synch/spinlock.h> 43 39 #include <atomic.h> … … 51 47 #include <cpu.h> 52 48 49 #ifdef CONFIG_SMP 50 53 51 /** Initialize spinlock 54 52 * … … 64 62 } 65 63 64 #ifdef CONFIG_DEBUG_SPINLOCK 65 66 66 /** Lock spinlock 67 67 * 68 * Lock spinlock. 69 * This version has limitted ability to report 70 * possible occurence of deadlock. 71 * 68 72 * @param lock Pointer to spinlock_t structure. 69 73 * 70 74 */ 71 void spinlock_lock(spinlock_t *lock) 72 { 75 void spinlock_lock_debug(spinlock_t *lock) 76 { 77 size_t i = 0; 78 bool deadlock_reported = false; 79 73 80 preemption_disable(); 74 75 bool deadlock_reported = false;76 size_t i = 0;77 78 81 while (atomic_flag_test_and_set_explicit(&lock->flag, memory_order_acquire)) { 79 cpu_spin_hint();80 81 #ifdef CONFIG_DEBUG_SPINLOCK82 82 /* 83 83 * We need to be careful about particular locks … … 111 111 deadlock_reported = true; 112 112 } 113 #endif 114 } 115 116 /* Avoid compiler warning with debug disabled. */ 117 (void) i; 113 } 118 114 119 115 if (deadlock_reported) … … 123 119 /** Unlock spinlock 124 120 * 121 * Unlock spinlock. 122 * 125 123 * @param sl Pointer to spinlock_t structure. 126 124 */ 127 void spinlock_unlock(spinlock_t *lock) 128 { 129 #ifdef CONFIG_DEBUG_SPINLOCK 125 void spinlock_unlock_debug(spinlock_t *lock) 126 { 130 127 ASSERT_SPINLOCK(spinlock_locked(lock), lock); 131 #endif132 128 133 129 atomic_flag_clear_explicit(&lock->flag, memory_order_release); … … 135 131 } 136 132 137 /** 133 #endif 134 135 /** Lock spinlock conditionally 136 * 138 137 * Lock spinlock conditionally. If the spinlock is not available 139 138 * at the moment, signal failure. … … 141 140 * @param lock Pointer to spinlock_t structure. 142 141 * 143 * @return true on success.142 * @return Zero on failure, non-zero otherwise. 144 143 * 145 144 */ … … 147 146 { 148 147 preemption_disable(); 149 150 148 bool ret = !atomic_flag_test_and_set_explicit(&lock->flag, memory_order_acquire); 151 149 … … 174 172 } 175 173 176 #endif /* CONFIG_SMP */ 174 #endif 175 176 /** Initialize interrupts-disabled spinlock 177 * 178 * @param lock IRQ spinlock to be initialized. 179 * @param name IRQ spinlock name. 180 * 181 */ 182 void irq_spinlock_initialize(irq_spinlock_t *lock, const char *name) 183 { 184 spinlock_initialize(&(lock->lock), name); 185 lock->guard = false; 186 lock->ipl = 0; 187 } 188 189 /** Lock interrupts-disabled spinlock 190 * 191 * Lock a spinlock which requires disabled interrupts. 192 * 193 * @param lock IRQ spinlock to be locked. 194 * @param irq_dis If true, disables interrupts before locking the spinlock. 195 * If false, interrupts are expected to be already disabled. 196 * 197 */ 198 void irq_spinlock_lock(irq_spinlock_t *lock, bool irq_dis) 199 { 200 if (irq_dis) { 201 ipl_t ipl = interrupts_disable(); 202 spinlock_lock(&(lock->lock)); 203 204 lock->guard = true; 205 lock->ipl = ipl; 206 } else { 207 ASSERT_IRQ_SPINLOCK(interrupts_disabled(), lock); 208 209 spinlock_lock(&(lock->lock)); 210 ASSERT_IRQ_SPINLOCK(!lock->guard, lock); 211 } 212 } 213 214 /** Unlock interrupts-disabled spinlock 215 * 216 * Unlock a spinlock which requires disabled interrupts. 217 * 218 * @param lock IRQ spinlock to be unlocked. 219 * @param irq_res If true, interrupts are restored to previously 220 * saved interrupt level. 221 * 222 */ 223 void irq_spinlock_unlock(irq_spinlock_t *lock, bool irq_res) 224 { 225 ASSERT_IRQ_SPINLOCK(interrupts_disabled(), lock); 226 227 if (irq_res) { 228 ASSERT_IRQ_SPINLOCK(lock->guard, lock); 229 230 lock->guard = false; 231 ipl_t ipl = lock->ipl; 232 233 spinlock_unlock(&(lock->lock)); 234 interrupts_restore(ipl); 235 } else { 236 ASSERT_IRQ_SPINLOCK(!lock->guard, lock); 237 spinlock_unlock(&(lock->lock)); 238 } 239 } 240 241 /** Lock interrupts-disabled spinlock 242 * 243 * Lock an interrupts-disabled spinlock conditionally. If the 244 * spinlock is not available at the moment, signal failure. 245 * Interrupts are expected to be already disabled. 246 * 247 * @param lock IRQ spinlock to be locked conditionally. 248 * 249 * @return Zero on failure, non-zero otherwise. 250 * 251 */ 252 bool irq_spinlock_trylock(irq_spinlock_t *lock) 253 { 254 ASSERT_IRQ_SPINLOCK(interrupts_disabled(), lock); 255 bool ret = spinlock_trylock(&(lock->lock)); 256 257 ASSERT_IRQ_SPINLOCK((!ret) || (!lock->guard), lock); 258 return ret; 259 } 260 261 /** Pass lock from one interrupts-disabled spinlock to another 262 * 263 * Pass lock from one IRQ spinlock to another IRQ spinlock 264 * without enabling interrupts during the process. 265 * 266 * The first IRQ spinlock is supposed to be locked. 267 * 268 * @param unlock IRQ spinlock to be unlocked. 269 * @param lock IRQ spinlock to be locked. 270 * 271 */ 272 void irq_spinlock_pass(irq_spinlock_t *unlock, irq_spinlock_t *lock) 273 { 274 ASSERT_IRQ_SPINLOCK(interrupts_disabled(), unlock); 275 276 /* Pass guard from unlock to lock */ 277 bool guard = unlock->guard; 278 ipl_t ipl = unlock->ipl; 279 unlock->guard = false; 280 281 spinlock_unlock(&(unlock->lock)); 282 spinlock_lock(&(lock->lock)); 283 284 ASSERT_IRQ_SPINLOCK(!lock->guard, lock); 285 286 if (guard) { 287 lock->guard = true; 288 lock->ipl = ipl; 289 } 290 } 291 292 /** Hand-over-hand locking of interrupts-disabled spinlocks 293 * 294 * Implement hand-over-hand locking between two interrupts-disabled 295 * spinlocks without enabling interrupts during the process. 296 * 297 * The first IRQ spinlock is supposed to be locked. 298 * 299 * @param unlock IRQ spinlock to be unlocked. 300 * @param lock IRQ spinlock to be locked. 301 * 302 */ 303 void irq_spinlock_exchange(irq_spinlock_t *unlock, irq_spinlock_t *lock) 304 { 305 ASSERT_IRQ_SPINLOCK(interrupts_disabled(), unlock); 306 307 spinlock_lock(&(lock->lock)); 308 ASSERT_IRQ_SPINLOCK(!lock->guard, lock); 309 310 /* Pass guard from unlock to lock */ 311 if (unlock->guard) { 312 lock->guard = true; 313 lock->ipl = unlock->ipl; 314 unlock->guard = false; 315 } 316 317 spinlock_unlock(&(unlock->lock)); 318 } 319 320 /** Find out whether the IRQ spinlock is currently locked. 321 * 322 * @param lock IRQ spinlock. 323 * @return True if the IRQ spinlock is locked, false otherwise. 324 */ 325 bool irq_spinlock_locked(irq_spinlock_t *ilock) 326 { 327 return spinlock_locked(&ilock->lock); 328 } 177 329 178 330 /** @}
Note:
See TracChangeset
for help on using the changeset viewer.