xref: /onnv-gate/usr/src/cmd/latencytop/common/latencytop.d (revision 11789:6c7658a179ca)
110673SKrishnendu.Sadhukhan@Sun.COM /*
210673SKrishnendu.Sadhukhan@Sun.COM  * CDDL HEADER START
310673SKrishnendu.Sadhukhan@Sun.COM  *
410673SKrishnendu.Sadhukhan@Sun.COM  * The contents of this file are subject to the terms of the
510673SKrishnendu.Sadhukhan@Sun.COM  * Common Development and Distribution License (the "License").
610673SKrishnendu.Sadhukhan@Sun.COM  * You may not use this file except in compliance with the License.
710673SKrishnendu.Sadhukhan@Sun.COM  *
810673SKrishnendu.Sadhukhan@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910673SKrishnendu.Sadhukhan@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1010673SKrishnendu.Sadhukhan@Sun.COM  * See the License for the specific language governing permissions
1110673SKrishnendu.Sadhukhan@Sun.COM  * and limitations under the License.
1210673SKrishnendu.Sadhukhan@Sun.COM  *
1310673SKrishnendu.Sadhukhan@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1410673SKrishnendu.Sadhukhan@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510673SKrishnendu.Sadhukhan@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1610673SKrishnendu.Sadhukhan@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1710673SKrishnendu.Sadhukhan@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1810673SKrishnendu.Sadhukhan@Sun.COM  *
1910673SKrishnendu.Sadhukhan@Sun.COM  * CDDL HEADER END
2010673SKrishnendu.Sadhukhan@Sun.COM  */
2110673SKrishnendu.Sadhukhan@Sun.COM /*
2210673SKrishnendu.Sadhukhan@Sun.COM  * Copyright (c) 2008-2009, Intel Corporation.
2310673SKrishnendu.Sadhukhan@Sun.COM  * All Rights Reserved.
2410673SKrishnendu.Sadhukhan@Sun.COM  */
2510673SKrishnendu.Sadhukhan@Sun.COM 
2610673SKrishnendu.Sadhukhan@Sun.COM #define	MAX_TAG		8
2710673SKrishnendu.Sadhukhan@Sun.COM #define	MAX_STACK	64
2810673SKrishnendu.Sadhukhan@Sun.COM 
2910673SKrishnendu.Sadhukhan@Sun.COM #pragma D option aggsize=8m
3010673SKrishnendu.Sadhukhan@Sun.COM #pragma D option bufsize=16m
3110673SKrishnendu.Sadhukhan@Sun.COM #pragma D option dynvarsize=16m
3210673SKrishnendu.Sadhukhan@Sun.COM #pragma D option aggrate=0
3310673SKrishnendu.Sadhukhan@Sun.COM #pragma D option stackframes=MAX_STACK
3410673SKrishnendu.Sadhukhan@Sun.COM /*
3510673SKrishnendu.Sadhukhan@Sun.COM  * Our D script needs to compile even if some of the TRANSLATE probes cannot
3610673SKrishnendu.Sadhukhan@Sun.COM  * be found. Missing probes can be caused by older kernel, different
3710673SKrishnendu.Sadhukhan@Sun.COM  * architecture, unloaded modules etc.
3810673SKrishnendu.Sadhukhan@Sun.COM  */
3910673SKrishnendu.Sadhukhan@Sun.COM #pragma D option zdefs
4010673SKrishnendu.Sadhukhan@Sun.COM 
4110673SKrishnendu.Sadhukhan@Sun.COM #if defined(ENABLE_SCHED)
42*11789SKrishnendu.Sadhukhan@Sun.COM #if defined(TRACE_PID)
43*11789SKrishnendu.Sadhukhan@Sun.COM #define TRACE_FILTER    / pid == 0 || pid == TRACE_PID /
44*11789SKrishnendu.Sadhukhan@Sun.COM #define TRACE_FILTER_COND(a)    / (pid == 0 || pid == TRACE_PID) && (a) /
45*11789SKrishnendu.Sadhukhan@Sun.COM #elif defined(TRACE_PGID)
46*11789SKrishnendu.Sadhukhan@Sun.COM #define TRACE_FILTER    / pid == 0 || curpsinfo->pr_pgid == TRACE_PGID /
47*11789SKrishnendu.Sadhukhan@Sun.COM #define TRACE_FILTER_COND(a)
48*11789SKrishnendu.Sadhukhan@Sun.COM     / (pid == 0 || curpsinfo->pr_pgid == TRACE_PGID) && (a) /
49*11789SKrishnendu.Sadhukhan@Sun.COM #else
5010673SKrishnendu.Sadhukhan@Sun.COM #define TRACE_FILTER
5110673SKrishnendu.Sadhukhan@Sun.COM #define TRACE_FILTER_COND(a)	/ (a) /
52*11789SKrishnendu.Sadhukhan@Sun.COM #endif
53*11789SKrishnendu.Sadhukhan@Sun.COM #else	/* ENABLE_SCHED */
54*11789SKrishnendu.Sadhukhan@Sun.COM #if defined(TRACE_PID)
55*11789SKrishnendu.Sadhukhan@Sun.COM #define TRACE_FILTER    / pid == TRACE_PID /
56*11789SKrishnendu.Sadhukhan@Sun.COM #define TRACE_FILTER_COND(a)    / (pid == TRACE_PID) && (a) /
57*11789SKrishnendu.Sadhukhan@Sun.COM #elif defined(TRACE_PGID)
58*11789SKrishnendu.Sadhukhan@Sun.COM #define TRACE_FILTER    / curpsinfo->pr_pgid == TRACE_PGID /
59*11789SKrishnendu.Sadhukhan@Sun.COM #define TRACE_FILTER_COND(a)    / (curpsinfo->pr_pgid == TRACE_PGID) && (a) /
6010673SKrishnendu.Sadhukhan@Sun.COM #else
6110673SKrishnendu.Sadhukhan@Sun.COM #define TRACE_FILTER	/ pid != 0 /
62*11789SKrishnendu.Sadhukhan@Sun.COM #define TRACE_FILTER_COND(a)    / (pid != 0) && (a) /
6310673SKrishnendu.Sadhukhan@Sun.COM #endif
64*11789SKrishnendu.Sadhukhan@Sun.COM #endif /* ENABLE_SCHED */
6510673SKrishnendu.Sadhukhan@Sun.COM 
6610673SKrishnendu.Sadhukhan@Sun.COM /* Threshold to filter WAKEABLE latencies. */
6710673SKrishnendu.Sadhukhan@Sun.COM #define FILTER_THRESHOLD	5000000
6810673SKrishnendu.Sadhukhan@Sun.COM /* From thread.h */
6910673SKrishnendu.Sadhukhan@Sun.COM #define T_WAKEABLE		2
7010673SKrishnendu.Sadhukhan@Sun.COM 
7110673SKrishnendu.Sadhukhan@Sun.COM /*
7210673SKrishnendu.Sadhukhan@Sun.COM  * This array is used to store timestamp of when threads are enqueued
7310673SKrishnendu.Sadhukhan@Sun.COM  * to dispatch queue.
7410673SKrishnendu.Sadhukhan@Sun.COM  * self-> is not accessible when enqueue happens.
7510673SKrishnendu.Sadhukhan@Sun.COM  */
7610673SKrishnendu.Sadhukhan@Sun.COM unsigned long long lt_timestamps[int, int];
7710673SKrishnendu.Sadhukhan@Sun.COM 
7810673SKrishnendu.Sadhukhan@Sun.COM self unsigned int lt_is_block_wakeable;
7910673SKrishnendu.Sadhukhan@Sun.COM self unsigned long long lt_sleep_start;
8010673SKrishnendu.Sadhukhan@Sun.COM self unsigned long long lt_sleep_duration;
8110673SKrishnendu.Sadhukhan@Sun.COM self unsigned long long lt_sch_delay;
8210673SKrishnendu.Sadhukhan@Sun.COM self unsigned int lt_counter;		/* only used in low overhead */
8310673SKrishnendu.Sadhukhan@Sun.COM self unsigned long long lt_timestamp;	/* only used in low overhead */
8410673SKrishnendu.Sadhukhan@Sun.COM self unsigned int lt_stackp;
8510673SKrishnendu.Sadhukhan@Sun.COM self unsigned int lt_prio[int];
8610673SKrishnendu.Sadhukhan@Sun.COM self string lt_cause[int];
8710673SKrishnendu.Sadhukhan@Sun.COM 
8810673SKrishnendu.Sadhukhan@Sun.COM this unsigned int priority;
8910673SKrishnendu.Sadhukhan@Sun.COM this string cause;
9010673SKrishnendu.Sadhukhan@Sun.COM 
9110673SKrishnendu.Sadhukhan@Sun.COM /*
9210673SKrishnendu.Sadhukhan@Sun.COM  * Clean up everything, otherwise we will run out of memory.
9310673SKrishnendu.Sadhukhan@Sun.COM  */
9410673SKrishnendu.Sadhukhan@Sun.COM proc:::lwp-exit
9510673SKrishnendu.Sadhukhan@Sun.COM {
9610673SKrishnendu.Sadhukhan@Sun.COM 	lt_timestamps[curpsinfo->pr_pid, curlwpsinfo->pr_lwpid] = 0;
9710673SKrishnendu.Sadhukhan@Sun.COM 
9810673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_sleep_start = 0;
9910673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_is_block_wakeable = 0;
10010673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_counter = 0;
10110673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_timestamp = 0;
10210673SKrishnendu.Sadhukhan@Sun.COM 
10310673SKrishnendu.Sadhukhan@Sun.COM 	/*
10410673SKrishnendu.Sadhukhan@Sun.COM 	 * Workaround: no way to clear associative array.
10510673SKrishnendu.Sadhukhan@Sun.COM 	 * We have to manually clear 0 ~ (MAX_TAG-1).
10610673SKrishnendu.Sadhukhan@Sun.COM 	 */
10710673SKrishnendu.Sadhukhan@Sun.COM 
10810673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_prio[0] = 0;
10910673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_prio[1] = 0;
11010673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_prio[2] = 0;
11110673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_prio[3] = 0;
11210673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_prio[4] = 0;
11310673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_prio[5] = 0;
11410673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_prio[6] = 0;
11510673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_prio[7] = 0;
11610673SKrishnendu.Sadhukhan@Sun.COM 
11710673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_cause[0] = 0;
11810673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_cause[1] = 0;
11910673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_cause[2] = 0;
12010673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_cause[3] = 0;
12110673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_cause[4] = 0;
12210673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_cause[5] = 0;
12310673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_cause[6] = 0;
12410673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_cause[7] = 0;
12510673SKrishnendu.Sadhukhan@Sun.COM }
12610673SKrishnendu.Sadhukhan@Sun.COM 
12710673SKrishnendu.Sadhukhan@Sun.COM #if !defined(ENABLE_LOW_OVERHEAD)
12810673SKrishnendu.Sadhukhan@Sun.COM /*
12910673SKrishnendu.Sadhukhan@Sun.COM  * Log timestamp when a thread is taken off the CPU.
13010673SKrishnendu.Sadhukhan@Sun.COM  */
13110673SKrishnendu.Sadhukhan@Sun.COM sched::resume:off-cpu
13210673SKrishnendu.Sadhukhan@Sun.COM TRACE_FILTER_COND(curlwpsinfo->pr_state == SSLEEP)
13310673SKrishnendu.Sadhukhan@Sun.COM {
13410673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_sleep_start = timestamp;
13510673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_is_block_wakeable = curthread->t_flag & T_WAKEABLE;
13610673SKrishnendu.Sadhukhan@Sun.COM 
13710673SKrishnendu.Sadhukhan@Sun.COM 	lt_timestamps[curpsinfo->pr_pid, curlwpsinfo->pr_lwpid] =
13810673SKrishnendu.Sadhukhan@Sun.COM 	    self->lt_sleep_start;
13910673SKrishnendu.Sadhukhan@Sun.COM }
14010673SKrishnendu.Sadhukhan@Sun.COM 
14110673SKrishnendu.Sadhukhan@Sun.COM /*
14210673SKrishnendu.Sadhukhan@Sun.COM  * Log timestamp when a thread is put on a dispatch queue and becomes runnable.
14310673SKrishnendu.Sadhukhan@Sun.COM  */
14410673SKrishnendu.Sadhukhan@Sun.COM sched:::enqueue
14510673SKrishnendu.Sadhukhan@Sun.COM /lt_timestamps[args[1]->pr_pid, args[0]->pr_lwpid] != 0/
14610673SKrishnendu.Sadhukhan@Sun.COM {
14710673SKrishnendu.Sadhukhan@Sun.COM 	lt_timestamps[args[1]->pr_pid, args[0]->pr_lwpid] = timestamp;
14810673SKrishnendu.Sadhukhan@Sun.COM }
14910673SKrishnendu.Sadhukhan@Sun.COM 
15010673SKrishnendu.Sadhukhan@Sun.COM /*
15110673SKrishnendu.Sadhukhan@Sun.COM  * Calculate latency when the thread is actually on the CPU.
15210673SKrishnendu.Sadhukhan@Sun.COM  * This is necessary in order to get the right stack.
15310673SKrishnendu.Sadhukhan@Sun.COM  */
15410673SKrishnendu.Sadhukhan@Sun.COM this unsigned long long end;
15510673SKrishnendu.Sadhukhan@Sun.COM this unsigned long long now;
15610673SKrishnendu.Sadhukhan@Sun.COM sched::resume:on-cpu
15710673SKrishnendu.Sadhukhan@Sun.COM /self->lt_sleep_start != 0/
15810673SKrishnendu.Sadhukhan@Sun.COM {
15910673SKrishnendu.Sadhukhan@Sun.COM 	this->end = lt_timestamps[curpsinfo->pr_pid, curlwpsinfo->pr_lwpid];
16010673SKrishnendu.Sadhukhan@Sun.COM 	this->now = timestamp;
16110673SKrishnendu.Sadhukhan@Sun.COM 	lt_timestamps[curpsinfo->pr_pid, curlwpsinfo->pr_lwpid] = 0;
16210673SKrishnendu.Sadhukhan@Sun.COM 	this->end = (this->end != 0 && this->end != self->lt_sleep_start)
16310673SKrishnendu.Sadhukhan@Sun.COM 	    ? this->end : this->now;
16410673SKrishnendu.Sadhukhan@Sun.COM 
16510673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_sch_delay = this->now - this->end;
16610673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_sleep_duration = this->end - self->lt_sleep_start;
16710673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_sleep_start = 0;
16810673SKrishnendu.Sadhukhan@Sun.COM }
16910673SKrishnendu.Sadhukhan@Sun.COM 
17010673SKrishnendu.Sadhukhan@Sun.COM /*
17110673SKrishnendu.Sadhukhan@Sun.COM  * Filter: drop all "large" latency when it is interruptible, i.e., sleep()
17210673SKrishnendu.Sadhukhan@Sun.COM  * etc.
17310673SKrishnendu.Sadhukhan@Sun.COM  */
17410673SKrishnendu.Sadhukhan@Sun.COM #if defined(ENABLE_FILTER)
17510673SKrishnendu.Sadhukhan@Sun.COM sched::resume:on-cpu
17610673SKrishnendu.Sadhukhan@Sun.COM /self->lt_sleep_duration > FILTER_THRESHOLD &&
17710673SKrishnendu.Sadhukhan@Sun.COM   self->lt_is_block_wakeable != 0/
17810673SKrishnendu.Sadhukhan@Sun.COM {
17910673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_sch_delay = 0;
18010673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_sleep_duration = 0;
18110673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_is_block_wakeable = 0;
18210673SKrishnendu.Sadhukhan@Sun.COM }
18310673SKrishnendu.Sadhukhan@Sun.COM #endif /* defined(ENABLE_FILTER) */
18410673SKrishnendu.Sadhukhan@Sun.COM 
18510673SKrishnendu.Sadhukhan@Sun.COM /*
18610673SKrishnendu.Sadhukhan@Sun.COM  * Write sleep time to the aggregation.
18710673SKrishnendu.Sadhukhan@Sun.COM  * lt_sleep_duration is the duration between the time when a thread is taken
18810673SKrishnendu.Sadhukhan@Sun.COM  * off the CPU and the time when it is enqueued again.
18910673SKrishnendu.Sadhukhan@Sun.COM  */
19010673SKrishnendu.Sadhukhan@Sun.COM sched::resume:on-cpu
19110673SKrishnendu.Sadhukhan@Sun.COM /self->lt_sleep_duration != 0/
19210673SKrishnendu.Sadhukhan@Sun.COM {
19310673SKrishnendu.Sadhukhan@Sun.COM 	this->cause = self->lt_stackp > 0 ?
19410673SKrishnendu.Sadhukhan@Sun.COM 	    self->lt_cause[self->lt_stackp - 1] : "";
19510673SKrishnendu.Sadhukhan@Sun.COM 	this->priority = self->lt_stackp > 0 ?
19610673SKrishnendu.Sadhukhan@Sun.COM 	    self->lt_prio[self->lt_stackp - 1] : 0;
19710673SKrishnendu.Sadhukhan@Sun.COM 
19810673SKrishnendu.Sadhukhan@Sun.COM 	@lt_call_count[pid, tid, stack(), this->cause,
19910673SKrishnendu.Sadhukhan@Sun.COM 	    this->priority] = count();
20010673SKrishnendu.Sadhukhan@Sun.COM 	@lt_call_sum[pid, tid, stack(), this->cause,
20110673SKrishnendu.Sadhukhan@Sun.COM 	    this->priority] = sum(self->lt_sleep_duration);
20210673SKrishnendu.Sadhukhan@Sun.COM 	@lt_call_max[pid, tid, stack(),  this->cause,
20310673SKrishnendu.Sadhukhan@Sun.COM 	    this->priority] = max(self->lt_sleep_duration);
20410673SKrishnendu.Sadhukhan@Sun.COM 
20510673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_is_block_wakeable = 0;	/* Clear the flag to avoid leak */
20610673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_sleep_duration = 0;
20710673SKrishnendu.Sadhukhan@Sun.COM }
20810673SKrishnendu.Sadhukhan@Sun.COM 
20910673SKrishnendu.Sadhukhan@Sun.COM /*
21010673SKrishnendu.Sadhukhan@Sun.COM  * Write time spent in queue to the aggregation.
21110673SKrishnendu.Sadhukhan@Sun.COM  * lt_sch_delay is the interval between the time when a thread becomes
21210673SKrishnendu.Sadhukhan@Sun.COM  * runnable and the time when it is actually on the CPU.
21310673SKrishnendu.Sadhukhan@Sun.COM  */
21410673SKrishnendu.Sadhukhan@Sun.COM sched::resume:on-cpu
21510673SKrishnendu.Sadhukhan@Sun.COM /self->lt_sch_delay != 0/
21610673SKrishnendu.Sadhukhan@Sun.COM {
21710673SKrishnendu.Sadhukhan@Sun.COM 	@lt_named_count[pid, tid, "Wait for available CPU"] = count();
21810673SKrishnendu.Sadhukhan@Sun.COM 	@lt_named_sum[pid, tid, "Wait for available CPU"] =
21910673SKrishnendu.Sadhukhan@Sun.COM 	    sum(self->lt_sch_delay);
22010673SKrishnendu.Sadhukhan@Sun.COM 	@lt_named_max[pid, tid, "Wait for available CPU"] =
22110673SKrishnendu.Sadhukhan@Sun.COM 	    max(self->lt_sch_delay);
22210673SKrishnendu.Sadhukhan@Sun.COM 
22310673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_sch_delay = 0;
22410673SKrishnendu.Sadhukhan@Sun.COM }
22510673SKrishnendu.Sadhukhan@Sun.COM 
22610673SKrishnendu.Sadhukhan@Sun.COM /*
22710673SKrishnendu.Sadhukhan@Sun.COM  * Probes to track latency caused by spinning on a lock.
22810673SKrishnendu.Sadhukhan@Sun.COM  */
22910673SKrishnendu.Sadhukhan@Sun.COM lockstat:::adaptive-spin
23010673SKrishnendu.Sadhukhan@Sun.COM TRACE_FILTER
23110673SKrishnendu.Sadhukhan@Sun.COM {
23210673SKrishnendu.Sadhukhan@Sun.COM 	@lt_named_count[pid, tid, "Adapt. lock spin"] = count();
23310673SKrishnendu.Sadhukhan@Sun.COM 	@lt_named_sum[pid, tid, "Adapt. lock spin"] = sum(arg1);
23410673SKrishnendu.Sadhukhan@Sun.COM 	@lt_named_max[pid, tid, "Adapt. lock spin"] = max(arg1);
23510673SKrishnendu.Sadhukhan@Sun.COM }
23610673SKrishnendu.Sadhukhan@Sun.COM 
23710673SKrishnendu.Sadhukhan@Sun.COM lockstat:::spin-spin
23810673SKrishnendu.Sadhukhan@Sun.COM TRACE_FILTER
23910673SKrishnendu.Sadhukhan@Sun.COM {
24010673SKrishnendu.Sadhukhan@Sun.COM 	@lt_named_count[pid, tid, "Spinlock spin"] = count();
24110673SKrishnendu.Sadhukhan@Sun.COM 	@lt_named_sum[pid, tid, "Spinlock spin"] = sum(arg1);
24210673SKrishnendu.Sadhukhan@Sun.COM 	@lt_named_max[pid, tid, "Spinlock spin"] = max(arg1);
24310673SKrishnendu.Sadhukhan@Sun.COM }
24410673SKrishnendu.Sadhukhan@Sun.COM 
24510673SKrishnendu.Sadhukhan@Sun.COM /*
24610673SKrishnendu.Sadhukhan@Sun.COM  * Probes to track latency caused by blocking on a lock.
24710673SKrishnendu.Sadhukhan@Sun.COM  */
24810673SKrishnendu.Sadhukhan@Sun.COM lockstat:::adaptive-block
24910673SKrishnendu.Sadhukhan@Sun.COM TRACE_FILTER
25010673SKrishnendu.Sadhukhan@Sun.COM {
25110673SKrishnendu.Sadhukhan@Sun.COM 	@lt_named_count[pid, tid, "#Adapt. lock block"] = count();
25210673SKrishnendu.Sadhukhan@Sun.COM 	@lt_named_sum[pid, tid, "#Adapt. lock block"] = sum(arg1);
25310673SKrishnendu.Sadhukhan@Sun.COM 	@lt_named_max[pid, tid, "#Adapt. lock block"] = max(arg1);
25410673SKrishnendu.Sadhukhan@Sun.COM }
25510673SKrishnendu.Sadhukhan@Sun.COM 
25610673SKrishnendu.Sadhukhan@Sun.COM lockstat:::rw-block
25710673SKrishnendu.Sadhukhan@Sun.COM TRACE_FILTER
25810673SKrishnendu.Sadhukhan@Sun.COM {
25910673SKrishnendu.Sadhukhan@Sun.COM 	@lt_named_count[pid, tid, "#RW. lock block"] = count();
26010673SKrishnendu.Sadhukhan@Sun.COM 	@lt_named_sum[pid, tid, "#RW. lock block"] = sum(arg1);
26110673SKrishnendu.Sadhukhan@Sun.COM 	@lt_named_max[pid, tid, "#RW. lock block"] = max(arg1);
26210673SKrishnendu.Sadhukhan@Sun.COM }
26310673SKrishnendu.Sadhukhan@Sun.COM 
26410673SKrishnendu.Sadhukhan@Sun.COM #if defined(ENABLE_SYNCOBJ)
26510673SKrishnendu.Sadhukhan@Sun.COM /*
26610673SKrishnendu.Sadhukhan@Sun.COM  * Probes to track latency caused by synchronization objects.
26710673SKrishnendu.Sadhukhan@Sun.COM  */
26810673SKrishnendu.Sadhukhan@Sun.COM this int stype;
26910673SKrishnendu.Sadhukhan@Sun.COM this unsigned long long wchan;
27010673SKrishnendu.Sadhukhan@Sun.COM this unsigned long long wtime;
27110673SKrishnendu.Sadhukhan@Sun.COM 
27210673SKrishnendu.Sadhukhan@Sun.COM sched:::wakeup
27310673SKrishnendu.Sadhukhan@Sun.COM /*
27410673SKrishnendu.Sadhukhan@Sun.COM  * Currently we are unable to track wakeup from sched, because all its LWP IDs
27510673SKrishnendu.Sadhukhan@Sun.COM  * are zero when we trace it and that makes lt_timestamps unusable.
27610673SKrishnendu.Sadhukhan@Sun.COM  */
27710673SKrishnendu.Sadhukhan@Sun.COM /args[1]->pr_pid != 0 &&
27810673SKrishnendu.Sadhukhan@Sun.COM     lt_timestamps[args[1]->pr_pid, args[0]->pr_lwpid] != 0/
27910673SKrishnendu.Sadhukhan@Sun.COM {
28010673SKrishnendu.Sadhukhan@Sun.COM 	this->stype = args[0]->pr_stype;
28110673SKrishnendu.Sadhukhan@Sun.COM 	this->wchan = args[0]->pr_wchan;
28210673SKrishnendu.Sadhukhan@Sun.COM 	/*
28310673SKrishnendu.Sadhukhan@Sun.COM 	 * We can use lt_timestamps[] here, because
28410673SKrishnendu.Sadhukhan@Sun.COM 	 * wakeup is always fired before enqueue.
28510673SKrishnendu.Sadhukhan@Sun.COM 	 * After enqueue, lt_timestamps[] will be overwritten.
28610673SKrishnendu.Sadhukhan@Sun.COM 	 */
28710673SKrishnendu.Sadhukhan@Sun.COM 	this->wtime = timestamp - lt_timestamps[args[1]->pr_pid,
28810673SKrishnendu.Sadhukhan@Sun.COM 	    args[0]->pr_lwpid];
28910673SKrishnendu.Sadhukhan@Sun.COM 
29010673SKrishnendu.Sadhukhan@Sun.COM 	@lt_sync_count[args[1]->pr_pid, args[0]->pr_lwpid, this->stype,
29110673SKrishnendu.Sadhukhan@Sun.COM 	    this->wchan] = count();
29210673SKrishnendu.Sadhukhan@Sun.COM 	@lt_sync_sum[args[1]->pr_pid, args[0]->pr_lwpid, this->stype,
29310673SKrishnendu.Sadhukhan@Sun.COM 	    this->wchan] = sum(this->wtime);
29410673SKrishnendu.Sadhukhan@Sun.COM 	@lt_sync_max[args[1]->pr_pid, args[0]->pr_lwpid, this->stype,
29510673SKrishnendu.Sadhukhan@Sun.COM 	    this->wchan] = max(this->wtime);
29610673SKrishnendu.Sadhukhan@Sun.COM }
29710673SKrishnendu.Sadhukhan@Sun.COM #endif /* defined(ENABLE_SYNCOBJ) */
29810673SKrishnendu.Sadhukhan@Sun.COM 
29910673SKrishnendu.Sadhukhan@Sun.COM #else /* !defined(ENABLE_LOW_OVERHEAD) */
30010673SKrishnendu.Sadhukhan@Sun.COM 
30110673SKrishnendu.Sadhukhan@Sun.COM /*
30210673SKrishnendu.Sadhukhan@Sun.COM  * This is the low overhead mode.
30310673SKrishnendu.Sadhukhan@Sun.COM  * In order to reduce the number of instructions executed during each
30410673SKrishnendu.Sadhukhan@Sun.COM  * off-cpu and on-cpu event, we do the following:
30510673SKrishnendu.Sadhukhan@Sun.COM  *
30610673SKrishnendu.Sadhukhan@Sun.COM  *	1. Use sampling and update aggregations only roughly 1/100 times
30710673SKrishnendu.Sadhukhan@Sun.COM  *		(SAMPLE_TIMES).
30810673SKrishnendu.Sadhukhan@Sun.COM  *	2. Do not track anything other than what is needed for "main" window.
30910673SKrishnendu.Sadhukhan@Sun.COM  *	3. Use as few thread local variables as possible.
31010673SKrishnendu.Sadhukhan@Sun.COM  */
31110673SKrishnendu.Sadhukhan@Sun.COM 
31210673SKrishnendu.Sadhukhan@Sun.COM #define SAMPLE_TIMES		100
31310673SKrishnendu.Sadhukhan@Sun.COM #define SAMPLE_THRESHOLD	50000000
31410673SKrishnendu.Sadhukhan@Sun.COM 
31510673SKrishnendu.Sadhukhan@Sun.COM /*
31610673SKrishnendu.Sadhukhan@Sun.COM  * Log timestamp when a thread is off CPU.
31710673SKrishnendu.Sadhukhan@Sun.COM  */
31810673SKrishnendu.Sadhukhan@Sun.COM sched::resume:off-cpu
31910673SKrishnendu.Sadhukhan@Sun.COM TRACE_FILTER_COND(curlwpsinfo->pr_state == SSLEEP)
32010673SKrishnendu.Sadhukhan@Sun.COM {
32110673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_timestamp = timestamp;
32210673SKrishnendu.Sadhukhan@Sun.COM #if defined(ENABLE_FILTER)
32310673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_is_block_wakeable = curthread->t_flag & T_WAKEABLE;
32410673SKrishnendu.Sadhukhan@Sun.COM #endif /* defined(ENABLE_FILTER) */
32510673SKrishnendu.Sadhukhan@Sun.COM }
32610673SKrishnendu.Sadhukhan@Sun.COM 
32710673SKrishnendu.Sadhukhan@Sun.COM /*
32810673SKrishnendu.Sadhukhan@Sun.COM  * Calculate latency when a thread is actually on the CPU.
32910673SKrishnendu.Sadhukhan@Sun.COM  */
33010673SKrishnendu.Sadhukhan@Sun.COM this int need_skip;
33110673SKrishnendu.Sadhukhan@Sun.COM sched::resume:on-cpu
33210673SKrishnendu.Sadhukhan@Sun.COM /self->lt_timestamp != 0/
33310673SKrishnendu.Sadhukhan@Sun.COM {
33410673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_timestamp = timestamp - self->lt_timestamp;
33510673SKrishnendu.Sadhukhan@Sun.COM 
33610673SKrishnendu.Sadhukhan@Sun.COM #if defined(ENABLE_FILTER)
33710673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_timestamp =
33810673SKrishnendu.Sadhukhan@Sun.COM 	    (self->lt_timestamp > FILTER_THRESHOLD &&
33910673SKrishnendu.Sadhukhan@Sun.COM 	    self->lt_is_block_wakeable != 0) ? 0 : self->lt_timestamp;
34010673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_is_block_wakeable = 0;
34110673SKrishnendu.Sadhukhan@Sun.COM #endif /* defined(ENABLE_FILTER) */
34210673SKrishnendu.Sadhukhan@Sun.COM 
34310673SKrishnendu.Sadhukhan@Sun.COM 	this->need_skip = (self->lt_counter < (SAMPLE_TIMES - 1) &&
34410673SKrishnendu.Sadhukhan@Sun.COM 	    self->lt_timestamp <= SAMPLE_THRESHOLD) ? 1 : 0;
34510673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_timestamp = this->need_skip ? 0 : self->lt_timestamp;
34610673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_counter += this->need_skip;
34710673SKrishnendu.Sadhukhan@Sun.COM }
34810673SKrishnendu.Sadhukhan@Sun.COM 
34910673SKrishnendu.Sadhukhan@Sun.COM /*
35010673SKrishnendu.Sadhukhan@Sun.COM  * Track large latency first.
35110673SKrishnendu.Sadhukhan@Sun.COM  */
35210673SKrishnendu.Sadhukhan@Sun.COM sched::resume:on-cpu
35310673SKrishnendu.Sadhukhan@Sun.COM /self->lt_timestamp > SAMPLE_THRESHOLD/
35410673SKrishnendu.Sadhukhan@Sun.COM {
35510673SKrishnendu.Sadhukhan@Sun.COM 	this->cause = self->lt_stackp > 0 ?
35610673SKrishnendu.Sadhukhan@Sun.COM 	    self->lt_cause[self->lt_stackp - 1] : "";
35710673SKrishnendu.Sadhukhan@Sun.COM 	this->priority = self->lt_stackp > 0 ?
35810673SKrishnendu.Sadhukhan@Sun.COM 	    self->lt_prio[self->lt_stackp - 1] : 0;
35910673SKrishnendu.Sadhukhan@Sun.COM 
36010673SKrishnendu.Sadhukhan@Sun.COM 	@lt_call_count[pid, tid, stack(), this->cause,
36110673SKrishnendu.Sadhukhan@Sun.COM 	    this->priority] = sum(1);
36210673SKrishnendu.Sadhukhan@Sun.COM 	@lt_call_sum[pid, tid, stack(), this->cause,
36310673SKrishnendu.Sadhukhan@Sun.COM 	    this->priority] = sum(self->lt_timestamp);
36410673SKrishnendu.Sadhukhan@Sun.COM 	@lt_call_max[pid, tid, stack(), this->cause,
36510673SKrishnendu.Sadhukhan@Sun.COM 	    this->priority] = max(self->lt_timestamp);
36610673SKrishnendu.Sadhukhan@Sun.COM 
36710673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_timestamp = 0;
36810673SKrishnendu.Sadhukhan@Sun.COM }
36910673SKrishnendu.Sadhukhan@Sun.COM 
37010673SKrishnendu.Sadhukhan@Sun.COM /*
37110673SKrishnendu.Sadhukhan@Sun.COM  * If we fall back to this probe, that means the latency is small and counter
37210673SKrishnendu.Sadhukhan@Sun.COM  * has reached SAMPLE_TIMES.
37310673SKrishnendu.Sadhukhan@Sun.COM  */
37410673SKrishnendu.Sadhukhan@Sun.COM sched::resume:on-cpu
37510673SKrishnendu.Sadhukhan@Sun.COM /self->lt_timestamp != 0/
37610673SKrishnendu.Sadhukhan@Sun.COM {
37710673SKrishnendu.Sadhukhan@Sun.COM 	this->cause = self->lt_stackp > 0 ?
37810673SKrishnendu.Sadhukhan@Sun.COM 	    self->lt_cause[self->lt_stackp - 1] : "";
37910673SKrishnendu.Sadhukhan@Sun.COM 	this->priority = self->lt_stackp > 0 ?
38010673SKrishnendu.Sadhukhan@Sun.COM 	    self->lt_prio[self->lt_stackp - 1] : 0;
38110673SKrishnendu.Sadhukhan@Sun.COM 
38210673SKrishnendu.Sadhukhan@Sun.COM 	/* Need +1 because lt_counter has not been updated in this cycle. */
38310673SKrishnendu.Sadhukhan@Sun.COM 	@lt_call_count[pid, tid, stack(), this->cause,
38410673SKrishnendu.Sadhukhan@Sun.COM 	    this->priority] = sum(self->lt_counter + 1);
38510673SKrishnendu.Sadhukhan@Sun.COM 	@lt_call_sum[pid, tid, stack(), this->cause,
38610673SKrishnendu.Sadhukhan@Sun.COM 	    this->priority] = sum((self->lt_counter + 1) * self->lt_timestamp);
38710673SKrishnendu.Sadhukhan@Sun.COM 	@lt_call_max[pid, tid, stack(), this->cause,
38810673SKrishnendu.Sadhukhan@Sun.COM 	    this->priority] = max(self->lt_timestamp);
38910673SKrishnendu.Sadhukhan@Sun.COM 
39010673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_timestamp = 0;
39110673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_counter = 0;
39210673SKrishnendu.Sadhukhan@Sun.COM }
39310673SKrishnendu.Sadhukhan@Sun.COM 
39410673SKrishnendu.Sadhukhan@Sun.COM #endif /* !defined(ENABLE_LOW_OVERHEAD) */
39510673SKrishnendu.Sadhukhan@Sun.COM 
39610673SKrishnendu.Sadhukhan@Sun.COM #define	TRANSLATE(entryprobe, returnprobe, cause, priority)		\
39710673SKrishnendu.Sadhukhan@Sun.COM entryprobe								\
39810673SKrishnendu.Sadhukhan@Sun.COM TRACE_FILTER_COND(self->lt_stackp == 0 ||				\
39910673SKrishnendu.Sadhukhan@Sun.COM     (self->lt_stackp < MAX_TAG &&					\
40010673SKrishnendu.Sadhukhan@Sun.COM     self->lt_prio[self->lt_stackp - 1] <= priority) )			\
40110673SKrishnendu.Sadhukhan@Sun.COM {									\
40210673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_prio[self->lt_stackp] = priority;			\
40310673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_cause[self->lt_stackp] = cause;			\
40410673SKrishnendu.Sadhukhan@Sun.COM 	++self->lt_stackp;						\
40510673SKrishnendu.Sadhukhan@Sun.COM }									\
40610673SKrishnendu.Sadhukhan@Sun.COM returnprobe								\
40710673SKrishnendu.Sadhukhan@Sun.COM TRACE_FILTER_COND(self->lt_stackp > 0 &&				\
40810673SKrishnendu.Sadhukhan@Sun.COM     self->lt_cause[self->lt_stackp - 1] == cause)			\
40910673SKrishnendu.Sadhukhan@Sun.COM {									\
41010673SKrishnendu.Sadhukhan@Sun.COM 	--self->lt_stackp;						\
41110673SKrishnendu.Sadhukhan@Sun.COM 	self->lt_cause[self->lt_stackp] = NULL;				\
41210673SKrishnendu.Sadhukhan@Sun.COM }
41310673SKrishnendu.Sadhukhan@Sun.COM 
41410673SKrishnendu.Sadhukhan@Sun.COM /*
41510673SKrishnendu.Sadhukhan@Sun.COM  * Syscalls have a priority of 10. This is to make sure that latency is
41610673SKrishnendu.Sadhukhan@Sun.COM  * traced to one of the syscalls only if nothing else matches.
41710673SKrishnendu.Sadhukhan@Sun.COM  * We put this special probe here because it uses "probefunc" variable instead
41810673SKrishnendu.Sadhukhan@Sun.COM  * of a constant string.
41910673SKrishnendu.Sadhukhan@Sun.COM  */
42010673SKrishnendu.Sadhukhan@Sun.COM 
42110673SKrishnendu.Sadhukhan@Sun.COM TRANSLATE(syscall:::entry, syscall:::return, probefunc, 10)
422