diff options
author | davide <davide@FreeBSD.org> | 2012-03-16 20:32:11 +0000 |
---|---|---|
committer | davide <davide@FreeBSD.org> | 2012-03-16 20:32:11 +0000 |
commit | cd0c342e57c366c5630617a925171a6b0e6b0cec (patch) | |
tree | a51bea01da15cf0d2423ee72b8a1d50f80612fdf /sys/kern/kern_umtx.c | |
parent | 9c671fcacaa05105013becd8a9a70514228bb3fd (diff) | |
download | FreeBSD-src-cd0c342e57c366c5630617a925171a6b0e6b0cec.zip FreeBSD-src-cd0c342e57c366c5630617a925171a6b0e6b0cec.tar.gz |
Add rudimentary profiling of the hash table used in the in the umtx code to
hold active lock queues.
Reviewed by: attilio
Approved by: davidxu, gnn (mentor)
MFC after: 3 weeks
Diffstat (limited to 'sys/kern/kern_umtx.c')
-rw-r--r-- | sys/kern/kern_umtx.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c index 3888ce9..28eaf81 100644 --- a/sys/kern/kern_umtx.c +++ b/sys/kern/kern_umtx.c @@ -29,6 +29,8 @@ __FBSDID("$FreeBSD$"); #include "opt_compat.h" +#include "opt_umtx_profiling.h" + #include <sys/param.h> #include <sys/kernel.h> #include <sys/limits.h> @@ -154,6 +156,10 @@ struct umtxq_chain { /* All PI in the list */ TAILQ_HEAD(,umtx_pi) uc_pi_list; +#ifdef UMTX_PROFILING + int length; + int max_length; +#endif }; #define UMTXQ_LOCKED_ASSERT(uc) mtx_assert(&(uc)->uc_lock, MA_OWNED) @@ -190,6 +196,12 @@ static SYSCTL_NODE(_debug, OID_AUTO, umtx, CTLFLAG_RW, 0, "umtx debug"); SYSCTL_INT(_debug_umtx, OID_AUTO, umtx_pi_allocated, CTLFLAG_RD, &umtx_pi_allocated, 0, "Allocated umtx_pi"); +#ifdef UMTX_PROFILING +static long max_length; +SYSCTL_LONG(_debug_umtx, OID_AUTO, max_length, CTLFLAG_RD, &max_length, 0, "max_length"); +static SYSCTL_NODE(_debug_umtx, OID_AUTO, chains, CTLFLAG_RD, 0, "umtx chain stats"); +#endif + static void umtxq_sysinit(void *); static void umtxq_hash(struct umtx_key *key); static struct umtxq_chain *umtxq_getchain(struct umtx_key *key); @@ -215,6 +227,27 @@ SYSINIT(umtx, SI_SUB_EVENTHANDLER+1, SI_ORDER_MIDDLE, umtxq_sysinit, NULL); static struct mtx umtx_lock; +#ifdef UMTX_PROFILING +static void +umtx_init_profiling(void) +{ + struct sysctl_oid *chain_oid; + char chain_name[10]; + int i; + + for (i = 0; i < UMTX_CHAINS; ++i) { + snprintf(chain_name, sizeof(chain_name), "%d", i); + chain_oid = SYSCTL_ADD_NODE(NULL, + SYSCTL_STATIC_CHILDREN(_debug_umtx_chains), OID_AUTO, + chain_name, CTLFLAG_RD, NULL, "umtx hash stats"); + SYSCTL_ADD_INT(NULL, SYSCTL_CHILDREN(chain_oid), OID_AUTO, + "max_length0", CTLFLAG_RD, &umtxq_chains[0][i].max_length, 0, NULL); + SYSCTL_ADD_INT(NULL, SYSCTL_CHILDREN(chain_oid), OID_AUTO, + "max_length1", CTLFLAG_RD, &umtxq_chains[1][i].max_length, 0, NULL); + } +} +#endif + static void umtxq_sysinit(void *arg __unused) { @@ -232,8 +265,15 @@ umtxq_sysinit(void *arg __unused) TAILQ_INIT(&umtxq_chains[i][j].uc_pi_list); umtxq_chains[i][j].uc_busy = 0; umtxq_chains[i][j].uc_waiters = 0; + #ifdef UMTX_PROFILING + umtxq_chains[i][j].length = 0; + umtxq_chains[i][j].max_length = 0; + #endif } } + #ifdef UMTX_PROFILING + umtx_init_profiling(); + #endif mtx_init(&umtx_lock, "umtx lock", NULL, MTX_SPIN); EVENTHANDLER_REGISTER(process_exec, umtx_exec_hook, NULL, EVENTHANDLER_PRI_ANY); @@ -384,6 +424,14 @@ umtxq_insert_queue(struct umtx_q *uq, int q) TAILQ_INSERT_TAIL(&uh->head, uq, uq_link); uh->length++; + #ifdef UMTX_PROFILING + uc->length++; + if (uc->length > uc->max_length) { + uc->max_length = uc->length; + if (uc->max_length > max_length) + max_length = uc->max_length; + } + #endif uq->uq_flags |= UQF_UMTXQ; uq->uq_cur_queue = uh; return; @@ -401,6 +449,9 @@ umtxq_remove_queue(struct umtx_q *uq, int q) uh = uq->uq_cur_queue; TAILQ_REMOVE(&uh->head, uq, uq_link); uh->length--; + #ifdef UMTX_PROFILING + uc->length--; + #endif uq->uq_flags &= ~UQF_UMTXQ; if (TAILQ_EMPTY(&uh->head)) { KASSERT(uh->length == 0, |