latencytop.d revision de3d2ce46fc25c7b67ccbae4afe5f15e5357568f
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2008-2009, Intel Corporation.
* All Rights Reserved.
*/
#if defined(ENABLE_SCHED)
#define TRACE_FILTER
#define TRACE_FILTER_COND(a) / (a) /
#else
#define TRACE_FILTER / pid != 0 /
#define TRACE_FILTER_COND(a) / pid != 0 && (a) /
#endif
#define FILTER_THRESHOLD 5000000
/* From thread.h */
#define T_WAKEABLE 2
/*
* This array is used to store the timestamp when threads are enqueued
* to dispq.
* self-> is not accessible when enqueue happens.
*/
unsigned long long lt_timestamps[int, int];
self unsigned int lt_is_block_wakeable;
self unsigned long long lt_sleep_start;
self unsigned long long lt_sleep_duration;
self unsigned long long lt_sch_delay;
/*
* Make sure we leave nothing behind,
* otherwise memory will eventually run out.
*/
{
self->lt_sleep_start = 0;
self->lt_is_block_wakeable = 0;
self->lt_counter = 0;
self->lt_timestamp = 0;
}
#if !defined(ENABLE_LOW_OVERHEAD)
/*
* Log timestamp when a thread is off CPU.
*/
{
}
/*
* Log timestamp when a thread is put on a dispatch queue and becomes runnable.
*/
{
}
/*
* Calculate latencies when the thread is actually on CPU.
* This is necessary to get the right stack().
*/
/ self->lt_sleep_start != 0 /
{
self->lt_sleep_start = 0;
}
/*
* Filter: drop all "large" latencies when it is wakeable,
* trying to filter sleep() etc.
*/
#if defined(ENABLE_FILTER)
self->lt_is_block_wakeable != 0 /
{
self->lt_sch_delay = 0;
self->lt_sleep_duration = 0;
self->lt_is_block_wakeable = 0;
}
#endif /* defined(ENABLE_FILTER) */
/*
* Write sleep time to the aggregation.
* lt_sleep_duration is from thread off cpu to it is enqueued again.
*/
/ self->lt_sleep_duration != 0 /
{
self->lt_sleep_duration = 0;
}
/*
* Write time spent in queue to the aggregation.
* lt_sch_delay: the interval between "thread runnable" and "thread on cpu".
*/
/ self->lt_sch_delay != 0 /
{
self->lt_sch_delay = 0;
}
/*
* Probes that tracks lock spinning
*/
{
}
{
}
/*
* Probes that tracks lock blocking
*/
{
}
{
}
#if defined(ENABLE_SYNCOBJ)
/*
* Probes that tracks synchronization objects.
*/
/*
* Currently we are not able to track wakeup from sched, because all lwpid
* are zero for when we trace sched. That makes lt_timestamps not usable.
*/
{
/*
* We can use lt_timestamps[] here, because
* wakeup is always fired before enqueue.
* After enqueue, lt_timestamps[] will be overwritten.
*/
}
#endif /* defined(ENABLE_SYNCOBJ) */
#else /* !defined(ENABLE_LOW_OVERHEAD) */
/*
* This is the low overhead mode.
* In order to reduce the number of instructions executed during each
* off-cpu and on-cpu event, we do:
* 1. Use sampling, only update aggregations roughly 1/100 times (SAMPLE_TIMES).
* 2. Do not track anything other than needed for "main" window.
* 3. Use as few thread local variables as possible.
*/
#define SAMPLE_TIMES 100
#define SAMPLE_THRESHOLD 50000000
/*
* Log timestamp when a thread is off CPU.
*/
{
#if defined(ENABLE_FILTER)
#endif /* defined(ENABLE_FILTER) */
}
/*
* Calculate latencies when the thread is actually on CPU.
*/
/ self->lt_timestamp != 0 /
{
#if defined(ENABLE_FILTER)
self->lt_timestamp =
self->lt_is_block_wakeable = 0;
#endif /* defined(ENABLE_FILTER) */
}
/*
* Log large ones first.
*/
{
self->lt_timestamp = 0;
}
/*
* If we fall to this probe, this must be a small latency and counter
* reaches SAMPLE_TIMES.
*/
/ self->lt_timestamp != 0 /
{
/* Need +1 because lt_counter has not been updated in this cycle. */
self->lt_timestamp = 0;
self->lt_counter = 0;
}
#endif /* !defined(ENABLE_LOW_OVERHEAD) */