[291622] Contribution for LTTng JNI improvement
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng / src / org / eclipse / linuxtools / lttng / state / evProcessor / state / AbsStateUpdate.java
CommitLineData
5d10d135
ASL
1/*******************************************************************************
2 * Copyright (c) 2009 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
11 *******************************************************************************/
12package org.eclipse.linuxtools.lttng.state.evProcessor.state;
13
58c60db3 14import java.util.List;
5d10d135
ASL
15
16import org.eclipse.linuxtools.lttng.TraceDebug;
17import org.eclipse.linuxtools.lttng.event.LttngEvent;
58c60db3 18import org.eclipse.linuxtools.lttng.event.LttngEventField;
5d10d135 19import org.eclipse.linuxtools.lttng.state.StateStrings;
58c60db3 20import org.eclipse.linuxtools.lttng.state.StateStrings.Fields;
5d10d135
ASL
21import org.eclipse.linuxtools.lttng.state.StateStrings.IRQMode;
22import org.eclipse.linuxtools.lttng.state.StateStrings.ProcessStatus;
88144d4a 23import org.eclipse.linuxtools.lttng.state.evProcessor.IEventProcessing;
5d10d135
ASL
24import org.eclipse.linuxtools.lttng.state.model.LTTngCPUState;
25import org.eclipse.linuxtools.lttng.state.model.LttngBdevState;
26import org.eclipse.linuxtools.lttng.state.model.LttngExecutionState;
27import org.eclipse.linuxtools.lttng.state.model.LttngIRQState;
28import org.eclipse.linuxtools.lttng.state.model.LttngProcessState;
29import org.eclipse.linuxtools.lttng.state.model.LttngTraceState;
58c60db3 30import org.eclipse.linuxtools.tmf.event.TmfEventField;
5d10d135
ASL
31import org.eclipse.linuxtools.tmf.event.TmfTimestamp;
32
58c60db3 33public abstract class AbsStateUpdate implements IEventProcessing {
5d10d135
ASL
34
35 // ========================================================================
36 // Data
37 // =======================================================================
38 protected static final Long ANY_CPU = 0L;
39
40 // ========================================================================
41 // push and pop from stack
42 // =======================================================================
43 protected void push_state(Long cpu, StateStrings.ExecutionMode execMode,
44 String submode, TmfTimestamp eventTime, LttngTraceState traceSt) {
45
46 LttngProcessState process = traceSt.getRunning_process().get(cpu);
47 LttngExecutionState exe_state = new LttngExecutionState();
48 exe_state.setExec_mode(execMode);
49 exe_state.setExec_submode(submode);
58c60db3
FC
50 exe_state.setEntry_Time(eventTime);
51 exe_state.setChange_Time(eventTime);
5d10d135 52 exe_state.setCum_cpu_time(0L);
88144d4a 53 exe_state.setProc_status(process.getState().getProc_status());
58c60db3 54 process.setState(exe_state);
5d10d135
ASL
55 process.pushToExecutionStack(exe_state);
56 }
57
58 protected void pop_state(Long cpu, StateStrings.ExecutionMode execMode,
59 LttngTraceState traceSt, TmfTimestamp eventTime) {
60
61 LttngProcessState process = traceSt.getRunning_process().get(cpu);
62
63 if (!process.getState().getExec_mode().equals(execMode)) {
64 // Different execution mode
65 TraceDebug.debug("Different Execution Mode type \n\tTime:"
66 + eventTime.toString() + "\n\tprocess state has: \n\t"
67 + process.getState().getExec_mode().toString()
68 + "\n\twhen pop_int is:\n\t" + execMode.toString());
69 return;
70 }
71
5d10d135 72 process.popFromExecutionStack();
58c60db3
FC
73 process.setState(process.peekFromExecutionStack());
74 process.getState().setChange_Time(eventTime);
5d10d135
ASL
75 }
76
77 protected void irq_push_mode(LttngIRQState irqst, IRQMode state) {
78 irqst.pushToIrqStack(state);
79 }
80
81 protected void irq_set_base_mode(LttngIRQState irqst, IRQMode state) {
82 irqst.clearAndSetBaseToIrqStack(state);
83 }
84
85 protected void irq_pop_mode(LttngIRQState irqst) {
86 irqst.popFromIrqStack();
87 }
88
89 protected void cpu_push_mode(LTTngCPUState cpust, StateStrings.CpuMode state) {
90 // The initialization (init) creates a LttngCPUState instance per
91 // available cpu in the system
92 cpust.pushToCpuStack(state);
93 }
94
95 protected void cpu_pop_mode(LTTngCPUState cpust) {
96 cpust.popFromCpuStack();
97 }
98
99 /* clears the stack and sets the state passed as argument */
100 protected void cpu_set_base_mode(LTTngCPUState cpust,
101 StateStrings.CpuMode state) {
102 cpust.clearAndSetBaseToCpuStack(state);
103 }
104
105 protected void bdev_pop_mode(LttngBdevState bdevst) {
106 bdevst.popFromBdevStack();
107 }
108
109 /**
110 * Push a new received function pointer to the user_stack
111 *
112 * @param traceSt
113 * @param funcptr
114 * @param cpu
115 */
116 protected void push_function(LttngTraceState traceSt, Long funcptr, Long cpu) {
117 // Get the related process
118 LttngProcessState process = traceSt.getRunning_process().get(cpu);
119
120 // update stack
121 process.pushToUserStack(funcptr);
122
123 // update the pointer to the current function on the corresponding
124 // process
125 process.setCurrent_function(funcptr);
126 }
127
128 protected void pop_function(LttngTraceState traceSt, LttngEvent trcEvent,
129 Long funcptr) {
130 Long cpu = trcEvent.getCpuId();
131 LttngProcessState process = traceSt.getRunning_process().get(cpu);
132 Long curr_function = process.getCurrent_function();
133
134 if (curr_function != null && curr_function != funcptr) {
135 TraceDebug.debug("Different functions: " + funcptr + " current: "
136 + curr_function + " time stamp: "
137 + trcEvent.getTimestamp().toString());
138
139 // g_info("Different functions (%lu.%09lu): ignore it\n",
140 // tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
141 // g_info("process state has %" PRIu64 " when pop_function is %"
142 // PRIu64
143 // "\n",
144 // process->current_function, funcptr);
145 // g_info("{ %u, %u, %s, %s, %s }\n",
146 // process->pid,
147 // process->ppid,
148 // g_quark_to_string(process->name),
149 // g_quark_to_string(process->brand),
150 // g_quark_to_string(process->state->s));
151 return;
152 }
153
154 process.popFromUserStack();
155 process.setCurrent_function(process.peekFromUserStack());
156 }
157
158 // ========================================================================
159 // General methods
160 // =======================================================================
58c60db3
FC
161 /**
162 * protected method used when only one Field is expected with Type "Long" if
163 * the number of fields is greater, the first field is returned and a
164 * tracing message is sent Null is returned if the value could not be
165 * extracted.
166 *
167 * @param trcEvent
168 * @param traceSt
169 * @param expectedNumFields
170 * @return
171 */
172 protected Long getDField(LttngEvent trcEvent, LttngTraceState traceSt,
173 Fields expectedField) {
174 Long fieldVal = null;
175 TmfEventField[] fields = trcEvent.getContent().getFields();
176 String[] fieldLabels = trcEvent.getContent().getFormat().getLabels();
177
178 // Only one field expected
179 if (fields.length != 1 || fieldLabels.length != 1) {
180 StringBuilder sb = new StringBuilder(
181 "Unexpected number of fields received: " + fields.length
182 + " for Event: " + trcEvent.getMarkerName() + "\n\t\tFields: ");
183
184 for (TmfEventField field : fields) {
185 sb.append(((LttngEventField)field).getName() + " ");
186 }
187
188 TraceDebug.debug(sb.toString());
189 if (fields.length == 0) {
190 return null;
191 }
192 }
193
194 LttngEventField field = (LttngEventField) fields[0];
195 String fieldname = field.getName();
196 String expectedFieldName = expectedField.getInName();
197 if (fieldname.equals(expectedFieldName)) {
198 Object fieldObj = field.getValue();
199 if (fieldObj instanceof Long) {
200 // Expected value found
201 fieldVal = (Long) field.getValue();
202 } else {
203 if (TraceDebug.isDEBUG()) {
204 TraceDebug
205 .debug("Unexpected field Type. Expected: Long, Received: "
206 + fieldObj.getClass().getSimpleName());
207 }
208 return null;
209 }
210 } else {
211 TraceDebug.debug("Unexpected field received: " + fieldname
212 + " Expected: " + expectedFieldName);
213 return null;
214 }
215
216 return fieldVal;
217 }
218
219 /**
220 * protected method used when a Field is requested among several available
221 * fields and the expected type is Long
222 *
223 * @param trcEvent
224 * @param traceSt
225 * @param expectedNumFields
226 * @return
227 */
228 protected Long getAFieldLong(LttngEvent trcEvent, LttngTraceState traceSt,
229 Fields expectedField) {
230 Long fieldVal = null;
231 TmfEventField[] fields = trcEvent.getContent().getFields();
232
233 // At least one field expected
234 if (fields.length == 0) {
235 TraceDebug.debug("Unexpected number of fields received: "
236 + fields.length);
237 return null;
238 }
239
240 LttngEventField field;
241 String fieldname;
242 String expectedFieldName = expectedField.getInName();
243 for (int i = 0; i < fields.length; i++) {
244 field = (LttngEventField) fields[i];
245 fieldname = field.getName();
246 if (fieldname.equals(expectedFieldName)) {
247 Object fieldObj = field.getValue();
248 if (fieldObj instanceof Long) {
249 // Expected value found
250 fieldVal = (Long) field.getValue();
251 // if (expectedField == Fields.LTT_FIELD_TYPE) {
252 // TraceDebug.debug("Field Type value is: " + fieldVal);
253 // }
254 break;
255 } else {
256 if (TraceDebug.isDEBUG()) {
257 TraceDebug
258 .debug("Unexpected field Type. Expected: Long, Received: "
259 + fieldObj.getClass().getSimpleName());
260 }
261 return null;
262 }
263 }
264 }
265
266 if (fieldVal == null) {
267 if (TraceDebug.isDEBUG()) {
268 sendNoFieldFoundMsg(fields, expectedFieldName);
269 }
270 }
271 return fieldVal;
272 }
273
274 /**
275 * protected method used when a Field is requested among several available
276 * fields and the expected type is String
277 *
278 * @param trcEvent
279 * @param traceSt
280 * @param expectedNumFields
281 * @return
282 */
283 protected String getAFieldString(LttngEvent trcEvent,
284 LttngTraceState traceSt, Fields expectedField) {
285 String fieldVal = null;
286 TmfEventField[] fields = trcEvent.getContent().getFields();
287
288 // Only one field expected
289 if (fields.length == 0) {
290 TraceDebug.debug("Unexpected number of fields received: "
291 + fields.length);
292 return null;
293 }
294
295 LttngEventField field;
296 String fieldname;
297 String expectedFieldName = expectedField.getInName();
298 for (int i = 0; i < fields.length; i++) {
299 field = (LttngEventField) fields[i];
300 fieldname = field.getName();
301 if (fieldname.equals(expectedFieldName)) {
302 Object fieldObj = field.getValue();
303 if (fieldObj instanceof String) {
304 // Expected value found
305 fieldVal = (String) field.getValue();
306 break;
307 } else {
308 if (TraceDebug.isDEBUG()) {
309 TraceDebug
310 .debug("Unexpected field Type. Expected: String, Received: "
311 + fieldObj.getClass().getSimpleName());
312 }
313 return null;
314 }
315 }
316 }
317
318 if (fieldVal == null) {
319 if (TraceDebug.isDEBUG()) {
320 sendNoFieldFoundMsg(fields, expectedFieldName);
321 }
322 }
323 return fieldVal;
324 }
325
326 protected void sendNoFieldFoundMsg(TmfEventField[] fields,
327 String expectedFieldName) {
328 LttngEventField field;
329 StringBuilder sb = new StringBuilder("Field not found, requested: "
330 + expectedFieldName);
331 sb.append(" number of fields: " + fields.length + "Fields: ");
332 for (int i = 0; i < fields.length; i++) {
333 field = (LttngEventField) fields[i];
334 sb.append(field.getName() + " ");
335 }
336
337 TraceDebug.debug(sb.toString(), 5);
338 }
339
5d10d135
ASL
340 // Adaption from MKDEV macro
341 protected Long mkdev(Long major, Long minor) {
342 Long result = null;
343 if (major != null && minor != null) {
344 result = (major << 20) | minor;
345 }
346 return result;
347 }
348
349 /*
350 * FIXME : this function should be called when we receive an event telling
351 * that release_task has been called in the kernel. In happens generally
58c60db3 352 * when the parent waits for its child terminaison, but may also happen in
5d10d135
ASL
353 * special cases in the child's exit : when the parent ignores its children
354 * SIGCCHLD or has the flag SA_NOCLDWAIT. It can also happen when the child
355 * is part of a killed thread group, but isn't the leader.
356 */
357 protected boolean exit_process(LttngTraceState ts, LttngProcessState process) {
358 /*
359 * Wait for both schedule with exit dead and process free to happen.
360 * They can happen in any order.
361 */
362 process.incrementFree_events();
363 if (process.getFree_events() < 2) {
364 return false;
365 }
366
367 process.clearExecutionStack();
368 process.clearUserStack();
58c60db3 369 ts.getProcesses().remove(process);
5d10d135
ASL
370
371 return true;
372 }
373
58c60db3
FC
374 /**
375 * Find the process matching the given pid and cpu
376 *
377 * If cpu is 0, the cpu value is not matched and the selection is based on
378 * pid value only
379 *
380 * @param ts
381 * @param cpu
382 * @param pid
383 * @return
384 */
385 protected LttngProcessState lttv_state_find_process(LttngTraceState ts,
386 Long cpu, Long pid) {
387 // Define the return value
388 LttngProcessState process = null;
389
390 // Obtain the list of available processes
391 List<LttngProcessState> processList = ts.getProcesses();
392
393 // find the process matching pid and cpu,
394 // TODO: This may need to be improved since the pid may be re-used and
395 // the creation time may need to be considered.
396 // NOTE: A hash search shall be used
397 for (LttngProcessState dprocess : processList) {
398 if (dprocess.getPid().equals(pid)) {
399 if (dprocess.getCpu().equals(cpu) || cpu.longValue() == 0L) {
400 return dprocess;
401 }
402 }
403 }
404
405 return process;
406 }
407
408 /**
409 * @param ts
410 * @param cpu
411 * @param pid
412 * @param timestamp
413 * , Used when a new process is needed
414 * @return
415 */
416 protected LttngProcessState lttv_state_find_process_or_create(
417 LttngTraceState ts, Long cpu, Long pid, final TmfTimestamp timestamp) {
418
419 LttngProcessState process = lttv_state_find_process(ts, cpu, pid);
420 /* Put ltt_time_zero creation time for unexisting processes */
421 if (process == null) {
422 process = create_process(ts, cpu, pid, 0L, timestamp);
423 }
424 return process;
425 }
426
5d10d135
ASL
427 /**
428 * @param traceSt
429 * @param cpu
430 * @param pid
431 * @param tgid
432 * @param timestamp
433 * @return
434 */
435 protected LttngProcessState create_process(LttngTraceState traceSt,
436 Long cpu, Long pid, Long tgid, final TmfTimestamp timestamp) {
437 LttngProcessState process = create_process(traceSt, cpu, pid, tgid,
438 ProcessStatus.LTTV_STATE_UNNAMED.getInName(), timestamp);
439 return process;
440 }
441
442 /**
443 * @param traceSt
444 * @param cpu
445 * @param pid
446 * @param tgid
447 * @param name
448 * @param timestamp
449 * @return
450 */
451 protected LttngProcessState create_process(LttngTraceState traceSt,
452 Long cpu, Long pid, Long tgid, String name,
453 final TmfTimestamp timestamp) {
454 LttngProcessState process;
58c60db3
FC
455 process = new LttngProcessState(cpu, pid, tgid, name, timestamp);
456 traceSt.getProcesses().add(process);
5d10d135
ASL
457 return process;
458 }
459
460}
This page took 0.043097 seconds and 5 git commands to generate.