Date: Mon, 26 Jun 2006 20:54:13 GMT From: Kip Macy <kmacy@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 100089 for review Message-ID: <200606262054.k5QKsDq7022302@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=100089 Change 100089 by kmacy@kmacy_storage:sun4v_work_sleepq on 2006/06/26 20:53:51 add profiling for rwlocks not convinced of correctness as there don't appear to be any contended rwlocks on my workloads Affected files ... .. //depot/projects/kmacy_sun4v/src/sys/kern/kern_rwlock.c#4 edit Differences ... ==== //depot/projects/kmacy_sun4v/src/sys/kern/kern_rwlock.c#4 (text+ko) ==== @@ -44,7 +44,7 @@ #include <sys/rwlock.h> #include <sys/systm.h> #include <sys/turnstile.h> - +#include <sys/lock_profile.h> #include <machine/cpu.h> #ifdef DDB @@ -80,12 +80,19 @@ #define _rw_assert(rw, what, file, line) #endif +#ifdef SMP +#define smp_turnstile_valid(obj) (turnstile_lookup((obj)) != NULL) +#else +#define smp_turnstile(obj) +#endif + void rw_init(struct rwlock *rw, const char *name) { rw->rw_lock = RW_UNLOCKED; + lock_profile_init(&rw->rw_object, name); lock_init(&rw->rw_object, &lock_class_rw, name, NULL, LO_WITNESS | LO_RECURSABLE | LO_UPGRADABLE); } @@ -95,6 +102,7 @@ { KASSERT(rw->rw_lock == RW_UNLOCKED, ("rw lock not unlocked")); + lock_profile_destroy(&rw->rw_object); lock_destroy(&rw->rw_object); } @@ -109,14 +117,17 @@ void _rw_wlock(struct rwlock *rw, const char *file, int line) { - + uint64_t waitstart; + MPASS(curthread != NULL); KASSERT(rw_wowner(rw) != curthread, ("%s (%s): wlock already held @ %s:%d", __func__, rw->rw_object.lo_name, file, line)); WITNESS_CHECKORDER(&rw->rw_object, LOP_NEWORDER | LOP_EXCLUSIVE, file, line); + lock_profile_waitstart(&waitstart); __rw_wlock(rw, curthread, file, line); + lock_profile_obtain_lock_success(&rw->rw_object, waitstart, file, line); LOCK_LOG_LOCK("WLOCK", &rw->rw_object, 0, 0, file, line); WITNESS_LOCK(&rw->rw_object, LOP_EXCLUSIVE, file, line); } @@ -129,6 +140,7 @@ _rw_assert(rw, RA_WLOCKED, file, line); WITNESS_UNLOCK(&rw->rw_object, LOP_EXCLUSIVE, file, line); LOCK_LOG_LOCK("WUNLOCK", &rw->rw_object, 0, 0, file, line); + lock_profile_release_lock(&rw->rw_object); __rw_wunlock(rw, curthread, file, line); } @@ -139,6 +151,8 @@ volatile struct thread *owner; #endif uintptr_t x; + uint64_t waitstart; + int contested; KASSERT(rw_wowner(rw) != curthread, ("%s (%s): wlock already held @ %s:%d", __func__, @@ -156,6 +170,7 @@ * be blocked on the writer, and the writer would be blocked * waiting for the reader to release its original read lock. */ + lock_profile_waitstart(&waitstart); for (;;) { /* * Handle the easy case. If no other thread has a write @@ -169,7 +184,6 @@ */ x = rw->rw_lock; if (x & RW_LOCK_READ) { - /* * The RW_LOCK_READ_WAITERS flag should only be set * if another thread currently holds a write lock, @@ -178,6 +192,9 @@ MPASS((x & RW_LOCK_READ_WAITERS) == 0); if (atomic_cmpset_acq_ptr(&rw->rw_lock, x, x + RW_ONE_READER)) { + if ((x & ((1<<RW_READERS_SHIFT)-1)) == 0) + lock_profile_obtain_lock_success(&rw->rw_object, waitstart, file, line); + if (LOCK_LOG_TEST(&rw->rw_object, 0)) CTR4(KTR_LOCK, "%s: %p succeed %p -> %p", __func__, @@ -186,6 +203,7 @@ break; } cpu_spinwait(); + lock_profile_obtain_lock_failed(&rw->rw_object, &contested); continue; } @@ -234,6 +252,7 @@ */ owner = (struct thread *)RW_OWNER(x); if (TD_IS_RUNNING(owner)) { + lock_profile_obtain_lock_failed(&rw->rw_object, &contested); turnstile_release(&rw->rw_object); if (LOCK_LOG_TEST(&rw->rw_object, 0)) CTR3(KTR_LOCK, "%s: spinning on %p held by %p", @@ -279,7 +298,6 @@ LOCK_LOG_LOCK("RUNLOCK", &rw->rw_object, 0, 0, file, line); /* TODO: drop "owner of record" here. */ - for (;;) { /* * See if there is more than one read lock held. If so, @@ -297,7 +315,8 @@ break; } continue; - } + } else + lock_profile_release_lock(&rw->rw_object); /* * We should never have read waiters while at least one @@ -328,7 +347,8 @@ break; } continue; - } + } + /* * There should just be one reader with one or more @@ -394,6 +414,7 @@ volatile struct thread *owner; #endif uintptr_t v; + int contested; if (LOCK_LOG_TEST(&rw->rw_object, 0)) CTR5(KTR_LOCK, "%s: %s contested (lock=%p) at %s:%d", __func__, @@ -434,6 +455,7 @@ } turnstile_release(&rw->rw_object); cpu_spinwait(); + lock_profile_obtain_lock_failed(&rw->rw_object, &contested); continue; } @@ -447,6 +469,7 @@ v | RW_LOCK_WRITE_WAITERS)) { turnstile_release(&rw->rw_object); cpu_spinwait(); + lock_profile_obtain_lock_failed(&rw->rw_object, &contested); continue; } if (LOCK_LOG_TEST(&rw->rw_object, 0)) @@ -462,6 +485,7 @@ */ owner = (struct thread *)RW_OWNER(v); if (!(v & RW_LOCK_READ) && TD_IS_RUNNING(owner)) { + lock_profile_obtain_lock_failed(&rw->rw_object, &contested); turnstile_release(&rw->rw_object); if (LOCK_LOG_TEST(&rw->rw_object, 0)) CTR3(KTR_LOCK, "%s: spinning on %p held by %p", @@ -629,11 +653,7 @@ v = rw->rw_lock & RW_LOCK_WRITE_WAITERS; success = atomic_cmpset_acq_ptr(&rw->rw_lock, RW_READERS_LOCK(1) | v, tid | v); -#ifdef SMP - if (success && v && turnstile_lookup(&rw->rw_object) != NULL) -#else - if (success && v) -#endif + if (success && v && smp_turnstile_valid(&rw->rw_object)) turnstile_claim(&rw->rw_object); else turnstile_release(&rw->rw_object);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200606262054.k5QKsDq7022302>