4e5b076de71130a12047db997dfdac760c5cad83
1 # The MIT License (MIT)
3 # Copyright (C) 2015 - Julien Desfossez <jdesfossez@efficios.com>
4 # 2015 - Antoine Busque <abusque@efficios.com>
6 # Permission is hereby granted, free of charge, to any person obtaining a copy
7 # of this software and associated documentation files (the "Software"), to deal
8 # in the Software without restriction, including without limitation the rights
9 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 # copies of the Software, and to permit persons to whom the Software is
11 # furnished to do so, subject to the following conditions:
13 # The above copyright notice and this permission notice shall be included in
14 # all copies or substantial portions of the Software.
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 from ..common
import version_utils
28 class SchedStateProvider(sp
.StateProvider
):
29 # The priority offset for sched_wak* events was fixed in
30 # lttng-modules 2.7.1 upwards
31 PRIO_OFFSET_FIX_VERSION
= version_utils
.Version(2,7,1)
33 def __init__(self
, state
):
35 'sched_switch': self
._process
_sched
_switch
,
36 'sched_migrate_task': self
._process
_sched
_migrate
_task
,
37 'sched_wakeup': self
._process
_sched
_wakeup
,
38 'sched_wakeup_new': self
._process
_sched
_wakeup
,
39 'sched_waking': self
._process
_sched
_wakeup
,
40 'sched_process_fork': self
._process
_sched
_process
_fork
,
41 'sched_process_exec': self
._process
_sched
_process
_exec
,
42 'sched_pi_setprio': self
._process
_sched
_pi
_setprio
,
45 super().__init
__(state
, cbs
)
47 def _sched_switch_per_cpu(self
, cpu_id
, next_tid
):
48 if cpu_id
not in self
._state
.cpus
:
49 self
._state
.cpus
[cpu_id
] = sv
.CPU(cpu_id
)
51 cpu
= self
._state
.cpus
[cpu_id
]
52 # exclude swapper process
54 cpu
.current_tid
= None
56 cpu
.current_tid
= next_tid
58 def _create_proc(self
, tid
):
59 if tid
not in self
._state
.tids
:
61 # special case for the swapper
62 self
._state
.tids
[tid
] = sv
.Process(tid
=tid
, pid
=0)
64 self
._state
.tids
[tid
] = sv
.Process(tid
=tid
)
66 def _sched_switch_per_tid(self
, next_tid
, next_comm
, prev_tid
):
67 # Instantiate processes if new
68 self
._create
_proc
(prev_tid
)
69 self
._create
_proc
(next_tid
)
71 next_proc
= self
._state
.tids
[next_tid
]
72 next_proc
.comm
= next_comm
73 next_proc
.prev_tid
= prev_tid
75 def _check_prio_changed(self
, timestamp
, tid
, prio
):
80 proc
= self
._state
.tids
[tid
]
84 self
._state
.send_notification_cb(
85 'prio_changed', timestamp
=timestamp
, tid
=tid
, prio
=prio
)
87 def _process_sched_switch(self
, event
):
88 timestamp
= event
.timestamp
89 cpu_id
= event
['cpu_id']
90 next_tid
= event
['next_tid']
91 next_comm
= event
['next_comm']
92 next_prio
= event
['next_prio']
93 prev_tid
= event
['prev_tid']
94 prev_prio
= event
['prev_prio']
96 self
._sched
_switch
_per
_cpu
(cpu_id
, next_tid
)
97 self
._sched
_switch
_per
_tid
(next_tid
, next_comm
, prev_tid
)
98 self
._check
_prio
_changed
(timestamp
, prev_tid
, prev_prio
)
99 self
._check
_prio
_changed
(timestamp
, next_tid
, next_prio
)
101 wakee_proc
= self
._state
.tids
[next_tid
]
103 if wakee_proc
.last_waker
is not None:
104 waker_proc
= self
._state
.tids
[wakee_proc
.last_waker
]
107 'timestamp': timestamp
,
109 'prev_tid': prev_tid
,
110 'next_tid': next_tid
,
111 'next_comm': next_comm
,
112 'wakee_proc': wakee_proc
,
113 'waker_proc': waker_proc
,
116 self
._state
.send_notification_cb('sched_switch_per_cpu', **cb_data
)
117 self
._state
.send_notification_cb('sched_switch_per_tid', **cb_data
)
119 wakee_proc
.last_wakeup
= None
120 wakee_proc
.last_waker
= None
122 def _process_sched_migrate_task(self
, event
):
126 if tid
not in self
._state
.tids
:
129 proc
.comm
= event
['comm']
130 self
._state
.tids
[tid
] = proc
132 proc
= self
._state
.tids
[tid
]
134 self
._check
_prio
_changed
(event
.timestamp
, tid
, prio
)
135 self
._state
.send_notification_cb(
136 'sched_migrate_task', proc
=proc
, cpu_id
=event
['cpu_id'])
138 def _process_sched_wakeup(self
, event
):
139 target_cpu
= event
['target_cpu']
140 current_cpu
= event
['cpu_id']
144 if self
._state
.tracer_version
< self
.PRIO_OFFSET_FIX_VERSION
:
147 if target_cpu
not in self
._state
.cpus
:
148 self
._state
.cpus
[target_cpu
] = sv
.CPU(target_cpu
)
150 if current_cpu
not in self
._state
.cpus
:
151 self
._state
.cpus
[current_cpu
] = sv
.CPU(current_cpu
)
153 # If the TID is already executing on a CPU, ignore this wakeup
154 for cpu_id
in self
._state
.cpus
:
155 cpu
= self
._state
.cpus
[cpu_id
]
156 if cpu
.current_tid
== tid
:
159 if tid
not in self
._state
.tids
:
162 self
._state
.tids
[tid
] = proc
164 self
._check
_prio
_changed
(event
.timestamp
, tid
, prio
)
166 # A process can be woken up multiple times, only record
168 if self
._state
.tids
[tid
].last_wakeup
is None:
169 self
._state
.tids
[tid
].last_wakeup
= event
.timestamp
170 if self
._state
.cpus
[current_cpu
].current_tid
is not None:
171 self
._state
.tids
[tid
].last_waker
= \
172 self
._state
.cpus
[current_cpu
].current_tid
174 def _process_sched_process_fork(self
, event
):
175 child_tid
= event
['child_tid']
176 child_pid
= event
['child_pid']
177 child_comm
= event
['child_comm']
178 parent_pid
= event
['parent_pid']
179 parent_tid
= event
['parent_pid']
180 parent_comm
= event
['parent_comm']
182 if parent_tid
not in self
._state
.tids
:
183 self
._state
.tids
[parent_tid
] = sv
.Process(
184 parent_tid
, parent_pid
, parent_comm
)
186 self
._state
.tids
[parent_tid
].pid
= parent_pid
187 self
._state
.tids
[parent_tid
].comm
= parent_comm
189 parent_proc
= self
._state
.tids
[parent_pid
]
190 child_proc
= sv
.Process(child_tid
, child_pid
, child_comm
)
192 for fd
in parent_proc
.fds
:
193 old_fd
= parent_proc
.fds
[fd
]
194 child_proc
.fds
[fd
] = sv
.FD
.new_from_fd(old_fd
)
195 # Note: the parent_proc key in the notification function
196 # refers to the parent of the FD, which in this case is
197 # the child_proc created by the fork
198 self
._state
.send_notification_cb(
199 'create_fd', fd
=fd
, parent_proc
=child_proc
,
200 timestamp
=event
.timestamp
, cpu_id
=event
['cpu_id'])
202 self
._state
.tids
[child_tid
] = child_proc
204 def _process_sched_process_exec(self
, event
):
207 if tid
not in self
._state
.tids
:
210 self
._state
.tids
[tid
] = proc
212 proc
= self
._state
.tids
[tid
]
214 # Use LTTng procname context if available
215 if 'procname' in event
:
216 proc
.comm
= event
['procname']
220 if proc
.fds
[fd
].cloexec
:
223 self
._state
.send_notification_cb(
224 'close_fd', fd
=fd
, parent_proc
=proc
,
225 timestamp
=event
.timestamp
, cpu_id
=event
['cpu_id'])
228 def _process_sched_pi_setprio(self
, event
):
229 timestamp
= event
.timestamp
230 newprio
= event
['newprio']
233 self
._check
_prio
_changed
(timestamp
, tid
, newprio
)
This page took 0.034823 seconds and 4 git commands to generate.