Deleted Added
full compact
kern_rwlock.c (164246) kern_rwlock.c (167012)
1/*-
2 * Copyright (c) 2006 John Baldwin <jhb@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 18 unchanged lines hidden (view full) ---

27 * SUCH DAMAGE.
28 */
29
30/*
31 * Machine independent bits of reader/writer lock implementation.
32 */
33
34#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2006 John Baldwin <jhb@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 18 unchanged lines hidden (view full) ---

27 * SUCH DAMAGE.
28 */
29
30/*
31 * Machine independent bits of reader/writer lock implementation.
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD: head/sys/kern/kern_rwlock.c 164246 2006-11-13 05:41:46Z kmacy $");
35__FBSDID("$FreeBSD: head/sys/kern/kern_rwlock.c 167012 2007-02-26 08:26:44Z kmacy $");
36
37#include "opt_ddb.h"
38
39#include <sys/param.h>
40#include <sys/ktr.h>
41#include <sys/lock.h>
42#include <sys/mutex.h>
43#include <sys/proc.h>

--- 62 unchanged lines hidden (view full) ---

106 struct rw_args *args = arg;
107
108 rw_init(args->ra_rw, args->ra_desc);
109}
110
111void
112_rw_wlock(struct rwlock *rw, const char *file, int line)
113{
36
37#include "opt_ddb.h"
38
39#include <sys/param.h>
40#include <sys/ktr.h>
41#include <sys/lock.h>
42#include <sys/mutex.h>
43#include <sys/proc.h>

--- 62 unchanged lines hidden (view full) ---

106 struct rw_args *args = arg;
107
108 rw_init(args->ra_rw, args->ra_desc);
109}
110
111void
112_rw_wlock(struct rwlock *rw, const char *file, int line)
113{
114 uint64_t waitstart;
115
116 MPASS(curthread != NULL);
117 KASSERT(rw_wowner(rw) != curthread,
118 ("%s (%s): wlock already held @ %s:%d", __func__,
119 rw->rw_object.lo_name, file, line));
120 WITNESS_CHECKORDER(&rw->rw_object, LOP_NEWORDER | LOP_EXCLUSIVE, file,
121 line);
114
115 MPASS(curthread != NULL);
116 KASSERT(rw_wowner(rw) != curthread,
117 ("%s (%s): wlock already held @ %s:%d", __func__,
118 rw->rw_object.lo_name, file, line));
119 WITNESS_CHECKORDER(&rw->rw_object, LOP_NEWORDER | LOP_EXCLUSIVE, file,
120 line);
122 lock_profile_waitstart(&waitstart);
123 __rw_wlock(rw, curthread, file, line);
121 __rw_wlock(rw, curthread, file, line);
124 lock_profile_obtain_lock_success(&rw->rw_object, waitstart, file, line);
125 LOCK_LOG_LOCK("WLOCK", &rw->rw_object, 0, 0, file, line);
126 WITNESS_LOCK(&rw->rw_object, LOP_EXCLUSIVE, file, line);
127 curthread->td_locks++;
128}
129
130void
131_rw_wunlock(struct rwlock *rw, const char *file, int line)
132{

--- 28 unchanged lines hidden (view full) ---

161 * that we currently allow for read locks to recurse and we
162 * don't keep track of all the holders of read locks. Thus, if
163 * we were to block readers once a writer blocked and a reader
164 * tried to recurse on their reader lock after a writer had
165 * blocked we would end up in a deadlock since the reader would
166 * be blocked on the writer, and the writer would be blocked
167 * waiting for the reader to release its original read lock.
168 */
122 LOCK_LOG_LOCK("WLOCK", &rw->rw_object, 0, 0, file, line);
123 WITNESS_LOCK(&rw->rw_object, LOP_EXCLUSIVE, file, line);
124 curthread->td_locks++;
125}
126
127void
128_rw_wunlock(struct rwlock *rw, const char *file, int line)
129{

--- 28 unchanged lines hidden (view full) ---

158 * that we currently allow for read locks to recurse and we
159 * don't keep track of all the holders of read locks. Thus, if
160 * we were to block readers once a writer blocked and a reader
161 * tried to recurse on their reader lock after a writer had
162 * blocked we would end up in a deadlock since the reader would
163 * be blocked on the writer, and the writer would be blocked
164 * waiting for the reader to release its original read lock.
165 */
169 lock_profile_waitstart(&waitstart);
170 for (;;) {
171 /*
172 * Handle the easy case. If no other thread has a write
173 * lock, then try to bump up the count of read locks. Note
174 * that we have to preserve the current state of the
175 * RW_LOCK_WRITE_WAITERS flag. If we fail to acquire a
176 * read lock, then rw_lock must have changed, so restart
177 * the loop. Note that this handles the case of a

--- 6 unchanged lines hidden (view full) ---

184 /*
185 * The RW_LOCK_READ_WAITERS flag should only be set
186 * if another thread currently holds a write lock,
187 * and in that case RW_LOCK_READ should be clear.
188 */
189 MPASS((x & RW_LOCK_READ_WAITERS) == 0);
190 if (atomic_cmpset_acq_ptr(&rw->rw_lock, x,
191 x + RW_ONE_READER)) {
166 for (;;) {
167 /*
168 * Handle the easy case. If no other thread has a write
169 * lock, then try to bump up the count of read locks. Note
170 * that we have to preserve the current state of the
171 * RW_LOCK_WRITE_WAITERS flag. If we fail to acquire a
172 * read lock, then rw_lock must have changed, so restart
173 * the loop. Note that this handles the case of a

--- 6 unchanged lines hidden (view full) ---

180 /*
181 * The RW_LOCK_READ_WAITERS flag should only be set
182 * if another thread currently holds a write lock,
183 * and in that case RW_LOCK_READ should be clear.
184 */
185 MPASS((x & RW_LOCK_READ_WAITERS) == 0);
186 if (atomic_cmpset_acq_ptr(&rw->rw_lock, x,
187 x + RW_ONE_READER)) {
192 lock_profile_obtain_lock_success(&rw->rw_object, waitstart, file, line);
188 lock_profile_obtain_lock_success(&rw->rw_object, contested, waitstart, file, line);
193 if (LOCK_LOG_TEST(&rw->rw_object, 0))
194 CTR4(KTR_LOCK,
195 "%s: %p succeed %p -> %p", __func__,
196 rw, (void *)x,
197 (void *)(x + RW_ONE_READER));
198 break;
199 }
189 if (LOCK_LOG_TEST(&rw->rw_object, 0))
190 CTR4(KTR_LOCK,
191 "%s: %p succeed %p -> %p", __func__,
192 rw, (void *)x,
193 (void *)(x + RW_ONE_READER));
194 break;
195 }
196 lock_profile_obtain_lock_failed(&rw->rw_object, &contested, &waitstart);
200 cpu_spinwait();
197 cpu_spinwait();
201 lock_profile_obtain_lock_failed(&rw->rw_object, &contested);
202 continue;
203 }
204
205 /*
206 * Okay, now it's the hard case. Some other thread already
207 * has a write lock, so acquire the turnstile lock so we can
208 * begin the process of blocking.
209 */

--- 32 unchanged lines hidden (view full) ---

242#ifdef SMP
243 /*
244 * If the owner is running on another CPU, spin until
245 * the owner stops running or the state of the lock
246 * changes.
247 */
248 owner = (struct thread *)RW_OWNER(x);
249 if (TD_IS_RUNNING(owner)) {
198 continue;
199 }
200
201 /*
202 * Okay, now it's the hard case. Some other thread already
203 * has a write lock, so acquire the turnstile lock so we can
204 * begin the process of blocking.
205 */

--- 32 unchanged lines hidden (view full) ---

238#ifdef SMP
239 /*
240 * If the owner is running on another CPU, spin until
241 * the owner stops running or the state of the lock
242 * changes.
243 */
244 owner = (struct thread *)RW_OWNER(x);
245 if (TD_IS_RUNNING(owner)) {
250 lock_profile_obtain_lock_failed(&rw->rw_object, &contested);
246 lock_profile_obtain_lock_failed(&rw->rw_object, &contested, &waitstart);
251 turnstile_release(&rw->rw_object);
252 if (LOCK_LOG_TEST(&rw->rw_object, 0))
253 CTR3(KTR_LOCK, "%s: spinning on %p held by %p",
254 __func__, rw, owner);
255 while ((struct thread*)RW_OWNER(rw->rw_lock)== owner &&
256 TD_IS_RUNNING(owner))
257 cpu_spinwait();
258 continue;

--- 147 unchanged lines hidden (view full) ---

406 * read or write lock.
407 */
408void
409_rw_wlock_hard(struct rwlock *rw, uintptr_t tid, const char *file, int line)
410{
411#ifdef SMP
412 volatile struct thread *owner;
413#endif
247 turnstile_release(&rw->rw_object);
248 if (LOCK_LOG_TEST(&rw->rw_object, 0))
249 CTR3(KTR_LOCK, "%s: spinning on %p held by %p",
250 __func__, rw, owner);
251 while ((struct thread*)RW_OWNER(rw->rw_lock)== owner &&
252 TD_IS_RUNNING(owner))
253 cpu_spinwait();
254 continue;

--- 147 unchanged lines hidden (view full) ---

402 * read or write lock.
403 */
404void
405_rw_wlock_hard(struct rwlock *rw, uintptr_t tid, const char *file, int line)
406{
407#ifdef SMP
408 volatile struct thread *owner;
409#endif
414 int contested;
415 uintptr_t v;
416
417 if (LOCK_LOG_TEST(&rw->rw_object, 0))
418 CTR5(KTR_LOCK, "%s: %s contested (lock=%p) at %s:%d", __func__,
419 rw->rw_object.lo_name, (void *)rw->rw_lock, file, line);
420
421 while (!_rw_write_lock(rw, tid)) {
422 turnstile_lock(&rw->rw_object);

--- 25 unchanged lines hidden (view full) ---

448 tid | RW_LOCK_WRITE_WAITERS)) {
449 turnstile_claim(&rw->rw_object);
450 CTR2(KTR_LOCK, "%s: %p claimed by new writer",
451 __func__, rw);
452 break;
453 }
454 turnstile_release(&rw->rw_object);
455 cpu_spinwait();
410 uintptr_t v;
411
412 if (LOCK_LOG_TEST(&rw->rw_object, 0))
413 CTR5(KTR_LOCK, "%s: %s contested (lock=%p) at %s:%d", __func__,
414 rw->rw_object.lo_name, (void *)rw->rw_lock, file, line);
415
416 while (!_rw_write_lock(rw, tid)) {
417 turnstile_lock(&rw->rw_object);

--- 25 unchanged lines hidden (view full) ---

443 tid | RW_LOCK_WRITE_WAITERS)) {
444 turnstile_claim(&rw->rw_object);
445 CTR2(KTR_LOCK, "%s: %p claimed by new writer",
446 __func__, rw);
447 break;
448 }
449 turnstile_release(&rw->rw_object);
450 cpu_spinwait();
456 lock_profile_obtain_lock_failed(&rw->rw_object, &contested);
457 continue;
458 }
459
460 /*
461 * If the RW_LOCK_WRITE_WAITERS flag isn't set, then try to
462 * set it. If we fail to set it, then loop back and try
463 * again.
464 */
465 if (!(v & RW_LOCK_WRITE_WAITERS)) {
466 if (!atomic_cmpset_ptr(&rw->rw_lock, v,
467 v | RW_LOCK_WRITE_WAITERS)) {
468 turnstile_release(&rw->rw_object);
469 cpu_spinwait();
451 continue;
452 }
453
454 /*
455 * If the RW_LOCK_WRITE_WAITERS flag isn't set, then try to
456 * set it. If we fail to set it, then loop back and try
457 * again.
458 */
459 if (!(v & RW_LOCK_WRITE_WAITERS)) {
460 if (!atomic_cmpset_ptr(&rw->rw_lock, v,
461 v | RW_LOCK_WRITE_WAITERS)) {
462 turnstile_release(&rw->rw_object);
463 cpu_spinwait();
470 lock_profile_obtain_lock_failed(&rw->rw_object, &contested);
471 continue;
472 }
473 if (LOCK_LOG_TEST(&rw->rw_object, 0))
474 CTR2(KTR_LOCK, "%s: %p set write waiters flag",
475 __func__, rw);
476 }
477
478#ifdef SMP
479 /*
480 * If the lock is write locked and the owner is
481 * running on another CPU, spin until the owner stops
482 * running or the state of the lock changes.
483 */
484 owner = (struct thread *)RW_OWNER(v);
485 if (!(v & RW_LOCK_READ) && TD_IS_RUNNING(owner)) {
464 continue;
465 }
466 if (LOCK_LOG_TEST(&rw->rw_object, 0))
467 CTR2(KTR_LOCK, "%s: %p set write waiters flag",
468 __func__, rw);
469 }
470
471#ifdef SMP
472 /*
473 * If the lock is write locked and the owner is
474 * running on another CPU, spin until the owner stops
475 * running or the state of the lock changes.
476 */
477 owner = (struct thread *)RW_OWNER(v);
478 if (!(v & RW_LOCK_READ) && TD_IS_RUNNING(owner)) {
486 lock_profile_obtain_lock_failed(&rw->rw_object, &contested);
487 turnstile_release(&rw->rw_object);
488 if (LOCK_LOG_TEST(&rw->rw_object, 0))
489 CTR3(KTR_LOCK, "%s: spinning on %p held by %p",
490 __func__, rw, owner);
491 while ((struct thread*)RW_OWNER(rw->rw_lock)== owner &&
492 TD_IS_RUNNING(owner))
493 cpu_spinwait();
494 continue;

--- 344 unchanged lines hidden ---
479 turnstile_release(&rw->rw_object);
480 if (LOCK_LOG_TEST(&rw->rw_object, 0))
481 CTR3(KTR_LOCK, "%s: spinning on %p held by %p",
482 __func__, rw, owner);
483 while ((struct thread*)RW_OWNER(rw->rw_lock)== owner &&
484 TD_IS_RUNNING(owner))
485 cpu_spinwait();
486 continue;

--- 344 unchanged lines hidden ---