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 * Michel Dagenais (michel.dagenais@polymtl.ca) - Reference C implementation, used with permission
12 *******************************************************************************/
14 package org
.eclipse
.linuxtools
.lttng
.state
.evProcessor
.state
;
18 import org
.eclipse
.linuxtools
.lttng
.LttngConstants
;
19 import org
.eclipse
.linuxtools
.lttng
.TraceDebug
;
20 import org
.eclipse
.linuxtools
.lttng
.event
.LttngEvent
;
21 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
;
22 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.BdevMode
;
23 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.CpuMode
;
24 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.Events
;
25 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.ExecutionMode
;
26 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.ExecutionSubMode
;
27 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.Fields
;
28 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.IRQMode
;
29 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.ProcessStatus
;
30 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.ProcessType
;
31 import org
.eclipse
.linuxtools
.lttng
.state
.evProcessor
.ILttngEventProcessor
;
32 import org
.eclipse
.linuxtools
.lttng
.state
.model
.LTTngCPUState
;
33 import org
.eclipse
.linuxtools
.lttng
.state
.model
.LttngBdevState
;
34 import org
.eclipse
.linuxtools
.lttng
.state
.model
.LttngExecutionState
;
35 import org
.eclipse
.linuxtools
.lttng
.state
.model
.LttngIRQState
;
36 import org
.eclipse
.linuxtools
.lttng
.state
.model
.LttngProcessState
;
37 import org
.eclipse
.linuxtools
.lttng
.state
.model
.LttngSoftIRQState
;
38 import org
.eclipse
.linuxtools
.lttng
.state
.model
.LttngTraceState
;
39 import org
.eclipse
.linuxtools
.lttng
.state
.model
.LttngTrapState
;
40 import org
.eclipse
.linuxtools
.tmf
.event
.TmfTimestamp
;
43 * Wraps the creation of individual handlers, each method creates and instance
44 * of the corresponding handler
49 class StateUpdateHandlers
{
51 final ILttngEventProcessor
getSyscallEntryHandler() {
52 AbsStateUpdate handler
= new AbsStateUpdate() {
56 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
58 Long cpu
= trcEvent
.getCpuId();
60 // No syscall_entry update for initialization process
61 LttngProcessState process
= traceSt
.getRunning_process().get(
63 if ((process
!= null) && (process
.getPid() != null)
64 && (process
.getPid().longValue() == 0L)) {
68 // Get the expected event field
69 Long syscall
= getAFieldLong(trcEvent
, traceSt
,
70 Fields
.LTT_FIELD_SYSCALL_ID
);
72 String submode
= null;
74 if (syscall
== null) {
76 .debug("Syscall Field not found, traceVent time: " //$NON-NLS-1$
77 + trcEvent
.getTimestamp());
79 submode
= traceSt
.getSyscall_names().get(syscall
);
80 // Note: For statistics performance improvement only the integer value of syscall is used
81 // as well as a bit mask is applied!
82 submodeId
= syscall
.intValue() | LttngConstants
.STATS_SYS_CALL_NAME_ID
;
85 if (submode
== null) {
86 submode
= ExecutionSubMode
.LTTV_STATE_SUBMODE_UNKNOWN
.getInName();
87 submodeId
= ExecutionSubMode
.LTTV_STATE_SUBMODE_UNKNOWN
.ordinal() | LttngConstants
.STATS_NONE_ID
;
90 push_state(cpu
, StateStrings
.ExecutionMode
.LTTV_STATE_SYSCALL
,
91 submode
, submodeId
, trcEvent
.getTimestamp(), traceSt
);
98 final ILttngEventProcessor
getsySyscallExitHandler() {
99 AbsStateUpdate handler
= new AbsStateUpdate() {
103 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
105 Long cpu
= trcEvent
.getCpuId();
106 LttngProcessState process
= traceSt
.getRunning_process().get(
109 // No syscall_entry update for initialization process
110 if ((process
!= null) && (process
.getPid() != null)
111 && (process
.getPid().longValue() == 0L)) {
115 pop_state(cpu
, StateStrings
.ExecutionMode
.LTTV_STATE_SYSCALL
,
116 traceSt
, trcEvent
.getTimestamp());
125 * Update stacks related to the parsing of an LttngEvent
129 final ILttngEventProcessor
getTrapEntryHandler() {
130 AbsStateUpdate handler
= new AbsStateUpdate() {
134 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
135 Long cpu
= trcEvent
.getCpuId();
137 Long trap
= getAFieldLong(trcEvent
, traceSt
,
138 Fields
.LTT_FIELD_TRAP_ID
);
141 .debug("Trap field could not be found, event time: " //$NON-NLS-1$
142 + trcEvent
.getTimestamp());
146 // ready the trap submode name
147 String submode
= traceSt
.getTrap_names().get(trap
);
148 // Note: For statistics performance improvement only the integer value of trap is used
149 // as well as a bit mask is applied!
151 int submodeId
= trap
.intValue() | LttngConstants
.STATS_TRAP_NAME_ID
;
153 if (submode
== null) {
154 submode
= ExecutionSubMode
.LTTV_STATE_SUBMODE_UNKNOWN
.getInName();
155 submodeId
= ExecutionSubMode
.LTTV_STATE_SUBMODE_UNKNOWN
.ordinal() | LttngConstants
.STATS_NONE_ID
;
158 /* update process state */
159 push_state(cpu
, StateStrings
.ExecutionMode
.LTTV_STATE_TRAP
,
160 submode
, submodeId
, trcEvent
.getTimestamp(), traceSt
);
162 /* update cpu status */
163 LTTngCPUState cpust
= traceSt
.getCpu_states().get(cpu
);
164 cpu_push_mode(cpust
, StateStrings
.CpuMode
.LTTV_CPU_TRAP
);
165 cpust
.pushToTrapStack(trap
); /* update trap status */
168 LttngTrapState trap_state
= null;
169 trap_state
= traceSt
.getTrap_states().get(trap
);
171 // If the trape_state exists, just increment it's counter,
172 // otherwise, create it
173 if ( trap_state
== null ) {
174 trap_state
= new LttngTrapState();
175 trap_state
.incrementRunning();
176 traceSt
.getTrap_states().put(trap
, trap_state
);
179 trap_state
.incrementRunning();
193 final ILttngEventProcessor
getTrapExitHandler() {
194 AbsStateUpdate handler
= new AbsStateUpdate() {
198 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
200 Long cpu
= trcEvent
.getCpuId();
201 LTTngCPUState cpust
= traceSt
.getCpu_states().get(cpu
);
202 Long trap
= cpust
.popFromTrapStack();
204 /* update process state */
205 pop_state(cpu
, ExecutionMode
.LTTV_STATE_TRAP
, traceSt
, trcEvent
208 /* update cpu status */
212 traceSt
.getTrap_states().get(trap
).decrementRunning();
215 // TraceDebug.debug("remove this line");
229 final ILttngEventProcessor
getIrqEntryHandler() {
230 AbsStateUpdate handler
= new AbsStateUpdate() {
234 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
236 Long cpu
= trcEvent
.getCpuId();
238 Long irq
= getAFieldLong(trcEvent
, traceSt
,
239 Fields
.LTT_FIELD_IRQ_ID
);
240 if (irq
== null || traceSt
.getIrq_states().get(irq
) == null) {
242 TraceDebug
.debug("Invalid irq (" + irq
+ "), ts = " + trcEvent
.getOriginalTimestamp()); //$NON-NLS-1$ //$NON-NLS-2$
248 submode
= traceSt
.getIrq_names().get(irq
);
249 // Note: For statistics performance improvement only the integer value of irq is used
250 // as well as a bit mask is applied!
251 int submodeId
= irq
.intValue() | LttngConstants
.STATS_IRQ_NAME_ID
;
253 if (submode
== null) {
254 submode
= ExecutionSubMode
.LTTV_STATE_SUBMODE_UNKNOWN
.getInName();
255 submodeId
= ExecutionSubMode
.LTTV_STATE_SUBMODE_UNKNOWN
.ordinal() | LttngConstants
.STATS_NONE_ID
;
259 * Do something with the info about being in user or system mode
262 push_state(cpu
, ExecutionMode
.LTTV_STATE_IRQ
, submode
, submodeId
, trcEvent
263 .getTimestamp(), traceSt
);
265 /* update cpu state */
266 LTTngCPUState cpust
= traceSt
.getCpu_states().get(cpu
);
267 cpu_push_mode(cpust
, CpuMode
.LTTV_CPU_IRQ
); /* mode stack */
268 cpust
.pushToIrqStack(irq
); /* last irq */
270 /* udpate irq state */
271 irq_push_mode(traceSt
.getIrq_states().get(irq
),
272 IRQMode
.LTTV_IRQ_BUSY
);
284 final ILttngEventProcessor
getSoftIrqExitHandler() {
285 AbsStateUpdate handler
= new AbsStateUpdate() {
289 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
291 Long cpu
= trcEvent
.getCpuId();
292 LTTngCPUState cpust
= traceSt
.getCpu_states().get(cpu
);
293 Long softirq
= cpust
.popFromSoftIrqStack();
295 // Update process status
296 pop_state(cpu
, ExecutionMode
.LTTV_STATE_SOFT_IRQ
, traceSt
,
297 trcEvent
.getTimestamp());
299 /* update softirq status */
301 LttngSoftIRQState softIrqstate
= traceSt
302 .getSoft_irq_states().get(softirq
);
303 if (softIrqstate
!= null) {
304 softIrqstate
.decrementRunning();
308 /* update cpu status */
321 final ILttngEventProcessor
getIrqExitHandler() {
322 AbsStateUpdate handler
= new AbsStateUpdate() {
326 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
328 Long cpu
= trcEvent
.getCpuId();
330 /* update process state */
331 pop_state(cpu
, ExecutionMode
.LTTV_STATE_IRQ
, traceSt
, trcEvent
334 /* update cpu status */
335 LTTngCPUState cpust
= traceSt
.getCpu_states().get(cpu
);
338 /* update irq status */
339 Long last_irq
= cpust
.popFromIrqStack();
340 if (last_irq
!= -1L) {
341 LttngIRQState irq_state
= traceSt
.getIrq_states().get(
343 irq_pop_mode(irq_state
);
357 final ILttngEventProcessor
getSoftIrqRaiseHandler() {
358 AbsStateUpdate handler
= new AbsStateUpdate() {
360 private Events eventType
= Events
.LTT_EVENT_SOFT_IRQ_RAISE
;
364 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
366 // Long cpu = trcEvent.getCpuId();
369 Long softirq
= getAFieldLong(trcEvent
, traceSt
,
370 Fields
.LTT_FIELD_SOFT_IRQ_ID
);
372 if (softirq
== null) {
373 TraceDebug
.debug("Soft_irq_id not found in " //$NON-NLS-1$
374 + eventType
.getInName() + " time: " //$NON-NLS-1$
375 + trcEvent
.getTimestamp());
380 // String[] softIrqNames = traceSt.getSoft_irq_names();
381 // if (softirq < softIrqNames.length) {
382 // submode = softIrqNames[softirq];
384 // submode = "softirq " + softirq;
387 /* update softirq status */
388 /* a soft irq raises are not cumulative */
389 LttngSoftIRQState irqState
= traceSt
.getSoft_irq_states().get(
391 if (irqState
!= null) {
392 irqState
.setPending(1L);
395 .debug("unexpected soft irq id value: " + softirq
); //$NON-NLS-1$
409 final ILttngEventProcessor
getSoftIrqEntryHandler() {
410 AbsStateUpdate handler
= new AbsStateUpdate() {
414 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
417 Long cpu
= trcEvent
.getCpuId();
420 Long softirq
= getAFieldLong(trcEvent
, traceSt
,
421 Fields
.LTT_FIELD_SOFT_IRQ_ID
);
423 if (softirq
== null) {
424 TraceDebug
.debug("Soft IRQ ID not found, eventTime: " //$NON-NLS-1$
425 + trcEvent
.getTimestamp());
430 Map
<Long
, String
> softIrqNames
= traceSt
.getSoft_irq_names();
431 String submode
= softIrqNames
.get(softirq
);
432 if (submode
== null) {
433 submode
= "softirq " + softirq
; //$NON-NLS-1$
434 softIrqNames
.put(softirq
, submode
);
437 // Note: For statistics performance improvement only the integer value of softirq is used
438 // as well as a bit mask is applied!
439 int submodeId
= softirq
.intValue() | LttngConstants
.STATS_SOFT_IRQ_NAME_ID
;
441 /* update softirq status */
442 LttngSoftIRQState irqState
= traceSt
.getSoft_irq_states().get(
444 if (irqState
!= null) {
445 irqState
.decrementPending();
446 irqState
.incrementRunning();
449 .debug("unexpected soft irq id value: " + softirq
); //$NON-NLS-1$
452 /* update cpu state */
453 LTTngCPUState cpu_state
= traceSt
.getCpu_states().get(cpu
);
454 cpu_state
.pushToSoftIrqStack(softirq
);
455 cpu_push_mode(cpu_state
, CpuMode
.LTTV_CPU_SOFT_IRQ
);
457 /* update process execution mode state stack */
458 push_state(cpu
, ExecutionMode
.LTTV_STATE_SOFT_IRQ
, submode
, submodeId
,
459 trcEvent
.getTimestamp(), traceSt
);
469 * Method to handle the event: LTT_EVENT_LIST_INTERRRUPT
473 final ILttngEventProcessor
getEnumInterruptHandler() {
474 AbsStateUpdate handler
= new AbsStateUpdate() {
476 private Events eventType
= Events
.LTT_EVENT_LIST_INTERRUPT
;
480 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
481 String action
= getAFieldString(trcEvent
, traceSt
,
482 Fields
.LTT_FIELD_ACTION
);
483 Long irq
= getAFieldLong(trcEvent
, traceSt
,
484 Fields
.LTT_FIELD_IRQ_ID
);
486 if (action
== null) {
487 TraceDebug
.debug("Field Action not found in event " //$NON-NLS-1$
488 + eventType
.getInName() + " time: " //$NON-NLS-1$
489 + trcEvent
.getTimestamp());
494 TraceDebug
.debug("Field irq_id not found in event " //$NON-NLS-1$
495 + eventType
.getInName() + " time: " //$NON-NLS-1$
496 + trcEvent
.getTimestamp());
500 Map
<Long
, String
> irq_names
= traceSt
.getIrq_names();
502 irq_names
.put(irq
, action
);
511 * Handle the event LTT_EVENT_REQUEST_ISSUE
515 final ILttngEventProcessor
getBdevRequestIssueHandler() {
516 AbsStateUpdate handler
= new AbsStateUpdate() {
520 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
523 Long major
= getAFieldLong(trcEvent
, traceSt
,
524 Fields
.LTT_FIELD_MAJOR
);
525 Long minor
= getAFieldLong(trcEvent
, traceSt
,
526 Fields
.LTT_FIELD_MINOR
);
527 Long operation
= getAFieldLong(trcEvent
, traceSt
,
528 Fields
.LTT_FIELD_OPERATION
);
530 // calculate bdevcode
531 Long devcode
= mkdev(major
, minor
);
533 if (devcode
== null) {
535 .debug("incorrect calcualtion of bdevcode input( major: " //$NON-NLS-1$
537 + " minor: " //$NON-NLS-1$
539 + " operation: " + operation
); //$NON-NLS-1$
543 Map
<Long
, LttngBdevState
> bdev_states
= traceSt
546 LttngBdevState bdevState
= bdev_states
.get(devcode
);
547 if (bdevState
== null) {
548 bdevState
= new LttngBdevState();
551 // update the mode in the stack
552 if (operation
== 0L) {
553 bdevState
.pushToBdevStack(BdevMode
.LTTV_BDEV_BUSY_READING
);
555 bdevState
.pushToBdevStack(BdevMode
.LTTV_BDEV_BUSY_WRITING
);
558 // make sure it is included in the set
559 bdev_states
.put(devcode
, bdevState
);
569 * Handling event: LTT_EVENT_REQUEST_COMPLETE
572 * FIELDS(LTT_FIELD_MAJOR, LTT_FIELD_MINOR, LTT_FIELD_OPERATION
577 final ILttngEventProcessor
getBdevRequestCompleteHandler() {
578 AbsStateUpdate handler
= new AbsStateUpdate() {
582 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
585 Long major
= getAFieldLong(trcEvent
, traceSt
,
586 Fields
.LTT_FIELD_MAJOR
);
587 Long minor
= getAFieldLong(trcEvent
, traceSt
,
588 Fields
.LTT_FIELD_MINOR
);
589 Long operation
= getAFieldLong(trcEvent
, traceSt
,
590 Fields
.LTT_FIELD_OPERATION
);
592 // calculate bdevcode
593 Long devcode
= mkdev(major
, minor
);
595 if (devcode
== null) {
597 .debug("incorrect calcualtion of bdevcode input( major: " //$NON-NLS-1$
599 + " minor: " //$NON-NLS-1$
601 + " operation: " + operation
); //$NON-NLS-1$
605 Map
<Long
, LttngBdevState
> bdev_states
= traceSt
608 LttngBdevState bdevState
= bdev_states
.get(devcode
);
609 if (bdevState
== null) {
610 bdevState
= new LttngBdevState();
613 /* update block device */
614 bdev_pop_mode(bdevState
);
625 * Handles event: LTT_EVENT_FUNCTION_ENTRY
628 * FIELDS: LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE
633 final ILttngEventProcessor
getFunctionEntryHandler() {
634 AbsStateUpdate handler
= new AbsStateUpdate() {
638 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
639 Long cpu
= trcEvent
.getCpuId();
640 Long funcptr
= getAFieldLong(trcEvent
, traceSt
,
641 Fields
.LTT_FIELD_THIS_FN
);
643 push_function(traceSt
, funcptr
, cpu
);
655 final ILttngEventProcessor
getFunctionExitHandler() {
656 AbsStateUpdate handler
= new AbsStateUpdate() {
660 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
662 Long funcptr
= getAFieldLong(trcEvent
, traceSt
,
663 Fields
.LTT_FIELD_THIS_FN
);
665 pop_function(traceSt
, trcEvent
, funcptr
);
675 * process event: LTT_EVENT_SYS_CALL_TABLE
678 * fields: LTT_FIELD_ID, LTT_FIELD_ADDRESS, LTT_FIELD_SYMBOL
683 final ILttngEventProcessor
getDumpSyscallHandler() {
684 AbsStateUpdate handler
= new AbsStateUpdate() {
688 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
689 // obtain the syscall id
690 Long id
= getAFieldLong(trcEvent
, traceSt
, Fields
.LTT_FIELD_ID
);
692 // Long address = getAFieldLong(trcEvent, traceSt,
693 // Fields.LTT_FIELD_ADDRESS);
696 String symbol
= getAFieldString(trcEvent
, traceSt
,
697 Fields
.LTT_FIELD_SYMBOL
);
699 // fill the symbol to the sycall_names collection
700 traceSt
.getSyscall_names().put(id
, symbol
);
710 * Handles event: LTT_EVENT_KPROBE_TABLE
713 * Fields: LTT_FIELD_IP, LTT_FIELD_SYMBOL
718 final ILttngEventProcessor
getDumpKprobeHandler() {
719 AbsStateUpdate handler
= new AbsStateUpdate() {
723 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
725 Long ip
= getAFieldLong(trcEvent
, traceSt
, Fields
.LTT_FIELD_IP
);
726 String symbol
= getAFieldString(trcEvent
, traceSt
,
727 Fields
.LTT_FIELD_SYMBOL
);
729 traceSt
.getKprobe_table().put(ip
, symbol
);
740 * Handles: LTT_EVENT_SOFTIRQ_VEC
743 * Fields: LTT_FIELD_ID, LTT_FIELD_ADDRESS, LTT_FIELD_SYMBOL
748 final ILttngEventProcessor
getDumpSoftIrqHandler() {
749 AbsStateUpdate handler
= new AbsStateUpdate() {
753 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
756 Long id
= getAFieldLong(trcEvent
, traceSt
, Fields
.LTT_FIELD_ID
);
758 // Address not needed
759 // Long address = ltt_event_get_long_unsigned(e,
760 // lttv_trace_get_hook_field(th,
764 String symbol
= getAFieldString(trcEvent
, traceSt
,
765 Fields
.LTT_FIELD_SYMBOL
);
767 // Register the soft irq name
768 traceSt
.getSoft_irq_names().put(id
, symbol
);
778 * Handles: LTT_EVENT_SCHED_SCHEDULE
781 * Fields: LTT_FIELD_PREV_PID, LTT_FIELD_NEXT_PID, LTT_FIELD_PREV_STATE
786 final ILttngEventProcessor
getSchedChangeHandler() {
787 AbsStateUpdate handler
= new AbsStateUpdate() {
791 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
793 Long cpu
= trcEvent
.getCpuId();
794 TmfTimestamp eventTime
= trcEvent
.getTimestamp();
796 LttngProcessState process
= traceSt
.getRunning_process().get(
799 Long pid_out
= getAFieldLong(trcEvent
, traceSt
,
800 Fields
.LTT_FIELD_PREV_PID
);
801 Long pid_in
= getAFieldLong(trcEvent
, traceSt
,
802 Fields
.LTT_FIELD_NEXT_PID
);
803 Long state_out
= getAFieldLong(trcEvent
, traceSt
,
804 Fields
.LTT_FIELD_PREV_STATE
);
806 if (process
!= null) {
809 * We could not know but it was not the idle process
810 * executing. This should only happen at the beginning,
811 * before the first schedule event, and when the initial
812 * information (current process for each CPU) is missing. It
813 * is not obvious how we could, after the fact, compensate
814 * the wrongly attributed statistics.
817 // This test only makes sense once the state is known and if
820 // missing events. We need to silently ignore schedchange
823 // process_free, or it causes glitches. (FIXME)
824 // if(unlikely(process->pid != pid_out)) {
825 // g_assert(process->pid == 0);
827 if ((process
.getPid().longValue() == 0L)
828 && (process
.getState().getExec_mode() == ExecutionMode
.LTTV_STATE_MODE_UNKNOWN
)) {
829 if ((pid_out
!= null) && (pid_out
.longValue() == 0L)) {
831 * Scheduling out of pid 0 at beginning of the trace
832 * : we know for sure it is in syscall mode at this
836 process
.getState().setExec_mode(
837 ExecutionMode
.LTTV_STATE_SYSCALL
);
838 process
.getState().setProc_status(
839 ProcessStatus
.LTTV_STATE_WAIT
);
840 process
.getState().setChange_Time(
841 trcEvent
.getTimestamp().getValue());
842 process
.getState().setEntry_Time(
843 trcEvent
.getTimestamp().getValue());
846 if (process
.getState().getProc_status() == ProcessStatus
.LTTV_STATE_EXIT
) {
847 process
.getState().setProc_status(
848 ProcessStatus
.LTTV_STATE_ZOMBIE
);
849 process
.getState().setChange_Time(
850 trcEvent
.getTimestamp().getValue());
852 if ((state_out
!= null)
853 && (state_out
.longValue() == 0L)) {
854 process
.getState().setProc_status(
855 ProcessStatus
.LTTV_STATE_WAIT_CPU
);
857 process
.getState().setProc_status(
858 ProcessStatus
.LTTV_STATE_WAIT
);
861 process
.getState().setChange_Time(
862 trcEvent
.getTimestamp().getValue());
865 if ((state_out
!= null)
866 && (state_out
== 32L || state_out
== 64L)) { /*
871 /* see sched.h for states */
872 if (!exit_process(traceSt
, process
)) {
873 process
.getState().setProc_status(
874 ProcessStatus
.LTTV_STATE_DEAD
);
875 process
.getState().setChange_Time(
876 trcEvent
.getTimestamp().getValue());
881 process
= lttv_state_find_process_or_create(traceSt
, cpu
,
884 traceSt
.getRunning_process().put(cpu
, process
);
886 process
.getState().setProc_status(ProcessStatus
.LTTV_STATE_RUN
);
887 process
.getState().setChange_Time(eventTime
.getValue());
889 // process->state->s = LTTV_STATE_RUN;
890 // if(process->usertrace)
891 // process->usertrace->cpu = cpu;
892 // process->last_cpu_index =
893 // ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
895 // process->state->change = s->parent.timestamp;
897 LTTngCPUState cpu_state
= traceSt
.getCpu_states().get(cpu
);
898 /* update cpu status */
899 if ((pid_in
!= null) && (pid_in
.longValue() == 0L)) {
901 /* going to idle task */
902 cpu_set_base_mode(cpu_state
, CpuMode
.LTTV_CPU_IDLE
);
905 * scheduling a real task. we must be careful here: if we
906 * just schedule()'ed to a process that is in a trap, we
907 * must put the cpu in trap mode
909 cpu_set_base_mode(cpu_state
, CpuMode
.LTTV_CPU_BUSY
);
910 if (process
.getState().getExec_mode() == ExecutionMode
.LTTV_STATE_TRAP
) {
911 cpu_push_mode(cpu_state
, CpuMode
.LTTV_CPU_TRAP
);
923 * Handles: LTT_EVENT_PROCESS_FORK
926 * Fields: FIELD_ARRAY(LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID,
927 * LTT_FIELD_CHILD_TGID)
932 final ILttngEventProcessor
getProcessForkHandler() {
933 AbsStateUpdate handler
= new AbsStateUpdate() {
937 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
939 Long cpu
= trcEvent
.getCpuId();
940 LttngProcessState process
= traceSt
.getRunning_process().get(
942 TmfTimestamp timeStamp
= trcEvent
.getTimestamp();
945 // Long parent_pid = getAFieldLong(trcEvent, traceSt,
946 // Fields.LTT_FIELD_PARENT_PID);
949 /* In the Linux Kernel, there is one PID per thread. */
950 Long child_pid
= getAFieldLong(trcEvent
, traceSt
,
951 Fields
.LTT_FIELD_CHILD_PID
);
954 /* tgid in the Linux kernel is the "real" POSIX PID. */
955 Long child_tgid
= getAFieldLong(trcEvent
, traceSt
,
956 Fields
.LTT_FIELD_CHILD_TGID
);
957 if (child_tgid
== null) {
962 * Mathieu : it seems like the process might have been scheduled
963 * in before the fork, and, in a rare case, might be the current
964 * process. This might happen in a SMP case where we don't have
965 * enough precision on the clocks.
967 * Test reenabled after precision fixes on time. (Mathieu)
970 // zombie_process = lttv_state_find_process(ts, ANY_CPU,
973 // if(unlikely(zombie_process != NULL)) {
974 // /* Reutilisation of PID. Only now we are sure that the old
976 // * has been released. FIXME : should know when release_task
980 // guint num_cpus = ltt_trace_get_num_cpu(ts->parent.t);
982 // for(i=0; i< num_cpus; i++) {
983 // g_assert(zombie_process != ts->running_process[i]);
986 // exit_process(s, zombie_process);
990 if (process
.getPid().equals(child_pid
)) {
992 .debug("Unexpected, process pid equal to child pid: " //$NON-NLS-1$
994 + " Event Time: " //$NON-NLS-1$
995 + trcEvent
.getTimestamp());
998 // g_assert(process->pid != child_pid);
999 // FIXME : Add this test in the "known state" section
1000 // g_assert(process->pid == parent_pid);
1001 LttngProcessState child_process
= lttv_state_find_process(
1002 traceSt
, ANY_CPU
, child_pid
);
1003 if (child_process
== null) {
1004 child_process
= create_process(traceSt
, cpu
, child_pid
,
1005 child_tgid
, timeStamp
);
1006 child_process
.setPpid(process
.getPid(), timeStamp
.getValue());
1009 * The process has already been created : due to time
1010 * imprecision between multiple CPUs : it has been scheduled
1011 * in before creation. Note that we shouldn't have this kind
1014 * Simply put a correct parent.
1016 StringBuilder sb
= new StringBuilder("Process " + child_pid
); //$NON-NLS-1$
1017 sb
.append(" has been created at [" //$NON-NLS-1$
1018 + child_process
.getCreation_time() + "] "); //$NON-NLS-1$
1019 sb
.append("and inserted at [" //$NON-NLS-1$
1020 + child_process
.getInsertion_time() + "] "); //$NON-NLS-1$
1021 sb
.append("before \nfork on cpu " + cpu
+ " Event time: [" //$NON-NLS-1$ //$NON-NLS-2$
1022 + trcEvent
+ "]\n."); //$NON-NLS-1$
1024 .append("Probably an unsynchronized TSD problem on the traced machine."); //$NON-NLS-1$
1025 TraceDebug
.debug(sb
.toString());
1027 // g_assert(0); /* This is a problematic case : the process
1030 // before the fork event */
1031 child_process
.setPpid(process
.getPid());
1032 child_process
.setTgid(child_tgid
);
1035 if (!child_process
.getName().equals(
1036 ProcessStatus
.LTTV_STATE_UNNAMED
.getInName())) {
1037 TraceDebug
.debug("Unexpected child process status: " //$NON-NLS-1$
1038 + child_process
.getName());
1041 child_process
.setName(process
.getName());
1042 child_process
.setBrand(process
.getBrand());
1053 * Handles: LTT_EVENT_KTHREAD_CREATE
1056 * Fields: LTT_FIELD_PID
1061 final ILttngEventProcessor
getProcessKernelThreadHandler() {
1062 AbsStateUpdate handler
= new AbsStateUpdate() {
1066 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
1068 * We stamp a newly created process as kernel_thread. The thread
1069 * should not be running yet.
1072 LttngExecutionState exState
;
1074 LttngProcessState process
;
1077 pid
= getAFieldLong(trcEvent
, traceSt
, Fields
.LTT_FIELD_PID
);
1078 // s->parent.target_pid = pid;
1080 process
= lttv_state_find_process_or_create(traceSt
, ANY_CPU
,
1081 pid
, new TmfTimestamp());
1083 if (!process
.getState().getProc_status().equals(
1084 ProcessStatus
.LTTV_STATE_DEAD
)) {
1085 // Leave only the first element in the stack with execution
1088 exState
= process
.getFirstElementFromExecutionStack();
1089 exState
.setExec_mode(ExecutionMode
.LTTV_STATE_SYSCALL
);
1090 process
.clearExecutionStack();
1091 process
.pushToExecutionStack(exState
);
1094 process
.setType(ProcessType
.LTTV_STATE_KERNEL_THREAD
);
1105 * Handles: LTT_EVENT_PROCESS_EXIT
1113 final ILttngEventProcessor
getProcessExitHandler() {
1114 AbsStateUpdate handler
= new AbsStateUpdate() {
1118 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
1121 LttngProcessState process
;
1123 pid
= getAFieldLong(trcEvent
, traceSt
, Fields
.LTT_FIELD_PID
);
1124 // s->parent.target_pid = pid;
1126 // FIXME : Add this test in the "known state" section
1127 // g_assert(process->pid == pid);
1129 process
= lttv_state_find_process(traceSt
, ANY_CPU
, pid
);
1130 if (process
!= null) {
1131 process
.getState().setProc_status(
1132 ProcessStatus
.LTTV_STATE_EXIT
);
1143 * Handles: LTT_EVENT_PROCESS_FREE
1146 * Fields: LTT_FIELD_PID
1151 final ILttngEventProcessor
getProcessFreeHandler() {
1152 AbsStateUpdate handler
= new AbsStateUpdate() {
1156 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
1159 LttngProcessState process
;
1161 /* PID of the process to release */
1162 release_pid
= getAFieldLong(trcEvent
, traceSt
,
1163 Fields
.LTT_FIELD_PID
);
1164 // s->parent.target_pid = release_pid;
1166 if ((release_pid
!= null) && (release_pid
.longValue() == 0L)) {
1167 TraceDebug
.debug("Unexpected release_pid: 0, Event time: " //$NON-NLS-1$
1168 + trcEvent
.getTimestamp());
1171 process
= lttv_state_find_process(traceSt
, ANY_CPU
, release_pid
);
1172 if (process
!= null) {
1173 exit_process(traceSt
, process
);
1178 // if(process != null) {
1180 * release_task is happening at kernel level : we can now safely
1181 * release the data structure of the process
1183 // This test is fun, though, as it may happen that
1184 // at time t : CPU 0 : process_free
1185 // at time t+150ns : CPU 1 : schedule out
1186 // Clearly due to time imprecision, we disable it. (Mathieu)
1187 // If this weird case happen, we have no choice but to put the
1188 // Currently running process on the cpu to 0.
1189 // I re-enable it following time precision fixes. (Mathieu)
1190 // Well, in the case where an process is freed by a process on
1193 // and still scheduled, it happens that this is the schedchange
1196 // drop the last reference count. Do not free it here!
1198 // int num_cpus = ltt_trace_get_num_cpu(ts->parent.t);
1200 // for(i=0; i< num_cpus; i++) {
1201 // //g_assert(process != ts->running_process[i]);
1202 // if(process == ts->running_process[i]) {
1203 // //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
1207 // if(i == num_cpus) /* process is not scheduled */
1208 // exit_process(s, process);
1220 * Handles: LTT_EVENT_EXEC
1223 * FIELDS: LTT_FIELD_FILENAME
1228 final ILttngEventProcessor
getProcessExecHandler() {
1229 AbsStateUpdate handler
= new AbsStateUpdate() {
1233 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
1235 Long cpu
= trcEvent
.getCpuId();
1236 LttngProcessState process
= traceSt
.getRunning_process().get(
1239 // #if 0//how to use a sequence that must be transformed in a
1241 // /* PID of the process to release */
1242 // guint64 name_len = ltt_event_field_element_number(e,
1243 // lttv_trace_get_hook_field(th, 0));
1244 // //name = ltt_event_get_string(e,
1245 // lttv_trace_get_hook_field(th, 0));
1246 // LttField *child = ltt_event_field_element_select(e,
1247 // lttv_trace_get_hook_field(th, 0), 0);
1248 // gchar *name_begin =
1249 // (gchar*)(ltt_event_data(e)+ltt_event_field_offset(e, child));
1250 // gchar *null_term_name = g_new(gchar, name_len+1);
1251 // memcpy(null_term_name, name_begin, name_len);
1252 // null_term_name[name_len] = '\0';
1253 // process->name = g_quark_from_string(null_term_name);
1256 process
.setName(getAFieldString(trcEvent
, traceSt
,
1257 Fields
.LTT_FIELD_FILENAME
));
1258 process
.setBrand(StateStrings
.LTTV_STATE_UNBRANDED
);
1268 * LTT_EVENT_THREAD_BRAND
1271 * FIELDS: LTT_FIELD_NAME
1276 final ILttngEventProcessor
GetThreadBrandHandler() {
1277 AbsStateUpdate handler
= new AbsStateUpdate() {
1281 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
1284 Long cpu
= trcEvent
.getCpuId();
1285 LttngProcessState process
= traceSt
.getRunning_process().get(
1288 name
= getAFieldString(trcEvent
, traceSt
, Fields
.LTT_FIELD_NAME
);
1289 process
.setBrand(name
);
1300 final ILttngEventProcessor
getStateDumpEndHandler() {
1301 AbsStateUpdate handler
= new AbsStateUpdate() {
1305 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
1307 /* For all processes */
1309 * if kernel thread, if stack[0] is unknown, set to syscall
1312 /* else, if stack[0] is unknown, set to user mode, running */
1313 LttngProcessState
[] processes
= traceSt
.getProcesses();
1314 TmfTimestamp time
= trcEvent
.getTimestamp();
1316 for (int pos
= 0; pos
< processes
.length
; pos
++) {
1317 fix_process(processes
[pos
], time
);
1320 // Set the current process to be running
1321 // TODO Should we do it for all process running on a cpu?
1322 LttngProcessState process
= traceSt
.getRunning_process().get(trcEvent
.getCpuId());
1323 process
.getState().setProc_status(ProcessStatus
.LTTV_STATE_RUN
);
1330 * Private method used to establish the first execution state in the
1331 * stack for a given process
1336 private void fix_process(LttngProcessState process
,
1337 TmfTimestamp timestamp
) {
1339 LttngExecutionState es
;
1341 if (process
.getType() == ProcessType
.LTTV_STATE_KERNEL_THREAD
) {
1342 es
= process
.getFirstElementFromExecutionStack();
1344 if (es
.getExec_mode() == ExecutionMode
.LTTV_STATE_MODE_UNKNOWN
) {
1345 es
.setExec_mode(ExecutionMode
.LTTV_STATE_SYSCALL
);
1346 es
.setExec_submode(ExecutionSubMode
.LTTV_STATE_SUBMODE_NONE
.getInName());
1347 // Note: For statistics performance improvement a integer representation of the submode is used
1348 // as well as a bit mask is applied!
1349 es
.setExec_submode_id(StateStrings
.ExecutionSubMode
.LTTV_STATE_SUBMODE_NONE
.ordinal() | LttngConstants
.STATS_NONE_ID
);
1350 es
.setEntry_Time(timestamp
.getValue());
1351 es
.setChange_Time(timestamp
.getValue());
1352 es
.setCum_cpu_time(0L);
1353 if (es
.getProc_status() == ProcessStatus
.LTTV_STATE_UNNAMED
) {
1354 es
.setProc_status(ProcessStatus
.LTTV_STATE_WAIT
);
1358 es
= process
.getFirstElementFromExecutionStack();
1359 if (es
.getExec_mode() == ExecutionMode
.LTTV_STATE_MODE_UNKNOWN
) {
1360 es
.setExec_mode(ExecutionMode
.LTTV_STATE_USER_MODE
);
1361 es
.setExec_submode(ExecutionSubMode
.LTTV_STATE_SUBMODE_NONE
.getInName());
1362 // Note: For statistics performance improvement a integer representation of the submode is used
1363 // as well as a bit mask is applied!
1364 es
.setExec_submode_id(StateStrings
.ExecutionSubMode
.LTTV_STATE_SUBMODE_NONE
.ordinal() | LttngConstants
.STATS_NONE_ID
);
1365 es
.setEntry_Time(timestamp
.getValue());
1366 es
.setChange_Time(timestamp
.getValue());
1367 es
.setCum_cpu_time(0L);
1368 if (es
.getProc_status() == ProcessStatus
.LTTV_STATE_UNNAMED
) {
1369 es
.setProc_status(ProcessStatus
.LTTV_STATE_RUN
);
1372 // If the first element is also the one on top... mean
1373 // we have ONE element on the stack
1374 if (process
.getFirstElementFromExecutionStack() == process
1375 .peekFromExecutionStack()) {
1377 * Still in bottom unknown mode, means never did a
1378 * system call May be either in user mode, syscall
1379 * mode, running or waiting.
1382 * FIXME : we may be tagging syscall mode when being
1385 // Get a new execution State
1386 es
= new LttngExecutionState();
1388 // initialize values
1389 es
.setExec_mode(ExecutionMode
.LTTV_STATE_SYSCALL
);
1390 es
.setExec_submode(ExecutionSubMode
.LTTV_STATE_SUBMODE_NONE
.getInName());
1391 // Note: For statistics performance improvement a integer representation of the submode is used
1392 // as well as a bit mask is applied!
1393 es
.setExec_submode_id(StateStrings
.ExecutionSubMode
.LTTV_STATE_SUBMODE_NONE
.ordinal() | LttngConstants
.STATS_NONE_ID
);
1394 es
.setEntry_Time(timestamp
.getValue());
1395 es
.setChange_Time(timestamp
.getValue());
1396 es
.setCum_cpu_time(0L);
1397 es
.setProc_status(ProcessStatus
.LTTV_STATE_WAIT
);
1399 // Push the new state to the stack
1400 process
.pushToExecutionStack(es
);
1411 * Handles: LTT_EVENT_PROCESS_STATE
1414 * FIELDS: LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
1415 * LTT_FIELD_TYPE, LTT_FIELD_MODE, LTT_FIELD_SUBMODE, LTT_FIELD_STATUS,
1421 final ILttngEventProcessor
getEnumProcessStateHandler() {
1422 AbsStateUpdate handler
= new AbsStateUpdate() {
1426 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
1432 Long cpu
= trcEvent
.getCpuId();
1434 LttngProcessState process
= traceSt
.getRunning_process().get(
1436 LttngProcessState parent_process
;
1438 // String mode, submode, status;
1439 LttngExecutionState es
;
1442 pid
= getAFieldLong(trcEvent
, traceSt
, Fields
.LTT_FIELD_PID
);
1445 parent_pid
= getAFieldLong(trcEvent
, traceSt
,
1446 Fields
.LTT_FIELD_PARENT_PID
);
1449 command
= getAFieldString(trcEvent
, traceSt
,
1450 Fields
.LTT_FIELD_NAME
);
1452 Long typeVal
= getAFieldLong(trcEvent
, traceSt
,
1453 Fields
.LTT_FIELD_TYPE
);
1455 type
= ProcessType
.LTTV_STATE_KERNEL_THREAD
.getInName();
1456 if ((typeVal
!= null) && (typeVal
.longValue() == 0L)) {
1457 type
= ProcessType
.LTTV_STATE_USER_THREAD
.getInName();
1461 // mode = getAFieldString(trcEvent, traceSt,
1462 // Fields.LTT_FIELD_MODE);
1465 // submode = getAFieldString(trcEvent, traceSt,
1466 // Fields.LTT_FIELD_SUBMODE);
1469 // status = getAFieldString(trcEvent, traceSt,
1470 // Fields.LTT_FIELD_STATUS);
1473 tgid
= getAFieldLong(trcEvent
, traceSt
, Fields
.LTT_FIELD_TGID
);
1478 if ((pid
!= null) && (pid
.longValue() == 0L)) {
1479 for (Long acpu
: traceSt
.getCpu_states().keySet()) {
1480 process
= lttv_state_find_process(traceSt
, acpu
, pid
);
1481 if (process
!= null) {
1482 process
.setPpid(parent_pid
);
1483 process
.setTgid(tgid
);
1484 process
.setName(command
);
1486 .setType(ProcessType
.LTTV_STATE_KERNEL_THREAD
);
1488 StringBuilder sb
= new StringBuilder(
1489 "Unexpected, null process read from the TraceState list of processes, event time: " //$NON-NLS-1$
1490 + trcEvent
.getTimestamp());
1491 TraceDebug
.debug(sb
.toString());
1496 * The process might exist if a process was forked while
1497 * performing the state dump.
1499 process
= lttv_state_find_process(traceSt
, ANY_CPU
, pid
);
1500 if (process
== null) {
1501 parent_process
= lttv_state_find_process(traceSt
,
1502 ANY_CPU
, parent_pid
);
1503 TmfTimestamp eventTime
= trcEvent
.getTimestamp();
1504 process
= create_process(traceSt
, cpu
, pid
, tgid
,
1505 command
, eventTime
);
1506 if (parent_process
!= null) {
1507 process
.setPpid(parent_process
.getPid(), eventTime
.getValue());
1510 /* Keep the stack bottom : a running user mode */
1512 * Disabled because of inconsistencies in the current
1515 if (type
.equals(ProcessType
.LTTV_STATE_KERNEL_THREAD
1518 * FIXME Kernel thread : can be in syscall or
1519 * interrupt or trap.
1522 * Will cause expected trap when in fact being
1523 * syscall (even after end of statedump event) Will
1524 * cause expected interrupt when being syscall.
1525 * (only before end of statedump event)
1527 // process type is USER_THREAD by default.
1529 .setType(ProcessType
.LTTV_STATE_KERNEL_THREAD
);
1533 //Only one entry needed in the execution stack
1534 process
.popFromExecutionStack();
1535 es
= process
.getState();
1536 es
.setExec_mode(ExecutionMode
.LTTV_STATE_MODE_UNKNOWN
);
1537 es
.setProc_status(ProcessStatus
.LTTV_STATE_UNNAMED
);
1538 es
.setExec_submode(ExecutionSubMode
.LTTV_STATE_SUBMODE_UNKNOWN
1540 // Note: For statistics performance improvement a integer representation of the submode is used
1541 // as well as a bit mask is applied!
1542 es
.setExec_submode_id(StateStrings
.ExecutionSubMode
.LTTV_STATE_SUBMODE_UNKNOWN
.ordinal() | LttngConstants
.STATS_NONE_ID
);
1545 // /* UNKNOWN STATE */
1547 // es = process->state =
1548 // &g_array_index(process->execution_stack,
1549 // LttvExecutionState, 1);
1550 // es->t = LTTV_STATE_MODE_UNKNOWN;
1551 // es->s = LTTV_STATE_UNNAMED;
1552 // es->n = LTTV_STATE_SUBMODE_UNKNOWN;
1557 * The process has already been created : Probably was
1558 * forked while dumping the process state or was simply
1559 * scheduled in prior to get the state dump event.
1561 process
.setPpid(parent_pid
);
1562 process
.setTgid(tgid
);
1563 process
.setName(command
);
1564 if (type
.equals(ProcessType
.LTTV_STATE_KERNEL_THREAD
1567 .setType(ProcessType
.LTTV_STATE_KERNEL_THREAD
);
1569 process
.setType(ProcessType
.LTTV_STATE_USER_THREAD
);
1573 // &g_array_index(process->execution_stack,
1574 // LttvExecutionState,
1577 // if(es->t == LTTV_STATE_MODE_UNKNOWN) {
1578 // if(type == LTTV_STATE_KERNEL_THREAD)
1579 // es->t = LTTV_STATE_SYSCALL;
1581 // es->t = LTTV_STATE_USER_MODE;
1585 * Don't mess around with the stack, it will eventually
1586 * become ok after the end of state dump.