File: schedtimes.stp

package info (click to toggle)
systemtap 4.0-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 36,436 kB
  • sloc: cpp: 72,388; ansic: 58,430; xml: 47,797; exp: 40,417; sh: 10,793; python: 2,759; perl: 2,252; tcl: 1,305; makefile: 1,119; lisp: 105; java: 102; awk: 101; asm: 91; sed: 16
file content (160 lines) | stat: -rwxr-xr-x 3,939 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#! /usr/bin/env stap

############################################################
# Schedtimes.stp
#
# Copyright (C) 2009, 2014 Red Hat, Inc.
#
# This program is free software you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.

# Authors: Jason Baron <jbaron@redhat.com>
#          Josh Stone <jistone@redhat.com>
# profiles threads and displays their run times, queued times,
# wait times, including i/o wait times.
# Has two modes. When no arguments are given it profiles all
# threads. Alternatively, you can pass -c "program name"
############################################################

//constants
global DEAD=-1, RUNNING=1, QUEUED=2, SLEEPING=3

global run_time, queued_time, sleep_time, iowait_time
global pid_state, pid_names


// For new enough kernels, roughly 2.6.32+, the @defined(@task->in_iowait)
// tests will succeed and reduce these macros to nothing, including these
// pid-iowait arrays.  For older kernels, the rq fallback will remain.
global pid_in_iowait
global pid_iowait_count

@define in_iowait(task) %(
  @choose_defined(@task->in_iowait,
    (pid_in_iowait[@task->pid] ? pid_in_iowait[@task->pid]-- : 0))
%)

@define clear_iowait(rq, task) %(
    if (!@defined(@task->in_iowait))
      pid_iowait_count[@task->pid] = @nr_iowait(@rq)
%)

@define set_iowait(rq, task) %(
    if (!@defined(@task->in_iowait))
      pid_in_iowait[@task->pid] = (@nr_iowait(@rq) > pid_iowait_count[@task->pid])
%)

@define nr_iowait(rq) %(
    atomic_read(&@cast(@rq, "rq")->nr_iowait)
%)


global previous_timestamp

function timestamp()
{
  return cpu_clock_us(0)
}

function update_times(pid, now)
{
  delta = now - previous_timestamp[pid]
  previous_timestamp[pid] = now

  if ((state = pid_state[pid]) > 0) {
    if (state == SLEEPING)
      sleep_time[pid] += delta
    else if (state == QUEUED)
      queued_time[pid] += delta
    else if (state == RUNNING)
      run_time[pid] += delta
  }

  return delta
}


function task_targeted(task)
{
  pid = task_pid(task)
  if (pid && (!target() || target_set_pid(pid))) {
    pid_names[task_tid(task)] = task_execname(task)
    return 1
  }
  return 0
}

// Update the task name after exec
probe kernel.trace("sched_process_exec")!,
      kprocess.exec_complete
{
  if (tid() in pid_names)
    pid_names[tid()] = execname()
}


probe kernel.trace("sched_switch")
{
  // Task $prev is scheduled off this cpu
  if (task_targeted($prev)) {
    pid = $prev->pid
    state = $prev->state
    update_times(pid, timestamp())

    if (state > 0) {
      @set_iowait($rq, $prev)
      pid_state[pid] = SLEEPING
    } else if (state == 0) {
      pid_state[pid] = QUEUED
    } else {
      pid_state[pid] = DEAD
    }
  }

  // Task $next is scheduled onto this cpu
  if (task_targeted($next)) {
    pid = $next->pid
    update_times(pid, timestamp())

    @clear_iowait($rq, $next)
    pid_state[pid] = RUNNING
  }
}

probe kernel.trace("sched_wakeup")
{
  // Task $p is awakened
  if (@choose_defined($success, 1) && task_targeted($p)) {
    pid = $p->pid
    delta = update_times(pid, timestamp())
    if (pid_state[pid] == SLEEPING && @in_iowait($p)) {
      iowait_time[pid] += delta
    }
    pid_state[pid] = QUEUED
  }
}

// Give task $p a final accounting
probe kernel.trace("sched_process_exit")
{
  if (task_targeted($p)) {
    pid = $p->pid
    update_times(pid, timestamp())
    pid_state[pid] = DEAD
  }
}

probe end
{
  t = timestamp()
  printf ("\n%16s: %6s %10s %10s %10s %10s %10s\n\n",
         "execname", "pid", "run(us)", "sleep(us)", "iowait(us)",
         "queued(us)", "total(us)")
  foreach (pid+ in pid_state) {
    update_times(pid, t)
    printf("%16s: %6d %10d %10d %10d %10d %10d\n", pid_names[pid], pid,
           run_time[pid], sleep_time[pid], iowait_time[pid], queued_time[pid],
           (run_time[pid] + sleep_time[pid] + queued_time[pid]))
  }
}