lttng: Move CTF dummy state provider to the test package
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng2.kernel.core / src / org / eclipse / linuxtools / internal / lttng2 / kernel / core / stateprovider / CtfKernelHandler.java
CommitLineData
efc403bb
AM
1/*******************************************************************************
2 * Copyright (c) 2012 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
13package org.eclipse.linuxtools.internal.lttng2.kernel.core.stateprovider;
14
15import java.util.HashMap;
16import java.util.Vector;
17import java.util.concurrent.BlockingQueue;
18
19import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfEvent;
20import org.eclipse.linuxtools.tmf.core.event.ITmfEventField;
21import org.eclipse.linuxtools.tmf.core.statesystem.AttributeNotFoundException;
22import org.eclipse.linuxtools.tmf.core.statesystem.StateHistorySystem;
23import org.eclipse.linuxtools.tmf.core.statesystem.StateSystem;
24import org.eclipse.linuxtools.tmf.core.statesystem.TimeRangeException;
25import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue;
26import org.eclipse.linuxtools.tmf.core.statevalue.StateValueTypeException;
27import org.eclipse.linuxtools.tmf.core.statevalue.TmfStateValue;
28
29/**
30 * This is the reference "state provider" for LTTng 2.0 kernel traces.
31 *
32 * @author alexmont
33 *
34 */
dc0f7bfe 35class CtfKernelHandler implements Runnable {
efc403bb
AM
36
37 private final BlockingQueue<CtfTmfEvent> inQueue;
38 private StateSystem ss;
39
40 private CtfTmfEvent currentEvent;
41
42 /*
43 * We can keep handles to some Attribute Nodes so these don't need to be
44 * re-found (re-hashed Strings etc.) every new event
45 */
46 Vector<Integer> currentCPUNodes;
47 Vector<Integer> currentThreadNodes;
48
49 /* Event names HashMap. TODO: This can be discarded once we move to Java 7 */
50 private final HashMap<String, Integer> knownEventNames;
51
dc0f7bfe 52 CtfKernelHandler(BlockingQueue<CtfTmfEvent> eventsQueue) {
efc403bb
AM
53 assert (eventsQueue != null);
54 this.inQueue = eventsQueue;
55 currentCPUNodes = new Vector<Integer>();
56 currentThreadNodes = new Vector<Integer>();
57
58 knownEventNames = fillEventNames();
59 }
60
61 void assignStateSystem(StateSystem targetSS) {
62 this.ss = targetSS;
63 }
64
65 StateSystem getStateSystem() {
66 return ss;
67 }
68
69 @Override
70 public void run() {
71 if (ss == null) {
72 System.err.println("Cannot run event manager without assigning a target state system first!"); //$NON-NLS-1$
73 return;
74 }
75 CtfTmfEvent event;
76
77 try {
78 event = inQueue.take();
f13dfe18 79 while (event.getTimestampValue() != -1) {
efc403bb
AM
80 processEvent(event);
81 event = inQueue.take();
82 }
83 /* We've received the last event, clean up */
84 closeStateSystem();
85 return;
86 } catch (InterruptedException e) {
87 /* We've been interrupted abnormally */
88 System.out.println("Event handler interrupted!"); //$NON-NLS-1$
89 e.printStackTrace();
90 }
91 }
92
93 private void closeStateSystem() {
94 /* Close the History system, if there is one */
95 if (ss.getClass() == StateHistorySystem.class) {
96 try {
97 ((StateHistorySystem) ss).closeHistory(currentEvent.getTimestamp().getValue());
98 } catch (TimeRangeException e) {
99 /*
100 * Since we're using currentEvent.getTimestamp, this shouldn't
101 * cause any problem
102 */
103 e.printStackTrace();
104 }
105 }
106 }
107
108 @SuppressWarnings("nls")
109 private void processEvent(CtfTmfEvent event) {
110 currentEvent = event;
111 ITmfEventField content = event.getContent();
2130a4fb 112 String eventName = event.getEventName();
efc403bb
AM
113
114 long ts = event.getTimestamp().getValue();
115 int quark;
116 ITmfStateValue value;
117 Integer eventCpu = event.getCPU();
118 Integer currentCPUNode, currentThreadNode, tidNode;
119
120 /* Adjust the current nodes Vectors if we see a new CPU in an event */
121 if (eventCpu >= currentCPUNodes.size()) {
122 /* We need to add this node to the vector */
123 for (Integer i = currentCPUNodes.size(); i < eventCpu + 1; i++) {
124 quark = ss.getQuarkAbsoluteAndAdd("CPUs", i.toString());
125 currentCPUNodes.add(quark);
126
127 quark = ss.getQuarkAbsoluteAndAdd("Threads", "unknown");
128 currentThreadNodes.add(quark);
129 }
130 }
131
132 currentCPUNode = currentCPUNodes.get(eventCpu);
133 currentThreadNode = currentThreadNodes.get(eventCpu);
134 assert (currentCPUNode != null);
135 assert (currentThreadNode != null);
136
137 try {
138 /*
139 * Feed event to the history system if it's known to cause a state
140 * transition See:
141 * https://projectwiki.dorsal.polymtl.ca/index.php/State_transitions
142 */
143 switch (getEventIndex(eventName)) {
144
145 case 1: // "exit_syscall":
146 /* Fields: int64 ret */
147 /* Pop "syscall" from the Exec_mode_stack */
148 quark = ss.getQuarkRelativeAndAdd(currentThreadNode,
149 "Exec_mode_stack");
150 try {
151 ss.popAttribute(ts, quark);
152 } catch (AttributeNotFoundException e1) {
153 /*
154 * meh, can happen if we're missing events, we'll just
155 * silently ignore it.
156 */
157 System.err.println(event.getTimestamp()
158 + " Popping empty attribute: " + e1.getMessage()); //$NON-NLS-1$
159 }
160 break;
161
162 case 2: // "irq_handler_entry":
163 /* Fields: int32 irq, string name */
164 Integer irqId = ((Long) content.getField("irq").getValue()).intValue();
165
166 /* Push the IRQ to the CPU's IRQ_stack */
167 quark = ss.getQuarkRelativeAndAdd(currentCPUNode, "IRQ_stack");
168 value = TmfStateValue.newValueInt(irqId);
169 ss.pushAttribute(ts, value, quark);
170
171 /* Change the status of the running process to interrupted */
172 quark = ss.getQuarkRelativeAndAdd(currentThreadNode, "Status");
173 value = TmfStateValue.newValueInt(STATE_PROCESS_STATUS_WAIT_CPU);
174 ss.modifyAttribute(ts, value, quark);
175 break;
176
177 case 3: // "irq_handler_exit":
178 /* Fields: int32 irq, int32 ret */
179 int stackDepth = 0;
180
181 /* Pop the IRQ from the CPU's IRQ_stack */
182 quark = ss.getQuarkRelativeAndAdd(currentCPUNode, "IRQ_stack");
183 try {
184 ss.popAttribute(ts, quark);
185 } catch (AttributeNotFoundException e1) {
186 System.err.print(event.getTimestamp()
187 + " Popping empty attribute: " + e1.getMessage());
188 }
189
190 /*
191 * If this was the last IRQ on the stack, set the process back
192 * to running
193 */
194 /* 'quark' should still be valid */
195 try {
196 stackDepth = ss.queryOngoingState(quark).unboxInt();
197 } catch (StateValueTypeException e) {
198 /* IRQ_stack SHOULD be of int type, this shouldn't happen */
199 e.printStackTrace();
200 }
201 if (stackDepth == 0) {
202 quark = ss.getQuarkRelativeAndAdd(currentThreadNode,
203 "Status");
204 value = TmfStateValue.newValueInt(STATE_PROCESS_STATUS_RUN);
205 ss.modifyAttribute(ts, value, quark);
206 }
207 break;
208
209 case 4: // "softirq_entry":
210 /* Fields: int32 vec */
211 break;
212
213 case 5: // "softirq_exit":
214 /* Fields: int32 vec */
215 break;
216
217 case 6: // "softirq_raise":
218 /* Fields: int32 vec */
219 break;
220
221 case 7: // "sched_switch":
222 /*
223 * Fields: string prev_comm, int32 prev_tid, int32 prev_prio,
224 * int64 prev_state, string next_comm, int32 next_tid, int32
225 * next_prio
226 */
227
228 // prev_comm doesn't seem to get populated...
229 String prevProcessName = (String) content.getField("prev_comm").getValue();
230 Integer prevTid = ((Long) content.getField("prev_tid").getValue()).intValue();
231 Long prevState = (Long) content.getField("prev_state").getValue();
232
233 String nextProcessName = (String) content.getField("next_comm").getValue();
234 Integer nextTid = ((Long) content.getField("next_tid").getValue()).intValue();
235
236 /* Update the name of the process going out (if needed) */
237 quark = ss.getQuarkRelativeAndAdd(currentThreadNode,
238 "Exec_name");
239 value = TmfStateValue.newValueString(prevProcessName);
240 ss.updateOngoingState(value, quark);
241
242 /* Update the currentThreadNodes pointer */
243 Integer newCurrentThreadNode = ss.getQuarkAbsoluteAndAdd(
244 "Threads", nextTid.toString());
245 currentThreadNodes.set(eventCpu, newCurrentThreadNode);
246
247 /* Set the status of the new scheduled process */
248 quark = ss.getQuarkRelativeAndAdd(newCurrentThreadNode,
249 "Status");
250 value = TmfStateValue.newValueInt(STATE_PROCESS_STATUS_RUN);
251 ss.modifyAttribute(ts, value, quark);
252
253 /* Set the exec name of the new process */
254 quark = ss.getQuarkRelativeAndAdd(newCurrentThreadNode,
255 "Exec_name");
256 value = TmfStateValue.newValueString(nextProcessName);
257 ss.modifyAttribute(ts, value, quark);
258
259 /* Set the status of the process that got scheduled out */
260 quark = ss.getQuarkAbsoluteAndAdd("Threads",
261 prevTid.toString(), "Status");
262 value = TmfStateValue.newValueInt(prevState.intValue());
263 ss.modifyAttribute(ts, value, quark);
264
265 /* Set the current scheduled process on the relevant CPU */
266 quark = ss.getQuarkRelativeAndAdd(currentCPUNode,
267 "Current_thread");
268 value = TmfStateValue.newValueInt(nextTid);
269 ss.modifyAttribute(ts, value, quark);
270 break;
271
272 case 8: // "sched_process_fork":
273 /*
274 * Fields: string parent_comm, int32 parent_tid, string
275 * child_comm, int32 child_tid
276 */
277
278 // String parentProcessName = (String)
279 // event.getFieldValue("parent_comm");
634c67e6
AM
280 String childProcessName;
281 childProcessName = (String) content.getField("child_comm").getValue();
efc403bb
AM
282 // assert ( parentProcessName.equals(childProcessName) );
283
284 Integer parentTid = ((Long) content.getField("parent_tid").getValue()).intValue();
285 Integer childTid = ((Long) content.getField("child_tid").getValue()).intValue();
286
287 tidNode = ss.getQuarkAbsoluteAndAdd("Threads",
288 childTid.toString());
289
290 /*
291 * Add the new process with its known TID, PPID, and initial
292 * Exec_name
293 */
294 quark = ss.getQuarkRelativeAndAdd(tidNode, "PPID");
295 value = TmfStateValue.newValueInt(parentTid);
296 ss.modifyAttribute(ts, value, quark);
297
298 /* Set the new process' exec_name */
299 quark = ss.getQuarkRelativeAndAdd(tidNode, "Exec_name");
300 value = TmfStateValue.newValueString(childProcessName);
301 ss.modifyAttribute(ts, value, quark);
302 break;
303
304 case 9: // "sched_process_exit":
305 /* Fields: string comm, int32 tid, int32 prio */
306 String processName = (String) content.getField("comm").getValue();
307 Integer tid = ((Long) content.getField("tid").getValue()).intValue();
308
309 /* Update the process' name, if we don't have it */
310 quark = ss.getQuarkAbsoluteAndAdd("Threads", tid.toString(),
311 "Exec_name");
312 value = TmfStateValue.newValueString(processName);
313 ss.updateOngoingState(value, quark);
314
315 /*
316 * Remove the process and all its sub-attributes from the
317 * current state
318 */
319 quark = ss.getQuarkAbsoluteAndAdd("Threads", tid.toString());
320 ss.removeAttribute(ts, quark);
321 break;
322
323 case 10: // "sched_process_free":
324 /* Fields: string comm, int32 tid, int32 prio */
325 break;
326
327 // FIXME Not available with CTF. Use event context?
328 // case LTT_EVENT_EXEC:
329 // filename = new String((byte[]) event.getField(0));
330 //
331 // /* Change the Exec_name of the process */
332 // quark = ss.getQuarkRelativePath(true, currentThreadNode,
333 // "Exec_name");
334 // ss.modifyAttribute(ts, filename, quark);
335 // break;
336
337 default:
338 /* Other event types not covered by the main switch */
339
340 if (eventName.startsWith("sys_")
341 || eventName.startsWith("compat_sys_")) {
342 /*
343 * This is a replacement for the old sys_enter event. Now
344 * syscall names are listed into the event type
345 */
346
347 /*
348 * Push the syscall name on the Exec_mode_stack of the
349 * relevant PID
350 */
351 quark = ss.getQuarkRelativeAndAdd(currentThreadNode,
352 "Exec_mode_stack");
353 value = TmfStateValue.newValueString(eventName);
354 ss.pushAttribute(ts, value, quark);
355 }
356
357 break;
358 } // End of switch
359
360 /*
361 * Statistics
362 */
363
634c67e6
AM
364 /* Number of events of each type, globally */
365 // quark = ss.getQuarkAbsoluteAndAdd("Stats", "Event_types",
366 // eventName);
367 // ss.incrementAttribute(ts, quark);
368
369 /* Nb of events per CPU */
370 // quark = ss.getQuarkRelativeAndAdd(currentCPUNode, "Stats",
371 // "Event_types", eventName);
372 // ss.incrementAttribute(ts, quark);
373
374 /* Nb of events per process */
375 // quark = ss.getQuarkRelativeAndAdd(currentThreadNode, "Stats",
376 // "Event_types", eventName);
377 // ss.incrementAttribute(ts, quark);
efc403bb
AM
378
379 // end of big non-indented try
380 } catch (AttributeNotFoundException ae) {
381 /*
382 * This would indicate a problem with the logic of the manager here,
383 * so it shouldn't happen.
384 */
385 ae.printStackTrace();
386
387 } catch (TimeRangeException tre) {
388 /*
389 * This would happen if the events in the trace aren't ordered
390 * chronologically, which should never be the case ...
391 */
392 System.err.println("TimeRangeExcpetion caught in the state system's event manager.");
393 System.err.println("Are the events in the trace correctly ordered?");
394 tre.printStackTrace();
395
396 } catch (StateValueTypeException sve) {
397 /*
398 * This would happen if we were trying to push/pop attributes not of
399 * type integer. Which, once again, should never happen.
400 */
401 sve.printStackTrace();
402 }
403
404 }
405
406 @SuppressWarnings("nls")
407 private static HashMap<String, Integer> fillEventNames() {
408 /*
409 * TODO Replace with straight strings in the switch/case once we move to
410 * Java 7
411 */
412 /*
413 * This is still, imo, cleaner than the wtf-were-they-thinking Java
414 * Enums
415 */
416 HashMap<String, Integer> map = new HashMap<String, Integer>();
417
418 map.put("exit_syscall", 1);
419 map.put("irq_handler_entry", 2);
420 map.put("irq_handler_exit", 3);
421 map.put("softirq_entry", 4);
422 map.put("softirq_exit", 5);
423 map.put("softirq_raise", 6);
424 map.put("sched_switch", 7);
425 map.put("sched_process_fork", 8);
426 map.put("sched_process_exit", 9);
427 map.put("sched_process_free", 10);
428
429 return map;
430 }
431
432 private int getEventIndex(String eventName) {
433 Integer ret = knownEventNames.get(eventName);
434 return (ret != null) ? ret : -1;
435 }
436
437 /* Process status */
438 private final static int STATE_PROCESS_STATUS_WAIT_CPU = 1;
439 private final static int STATE_PROCESS_STATUS_RUN = 2;
440}
This page took 0.040659 seconds and 5 git commands to generate.