1192853Ssson/*-
2192853Ssson * Copyright 2008-2009 Stacey Son <sson@FreeBSD.org>
3192853Ssson *
4192853Ssson * Redistribution and use in source and binary forms, with or without
5192853Ssson * modification, are permitted provided that the following conditions
6192853Ssson * are met:
7192853Ssson * 1. Redistributions of source code must retain the above copyright
8192853Ssson *    notice, this list of conditions and the following disclaimer.
9192853Ssson * 2. Redistributions in binary form must reproduce the above copyright
10192853Ssson *    notice, this list of conditions and the following disclaimer in the
11192853Ssson *    documentation and/or other materials provided with the distribution.
12192853Ssson *
13192853Ssson * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14192853Ssson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15192853Ssson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16192853Ssson * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17192853Ssson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18192853Ssson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19192853Ssson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20192853Ssson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21192853Ssson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22192853Ssson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23192853Ssson * SUCH DAMAGE.
24192853Ssson */
25192853Ssson
26285703Smarkj#include <sys/cdefs.h>
27285703Smarkj__FBSDID("$FreeBSD: stable/11/sys/kern/kern_lockstat.c 327409 2017-12-31 03:35:34Z mjg $");
28192853Ssson
29285703Smarkj#include <sys/param.h>
30315339Smjg#include <sys/systm.h>
31285664Smarkj#include <sys/lock.h>
32192853Ssson#include <sys/lockstat.h>
33285703Smarkj#include <sys/sdt.h>
34285664Smarkj#include <sys/time.h>
35192853Ssson
36285703SmarkjSDT_PROVIDER_DEFINE(lockstat);
37285703Smarkj
38285703SmarkjSDT_PROBE_DEFINE1(lockstat, , , adaptive__acquire, "struct mtx *");
39285703SmarkjSDT_PROBE_DEFINE1(lockstat, , , adaptive__release, "struct mtx *");
40285703SmarkjSDT_PROBE_DEFINE2(lockstat, , , adaptive__spin, "struct mtx *", "uint64_t");
41285703SmarkjSDT_PROBE_DEFINE2(lockstat, , , adaptive__block, "struct mtx *", "uint64_t");
42285703Smarkj
43285703SmarkjSDT_PROBE_DEFINE1(lockstat, , , spin__acquire, "struct mtx *");
44285703SmarkjSDT_PROBE_DEFINE1(lockstat, , , spin__release, "struct mtx *");
45285703SmarkjSDT_PROBE_DEFINE2(lockstat, , , spin__spin, "struct mtx *", "uint64_t");
46285703Smarkj
47285704SmarkjSDT_PROBE_DEFINE2(lockstat, , , rw__acquire, "struct rwlock *", "int");
48285704SmarkjSDT_PROBE_DEFINE2(lockstat, , , rw__release, "struct rwlock *", "int");
49285703SmarkjSDT_PROBE_DEFINE5(lockstat, , , rw__block, "struct rwlock *", "uint64_t", "int",
50285703Smarkj    "int", "int");
51285703SmarkjSDT_PROBE_DEFINE2(lockstat, , , rw__spin, "struct rwlock *", "uint64_t");
52285703SmarkjSDT_PROBE_DEFINE1(lockstat, , , rw__upgrade, "struct rwlock *");
53285703SmarkjSDT_PROBE_DEFINE1(lockstat, , , rw__downgrade, "struct rwlock *");
54285703Smarkj
55285704SmarkjSDT_PROBE_DEFINE2(lockstat, , , sx__acquire, "struct sx *", "int");
56285704SmarkjSDT_PROBE_DEFINE2(lockstat, , , sx__release, "struct sx *", "int");
57285703SmarkjSDT_PROBE_DEFINE5(lockstat, , , sx__block, "struct sx *", "uint64_t", "int",
58285703Smarkj    "int", "int");
59285703SmarkjSDT_PROBE_DEFINE2(lockstat, , , sx__spin, "struct sx *", "uint64_t");
60285703SmarkjSDT_PROBE_DEFINE1(lockstat, , , sx__upgrade, "struct sx *");
61285703SmarkjSDT_PROBE_DEFINE1(lockstat, , , sx__downgrade, "struct sx *");
62285703Smarkj
63285703SmarkjSDT_PROBE_DEFINE2(lockstat, , , thread__spin, "struct mtx *", "uint64_t");
64285703Smarkj
65327409Smjgvolatile int __read_frequently lockstat_enabled;
66192853Ssson
67192853Sssonuint64_t
68285664Smarkjlockstat_nsecs(struct lock_object *lo)
69192853Ssson{
70192853Ssson	struct bintime bt;
71192853Ssson	uint64_t ns;
72192853Ssson
73285663Smarkj	if (!lockstat_enabled)
74285663Smarkj		return (0);
75285664Smarkj	if ((lo->lo_flags & LO_NOPROFILE) != 0)
76285664Smarkj		return (0);
77285663Smarkj
78192853Ssson	binuptime(&bt);
79192853Ssson	ns = bt.sec * (uint64_t)1000000000;
80192853Ssson	ns += ((uint64_t)1000000000 * (uint32_t)(bt.frac >> 32)) >> 32;
81192853Ssson	return (ns);
82192853Ssson}
83