Changeset 2b4a9f26 in mainline
- Timestamp:
- 2010-05-20T19:30:18Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 42bbbe2
- Parents:
- b10e6e31
- Location:
- kernel
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/ia32/include/asm.h
rb10e6e31 r2b4a9f26 38 38 39 39 #include <arch/pm.h> 40 #include <arch/cpu.h> 40 41 #include <typedefs.h> 41 42 #include <config.h> … … 299 300 } 300 301 302 /** Check interrupts state. 303 * 304 * @return True if interrupts are disabled. 305 * 306 */ 307 static inline bool interrupts_disabled(void) 308 { 309 ipl_t v; 310 311 asm volatile ( 312 "pushf\n" 313 "popl %[v]\n" 314 : [v] "=r" (v) 315 ); 316 317 return ((v & EFLAGS_IF) == 0); 318 } 319 301 320 /** Write to MSR */ 302 321 static inline void write_msr(uint32_t msr, uint64_t value) -
kernel/doc/synchronization
rb10e6e31 r2b4a9f26 5 5 | spinlock_t | 6 6 +------------+ 7 | 8 +------------------------------+ 9 | 10 INTERRUPTS-DISABLED SPINNING LOCKS | 11 irq_spinlock_lock, irq_spinlock_trylock, irq_spinlock_unlock | 12 +----------------+ | 13 | irq_spinlock_t |<--------------------+ 14 +----------------+ 15 16 7 17 8 18 WAIT QUEUES … … 10 20 +---------+ 11 21 | waitq_t | 12 13 22 +---------+ 23 / \ 14 24 SEMAPHORES / \ CONDITION VARIABLES 15 25 semaphore_down_timeout, semaphore_up condvar_wait_timeout, condvar_signal … … 18 28 +--------------+ +-----------+ 19 29 | ^ 20 30 | | 21 31 | +------+ 22 V / 32 V / 23 33 MUTEXES / READERS/WRITERS LOCKS 24 34 mutex_lock_timeout, mutex_unlock rwlock_reader/writer_lock_timeout, rwlock_unlock 25 35 +---------+ / +----------+ 26 27 28 29 36 | mutex_t |------------------------------->| rwlock_t | 37 +---------+ / +----------+ 38 | / 39 +------------------------+ -
kernel/generic/include/synch/spinlock.h
rb10e6e31 r2b4a9f26 49 49 #ifdef CONFIG_DEBUG_SPINLOCK 50 50 const char *name; 51 #endif 51 #endif /* CONFIG_DEBUG_SPINLOCK */ 52 52 } spinlock_t; 53 53 … … 60 60 61 61 /* 62 * SPINLOCK_INITIALIZE is to be used for statically allocated spinlocks. 63 * It declares and initializes the lock. 62 * SPINLOCK_INITIALIZE and SPINLOCK_STATIC_INITIALIZE are to be used 63 * for statically allocated spinlocks. They declare (either as global 64 * or static) symbol and initialize the lock. 64 65 */ 65 66 #ifdef CONFIG_DEBUG_SPINLOCK … … 77 78 } 78 79 79 #define spinlock_lock(lock) spinlock_lock_debug((lock)) 80 #define spinlock_unlock(lock) spinlock_unlock_debug((lock)) 81 82 #else 80 #define ASSERT_SPINLOCK(expr, lock) \ 81 ASSERT_VERBOSE(expr, (lock)->name) 82 83 #define spinlock_lock(lock) spinlock_lock_debug((lock)) 84 #define spinlock_unlock(lock) spinlock_unlock_debug((lock)) 85 86 #else /* CONFIG_DEBUG_SPINLOCK */ 83 87 84 88 #define SPINLOCK_INITIALIZE_NAME(lock_name, desc_name) \ … … 92 96 } 93 97 94 #define spinlock_lock(lock) atomic_lock_arch(&(lock)->val) 95 #define spinlock_unlock(lock) spinlock_unlock_nondebug((lock)) 96 97 #endif 98 #define ASSERT_SPINLOCK(expr, lock) \ 99 ASSERT(expr) 100 101 #define spinlock_lock(lock) atomic_lock_arch(&(lock)->val) 102 #define spinlock_unlock(lock) spinlock_unlock_nondebug((lock)) 103 104 #endif /* CONFIG_DEBUG_SPINLOCK */ 98 105 99 106 #define SPINLOCK_INITIALIZE(lock_name) \ … … 103 110 SPINLOCK_STATIC_INITIALIZE_NAME(lock_name, #lock_name) 104 111 105 extern void spinlock_initialize(spinlock_t * lock, const char *name);106 extern int spinlock_trylock(spinlock_t * lock);107 extern void spinlock_lock_debug(spinlock_t * lock);108 extern void spinlock_unlock_debug(spinlock_t * lock);112 extern void spinlock_initialize(spinlock_t *, const char *); 113 extern int spinlock_trylock(spinlock_t *); 114 extern void spinlock_lock_debug(spinlock_t *); 115 extern void spinlock_unlock_debug(spinlock_t *); 109 116 110 117 /** Unlock spinlock … … 113 120 * 114 121 * @param sl Pointer to spinlock_t structure. 122 * 115 123 */ 116 124 static inline void spinlock_unlock_nondebug(spinlock_t *lock) … … 141 149 } 142 150 143 #else 151 #else /* CONFIG_DEBUG_SPINLOCK */ 144 152 145 153 #define DEADLOCK_PROBE_INIT(pname) 146 154 #define DEADLOCK_PROBE(pname, value) 147 155 148 #endif 156 #endif /* CONFIG_DEBUG_SPINLOCK */ 149 157 150 158 #else /* CONFIG_SMP */ … … 160 168 #define SPINLOCK_INITIALIZE_NAME(name, desc_name) 161 169 #define SPINLOCK_STATIC_INITIALIZE_NAME(name, desc_name) 170 171 #define ASSERT_SPINLOCK(expr, lock) 162 172 163 173 #define spinlock_initialize(lock, name) … … 170 180 #define DEADLOCK_PROBE(pname, value) 171 181 182 #endif /* CONFIG_SMP */ 183 184 typedef struct { 185 spinlock_t lock; /**< Spinlock */ 186 bool guard; /**< Flag whether ipl is valid */ 187 ipl_t ipl; /**< Original interrupt level */ 188 } irq_spinlock_t; 189 190 #define IRQ_SPINLOCK_DECLARE(lock_name) irq_spinlock_t lock_name 191 #define IRQ_SPINLOCK_EXTERN(lock_name) extern irq_spinlock_t lock_name 192 193 #define ASSERT_IRQ_SPINLOCK(expr, irq_lock) \ 194 ASSERT_SPINLOCK(expr, &((irq_lock)->lock)) 195 196 /* 197 * IRQ_SPINLOCK_INITIALIZE and IRQ_SPINLOCK_STATIC_INITIALIZE are to be used 198 * for statically allocated interrupts-disabled spinlocks. They declare (either 199 * as global or static symbol) and initialize the lock. 200 */ 201 #ifdef CONFIG_DEBUG_SPINLOCK 202 203 #define IRQ_SPINLOCK_INITIALIZE_NAME(lock_name, desc_name) \ 204 irq_spinlock_t lock_name = { \ 205 .lock = { \ 206 .name = desc_name, \ 207 .val = { 0 } \ 208 }, \ 209 .guard = false, \ 210 .ipl = 0 \ 211 } 212 213 #define IRQ_SPINLOCK_STATIC_INITIALIZE_NAME(lock_name, desc_name) \ 214 static irq_spinlock_t lock_name = { \ 215 .lock = { \ 216 .name = desc_name, \ 217 .val = { 0 } \ 218 }, \ 219 .guard = false, \ 220 .ipl = 0 \ 221 } 222 223 #else /* CONFIG_DEBUG_SPINLOCK */ 224 225 #define IRQ_SPINLOCK_INITIALIZE_NAME(lock_name, desc_name) \ 226 irq_spinlock_t lock_name = { \ 227 .lock = { \ 228 .val = { 0 } \ 229 }, \ 230 .guard = false, \ 231 .ipl = 0 \ 232 } 233 234 #define IRQ_SPINLOCK_STATIC_INITIALIZE_NAME(lock_name, desc_name) \ 235 static irq_spinlock_t lock_name = { \ 236 .lock = { \ 237 .val = { 0 } \ 238 }, \ 239 .guard = false, \ 240 .ipl = 0 \ 241 } 242 243 #endif /* CONFIG_DEBUG_SPINLOCK */ 244 245 #define IRQ_SPINLOCK_INITIALIZE(lock_name) \ 246 IRQ_SPINLOCK_INITIALIZE_NAME(lock_name, #lock_name) 247 248 #define IRQ_SPINLOCK_STATIC_INITIALIZE(lock_name) \ 249 IRQ_SPINLOCK_STATIC_INITIALIZE_NAME(lock_name, #lock_name) 250 251 /** Initialize interrupts-disabled spinlock 252 * 253 * @param lock IRQ spinlock to be initialized. 254 * @param name IRQ spinlock name. 255 * 256 */ 257 static inline void irq_spinlock_initialize(irq_spinlock_t *lock, const char *name) 258 { 259 spinlock_initialize(&(lock->lock), name); 260 lock->guard = false; 261 lock->ipl = 0; 262 } 263 264 /** Lock interrupts-disabled spinlock 265 * 266 * Lock a spinlock which requires disabled interrupts. 267 * 268 * @param lock IRQ spinlock to be locked. 269 * @param irq_dis If true, interrupts are actually disabled 270 * prior locking the spinlock. If false, interrupts 271 * are expected to be already disabled. 272 * 273 */ 274 static inline void irq_spinlock_lock(irq_spinlock_t *lock, bool irq_dis) 275 { 276 if (irq_dis) { 277 ipl_t ipl = interrupts_disable(); 278 spinlock_lock(&(lock->lock)); 279 280 lock->guard = true; 281 lock->ipl = ipl; 282 } else { 283 ASSERT_IRQ_SPINLOCK(interrupts_disabled(), lock); 284 285 spinlock_lock(&(lock->lock)); 286 ASSERT_IRQ_SPINLOCK(!lock->guard, lock); 287 } 288 } 289 290 /** Unlock interrupts-disabled spinlock 291 * 292 * Unlock a spinlock which requires disabled interrupts. 293 * 294 * @param lock IRQ spinlock to be unlocked. 295 * @param irq_res If true, interrupts are restored to previously 296 * saved interrupt level. 297 * 298 */ 299 static inline void irq_spinlock_unlock(irq_spinlock_t *lock, bool irq_res) 300 { 301 ASSERT_IRQ_SPINLOCK(interrupts_disabled(), lock); 302 303 if (irq_res) { 304 ASSERT_IRQ_SPINLOCK(lock->guard, lock); 305 306 lock->guard = false; 307 ipl_t ipl = lock->ipl; 308 309 spinlock_unlock(&(lock->lock)); 310 interrupts_restore(ipl); 311 } else { 312 ASSERT_IRQ_SPINLOCK(!lock->guard, lock); 313 spinlock_unlock(&(lock->lock)); 314 } 315 } 316 317 /** Lock interrupts-disabled spinlock 318 * 319 * Lock an interrupts-disabled spinlock conditionally. If the 320 * spinlock is not available at the moment, signal failure. 321 * Interrupts are expected to be already disabled. 322 * 323 * @param lock IRQ spinlock to be locked conditionally. 324 * 325 * @return Zero on failure, non-zero otherwise. 326 * 327 */ 328 static inline int irq_spinlock_trylock(irq_spinlock_t *lock) 329 { 330 ASSERT_IRQ_SPINLOCK(interrupts_disabled(), lock); 331 int rc = spinlock_trylock(&(lock->lock)); 332 333 ASSERT_IRQ_SPINLOCK(!lock->guard, lock); 334 return rc; 335 } 336 337 /** Pass lock from one interrupts-disabled spinlock to another 338 * 339 * Pass lock from one IRQ spinlock to another IRQ spinlock 340 * without enabling interrupts during the process. 341 * 342 * The first IRQ spinlock is supposed to be locked. 343 * 344 * @param unlock IRQ spinlock to be unlocked. 345 * @param lock IRQ spinlock to be locked. 346 * 347 */ 348 static inline void irq_spinlock_pass(irq_spinlock_t *unlock, 349 irq_spinlock_t *lock) 350 { 351 ASSERT_IRQ_SPINLOCK(interrupts_disabled(), unlock); 352 353 /* Pass guard from unlock to lock */ 354 bool guard = unlock->guard; 355 ipl_t ipl = unlock->ipl; 356 unlock->guard = false; 357 358 spinlock_unlock(&(unlock->lock)); 359 spinlock_lock(&(lock->lock)); 360 361 ASSERT_IRQ_SPINLOCK(!lock->guard, lock); 362 363 if (guard) { 364 lock->guard = true; 365 lock->ipl = ipl; 366 } 367 } 368 369 /** Hand-over-hand locking of interrupts-disabled spinlocks 370 * 371 * Implement hand-over-hand locking between two interrupts-disabled 372 * spinlocks without enabling interrupts during the process. 373 * 374 * The first IRQ spinlock is supposed to be locked. 375 * 376 * @param unlock IRQ spinlock to be unlocked. 377 * @param lock IRQ spinlock to be locked. 378 * 379 */ 380 static inline void irq_spinlock_exchange(irq_spinlock_t *unlock, 381 irq_spinlock_t *lock) 382 { 383 ASSERT_IRQ_SPINLOCK(interrupts_disabled(), unlock); 384 385 spinlock_lock(&(lock->lock)); 386 ASSERT_IRQ_SPINLOCK(!lock->guard, lock); 387 388 /* Pass guard from unlock to lock */ 389 if (unlock->guard) { 390 lock->guard = true; 391 lock->ipl = unlock->ipl; 392 unlock->guard = false; 393 } 394 395 spinlock_unlock(&(unlock->lock)); 396 } 397 172 398 #endif 173 399 174 #endif175 176 400 /** @} 177 401 */ -
kernel/generic/src/synch/spinlock.c
rb10e6e31 r2b4a9f26 128 128 void spinlock_unlock_debug(spinlock_t *lock) 129 129 { 130 ASSERT (atomic_get(&lock->val) != 0);130 ASSERT_SPINLOCK(atomic_get(&lock->val) != 0, lock); 131 131 132 132 /* … … 143 143 /** Lock spinlock conditionally 144 144 * 145 * Lock spinlock conditionally. 146 * If the spinlock is not available at the moment, 147 * signal failure. 145 * Lock spinlock conditionally. If the spinlock is not available 146 * at the moment, signal failure. 148 147 * 149 148 * @param lock Pointer to spinlock_t structure.
Note:
See TracChangeset
for help on using the changeset viewer.