Commit | Line | Data |
---|---|---|
efc403bb | 1 | /******************************************************************************* |
94cce698 | 2 | * Copyright (c) 2012, 2013 Ericsson |
efc403bb AM |
3 | * Copyright (c) 2010, 2011 École Polytechnique de Montréal |
4 | * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com> | |
d85d2a6d | 5 | * |
efc403bb AM |
6 | * All rights reserved. This program and the accompanying materials are |
7 | * made available under the terms of the Eclipse Public License v1.0 which | |
8 | * accompanies this distribution, and is available at | |
9 | * http://www.eclipse.org/legal/epl-v10.html | |
d85d2a6d | 10 | * |
efc403bb AM |
11 | *******************************************************************************/ |
12 | ||
13 | package org.eclipse.linuxtools.internal.lttng2.kernel.core.stateprovider; | |
14 | ||
79e0a1df | 15 | import java.util.HashMap; |
efc403bb | 16 | |
79e0a1df AM |
17 | import org.eclipse.linuxtools.internal.lttng2.kernel.core.Attributes; |
18 | import org.eclipse.linuxtools.internal.lttng2.kernel.core.LttngStrings; | |
19 | import org.eclipse.linuxtools.internal.lttng2.kernel.core.StateValues; | |
efc403bb AM |
20 | import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfEvent; |
21 | import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfTrace; | |
2c2f900e | 22 | import org.eclipse.linuxtools.tmf.core.event.ITmfEvent; |
79e0a1df AM |
23 | import org.eclipse.linuxtools.tmf.core.event.ITmfEventField; |
24 | import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException; | |
25 | import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException; | |
26 | import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException; | |
0fe46f2a | 27 | import org.eclipse.linuxtools.tmf.core.statesystem.AbstractTmfStateProvider; |
f1f86dfb | 28 | import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystemBuilder; |
79e0a1df AM |
29 | import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue; |
30 | import org.eclipse.linuxtools.tmf.core.statevalue.TmfStateValue; | |
efc403bb AM |
31 | |
32 | /** | |
33 | * This is the state change input plugin for TMF's state system which handles | |
34 | * the LTTng 2.0 kernel traces in CTF format. | |
d85d2a6d | 35 | * |
efc403bb | 36 | * It uses the reference handler defined in CTFKernelHandler.java. |
d85d2a6d | 37 | * |
efc403bb | 38 | * @author alexmont |
d85d2a6d | 39 | * |
efc403bb | 40 | */ |
d3ba47d4 | 41 | public class LttngKernelStateProvider extends AbstractTmfStateProvider { |
efc403bb | 42 | |
a96cc6be AM |
43 | /** |
44 | * Version number of this state provider. Please bump this if you modify the | |
45 | * contents of the generated state history in some way. | |
46 | */ | |
25e43749 | 47 | private static final int VERSION = 2; |
a96cc6be | 48 | |
79e0a1df AM |
49 | /* Event names HashMap. TODO: This can be discarded once we move to Java 7 */ |
50 | private final HashMap<String, Integer> knownEventNames; | |
efc403bb | 51 | |
6383e95d AM |
52 | // ------------------------------------------------------------------------ |
53 | // Constructor | |
54 | // ------------------------------------------------------------------------ | |
efc403bb AM |
55 | |
56 | /** | |
57 | * Instantiate a new state provider plugin. | |
d85d2a6d AM |
58 | * |
59 | * @param trace | |
efc403bb | 60 | * The LTTng 2.0 kernel trace directory |
efc403bb | 61 | */ |
d3ba47d4 | 62 | public LttngKernelStateProvider(CtfTmfTrace trace) { |
71f2da63 | 63 | super(trace, CtfTmfEvent.class, "LTTng Kernel"); //$NON-NLS-1$ |
79e0a1df | 64 | knownEventNames = fillEventNames(); |
2c2f900e | 65 | } |
efc403bb | 66 | |
6383e95d AM |
67 | // ------------------------------------------------------------------------ |
68 | // IStateChangeInput | |
69 | // ------------------------------------------------------------------------ | |
70 | ||
a96cc6be AM |
71 | @Override |
72 | public int getVersion() { | |
73 | return VERSION; | |
74 | } | |
75 | ||
2c2f900e | 76 | @Override |
f1f86dfb | 77 | public void assignTargetStateSystem(ITmfStateSystemBuilder ssb) { |
79e0a1df AM |
78 | /* We can only set up the locations once the state system is assigned */ |
79 | super.assignTargetStateSystem(ssb); | |
2c2f900e | 80 | } |
efc403bb | 81 | |
e96ab5c4 | 82 | @Override |
d3ba47d4 AM |
83 | public LttngKernelStateProvider getNewInstance() { |
84 | return new LttngKernelStateProvider((CtfTmfTrace) this.getTrace()); | |
e96ab5c4 AM |
85 | } |
86 | ||
efc403bb | 87 | @Override |
79e0a1df | 88 | protected void eventHandle(ITmfEvent ev) { |
79044a66 AM |
89 | /* |
90 | * AbstractStateChangeInput should have already checked for the correct | |
91 | * class type | |
92 | */ | |
79e0a1df AM |
93 | CtfTmfEvent event = (CtfTmfEvent) ev; |
94 | ||
95 | int quark; | |
96 | ITmfStateValue value; | |
97 | ||
98 | final ITmfEventField content = event.getContent(); | |
99 | final String eventName = event.getEventName(); | |
100 | final long ts = event.getTimestamp().getValue(); | |
101 | ||
2c2f900e | 102 | try { |
79e0a1df | 103 | /* Shortcut for the "current CPU" attribute node */ |
6383e95d | 104 | final Integer currentCPUNode = ss.getQuarkRelativeAndAdd(getNodeCPUs(), String.valueOf(event.getCPU())); |
79e0a1df AM |
105 | |
106 | /* | |
107 | * Shortcut for the "current thread" attribute node. It requires | |
108 | * querying the current CPU's current thread. | |
109 | */ | |
110 | quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.CURRENT_THREAD); | |
111 | value = ss.queryOngoingState(quark); | |
112 | int thread = value.unboxInt(); | |
6383e95d | 113 | final Integer currentThreadNode = ss.getQuarkRelativeAndAdd(getNodeThreads(), String.valueOf(thread)); |
79e0a1df AM |
114 | |
115 | /* | |
116 | * Feed event to the history system if it's known to cause a state | |
117 | * transition. | |
118 | */ | |
119 | switch (getEventIndex(eventName)) { | |
120 | ||
121 | case 1: // "exit_syscall": | |
122 | /* Fields: int64 ret */ | |
123 | { | |
124 | /* Clear the current system call on the process */ | |
125 | quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.SYSTEM_CALL); | |
126 | value = TmfStateValue.nullValue(); | |
127 | ss.modifyAttribute(ts, value, quark); | |
128 | ||
129 | /* Put the process' status back to user mode */ | |
130 | quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.STATUS); | |
dfb27cee | 131 | value = StateValues.PROCESS_STATUS_RUN_USERMODE_VALUE; |
79e0a1df AM |
132 | ss.modifyAttribute(ts, value, quark); |
133 | ||
134 | /* Put the CPU's status back to user mode */ | |
135 | quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.STATUS); | |
dfb27cee | 136 | value = StateValues.CPU_STATUS_RUN_USERMODE_VALUE; |
79e0a1df AM |
137 | ss.modifyAttribute(ts, value, quark); |
138 | } | |
139 | break; | |
140 | ||
141 | case 2: // "irq_handler_entry": | |
142 | /* Fields: int32 irq, string name */ | |
143 | { | |
144 | Integer irqId = ((Long) content.getField(LttngStrings.IRQ).getValue()).intValue(); | |
145 | ||
146 | /* Mark this IRQ as active in the resource tree. | |
147 | * The state value = the CPU on which this IRQ is sitting */ | |
6383e95d | 148 | quark = ss.getQuarkRelativeAndAdd(getNodeIRQs(), irqId.toString()); |
79e0a1df AM |
149 | value = TmfStateValue.newValueInt(event.getCPU()); |
150 | ss.modifyAttribute(ts, value, quark); | |
151 | ||
152 | /* Change the status of the running process to interrupted */ | |
153 | quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.STATUS); | |
dfb27cee | 154 | value = StateValues.PROCESS_STATUS_INTERRUPTED_VALUE; |
79e0a1df AM |
155 | ss.modifyAttribute(ts, value, quark); |
156 | ||
157 | /* Change the status of the CPU to interrupted */ | |
158 | quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.STATUS); | |
dfb27cee | 159 | value = StateValues.CPU_STATUS_IRQ_VALUE; |
79e0a1df AM |
160 | ss.modifyAttribute(ts, value, quark); |
161 | } | |
162 | break; | |
163 | ||
164 | case 3: // "irq_handler_exit": | |
165 | /* Fields: int32 irq, int32 ret */ | |
166 | { | |
167 | Integer irqId = ((Long) content.getField(LttngStrings.IRQ).getValue()).intValue(); | |
168 | ||
169 | /* Put this IRQ back to inactive in the resource tree */ | |
6383e95d | 170 | quark = ss.getQuarkRelativeAndAdd(getNodeIRQs(), irqId.toString()); |
79e0a1df AM |
171 | value = TmfStateValue.nullValue(); |
172 | ss.modifyAttribute(ts, value, quark); | |
173 | ||
174 | /* Set the previous process back to running */ | |
175 | setProcessToRunning(ts, currentThreadNode); | |
176 | ||
177 | /* Set the CPU status back to running or "idle" */ | |
178 | cpuExitInterrupt(ts, currentCPUNode, currentThreadNode); | |
179 | } | |
180 | break; | |
181 | ||
182 | case 4: // "softirq_entry": | |
183 | /* Fields: int32 vec */ | |
184 | { | |
185 | Integer softIrqId = ((Long) content.getField(LttngStrings.VEC).getValue()).intValue(); | |
186 | ||
187 | /* Mark this SoftIRQ as active in the resource tree. | |
188 | * The state value = the CPU on which this SoftIRQ is processed */ | |
6383e95d | 189 | quark = ss.getQuarkRelativeAndAdd(getNodeSoftIRQs(), softIrqId.toString()); |
79e0a1df AM |
190 | value = TmfStateValue.newValueInt(event.getCPU()); |
191 | ss.modifyAttribute(ts, value, quark); | |
192 | ||
193 | /* Change the status of the running process to interrupted */ | |
194 | quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.STATUS); | |
dfb27cee | 195 | value = StateValues.PROCESS_STATUS_INTERRUPTED_VALUE; |
79e0a1df AM |
196 | ss.modifyAttribute(ts, value, quark); |
197 | ||
198 | /* Change the status of the CPU to interrupted */ | |
199 | quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.STATUS); | |
dfb27cee | 200 | value = StateValues.CPU_STATUS_SOFTIRQ_VALUE; |
79e0a1df AM |
201 | ss.modifyAttribute(ts, value, quark); |
202 | } | |
203 | break; | |
204 | ||
205 | case 5: // "softirq_exit": | |
206 | /* Fields: int32 vec */ | |
207 | { | |
208 | Integer softIrqId = ((Long) content.getField(LttngStrings.VEC).getValue()).intValue(); | |
209 | ||
210 | /* Put this SoftIRQ back to inactive (= -1) in the resource tree */ | |
6383e95d | 211 | quark = ss.getQuarkRelativeAndAdd(getNodeSoftIRQs(), softIrqId.toString()); |
79e0a1df AM |
212 | value = TmfStateValue.nullValue(); |
213 | ss.modifyAttribute(ts, value, quark); | |
214 | ||
215 | /* Set the previous process back to running */ | |
216 | setProcessToRunning(ts, currentThreadNode); | |
217 | ||
218 | /* Set the CPU status back to "busy" or "idle" */ | |
219 | cpuExitInterrupt(ts, currentCPUNode, currentThreadNode); | |
220 | } | |
221 | break; | |
222 | ||
223 | case 6: // "softirq_raise": | |
224 | /* Fields: int32 vec */ | |
225 | { | |
226 | Integer softIrqId = ((Long) content.getField(LttngStrings.VEC).getValue()).intValue(); | |
227 | ||
228 | /* Mark this SoftIRQ as *raised* in the resource tree. | |
229 | * State value = -2 */ | |
6383e95d | 230 | quark = ss.getQuarkRelativeAndAdd(getNodeSoftIRQs(), softIrqId.toString()); |
dfb27cee | 231 | value = StateValues.SOFT_IRQ_RAISED_VALUE; |
79e0a1df AM |
232 | ss.modifyAttribute(ts, value, quark); |
233 | } | |
234 | break; | |
235 | ||
236 | case 7: // "sched_switch": | |
237 | /* | |
238 | * Fields: string prev_comm, int32 prev_tid, int32 prev_prio, int64 prev_state, | |
239 | * string next_comm, int32 next_tid, int32 next_prio | |
240 | */ | |
241 | { | |
242 | Integer prevTid = ((Long) content.getField(LttngStrings.PREV_TID).getValue()).intValue(); | |
f2338178 | 243 | Long prevState = (Long) content.getField(LttngStrings.PREV_STATE).getValue(); |
79e0a1df AM |
244 | String nextProcessName = (String) content.getField(LttngStrings.NEXT_COMM).getValue(); |
245 | Integer nextTid = ((Long) content.getField(LttngStrings.NEXT_TID).getValue()).intValue(); | |
246 | ||
6383e95d AM |
247 | Integer formerThreadNode = ss.getQuarkRelativeAndAdd(getNodeThreads(), prevTid.toString()); |
248 | Integer newCurrentThreadNode = ss.getQuarkRelativeAndAdd(getNodeThreads(), nextTid.toString()); | |
79e0a1df AM |
249 | |
250 | /* Set the status of the process that got scheduled out. */ | |
251 | quark = ss.getQuarkRelativeAndAdd(formerThreadNode, Attributes.STATUS); | |
f2338178 | 252 | if (prevState != 0) { |
dfb27cee | 253 | value = StateValues.PROCESS_STATUS_WAIT_BLOCKED_VALUE; |
f2338178 | 254 | } else { |
dfb27cee | 255 | value = StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE; |
f2338178 | 256 | } |
79e0a1df AM |
257 | ss.modifyAttribute(ts, value, quark); |
258 | ||
259 | /* Set the status of the new scheduled process */ | |
260 | setProcessToRunning(ts, newCurrentThreadNode); | |
261 | ||
262 | /* Set the exec name of the new process */ | |
263 | quark = ss.getQuarkRelativeAndAdd(newCurrentThreadNode, Attributes.EXEC_NAME); | |
264 | value = TmfStateValue.newValueString(nextProcessName); | |
265 | ss.modifyAttribute(ts, value, quark); | |
266 | ||
25e43749 AM |
267 | /* Make sure the PPID and system_call sub-attributes exist */ |
268 | ss.getQuarkRelativeAndAdd(newCurrentThreadNode, Attributes.SYSTEM_CALL); | |
269 | ss.getQuarkRelativeAndAdd(newCurrentThreadNode, Attributes.PPID); | |
79e0a1df AM |
270 | |
271 | /* Set the current scheduled process on the relevant CPU */ | |
272 | quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.CURRENT_THREAD); | |
273 | value = TmfStateValue.newValueInt(nextTid); | |
274 | ss.modifyAttribute(ts, value, quark); | |
275 | ||
276 | /* Set the status of the CPU itself */ | |
277 | if (nextTid > 0) { | |
278 | /* Check if the entering process is in kernel or user mode */ | |
279 | quark = ss.getQuarkRelativeAndAdd(newCurrentThreadNode, Attributes.SYSTEM_CALL); | |
280 | if (ss.queryOngoingState(quark).isNull()) { | |
dfb27cee | 281 | value = StateValues.CPU_STATUS_RUN_USERMODE_VALUE; |
79e0a1df | 282 | } else { |
dfb27cee | 283 | value = StateValues.CPU_STATUS_RUN_SYSCALL_VALUE; |
79e0a1df AM |
284 | } |
285 | } else { | |
dfb27cee | 286 | value = StateValues.CPU_STATUS_IDLE_VALUE; |
79e0a1df AM |
287 | } |
288 | quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.STATUS); | |
289 | ss.modifyAttribute(ts, value, quark); | |
290 | } | |
291 | break; | |
292 | ||
293 | case 8: // "sched_process_fork": | |
294 | /* Fields: string parent_comm, int32 parent_tid, | |
295 | * string child_comm, int32 child_tid */ | |
296 | { | |
297 | // String parentProcessName = (String) event.getFieldValue("parent_comm"); | |
298 | String childProcessName = (String) content.getField(LttngStrings.CHILD_COMM).getValue(); | |
299 | // assert ( parentProcessName.equals(childProcessName) ); | |
300 | ||
301 | Integer parentTid = ((Long) content.getField(LttngStrings.PARENT_TID).getValue()).intValue(); | |
302 | Integer childTid = ((Long) content.getField(LttngStrings.CHILD_TID).getValue()).intValue(); | |
303 | ||
6383e95d AM |
304 | Integer parentTidNode = ss.getQuarkRelativeAndAdd(getNodeThreads(), parentTid.toString()); |
305 | Integer childTidNode = ss.getQuarkRelativeAndAdd(getNodeThreads(), childTid.toString()); | |
79e0a1df AM |
306 | |
307 | /* Assign the PPID to the new process */ | |
308 | quark = ss.getQuarkRelativeAndAdd(childTidNode, Attributes.PPID); | |
309 | value = TmfStateValue.newValueInt(parentTid); | |
310 | ss.modifyAttribute(ts, value, quark); | |
311 | ||
312 | /* Set the new process' exec_name */ | |
313 | quark = ss.getQuarkRelativeAndAdd(childTidNode, Attributes.EXEC_NAME); | |
314 | value = TmfStateValue.newValueString(childProcessName); | |
315 | ss.modifyAttribute(ts, value, quark); | |
316 | ||
317 | /* Set the new process' status */ | |
318 | quark = ss.getQuarkRelativeAndAdd(childTidNode, Attributes.STATUS); | |
dfb27cee | 319 | value = StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE; |
79e0a1df AM |
320 | ss.modifyAttribute(ts, value, quark); |
321 | ||
322 | /* Set the process' syscall name, to be the same as the parent's */ | |
323 | quark = ss.getQuarkRelativeAndAdd(parentTidNode, Attributes.SYSTEM_CALL); | |
324 | value = ss.queryOngoingState(quark); | |
b46ea93c AM |
325 | if (value.isNull()) { |
326 | /* | |
327 | * Maybe we were missing info about the parent? At least we | |
328 | * will set the child right. Let's suppose "sys_clone". | |
329 | */ | |
330 | value = TmfStateValue.newValueString(LttngStrings.SYS_CLONE); | |
331 | } | |
79e0a1df AM |
332 | quark = ss.getQuarkRelativeAndAdd(childTidNode, Attributes.SYSTEM_CALL); |
333 | ss.modifyAttribute(ts, value, quark); | |
334 | } | |
335 | break; | |
336 | ||
337 | case 9: // "sched_process_exit": | |
338 | /* Fields: string comm, int32 tid, int32 prio */ | |
339 | break; | |
340 | ||
341 | case 10: // "sched_process_free": | |
342 | /* Fields: string comm, int32 tid, int32 prio */ | |
343 | /* | |
344 | * A sched_process_free will always happen after the sched_switch | |
345 | * that will remove the process from the cpu for the last time. So | |
346 | * this is when we should delete everything wrt to the process. | |
347 | */ | |
348 | { | |
349 | Integer tid = ((Long) content.getField(LttngStrings.TID).getValue()).intValue(); | |
350 | /* | |
351 | * Remove the process and all its sub-attributes from the | |
352 | * current state | |
353 | */ | |
6383e95d | 354 | quark = ss.getQuarkRelativeAndAdd(getNodeThreads(), tid.toString()); |
79e0a1df AM |
355 | ss.removeAttribute(ts, quark); |
356 | } | |
357 | break; | |
358 | ||
359 | case 11: // "lttng_statedump_process_state": | |
360 | /* Fields: | |
361 | * int32 type, int32 mode, int32 pid, int32 submode, int32 vpid, | |
362 | * int32 ppid, int32 tid, string name, int32 status, int32 vtid */ | |
363 | { | |
364 | Integer tid = ((Long) content.getField(LttngStrings.TID).getValue()).intValue(); | |
365 | int ppid = ((Long) content.getField(LttngStrings.PPID).getValue()).intValue(); | |
366 | int status = ((Long) content.getField(LttngStrings.STATUS).getValue()).intValue(); | |
367 | String name = (String) content.getField(LttngStrings.NAME).getValue(); | |
368 | /* | |
369 | * "mode" could be interesting too, but it doesn't seem to be | |
370 | * populated with anything relevant for now. | |
371 | */ | |
372 | ||
6383e95d | 373 | int curThreadNode = ss.getQuarkRelativeAndAdd(getNodeThreads(), tid.toString()); |
79e0a1df AM |
374 | |
375 | /* Set the process' name */ | |
376 | quark = ss.getQuarkRelativeAndAdd(curThreadNode, Attributes.EXEC_NAME); | |
377 | if (ss.queryOngoingState(quark).isNull()) { | |
378 | /* If the value didn't exist previously, set it */ | |
379 | value = TmfStateValue.newValueString(name); | |
380 | ss.modifyAttribute(ts, value, quark); | |
381 | } | |
382 | ||
383 | /* Set the process' PPID */ | |
384 | quark = ss.getQuarkRelativeAndAdd(curThreadNode, Attributes.PPID); | |
385 | if (ss.queryOngoingState(quark).isNull()) { | |
386 | value = TmfStateValue.newValueInt(ppid); | |
387 | ss.modifyAttribute(ts, value, quark); | |
388 | } | |
389 | ||
390 | /* Set the process' status */ | |
391 | quark = ss.getQuarkRelativeAndAdd(curThreadNode, Attributes.STATUS); | |
392 | if (ss.queryOngoingState(quark).isNull()) { | |
f2338178 MD |
393 | /* "2" here means "WAIT_FOR_CPU", and "5" "WAIT_BLOCKED" in the LTTng kernel. */ |
394 | if (status == 2) { | |
dfb27cee | 395 | value = StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE; |
f2338178 | 396 | } else if (status == 5) { |
dfb27cee | 397 | value = StateValues.PROCESS_STATUS_WAIT_BLOCKED_VALUE; |
79e0a1df | 398 | } else { |
dfb27cee | 399 | value = StateValues.PROCESS_STATUS_UNKNOWN_VALUE; |
79e0a1df AM |
400 | } |
401 | ss.modifyAttribute(ts, value, quark); | |
402 | } | |
403 | } | |
404 | break; | |
405 | ||
d1b933e7 AM |
406 | case 12: // "sched_wakeup": |
407 | case 13: // "sched_wakeup_new": | |
408 | /* Fields (same fields for both types): | |
409 | * string comm, int32 pid, int32 prio, int32 success, | |
410 | * int32 target_cpu */ | |
411 | { | |
412 | final int tid = ((Long) content.getField(LttngStrings.TID).getValue()).intValue(); | |
413 | final int threadNode = ss.getQuarkRelativeAndAdd(getNodeThreads(), String.valueOf(tid)); | |
414 | ||
415 | /* | |
416 | * The process indicated in the event's payload is now ready to | |
417 | * run. Assign it to the "wait for cpu" state. | |
418 | */ | |
419 | quark = ss.getQuarkRelativeAndAdd(threadNode, Attributes.STATUS); | |
dfb27cee | 420 | value = StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE; |
d1b933e7 AM |
421 | ss.modifyAttribute(ts, value, quark); |
422 | } | |
423 | break; | |
424 | ||
79e0a1df AM |
425 | default: |
426 | /* Other event types not covered by the main switch */ | |
427 | { | |
428 | if (eventName.startsWith(LttngStrings.SYSCALL_PREFIX) | |
429 | || eventName.startsWith(LttngStrings.COMPAT_SYSCALL_PREFIX)) { | |
430 | /* | |
431 | * This is a replacement for the old sys_enter event. Now | |
432 | * syscall names are listed into the event type | |
433 | */ | |
434 | ||
435 | /* Assign the new system call to the process */ | |
436 | quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.SYSTEM_CALL); | |
437 | value = TmfStateValue.newValueString(eventName); | |
438 | ss.modifyAttribute(ts, value, quark); | |
439 | ||
440 | /* Put the process in system call mode */ | |
441 | quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.STATUS); | |
dfb27cee | 442 | value = StateValues.PROCESS_STATUS_RUN_SYSCALL_VALUE; |
79e0a1df AM |
443 | ss.modifyAttribute(ts, value, quark); |
444 | ||
445 | /* Put the CPU in system call (kernel) mode */ | |
446 | quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.STATUS); | |
dfb27cee | 447 | value = StateValues.CPU_STATUS_RUN_SYSCALL_VALUE; |
79e0a1df AM |
448 | ss.modifyAttribute(ts, value, quark); |
449 | } | |
450 | } | |
451 | break; | |
452 | } // End of big switch | |
453 | ||
79e0a1df AM |
454 | } catch (AttributeNotFoundException ae) { |
455 | /* | |
456 | * This would indicate a problem with the logic of the manager here, | |
457 | * so it shouldn't happen. | |
458 | */ | |
459 | ae.printStackTrace(); | |
460 | ||
461 | } catch (TimeRangeException tre) { | |
462 | /* | |
463 | * This would happen if the events in the trace aren't ordered | |
464 | * chronologically, which should never be the case ... | |
465 | */ | |
466 | System.err.println("TimeRangeExcpetion caught in the state system's event manager."); //$NON-NLS-1$ | |
467 | System.err.println("Are the events in the trace correctly ordered?"); //$NON-NLS-1$ | |
468 | tre.printStackTrace(); | |
469 | ||
470 | } catch (StateValueTypeException sve) { | |
471 | /* | |
472 | * This would happen if we were trying to push/pop attributes not of | |
473 | * type integer. Which, once again, should never happen. | |
474 | */ | |
475 | sve.printStackTrace(); | |
2c2f900e AM |
476 | } |
477 | } | |
478 | ||
6383e95d AM |
479 | // ------------------------------------------------------------------------ |
480 | // Convenience methods for commonly-used attribute tree locations | |
481 | // ------------------------------------------------------------------------ | |
482 | ||
483 | private int getNodeCPUs() { | |
484 | return ss.getQuarkAbsoluteAndAdd(Attributes.CPUS); | |
79e0a1df AM |
485 | } |
486 | ||
6383e95d AM |
487 | private int getNodeThreads() { |
488 | return ss.getQuarkAbsoluteAndAdd(Attributes.THREADS); | |
489 | } | |
490 | ||
491 | private int getNodeIRQs() { | |
492 | return ss.getQuarkAbsoluteAndAdd(Attributes.RESOURCES, Attributes.IRQS); | |
493 | } | |
494 | ||
495 | private int getNodeSoftIRQs() { | |
496 | return ss.getQuarkAbsoluteAndAdd(Attributes.RESOURCES, Attributes.SOFT_IRQS); | |
497 | } | |
498 | ||
499 | // ------------------------------------------------------------------------ | |
500 | // Workaround for the lack of switch-on-strings in Java < 7 | |
501 | // ------------------------------------------------------------------------ | |
502 | ||
79e0a1df AM |
503 | private static HashMap<String, Integer> fillEventNames() { |
504 | /* | |
505 | * TODO Replace with straight strings in the switch/case once we move to | |
506 | * Java 7 | |
507 | */ | |
508 | HashMap<String, Integer> map = new HashMap<String, Integer>(); | |
509 | ||
510 | map.put(LttngStrings.EXIT_SYSCALL, 1); | |
511 | map.put(LttngStrings.IRQ_HANDLER_ENTRY, 2); | |
512 | map.put(LttngStrings.IRQ_HANDLER_EXIT, 3); | |
513 | map.put(LttngStrings.SOFTIRQ_ENTRY, 4); | |
514 | map.put(LttngStrings.SOFTIRQ_EXIT, 5); | |
515 | map.put(LttngStrings.SOFTIRQ_RAISE, 6); | |
516 | map.put(LttngStrings.SCHED_SWITCH, 7); | |
517 | map.put(LttngStrings.SCHED_PROCESS_FORK, 8); | |
518 | map.put(LttngStrings.SCHED_PROCESS_EXIT, 9); | |
519 | map.put(LttngStrings.SCHED_PROCESS_FREE, 10); | |
520 | map.put(LttngStrings.STATEDUMP_PROCESS_STATE, 11); | |
d1b933e7 AM |
521 | map.put(LttngStrings.SCHED_WAKEUP, 12); |
522 | map.put(LttngStrings.SCHED_WAKEUP_NEW, 13); | |
79e0a1df AM |
523 | |
524 | return map; | |
525 | } | |
526 | ||
527 | private int getEventIndex(String eventName) { | |
528 | Integer ret = knownEventNames.get(eventName); | |
529 | return (ret != null) ? ret : -1; | |
530 | } | |
531 | ||
6383e95d AM |
532 | // ------------------------------------------------------------------------ |
533 | // Advanced state-setting methods | |
534 | // ------------------------------------------------------------------------ | |
535 | ||
79e0a1df AM |
536 | /** |
537 | * When we want to set a process back to a "running" state, first check | |
538 | * its current System_call attribute. If there is a system call active, we | |
539 | * put the process back in the syscall state. If not, we put it back in | |
540 | * user mode state. | |
541 | */ | |
542 | private void setProcessToRunning(long ts, int currentThreadNode) | |
543 | throws AttributeNotFoundException, TimeRangeException, | |
544 | StateValueTypeException { | |
545 | int quark; | |
546 | ITmfStateValue value; | |
547 | ||
548 | quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.SYSTEM_CALL); | |
549 | if (ss.queryOngoingState(quark).isNull()) { | |
550 | /* We were in user mode before the interruption */ | |
dfb27cee | 551 | value = StateValues.PROCESS_STATUS_RUN_USERMODE_VALUE; |
79e0a1df AM |
552 | } else { |
553 | /* We were previously in kernel mode */ | |
dfb27cee | 554 | value = StateValues.PROCESS_STATUS_RUN_SYSCALL_VALUE; |
79e0a1df AM |
555 | } |
556 | quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.STATUS); | |
557 | ss.modifyAttribute(ts, value, quark); | |
558 | } | |
559 | ||
560 | /** | |
561 | * Similar logic as above, but to set the CPU's status when it's coming out | |
562 | * of an interruption. | |
563 | */ | |
564 | private void cpuExitInterrupt(long ts, int currentCpuNode, int currentThreadNode) | |
565 | throws StateValueTypeException, AttributeNotFoundException, | |
566 | TimeRangeException { | |
567 | int quark; | |
568 | ITmfStateValue value; | |
569 | ||
570 | quark = ss.getQuarkRelativeAndAdd(currentCpuNode, Attributes.CURRENT_THREAD); | |
571 | if (ss.queryOngoingState(quark).unboxInt() > 0) { | |
572 | /* There was a process on the CPU */ | |
573 | quark = ss.getQuarkRelative(currentThreadNode, Attributes.SYSTEM_CALL); | |
574 | if (ss.queryOngoingState(quark).isNull()) { | |
575 | /* That process was in user mode */ | |
dfb27cee | 576 | value = StateValues.CPU_STATUS_RUN_USERMODE_VALUE; |
79e0a1df AM |
577 | } else { |
578 | /* That process was in a system call */ | |
dfb27cee | 579 | value = StateValues.CPU_STATUS_RUN_SYSCALL_VALUE; |
79e0a1df AM |
580 | } |
581 | } else { | |
582 | /* There was no real process scheduled, CPU was idle */ | |
dfb27cee | 583 | value = StateValues.CPU_STATUS_IDLE_VALUE; |
2c2f900e | 584 | } |
79e0a1df AM |
585 | quark = ss.getQuarkRelativeAndAdd(currentCpuNode, Attributes.STATUS); |
586 | ss.modifyAttribute(ts, value, quark); | |
efc403bb AM |
587 | } |
588 | } |