1 /*******************************************************************************
2 * Copyright (c) 2009 Ericsson
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
10 * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
11 *******************************************************************************/
12 package org
.eclipse
.linuxtools
.lttng
.state
.evProcessor
.state
;
14 import java
.util
.List
;
16 import org
.eclipse
.linuxtools
.lttng
.TraceDebug
;
17 import org
.eclipse
.linuxtools
.lttng
.event
.LttngEvent
;
18 import org
.eclipse
.linuxtools
.lttng
.event
.LttngEventField
;
19 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
;
20 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.Fields
;
21 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.IRQMode
;
22 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.ProcessStatus
;
23 import org
.eclipse
.linuxtools
.lttng
.state
.evProcessor
.IEventProcessing
;
24 import org
.eclipse
.linuxtools
.lttng
.state
.model
.LTTngCPUState
;
25 import org
.eclipse
.linuxtools
.lttng
.state
.model
.LttngBdevState
;
26 import org
.eclipse
.linuxtools
.lttng
.state
.model
.LttngExecutionState
;
27 import org
.eclipse
.linuxtools
.lttng
.state
.model
.LttngIRQState
;
28 import org
.eclipse
.linuxtools
.lttng
.state
.model
.LttngProcessState
;
29 import org
.eclipse
.linuxtools
.lttng
.state
.model
.LttngTraceState
;
30 import org
.eclipse
.linuxtools
.tmf
.event
.TmfEventField
;
31 import org
.eclipse
.linuxtools
.tmf
.event
.TmfTimestamp
;
33 public abstract class AbsStateUpdate
implements IEventProcessing
{
35 // ========================================================================
37 // =======================================================================
38 protected static final Long ANY_CPU
= 0L;
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
) {
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
);
50 exe_state
.setEntry_Time(eventTime
);
51 exe_state
.setChange_Time(eventTime
);
52 exe_state
.setCum_cpu_time(0L);
53 exe_state
.setProc_status(process
.getState().getProc_status());
54 process
.setState(exe_state
);
55 process
.pushToExecutionStack(exe_state
);
58 protected void pop_state(Long cpu
, StateStrings
.ExecutionMode execMode
,
59 LttngTraceState traceSt
, TmfTimestamp eventTime
) {
61 LttngProcessState process
= traceSt
.getRunning_process().get(cpu
);
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());
72 process
.popFromExecutionStack();
73 process
.setState(process
.peekFromExecutionStack());
74 process
.getState().setChange_Time(eventTime
);
77 protected void irq_push_mode(LttngIRQState irqst
, IRQMode state
) {
78 irqst
.pushToIrqStack(state
);
81 protected void irq_set_base_mode(LttngIRQState irqst
, IRQMode state
) {
82 irqst
.clearAndSetBaseToIrqStack(state
);
85 protected void irq_pop_mode(LttngIRQState irqst
) {
86 irqst
.popFromIrqStack();
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
);
95 protected void cpu_pop_mode(LTTngCPUState cpust
) {
96 cpust
.popFromCpuStack();
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
);
105 protected void bdev_pop_mode(LttngBdevState bdevst
) {
106 bdevst
.popFromBdevStack();
110 * Push a new received function pointer to the user_stack
116 protected void push_function(LttngTraceState traceSt
, Long funcptr
, Long cpu
) {
117 // Get the related process
118 LttngProcessState process
= traceSt
.getRunning_process().get(cpu
);
121 process
.pushToUserStack(funcptr
);
123 // update the pointer to the current function on the corresponding
125 process
.setCurrent_function(funcptr
);
128 protected void pop_function(LttngTraceState traceSt
, LttngEvent trcEvent
,
130 Long cpu
= trcEvent
.getCpuId();
131 LttngProcessState process
= traceSt
.getRunning_process().get(cpu
);
132 Long curr_function
= process
.getCurrent_function();
134 if (curr_function
!= null && curr_function
!= funcptr
) {
135 TraceDebug
.debug("Different functions: " + funcptr
+ " current: "
136 + curr_function
+ " time stamp: "
137 + trcEvent
.getTimestamp().toString());
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 %"
144 // process->current_function, funcptr);
145 // g_info("{ %u, %u, %s, %s, %s }\n",
148 // g_quark_to_string(process->name),
149 // g_quark_to_string(process->brand),
150 // g_quark_to_string(process->state->s));
154 process
.popFromUserStack();
155 process
.setCurrent_function(process
.peekFromUserStack());
158 // ========================================================================
160 // =======================================================================
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
169 * @param expectedNumFields
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();
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: ");
184 for (TmfEventField field
: fields
) {
185 sb
.append(((LttngEventField
)field
).getName() + " ");
188 TraceDebug
.debug(sb
.toString());
189 if (fields
.length
== 0) {
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();
203 if (TraceDebug
.isDEBUG()) {
205 .debug("Unexpected field Type. Expected: Long, Received: "
206 + fieldObj
.getClass().getSimpleName());
211 TraceDebug
.debug("Unexpected field received: " + fieldname
212 + " Expected: " + expectedFieldName
);
220 * protected method used when a Field is requested among several available
221 * fields and the expected type is Long
225 * @param expectedNumFields
228 protected Long
getAFieldLong(LttngEvent trcEvent
, LttngTraceState traceSt
,
229 Fields expectedField
) {
230 Long fieldVal
= null;
231 TmfEventField
[] fields
= trcEvent
.getContent().getFields();
233 // At least one field expected
234 if (fields
.length
== 0) {
235 TraceDebug
.debug("Unexpected number of fields received: "
240 LttngEventField field
;
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);
256 if (TraceDebug
.isDEBUG()) {
258 .debug("Unexpected field Type. Expected: Long, Received: "
259 + fieldObj
.getClass().getSimpleName());
266 if (fieldVal
== null) {
267 if (TraceDebug
.isDEBUG()) {
268 sendNoFieldFoundMsg(fields
, expectedFieldName
);
275 * protected method used when a Field is requested among several available
276 * fields and the expected type is String
280 * @param expectedNumFields
283 protected String
getAFieldString(LttngEvent trcEvent
,
284 LttngTraceState traceSt
, Fields expectedField
) {
285 String fieldVal
= null;
286 TmfEventField
[] fields
= trcEvent
.getContent().getFields();
288 // Only one field expected
289 if (fields
.length
== 0) {
290 TraceDebug
.debug("Unexpected number of fields received: "
295 LttngEventField field
;
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();
308 if (TraceDebug
.isDEBUG()) {
310 .debug("Unexpected field Type. Expected: String, Received: "
311 + fieldObj
.getClass().getSimpleName());
318 if (fieldVal
== null) {
319 if (TraceDebug
.isDEBUG()) {
320 sendNoFieldFoundMsg(fields
, expectedFieldName
);
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() + " ");
337 TraceDebug
.debug(sb
.toString(), 5);
340 // Adaption from MKDEV macro
341 protected Long
mkdev(Long major
, Long minor
) {
343 if (major
!= null && minor
!= null) {
344 result
= (major
<< 20) | minor
;
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
352 * when the parent waits for its child terminaison, but may also happen in
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.
357 protected boolean exit_process(LttngTraceState ts
, LttngProcessState process
) {
359 * Wait for both schedule with exit dead and process free to happen.
360 * They can happen in any order.
362 process
.incrementFree_events();
363 if (process
.getFree_events() < 2) {
367 process
.clearExecutionStack();
368 process
.clearUserStack();
369 ts
.getProcesses().remove(process
);
375 * Find the process matching the given pid and cpu
377 * If cpu is 0, the cpu value is not matched and the selection is based on
385 protected LttngProcessState
lttv_state_find_process(LttngTraceState ts
,
386 Long cpu
, Long pid
) {
387 // Define the return value
388 LttngProcessState process
= null;
390 // Obtain the list of available processes
391 List
<LttngProcessState
> processList
= ts
.getProcesses();
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) {
413 * , Used when a new process is needed
416 protected LttngProcessState
lttv_state_find_process_or_create(
417 LttngTraceState ts
, Long cpu
, Long pid
, final TmfTimestamp timestamp
) {
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
);
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
);
451 protected LttngProcessState
create_process(LttngTraceState traceSt
,
452 Long cpu
, Long pid
, Long tgid
, String name
,
453 final TmfTimestamp timestamp
) {
454 LttngProcessState process
;
455 process
= new LttngProcessState(cpu
, pid
, tgid
, name
, timestamp
);
456 traceSt
.getProcesses().add(process
);