tmf: Introduce resolveIntEventAspectOfClassForEvent
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.os.linux.core / src / org / eclipse / tracecompass / internal / analysis / os / linux / core / kernelanalysis / KernelStateProvider.java
1 /*******************************************************************************
2 * Copyright (c) 2012, 2015 Ericsson
3 * Copyright (c) 2010, 2011 École Polytechnique de Montréal
4 * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
5 *
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
10 *
11 *******************************************************************************/
12
13 package org.eclipse.tracecompass.internal.analysis.os.linux.core.kernelanalysis;
14
15 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
16
17 import java.util.Map;
18
19 import org.eclipse.jdt.annotation.Nullable;
20 import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.Attributes;
21 import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.LinuxValues;
22 import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.StateValues;
23 import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
24 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
25 import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
26 import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
27 import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
28 import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
29 import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
30 import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
31 import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
32 import org.eclipse.tracecompass.tmf.core.event.aspect.TmfCpuAspect;
33 import org.eclipse.tracecompass.tmf.core.statesystem.AbstractTmfStateProvider;
34 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
35 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
36
37 import com.google.common.collect.ImmutableMap;
38
39 /**
40 * This is the state change input plugin for TMF's state system which handles
41 * the LTTng 2.0 kernel traces in CTF format.
42 *
43 * It uses the reference handler defined in CTFKernelHandler.java.
44 *
45 * @author alexmont
46 *
47 */
48 public class KernelStateProvider extends AbstractTmfStateProvider {
49
50 // ------------------------------------------------------------------------
51 // Static fields
52 // ------------------------------------------------------------------------
53
54 /**
55 * Version number of this state provider. Please bump this if you modify the
56 * contents of the generated state history in some way.
57 */
58 private static final int VERSION = 9;
59
60 private static final int IRQ_HANDLER_ENTRY_INDEX = 1;
61 private static final int IRQ_HANDLER_EXIT_INDEX = 2;
62 private static final int SOFT_IRQ_ENTRY_INDEX = 3;
63 private static final int SOFT_IRQ_EXIT_INDEX = 4;
64 private static final int SOFT_IRQ_RAISE_INDEX = 5;
65 private static final int SCHED_SWITCH_INDEX = 6;
66 private static final int SCHED_PROCESS_FORK_INDEX = 7;
67 private static final int SCHED_PROCESS_EXIT_INDEX = 8;
68 private static final int SCHED_PROCESS_FREE_INDEX = 9;
69 private static final int STATEDUMP_PROCESS_STATE_INDEX = 10;
70 private static final int SCHED_WAKEUP_INDEX = 11;
71 private static final int SCHED_PI_SETPRIO_INDEX = 12;
72
73
74 // ------------------------------------------------------------------------
75 // Fields
76 // ------------------------------------------------------------------------
77
78 private final Map<String, Integer> fEventNames;
79 private final IKernelAnalysisEventLayout fLayout;
80
81 // ------------------------------------------------------------------------
82 // Constructor
83 // ------------------------------------------------------------------------
84
85 /**
86 * Instantiate a new state provider plugin.
87 *
88 * @param trace
89 * The LTTng 2.0 kernel trace directory
90 * @param layout
91 * The event layout to use for this state provider. Usually
92 * depending on the tracer implementation.
93 */
94 public KernelStateProvider(ITmfTrace trace, IKernelAnalysisEventLayout layout) {
95 super(trace, "Kernel"); //$NON-NLS-1$
96 fLayout = layout;
97 fEventNames = buildEventNames(layout);
98 }
99
100 // ------------------------------------------------------------------------
101 // Event names management
102 // ------------------------------------------------------------------------
103
104 private static Map<String, Integer> buildEventNames(IKernelAnalysisEventLayout layout) {
105 ImmutableMap.Builder<String, Integer> builder = ImmutableMap.builder();
106
107 builder.put(layout.eventIrqHandlerEntry(), IRQ_HANDLER_ENTRY_INDEX);
108 builder.put(layout.eventIrqHandlerExit(), IRQ_HANDLER_EXIT_INDEX);
109 builder.put(layout.eventSoftIrqEntry(), SOFT_IRQ_ENTRY_INDEX);
110 builder.put(layout.eventSoftIrqExit(), SOFT_IRQ_EXIT_INDEX);
111 builder.put(layout.eventSoftIrqRaise(), SOFT_IRQ_RAISE_INDEX);
112 builder.put(layout.eventSchedSwitch(), SCHED_SWITCH_INDEX);
113 builder.put(layout.eventSchedPiSetprio(), SCHED_PI_SETPRIO_INDEX);
114 builder.put(layout.eventSchedProcessFork(), SCHED_PROCESS_FORK_INDEX);
115 builder.put(layout.eventSchedProcessExit(), SCHED_PROCESS_EXIT_INDEX);
116 builder.put(layout.eventSchedProcessFree(), SCHED_PROCESS_FREE_INDEX);
117
118 final String eventStatedumpProcessState = layout.eventStatedumpProcessState();
119 if (eventStatedumpProcessState != null) {
120 builder.put(eventStatedumpProcessState, STATEDUMP_PROCESS_STATE_INDEX);
121 }
122
123 for (String eventSchedWakeup : layout.eventsSchedWakeup()) {
124 builder.put(eventSchedWakeup, SCHED_WAKEUP_INDEX);
125 }
126
127 return checkNotNull(builder.build());
128 }
129
130 // ------------------------------------------------------------------------
131 // IStateChangeInput
132 // ------------------------------------------------------------------------
133
134 @Override
135 public int getVersion() {
136 return VERSION;
137 }
138
139 @Override
140 public void assignTargetStateSystem(ITmfStateSystemBuilder ssb) {
141 /* We can only set up the locations once the state system is assigned */
142 super.assignTargetStateSystem(ssb);
143 }
144
145 @Override
146 public KernelStateProvider getNewInstance() {
147 return new KernelStateProvider(this.getTrace(), fLayout);
148 }
149
150 @Override
151 protected void eventHandle(@Nullable ITmfEvent event) {
152 if (event == null) {
153 return;
154 }
155
156 Integer cpu = TmfTraceUtils.resolveIntEventAspectOfClassForEvent(event.getTrace(), TmfCpuAspect.class, event);
157 if (cpu == null) {
158 /* We couldn't find any CPU information, ignore this event */
159 return;
160 }
161
162 final String eventName = event.getName();
163 final long ts = event.getTimestamp().getValue();
164
165 try {
166 final ITmfStateSystemBuilder ss = checkNotNull(getStateSystemBuilder());
167
168 /* Shortcut for the "current CPU" attribute node */
169 final int currentCPUNode = ss.getQuarkRelativeAndAdd(getNodeCPUs(ss), cpu.toString());
170
171 /*
172 * Shortcut for the "current thread" attribute node. It requires
173 * querying the current CPU's current thread.
174 */
175 int quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.CURRENT_THREAD);
176 ITmfStateValue value = ss.queryOngoingState(quark);
177 int thread = value.isNull() ? -1 : value.unboxInt();
178 final int currentThreadNode = ss.getQuarkRelativeAndAdd(getNodeThreads(ss), String.valueOf(thread));
179
180 /*
181 * Feed event to the history system if it's known to cause a state
182 * transition.
183 */
184 Integer idx = fEventNames.get(eventName);
185 int intval = (idx == null ? -1 : idx.intValue());
186 switch (intval) {
187
188 case IRQ_HANDLER_ENTRY_INDEX:
189 {
190 Integer irqId = ((Long) event.getContent().getField(fLayout.fieldIrq()).getValue()).intValue();
191
192 /* Mark this IRQ as active in the resource tree.
193 * The state value = the CPU on which this IRQ is sitting */
194 quark = ss.getQuarkRelativeAndAdd(getNodeIRQs(ss), irqId.toString());
195 value = TmfStateValue.newValueInt(cpu.intValue());
196 ss.modifyAttribute(ts, value, quark);
197
198 /* Change the status of the running process to interrupted */
199 quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.STATUS);
200 value = StateValues.PROCESS_STATUS_INTERRUPTED_VALUE;
201 ss.modifyAttribute(ts, value, quark);
202
203 /* Change the status of the CPU to interrupted */
204 quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.STATUS);
205 value = StateValues.CPU_STATUS_IRQ_VALUE;
206 ss.modifyAttribute(ts, value, quark);
207 }
208 break;
209
210 case IRQ_HANDLER_EXIT_INDEX:
211 {
212 Integer irqId = ((Long) event.getContent().getField(fLayout.fieldIrq()).getValue()).intValue();
213
214 /* Put this IRQ back to inactive in the resource tree */
215 quark = ss.getQuarkRelativeAndAdd(getNodeIRQs(ss), irqId.toString());
216 value = TmfStateValue.nullValue();
217 ss.modifyAttribute(ts, value, quark);
218
219 /* Set the previous process back to running */
220 setProcessToRunning(ss, ts, currentThreadNode);
221
222 /* Set the CPU status back to running or "idle" */
223 cpuExitInterrupt(ss, ts, currentCPUNode, currentThreadNode);
224 }
225 break;
226
227 case SOFT_IRQ_ENTRY_INDEX:
228 {
229 Integer softIrqId = ((Long) event.getContent().getField(fLayout.fieldVec()).getValue()).intValue();
230
231 /* Mark this SoftIRQ as active in the resource tree.
232 * The state value = the CPU on which this SoftIRQ is processed */
233 quark = ss.getQuarkRelativeAndAdd(getNodeSoftIRQs(ss), softIrqId.toString());
234 value = TmfStateValue.newValueInt(cpu.intValue());
235 ss.modifyAttribute(ts, value, quark);
236
237 /* Change the status of the running process to interrupted */
238 quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.STATUS);
239 value = StateValues.PROCESS_STATUS_INTERRUPTED_VALUE;
240 ss.modifyAttribute(ts, value, quark);
241
242 /* Change the status of the CPU to interrupted */
243 quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.STATUS);
244 value = StateValues.CPU_STATUS_SOFTIRQ_VALUE;
245 ss.modifyAttribute(ts, value, quark);
246 }
247 break;
248
249 case SOFT_IRQ_EXIT_INDEX:
250 {
251 Integer softIrqId = ((Long) event.getContent().getField(fLayout.fieldVec()).getValue()).intValue();
252
253 /* Put this SoftIRQ back to inactive (= -1) in the resource tree */
254 quark = ss.getQuarkRelativeAndAdd(getNodeSoftIRQs(ss), softIrqId.toString());
255 value = TmfStateValue.nullValue();
256 ss.modifyAttribute(ts, value, quark);
257
258 /* Set the previous process back to running */
259 setProcessToRunning(ss, ts, currentThreadNode);
260
261 /* Set the CPU status back to "busy" or "idle" */
262 cpuExitInterrupt(ss, ts, currentCPUNode, currentThreadNode);
263 }
264 break;
265
266 case SOFT_IRQ_RAISE_INDEX:
267 /* Fields: int32 vec */
268 {
269 Integer softIrqId = ((Long) event.getContent().getField(fLayout.fieldVec()).getValue()).intValue();
270
271 /* Mark this SoftIRQ as *raised* in the resource tree.
272 * State value = -2 */
273 quark = ss.getQuarkRelativeAndAdd(getNodeSoftIRQs(ss), softIrqId.toString());
274 value = StateValues.SOFT_IRQ_RAISED_VALUE;
275 ss.modifyAttribute(ts, value, quark);
276 }
277 break;
278
279 case SCHED_SWITCH_INDEX:
280 {
281 ITmfEventField content = event.getContent();
282 Integer prevTid = ((Long) content.getField(fLayout.fieldPrevTid()).getValue()).intValue();
283 Long prevState = (Long) content.getField(fLayout.fieldPrevState()).getValue();
284 String nextProcessName = (String) content.getField(fLayout.fieldNextComm()).getValue();
285 Integer nextTid = ((Long) content.getField(fLayout.fieldNextTid()).getValue()).intValue();
286 Integer nextPrio = ((Long) content.getField(fLayout.fieldNextPrio()).getValue()).intValue();
287
288 Integer formerThreadNode = ss.getQuarkRelativeAndAdd(getNodeThreads(ss), prevTid.toString());
289 Integer newCurrentThreadNode = ss.getQuarkRelativeAndAdd(getNodeThreads(ss), nextTid.toString());
290
291 /*
292 * Empirical observations and look into the linux code have
293 * shown that the TASK_STATE_MAX flag is used internally and
294 * |'ed with other states, most often the running state, so it
295 * is ignored from the prevState value.
296 */
297 prevState = prevState & ~(LinuxValues.TASK_STATE_MAX);
298
299 /* Set the status of the process that got scheduled out. */
300 switch (prevState.intValue()) {
301 case LinuxValues.TASK_STATE_RUNNING:
302 value = StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE;
303 break;
304 case LinuxValues.TASK_INTERRUPTIBLE:
305 case LinuxValues.TASK_UNINTERRUPTIBLE:
306 value = StateValues.PROCESS_STATUS_WAIT_BLOCKED_VALUE;
307 break;
308 case LinuxValues.TASK_DEAD:
309 value = TmfStateValue.nullValue();
310 break;
311 default:
312 value = StateValues.PROCESS_STATUS_WAIT_UNKNOWN_VALUE;
313 break;
314 }
315
316 quark = ss.getQuarkRelativeAndAdd(formerThreadNode, Attributes.STATUS);
317 ss.modifyAttribute(ts, value, quark);
318
319 /* Set the status of the new scheduled process */
320 setProcessToRunning(ss, ts, newCurrentThreadNode);
321
322 /* Set the exec name of the new process */
323 quark = ss.getQuarkRelativeAndAdd(newCurrentThreadNode, Attributes.EXEC_NAME);
324 value = TmfStateValue.newValueString(nextProcessName);
325 ss.modifyAttribute(ts, value, quark);
326
327 /* Set the current prio for the new process */
328 quark = ss.getQuarkRelativeAndAdd(newCurrentThreadNode, Attributes.PRIO);
329 value = TmfStateValue.newValueInt(nextPrio);
330 ss.modifyAttribute(ts, value, quark);
331
332 /* Make sure the PPID and system_call sub-attributes exist */
333 ss.getQuarkRelativeAndAdd(newCurrentThreadNode, Attributes.SYSTEM_CALL);
334 ss.getQuarkRelativeAndAdd(newCurrentThreadNode, Attributes.PPID);
335
336 /* Set the current scheduled process on the relevant CPU */
337 quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.CURRENT_THREAD);
338 value = TmfStateValue.newValueInt(nextTid);
339 ss.modifyAttribute(ts, value, quark);
340
341 /* Set the status of the CPU itself */
342 if (nextTid > 0) {
343 /* Check if the entering process is in kernel or user mode */
344 quark = ss.getQuarkRelativeAndAdd(newCurrentThreadNode, Attributes.SYSTEM_CALL);
345 if (ss.queryOngoingState(quark).isNull()) {
346 value = StateValues.CPU_STATUS_RUN_USERMODE_VALUE;
347 } else {
348 value = StateValues.CPU_STATUS_RUN_SYSCALL_VALUE;
349 }
350 } else {
351 value = StateValues.CPU_STATUS_IDLE_VALUE;
352 }
353 quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.STATUS);
354 ss.modifyAttribute(ts, value, quark);
355 }
356 break;
357
358 case SCHED_PI_SETPRIO_INDEX:
359 {
360 ITmfEventField content = event.getContent();
361 Integer tid = ((Long) content.getField(fLayout.fieldTid()).getValue()).intValue();
362 Integer prio = ((Long) content.getField(fLayout.fieldNewPrio()).getValue()).intValue();
363
364 Integer updateThreadNode = ss.getQuarkRelativeAndAdd(getNodeThreads(ss), tid.toString());
365
366 /* Set the current prio for the new process */
367 quark = ss.getQuarkRelativeAndAdd(updateThreadNode, Attributes.PRIO);
368 value = TmfStateValue.newValueInt(prio);
369 ss.modifyAttribute(ts, value, quark);
370 }
371 break;
372
373 case SCHED_PROCESS_FORK_INDEX:
374 {
375 ITmfEventField content = event.getContent();
376 // String parentProcessName = (String) event.getFieldValue("parent_comm");
377 String childProcessName = (String) content.getField(fLayout.fieldChildComm()).getValue();
378 // assert ( parentProcessName.equals(childProcessName) );
379
380 Integer parentTid = ((Long) content.getField(fLayout.fieldParentTid()).getValue()).intValue();
381 Integer childTid = ((Long) content.getField(fLayout.fieldChildTid()).getValue()).intValue();
382
383 Integer parentTidNode = ss.getQuarkRelativeAndAdd(getNodeThreads(ss), parentTid.toString());
384 Integer childTidNode = ss.getQuarkRelativeAndAdd(getNodeThreads(ss), childTid.toString());
385
386 /* Assign the PPID to the new process */
387 quark = ss.getQuarkRelativeAndAdd(childTidNode, Attributes.PPID);
388 value = TmfStateValue.newValueInt(parentTid);
389 ss.modifyAttribute(ts, value, quark);
390
391 /* Set the new process' exec_name */
392 quark = ss.getQuarkRelativeAndAdd(childTidNode, Attributes.EXEC_NAME);
393 value = TmfStateValue.newValueString(childProcessName);
394 ss.modifyAttribute(ts, value, quark);
395
396 /* Set the new process' status */
397 quark = ss.getQuarkRelativeAndAdd(childTidNode, Attributes.STATUS);
398 value = StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE;
399 ss.modifyAttribute(ts, value, quark);
400
401 /* Set the process' syscall name, to be the same as the parent's */
402 quark = ss.getQuarkRelativeAndAdd(parentTidNode, Attributes.SYSTEM_CALL);
403 value = ss.queryOngoingState(quark);
404 if (value.isNull()) {
405 /*
406 * Maybe we were missing info about the parent? At least we
407 * will set the child right. Let's suppose "sys_clone".
408 */
409 value = TmfStateValue.newValueString(fLayout.eventSyscallEntryPrefix() + IKernelAnalysisEventLayout.INITIAL_SYSCALL_NAME);
410 }
411 quark = ss.getQuarkRelativeAndAdd(childTidNode, Attributes.SYSTEM_CALL);
412 ss.modifyAttribute(ts, value, quark);
413 }
414 break;
415
416 case SCHED_PROCESS_EXIT_INDEX:
417 break;
418
419 case SCHED_PROCESS_FREE_INDEX:
420 {
421 Integer tid = ((Long) event.getContent().getField(fLayout.fieldTid()).getValue()).intValue();
422 /*
423 * Remove the process and all its sub-attributes from the
424 * current state
425 */
426 quark = ss.getQuarkRelativeAndAdd(getNodeThreads(ss), tid.toString());
427 ss.removeAttribute(ts, quark);
428 }
429 break;
430
431 case STATEDUMP_PROCESS_STATE_INDEX:
432 /* LTTng-specific */
433 {
434 ITmfEventField content = event.getContent();
435 int tid = ((Long) content.getField("tid").getValue()).intValue(); //$NON-NLS-1$
436 int pid = ((Long) content.getField("pid").getValue()).intValue(); //$NON-NLS-1$
437 int ppid = ((Long) content.getField("ppid").getValue()).intValue(); //$NON-NLS-1$
438 int status = ((Long) content.getField("status").getValue()).intValue(); //$NON-NLS-1$
439 String name = (String) content.getField("name").getValue(); //$NON-NLS-1$
440 /*
441 * "mode" could be interesting too, but it doesn't seem to be
442 * populated with anything relevant for now.
443 */
444
445 int curThreadNode = ss.getQuarkRelativeAndAdd(getNodeThreads(ss), String.valueOf(tid));
446
447 /* Set the process' name */
448 quark = ss.getQuarkRelativeAndAdd(curThreadNode, Attributes.EXEC_NAME);
449 if (ss.queryOngoingState(quark).isNull()) {
450 /* If the value didn't exist previously, set it */
451 value = TmfStateValue.newValueString(name);
452 ss.modifyAttribute(ts, value, quark);
453 }
454
455 /* Set the process' PPID */
456 quark = ss.getQuarkRelativeAndAdd(curThreadNode, Attributes.PPID);
457 if (ss.queryOngoingState(quark).isNull()) {
458 if (pid == tid) {
459 /* We have a process. Use the 'PPID' field. */
460 value = TmfStateValue.newValueInt(ppid);
461 } else {
462 /* We have a thread, use the 'PID' field for the parent. */
463 value = TmfStateValue.newValueInt(pid);
464 }
465 ss.modifyAttribute(ts, value, quark);
466 }
467
468 /* Set the process' status */
469 quark = ss.getQuarkRelativeAndAdd(curThreadNode, Attributes.STATUS);
470 if (ss.queryOngoingState(quark).isNull()) {
471 switch (status) {
472 case LinuxValues.STATEDUMP_PROCESS_STATUS_WAIT_CPU:
473 value = StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE;
474 break;
475 case LinuxValues.STATEDUMP_PROCESS_STATUS_WAIT:
476 /*
477 * We have no information on what the process is waiting
478 * on (unlike a sched_switch for example), so we will
479 * use the WAIT_UNKNOWN state instead of the "normal"
480 * WAIT_BLOCKED state.
481 */
482 value = StateValues.PROCESS_STATUS_WAIT_UNKNOWN_VALUE;
483 break;
484 default:
485 value = StateValues.PROCESS_STATUS_UNKNOWN_VALUE;
486 }
487 ss.modifyAttribute(ts, value, quark);
488 }
489 }
490 break;
491
492 case SCHED_WAKEUP_INDEX:
493 {
494 final int tid = ((Long) event.getContent().getField(fLayout.fieldTid()).getValue()).intValue();
495 final int prio = ((Long) event.getContent().getField(fLayout.fieldPrio()).getValue()).intValue();
496 final int threadNode = ss.getQuarkRelativeAndAdd(getNodeThreads(ss), String.valueOf(tid));
497
498 /*
499 * The process indicated in the event's payload is now ready to
500 * run. Assign it to the "wait for cpu" state, but only if it
501 * was not already running.
502 */
503 quark = ss.getQuarkRelativeAndAdd(threadNode, Attributes.STATUS);
504 int status = ss.queryOngoingState(quark).unboxInt();
505
506 if (status != StateValues.PROCESS_STATUS_RUN_SYSCALL &&
507 status != StateValues.PROCESS_STATUS_RUN_USERMODE) {
508 value = StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE;
509 ss.modifyAttribute(ts, value, quark);
510 }
511
512 /*
513 * When a user changes a threads prio (e.g. with pthread_setschedparam),
514 * it shows in ftrace with a sched_wakeup.
515 */
516 quark = ss.getQuarkRelativeAndAdd(threadNode, Attributes.PRIO);
517 value = TmfStateValue.newValueInt(prio);
518 ss.modifyAttribute(ts, value, quark);
519 }
520 break;
521
522 default:
523 /* Other event types not covered by the main switch */
524 {
525 if (eventName.startsWith(fLayout.eventSyscallEntryPrefix())
526 || eventName.startsWith(fLayout.eventCompatSyscallEntryPrefix())) {
527
528 /* Assign the new system call to the process */
529 quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.SYSTEM_CALL);
530 value = TmfStateValue.newValueString(eventName);
531 ss.modifyAttribute(ts, value, quark);
532
533 /* Put the process in system call mode */
534 quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.STATUS);
535 value = StateValues.PROCESS_STATUS_RUN_SYSCALL_VALUE;
536 ss.modifyAttribute(ts, value, quark);
537
538 /* Put the CPU in system call (kernel) mode */
539 quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.STATUS);
540 value = StateValues.CPU_STATUS_RUN_SYSCALL_VALUE;
541 ss.modifyAttribute(ts, value, quark);
542
543 } else if (eventName.startsWith(fLayout.eventSyscallExitPrefix())) {
544
545 /* Clear the current system call on the process */
546 quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.SYSTEM_CALL);
547 value = TmfStateValue.nullValue();
548 ss.modifyAttribute(ts, value, quark);
549
550 /* Put the process' status back to user mode */
551 quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.STATUS);
552 value = StateValues.PROCESS_STATUS_RUN_USERMODE_VALUE;
553 ss.modifyAttribute(ts, value, quark);
554
555 /* Put the CPU's status back to user mode */
556 quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.STATUS);
557 value = StateValues.CPU_STATUS_RUN_USERMODE_VALUE;
558 ss.modifyAttribute(ts, value, quark);
559 }
560
561 }
562 break;
563 } // End of big switch
564
565 } catch (AttributeNotFoundException ae) {
566 /*
567 * This would indicate a problem with the logic of the manager here,
568 * so it shouldn't happen.
569 */
570 ae.printStackTrace();
571
572 } catch (TimeRangeException tre) {
573 /*
574 * This would happen if the events in the trace aren't ordered
575 * chronologically, which should never be the case ...
576 */
577 System.err.println("TimeRangeExcpetion caught in the state system's event manager."); //$NON-NLS-1$
578 System.err.println("Are the events in the trace correctly ordered?"); //$NON-NLS-1$
579 tre.printStackTrace();
580
581 } catch (StateValueTypeException sve) {
582 /*
583 * This would happen if we were trying to push/pop attributes not of
584 * type integer. Which, once again, should never happen.
585 */
586 sve.printStackTrace();
587 }
588 }
589
590 // ------------------------------------------------------------------------
591 // Convenience methods for commonly-used attribute tree locations
592 // ------------------------------------------------------------------------
593
594 private static int getNodeCPUs(ITmfStateSystemBuilder ssb) {
595 return ssb.getQuarkAbsoluteAndAdd(Attributes.CPUS);
596 }
597
598 private static int getNodeThreads(ITmfStateSystemBuilder ssb) {
599 return ssb.getQuarkAbsoluteAndAdd(Attributes.THREADS);
600 }
601
602 private static int getNodeIRQs(ITmfStateSystemBuilder ssb) {
603 return ssb.getQuarkAbsoluteAndAdd(Attributes.RESOURCES, Attributes.IRQS);
604 }
605
606 private static int getNodeSoftIRQs(ITmfStateSystemBuilder ssb) {
607 return ssb.getQuarkAbsoluteAndAdd(Attributes.RESOURCES, Attributes.SOFT_IRQS);
608 }
609
610 // ------------------------------------------------------------------------
611 // Advanced state-setting methods
612 // ------------------------------------------------------------------------
613
614 /**
615 * When we want to set a process back to a "running" state, first check
616 * its current System_call attribute. If there is a system call active, we
617 * put the process back in the syscall state. If not, we put it back in
618 * user mode state.
619 */
620 private static void setProcessToRunning(ITmfStateSystemBuilder ssb, long ts, int currentThreadNode)
621 throws AttributeNotFoundException, TimeRangeException,
622 StateValueTypeException {
623 int quark;
624 ITmfStateValue value;
625
626 quark = ssb.getQuarkRelativeAndAdd(currentThreadNode, Attributes.SYSTEM_CALL);
627 if (ssb.queryOngoingState(quark).isNull()) {
628 /* We were in user mode before the interruption */
629 value = StateValues.PROCESS_STATUS_RUN_USERMODE_VALUE;
630 } else {
631 /* We were previously in kernel mode */
632 value = StateValues.PROCESS_STATUS_RUN_SYSCALL_VALUE;
633 }
634 quark = ssb.getQuarkRelativeAndAdd(currentThreadNode, Attributes.STATUS);
635 ssb.modifyAttribute(ts, value, quark);
636 }
637
638 /**
639 * Similar logic as above, but to set the CPU's status when it's coming out
640 * of an interruption.
641 */
642 private static void cpuExitInterrupt(ITmfStateSystemBuilder ssb, long ts,
643 int currentCpuNode, int currentThreadNode)
644 throws StateValueTypeException, AttributeNotFoundException,
645 TimeRangeException {
646 int quark;
647 ITmfStateValue value;
648
649 quark = ssb.getQuarkRelativeAndAdd(currentCpuNode, Attributes.CURRENT_THREAD);
650 if (ssb.queryOngoingState(quark).unboxInt() > 0) {
651 /* There was a process on the CPU */
652 quark = ssb.getQuarkRelative(currentThreadNode, Attributes.SYSTEM_CALL);
653 if (ssb.queryOngoingState(quark).isNull()) {
654 /* That process was in user mode */
655 value = StateValues.CPU_STATUS_RUN_USERMODE_VALUE;
656 } else {
657 /* That process was in a system call */
658 value = StateValues.CPU_STATUS_RUN_SYSCALL_VALUE;
659 }
660 } else {
661 /* There was no real process scheduled, CPU was idle */
662 value = StateValues.CPU_STATUS_IDLE_VALUE;
663 }
664 quark = ssb.getQuarkRelativeAndAdd(currentCpuNode, Attributes.STATUS);
665 ssb.modifyAttribute(ts, value, quark);
666 }
667 }
This page took 0.059817 seconds and 5 git commands to generate.