Changes in kernel/generic/src/synch/spinlock.c [95d45482:4777e02] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/synch/spinlock.c
r95d45482 r4777e02 1 1 /* 2 2 * Copyright (c) 2001-2004 Jakub Jermar 3 * Copyright (c) 2023 Jiří Zárevúcky 3 4 * All rights reserved. 4 5 * … … 36 37 */ 37 38 39 #ifdef CONFIG_SMP 40 41 #include <arch/asm.h> 38 42 #include <synch/spinlock.h> 39 43 #include <atomic.h> … … 46 50 #include <stacktrace.h> 47 51 #include <cpu.h> 48 49 #ifdef CONFIG_SMP50 52 51 53 /** Initialize spinlock … … 62 64 } 63 65 64 #ifdef CONFIG_DEBUG_SPINLOCK65 66 66 /** Lock spinlock 67 *68 * Lock spinlock.69 * This version has limitted ability to report70 * possible occurence of deadlock.71 67 * 72 68 * @param lock Pointer to spinlock_t structure. 73 69 * 74 70 */ 75 void spinlock_lock _debug(spinlock_t *lock)71 void spinlock_lock(spinlock_t *lock) 76 72 { 73 preemption_disable(); 74 75 bool deadlock_reported = false; 77 76 size_t i = 0; 78 bool deadlock_reported = false;79 77 80 preemption_disable();81 78 while (atomic_flag_test_and_set_explicit(&lock->flag, memory_order_acquire)) { 79 cpu_spin_hint(); 80 81 #ifdef CONFIG_DEBUG_SPINLOCK 82 82 /* 83 83 * We need to be careful about particular locks … … 111 111 deadlock_reported = true; 112 112 } 113 #endif 113 114 } 115 116 /* Avoid compiler warning with debug disabled. */ 117 (void) i; 114 118 115 119 if (deadlock_reported) … … 119 123 /** Unlock spinlock 120 124 * 121 * Unlock spinlock.122 *123 125 * @param sl Pointer to spinlock_t structure. 124 126 */ 125 void spinlock_unlock _debug(spinlock_t *lock)127 void spinlock_unlock(spinlock_t *lock) 126 128 { 129 #ifdef CONFIG_DEBUG_SPINLOCK 127 130 ASSERT_SPINLOCK(spinlock_locked(lock), lock); 131 #endif 128 132 129 133 atomic_flag_clear_explicit(&lock->flag, memory_order_release); … … 131 135 } 132 136 133 #endif 134 135 /** Lock spinlock conditionally 136 * 137 /** 137 138 * Lock spinlock conditionally. If the spinlock is not available 138 139 * at the moment, signal failure. … … 140 141 * @param lock Pointer to spinlock_t structure. 141 142 * 142 * @return Zero on failure, non-zero otherwise.143 * @return true on success. 143 144 * 144 145 */ … … 146 147 { 147 148 preemption_disable(); 149 148 150 bool ret = !atomic_flag_test_and_set_explicit(&lock->flag, memory_order_acquire); 149 151 … … 172 174 } 173 175 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 } 176 #endif /* CONFIG_SMP */ 329 177 330 178 /** @}
Note:
See TracChangeset
for help on using the changeset viewer.