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
;
16 import org
.eclipse
.linuxtools
.lttng
.TraceDebug
;
17 import org
.eclipse
.linuxtools
.lttng
.event
.LttngEvent
;
18 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
;
19 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.BdevMode
;
20 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.CpuMode
;
21 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.Events
;
22 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.ExecutionMode
;
23 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.ExecutionSubMode
;
24 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.Fields
;
25 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.IRQMode
;
26 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.ProcessStatus
;
27 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.ProcessType
;
28 import org
.eclipse
.linuxtools
.lttng
.state
.evProcessor
.IEventProcessing
;
29 import org
.eclipse
.linuxtools
.lttng
.state
.model
.LTTngCPUState
;
30 import org
.eclipse
.linuxtools
.lttng
.state
.model
.LttngBdevState
;
31 import org
.eclipse
.linuxtools
.lttng
.state
.model
.LttngExecutionState
;
32 import org
.eclipse
.linuxtools
.lttng
.state
.model
.LttngIRQState
;
33 import org
.eclipse
.linuxtools
.lttng
.state
.model
.LttngProcessState
;
34 import org
.eclipse
.linuxtools
.lttng
.state
.model
.LttngSoftIRQState
;
35 import org
.eclipse
.linuxtools
.lttng
.state
.model
.LttngTraceState
;
36 import org
.eclipse
.linuxtools
.lttng
.state
.model
.LttngTrapState
;
37 import org
.eclipse
.linuxtools
.tmf
.event
.TmfTimestamp
;
40 * Wraps the creation of individual handlers, each method creates and instance
41 * of the corresponding handler
46 class StateUpdateHandlers
{
48 final IEventProcessing
getSyscallEntryHandler() {
49 AbsStateUpdate handler
= new AbsStateUpdate() {
51 private Events eventType
= Events
.LTT_EVENT_SYSCALL_ENTRY
;
54 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
56 Long cpu
= trcEvent
.getCpuId();
58 // No syscall_entry update for initialization process
59 LttngProcessState process
= traceSt
.getRunning_process().get(
61 if ((process
!= null) && (process
.getPid() != null)
62 && (process
.getPid().longValue() == 0L)) {
66 // Get the expected event field
67 Long syscall
= getAFieldLong(trcEvent
, traceSt
,
68 Fields
.LTT_FIELD_SYSCALL_ID
);
70 String submode
= null;
71 if (syscall
== null) {
73 .debug("Syscall Field not found, traceVent time: "
74 + trcEvent
.getTimestamp());
76 submode
= traceSt
.getSyscall_names().get(syscall
);
79 if (submode
== null) {
80 submode
= ExecutionSubMode
.LTTV_STATE_SUBMODE_UNKNOWN
84 push_state(cpu
, StateStrings
.ExecutionMode
.LTTV_STATE_SYSCALL
,
85 submode
, trcEvent
.getTimestamp(), traceSt
);
90 public Events
getEventHandleType() {
97 final IEventProcessing
getsySyscallExitHandler() {
98 AbsStateUpdate handler
= new AbsStateUpdate() {
100 private Events eventType
= Events
.LTT_EVENT_SYSCALL_EXIT
;
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());
122 public Events
getEventHandleType() {
130 * Update stacks related to the parsing of an LttngEvent
134 final IEventProcessing
getTrapEntryHandler() {
135 AbsStateUpdate handler
= new AbsStateUpdate() {
137 private Events eventType
= Events
.LTT_EVENT_TRAP_ENTRY
;
140 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
141 Long cpu
= trcEvent
.getCpuId();
143 Long trap
= getAFieldLong(trcEvent
, traceSt
,
144 Fields
.LTT_FIELD_TRAP_ID
);
147 .debug("Trap field could not be found, event time: "
148 + trcEvent
.getTimestamp());
152 // ready the trap submode name
153 String submode
= traceSt
.getTrap_names().get(trap
);
155 if (submode
== null) {
156 submode
= ExecutionSubMode
.LTTV_STATE_SUBMODE_UNKNOWN
160 /* update process state */
161 push_state(cpu
, StateStrings
.ExecutionMode
.LTTV_STATE_TRAP
,
162 submode
, trcEvent
.getTimestamp(), traceSt
);
164 /* update cpu status */
165 LTTngCPUState cpust
= traceSt
.getCpu_states().get(cpu
);
166 cpu_push_mode(cpust
, StateStrings
.CpuMode
.LTTV_CPU_TRAP
);
167 cpust
.pushToTrapStack(trap
); /* update trap status */
170 LttngTrapState trap_state
= null;
171 trap_state
= traceSt
.getTrap_states().get(trap
);
173 // If the trape_state exists, just increment it's counter,
174 // otherwise, create it
175 if ( trap_state
== null ) {
176 trap_state
= new LttngTrapState();
177 trap_state
.incrementRunning();
178 traceSt
.getTrap_states().put(trap
, trap_state
);
181 trap_state
.incrementRunning();
189 public Events
getEventHandleType() {
200 final IEventProcessing
getTrapExitHandler() {
201 AbsStateUpdate handler
= new AbsStateUpdate() {
203 private Events eventType
= Events
.LTT_EVENT_TRAP_EXIT
;
206 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
208 Long cpu
= trcEvent
.getCpuId();
209 LTTngCPUState cpust
= traceSt
.getCpu_states().get(cpu
);
210 Long trap
= cpust
.popFromTrapStack();
212 /* update process state */
213 pop_state(cpu
, ExecutionMode
.LTTV_STATE_TRAP
, traceSt
, trcEvent
216 /* update cpu status */
220 traceSt
.getTrap_states().get(trap
).decrementRunning();
223 // TraceDebug.debug("remove this line");
231 public Events
getEventHandleType() {
242 final IEventProcessing
getIrqEntryHandler() {
243 AbsStateUpdate handler
= new AbsStateUpdate() {
245 private Events eventType
= Events
.LTT_EVENT_IRQ_ENTRY
;
248 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
250 Long cpu
= trcEvent
.getCpuId();
252 Long irq
= getAFieldLong(trcEvent
, traceSt
,
253 Fields
.LTT_FIELD_IRQ_ID
);
259 submode
= traceSt
.getIrq_names().get(irq
);
261 if (submode
== null) {
262 submode
= ExecutionSubMode
.LTTV_STATE_SUBMODE_UNKNOWN
267 * Do something with the info about being in user or system mode
270 push_state(cpu
, ExecutionMode
.LTTV_STATE_IRQ
, submode
, trcEvent
271 .getTimestamp(), traceSt
);
273 /* update cpu state */
274 LTTngCPUState cpust
= traceSt
.getCpu_states().get(cpu
);
275 cpu_push_mode(cpust
, CpuMode
.LTTV_CPU_IRQ
); /* mode stack */
276 cpust
.pushToIrqStack(irq
); /* last irq */
278 /* udpate irq state */
279 irq_push_mode(traceSt
.getIrq_states().get(irq
),
280 IRQMode
.LTTV_IRQ_BUSY
);
285 public Events
getEventHandleType() {
296 final IEventProcessing
getSoftIrqExitHandler() {
297 AbsStateUpdate handler
= new AbsStateUpdate() {
299 private Events eventType
= Events
.LTT_EVENT_SOFT_IRQ_EXIT
;
302 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
304 Long cpu
= trcEvent
.getCpuId();
305 LTTngCPUState cpust
= traceSt
.getCpu_states().get(cpu
);
306 Long softirq
= cpust
.popFromSoftIrqStack();
308 // Update process status
309 pop_state(cpu
, ExecutionMode
.LTTV_STATE_SOFT_IRQ
, traceSt
,
310 trcEvent
.getTimestamp());
312 /* update softirq status */
314 LttngSoftIRQState softIrqstate
= traceSt
315 .getSoft_irq_states().get(softirq
);
316 softIrqstate
.decrementRunning();
319 /* update cpu status */
326 public Events
getEventHandleType() {
337 final IEventProcessing
getIrqExitHandler() {
338 AbsStateUpdate handler
= new AbsStateUpdate() {
340 private Events eventType
= Events
.LTT_EVENT_IRQ_EXIT
;
343 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
345 Long cpu
= trcEvent
.getCpuId();
347 /* update process state */
348 pop_state(cpu
, ExecutionMode
.LTTV_STATE_IRQ
, traceSt
, trcEvent
351 /* update cpu status */
352 LTTngCPUState cpust
= traceSt
.getCpu_states().get(cpu
);
355 /* update irq status */
356 Long last_irq
= cpust
.popFromIrqStack();
357 if (last_irq
!= -1L) {
358 LttngIRQState irq_state
= traceSt
.getIrq_states().get(
360 irq_pop_mode(irq_state
);
368 public Events
getEventHandleType() {
379 final IEventProcessing
getSoftIrqRaiseHandler() {
380 AbsStateUpdate handler
= new AbsStateUpdate() {
382 private Events eventType
= Events
.LTT_EVENT_SOFT_IRQ_RAISE
;
385 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
387 // Long cpu = trcEvent.getCpuId();
390 Long softirq
= getAFieldLong(trcEvent
, traceSt
,
391 Fields
.LTT_FIELD_SOFT_IRQ_ID
);
393 if (softirq
== null) {
394 TraceDebug
.debug("Soft_irq_id not found in "
395 + eventType
.getInName() + " time: "
396 + trcEvent
.getTimestamp());
401 // String[] softIrqNames = traceSt.getSoft_irq_names();
402 // if (softirq < softIrqNames.length) {
403 // submode = softIrqNames[softirq];
405 // submode = "softirq " + softirq;
408 /* update softirq status */
409 /* a soft irq raises are not cumulative */
410 LttngSoftIRQState irqState
= traceSt
.getSoft_irq_states().get(
412 if (irqState
!= null) {
413 irqState
.setPending(1L);
416 .debug("unexpected soft irq id value: " + softirq
);
424 public Events
getEventHandleType() {
435 final IEventProcessing
getSoftIrqEntryHandler() {
436 AbsStateUpdate handler
= new AbsStateUpdate() {
438 private Events eventType
= Events
.LTT_EVENT_SOFT_IRQ_ENTRY
;
441 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
444 Long cpu
= trcEvent
.getCpuId();
447 Long softirq
= getAFieldLong(trcEvent
, traceSt
,
448 Fields
.LTT_FIELD_SOFT_IRQ_ID
);
450 if (softirq
== null) {
451 TraceDebug
.debug("Soft IRQ ID not found, eventTime: "
452 + trcEvent
.getTimestamp());
457 Map
<Long
, String
> softIrqNames
= traceSt
.getSoft_irq_names();
458 String submode
= softIrqNames
.get(softirq
);
459 if (submode
== null) {
460 submode
= "softirq " + softirq
;
461 softIrqNames
.put(softirq
, submode
);
464 /* update softirq status */
465 LttngSoftIRQState irqState
= traceSt
.getSoft_irq_states().get(
467 if (irqState
!= null) {
468 irqState
.decrementPending();
469 irqState
.incrementRunning();
472 .debug("unexpected soft irq id value: " + softirq
);
475 /* update cpu state */
476 LTTngCPUState cpu_state
= traceSt
.getCpu_states().get(cpu
);
477 cpu_state
.pushToSoftIrqStack(softirq
);
478 cpu_push_mode(cpu_state
, CpuMode
.LTTV_CPU_SOFT_IRQ
);
480 /* update process execution mode state stack */
481 push_state(cpu
, ExecutionMode
.LTTV_STATE_SOFT_IRQ
, submode
,
482 trcEvent
.getTimestamp(), traceSt
);
489 public Events
getEventHandleType() {
497 * Method to handle the event: LTT_EVENT_LIST_INTERRRUPT
501 final IEventProcessing
getEnumInterruptHandler() {
502 AbsStateUpdate handler
= new AbsStateUpdate() {
504 private Events eventType
= Events
.LTT_EVENT_LIST_INTERRUPT
;
507 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
508 String action
= getAFieldString(trcEvent
, traceSt
,
509 Fields
.LTT_FIELD_ACTION
);
510 Long irq
= getAFieldLong(trcEvent
, traceSt
,
511 Fields
.LTT_FIELD_IRQ_ID
);
513 if (action
== null) {
514 TraceDebug
.debug("Field Action not found in event "
515 + eventType
.getInName() + " time: "
516 + trcEvent
.getTimestamp());
521 TraceDebug
.debug("Field irq_id not found in event "
522 + eventType
.getInName() + " time: "
523 + trcEvent
.getTimestamp());
527 Map
<Long
, String
> irq_names
= traceSt
.getIrq_names();
529 irq_names
.put(irq
, action
);
535 public Events
getEventHandleType() {
543 * Handle the event LTT_EVENT_REQUEST_ISSUE
547 final IEventProcessing
getBdevRequestIssueHandler() {
548 AbsStateUpdate handler
= new AbsStateUpdate() {
550 private Events eventType
= Events
.LTT_EVENT_REQUEST_ISSUE
;
553 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
556 Long major
= getAFieldLong(trcEvent
, traceSt
,
557 Fields
.LTT_FIELD_MAJOR
);
558 Long minor
= getAFieldLong(trcEvent
, traceSt
,
559 Fields
.LTT_FIELD_MINOR
);
560 Long operation
= getAFieldLong(trcEvent
, traceSt
,
561 Fields
.LTT_FIELD_OPERATION
);
563 // calculate bdevcode
564 Long devcode
= mkdev(major
, minor
);
566 if (devcode
== null) {
568 .debug("incorrect calcualtion of bdevcode input( major: "
572 + " operation: " + operation
);
576 Map
<Long
, LttngBdevState
> bdev_states
= traceSt
579 LttngBdevState bdevState
= bdev_states
.get(devcode
);
580 if (bdevState
== null) {
581 bdevState
= new LttngBdevState();
584 // update the mode in the stack
585 if (operation
== 0L) {
586 bdevState
.pushToBdevStack(BdevMode
.LTTV_BDEV_BUSY_READING
);
588 bdevState
.pushToBdevStack(BdevMode
.LTTV_BDEV_BUSY_WRITING
);
591 // make sure it is included in the set
592 bdev_states
.put(devcode
, bdevState
);
598 public Events
getEventHandleType() {
607 * Handling event: LTT_EVENT_REQUEST_COMPLETE
610 * FIELDS(LTT_FIELD_MAJOR, LTT_FIELD_MINOR, LTT_FIELD_OPERATION
615 final IEventProcessing
getBdevRequestCompleteHandler() {
616 AbsStateUpdate handler
= new AbsStateUpdate() {
618 private Events eventType
= Events
.LTT_EVENT_REQUEST_COMPLETE
;
621 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
624 Long major
= getAFieldLong(trcEvent
, traceSt
,
625 Fields
.LTT_FIELD_MAJOR
);
626 Long minor
= getAFieldLong(trcEvent
, traceSt
,
627 Fields
.LTT_FIELD_MINOR
);
628 Long operation
= getAFieldLong(trcEvent
, traceSt
,
629 Fields
.LTT_FIELD_OPERATION
);
631 // calculate bdevcode
632 Long devcode
= mkdev(major
, minor
);
634 if (devcode
== null) {
636 .debug("incorrect calcualtion of bdevcode input( major: "
640 + " operation: " + operation
);
644 Map
<Long
, LttngBdevState
> bdev_states
= traceSt
647 LttngBdevState bdevState
= bdev_states
.get(devcode
);
648 if (bdevState
== null) {
649 bdevState
= new LttngBdevState();
652 /* update block device */
653 bdev_pop_mode(bdevState
);
660 public Events
getEventHandleType() {
669 * Handles event: LTT_EVENT_FUNCTION_ENTRY
672 * FIELDS: LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE
677 final IEventProcessing
getFunctionEntryHandler() {
678 AbsStateUpdate handler
= new AbsStateUpdate() {
680 private Events eventType
= Events
.LTT_EVENT_FUNCTION_ENTRY
;
683 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
684 Long cpu
= trcEvent
.getCpuId();
685 Long funcptr
= getAFieldLong(trcEvent
, traceSt
,
686 Fields
.LTT_FIELD_THIS_FN
);
688 push_function(traceSt
, funcptr
, cpu
);
694 public Events
getEventHandleType() {
705 final IEventProcessing
getFunctionExitHandler() {
706 AbsStateUpdate handler
= new AbsStateUpdate() {
708 private Events eventType
= Events
.LTT_EVENT_FUNCTION_EXIT
;
711 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
713 Long funcptr
= getAFieldLong(trcEvent
, traceSt
,
714 Fields
.LTT_FIELD_THIS_FN
);
716 pop_function(traceSt
, trcEvent
, funcptr
);
722 public Events
getEventHandleType() {
731 * process event: LTT_EVENT_SYS_CALL_TABLE
734 * fields: LTT_FIELD_ID, LTT_FIELD_ADDRESS, LTT_FIELD_SYMBOL
739 final IEventProcessing
getDumpSyscallHandler() {
740 AbsStateUpdate handler
= new AbsStateUpdate() {
742 private Events eventType
= Events
.LTT_EVENT_SYS_CALL_TABLE
;
745 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
746 // obtain the syscall id
747 Long id
= getAFieldLong(trcEvent
, traceSt
, Fields
.LTT_FIELD_ID
);
749 // Long address = getAFieldLong(trcEvent, traceSt,
750 // Fields.LTT_FIELD_ADDRESS);
753 String symbol
= getAFieldString(trcEvent
, traceSt
,
754 Fields
.LTT_FIELD_SYMBOL
);
756 // fill the symbol to the sycall_names collection
757 traceSt
.getSyscall_names().put(id
, symbol
);
763 public Events
getEventHandleType() {
772 * Handles event: LTT_EVENT_KPROBE_TABLE
775 * Fields: LTT_FIELD_IP, LTT_FIELD_SYMBOL
780 final IEventProcessing
getDumpKprobeHandler() {
781 AbsStateUpdate handler
= new AbsStateUpdate() {
783 private Events eventType
= Events
.LTT_EVENT_KPROBE_TABLE
;
786 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
788 Long ip
= getAFieldLong(trcEvent
, traceSt
, Fields
.LTT_FIELD_IP
);
789 String symbol
= getAFieldString(trcEvent
, traceSt
,
790 Fields
.LTT_FIELD_SYMBOL
);
792 traceSt
.getKprobe_table().put(ip
, symbol
);
799 public Events
getEventHandleType() {
808 * Handles: LTT_EVENT_SOFTIRQ_VEC
811 * Fields: LTT_FIELD_ID, LTT_FIELD_ADDRESS, LTT_FIELD_SYMBOL
816 final IEventProcessing
getDumpSoftIrqHandler() {
817 AbsStateUpdate handler
= new AbsStateUpdate() {
819 private Events eventType
= Events
.LTT_EVENT_SOFTIRQ_VEC
;
822 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
825 Long id
= getAFieldLong(trcEvent
, traceSt
, Fields
.LTT_FIELD_ID
);
827 // Address not needed
828 // Long address = ltt_event_get_long_unsigned(e,
829 // lttv_trace_get_hook_field(th,
833 String symbol
= getAFieldString(trcEvent
, traceSt
,
834 Fields
.LTT_FIELD_SYMBOL
);
836 // Register the soft irq name
837 traceSt
.getSoft_irq_names().put(id
, symbol
);
843 public Events
getEventHandleType() {
852 * Handles: LTT_EVENT_SCHED_SCHEDULE
855 * Fields: LTT_FIELD_PREV_PID, LTT_FIELD_NEXT_PID, LTT_FIELD_PREV_STATE
860 final IEventProcessing
getSchedChangeHandler() {
861 AbsStateUpdate handler
= new AbsStateUpdate() {
863 private Events eventType
= Events
.LTT_EVENT_SCHED_SCHEDULE
;
866 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
868 Long cpu
= trcEvent
.getCpuId();
869 TmfTimestamp eventTime
= trcEvent
.getTimestamp();
871 LttngProcessState process
= traceSt
.getRunning_process().get(
874 Long pid_out
= getAFieldLong(trcEvent
, traceSt
,
875 Fields
.LTT_FIELD_PREV_PID
);
876 Long pid_in
= getAFieldLong(trcEvent
, traceSt
,
877 Fields
.LTT_FIELD_NEXT_PID
);
878 Long state_out
= getAFieldLong(trcEvent
, traceSt
,
879 Fields
.LTT_FIELD_PREV_STATE
);
881 if (process
!= null) {
884 * We could not know but it was not the idle process
885 * executing. This should only happen at the beginning,
886 * before the first schedule event, and when the initial
887 * information (current process for each CPU) is missing. It
888 * is not obvious how we could, after the fact, compensate
889 * the wrongly attributed statistics.
892 // This test only makes sense once the state is known and if
895 // missing events. We need to silently ignore schedchange
898 // process_free, or it causes glitches. (FIXME)
899 // if(unlikely(process->pid != pid_out)) {
900 // g_assert(process->pid == 0);
902 if ((process
.getPid().longValue() == 0L)
903 && (process
.getState().getExec_mode() == ExecutionMode
.LTTV_STATE_MODE_UNKNOWN
)) {
904 if ((pid_out
!= null) && (pid_out
.longValue() == 0L)) {
906 * Scheduling out of pid 0 at beginning of the trace
907 * : we know for sure it is in syscall mode at this
911 process
.getState().setExec_mode(
912 ExecutionMode
.LTTV_STATE_SYSCALL
);
913 process
.getState().setProc_status(
914 ProcessStatus
.LTTV_STATE_WAIT
);
915 process
.getState().setChange_Time(
916 trcEvent
.getTimestamp().getValue());
917 process
.getState().setEntry_Time(
918 trcEvent
.getTimestamp().getValue());
921 if (process
.getState().getProc_status() == ProcessStatus
.LTTV_STATE_EXIT
) {
922 process
.getState().setProc_status(
923 ProcessStatus
.LTTV_STATE_ZOMBIE
);
924 process
.getState().setChange_Time(
925 trcEvent
.getTimestamp().getValue());
927 if ((state_out
!= null)
928 && (state_out
.longValue() == 0L)) {
929 process
.getState().setProc_status(
930 ProcessStatus
.LTTV_STATE_WAIT_CPU
);
932 process
.getState().setProc_status(
933 ProcessStatus
.LTTV_STATE_WAIT
);
936 process
.getState().setChange_Time(
937 trcEvent
.getTimestamp().getValue());
940 if ((state_out
!= null)
941 && (state_out
== 32L || state_out
== 64L)) { /*
946 /* see sched.h for states */
947 if (!exit_process(traceSt
, process
)) {
948 process
.getState().setProc_status(
949 ProcessStatus
.LTTV_STATE_DEAD
);
950 process
.getState().setChange_Time(
951 trcEvent
.getTimestamp().getValue());
956 process
= lttv_state_find_process_or_create(traceSt
, cpu
,
959 traceSt
.getRunning_process().put(cpu
, process
);
961 process
.getState().setProc_status(ProcessStatus
.LTTV_STATE_RUN
);
962 process
.getState().setChange_Time(eventTime
.getValue());
964 // process->state->s = LTTV_STATE_RUN;
965 // if(process->usertrace)
966 // process->usertrace->cpu = cpu;
967 // process->last_cpu_index =
968 // ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
970 // process->state->change = s->parent.timestamp;
972 LTTngCPUState cpu_state
= traceSt
.getCpu_states().get(cpu
);
973 /* update cpu status */
974 if ((pid_in
!= null) && (pid_in
.longValue() == 0L)) {
976 /* going to idle task */
977 cpu_set_base_mode(cpu_state
, CpuMode
.LTTV_CPU_IDLE
);
980 * scheduling a real task. we must be careful here: if we
981 * just schedule()'ed to a process that is in a trap, we
982 * must put the cpu in trap mode
984 cpu_set_base_mode(cpu_state
, CpuMode
.LTTV_CPU_BUSY
);
985 if (process
.getState().getExec_mode() == ExecutionMode
.LTTV_STATE_TRAP
) {
986 cpu_push_mode(cpu_state
, CpuMode
.LTTV_CPU_TRAP
);
994 public Events
getEventHandleType() {
1003 * Handles: LTT_EVENT_PROCESS_FORK
1006 * Fields: FIELD_ARRAY(LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID,
1007 * LTT_FIELD_CHILD_TGID)
1012 final IEventProcessing
getProcessForkHandler() {
1013 AbsStateUpdate handler
= new AbsStateUpdate() {
1015 private Events eventType
= Events
.LTT_EVENT_PROCESS_FORK
;
1018 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
1020 Long cpu
= trcEvent
.getCpuId();
1021 LttngProcessState process
= traceSt
.getRunning_process().get(
1023 TmfTimestamp timeStamp
= trcEvent
.getTimestamp();
1026 // Long parent_pid = getAFieldLong(trcEvent, traceSt,
1027 // Fields.LTT_FIELD_PARENT_PID);
1030 /* In the Linux Kernel, there is one PID per thread. */
1031 Long child_pid
= getAFieldLong(trcEvent
, traceSt
,
1032 Fields
.LTT_FIELD_CHILD_PID
);
1035 /* tgid in the Linux kernel is the "real" POSIX PID. */
1036 Long child_tgid
= getAFieldLong(trcEvent
, traceSt
,
1037 Fields
.LTT_FIELD_CHILD_TGID
);
1038 if (child_tgid
== null) {
1043 * Mathieu : it seems like the process might have been scheduled
1044 * in before the fork, and, in a rare case, might be the current
1045 * process. This might happen in a SMP case where we don't have
1046 * enough precision on the clocks.
1048 * Test reenabled after precision fixes on time. (Mathieu)
1051 // zombie_process = lttv_state_find_process(ts, ANY_CPU,
1054 // if(unlikely(zombie_process != NULL)) {
1055 // /* Reutilisation of PID. Only now we are sure that the old
1057 // * has been released. FIXME : should know when release_task
1061 // guint num_cpus = ltt_trace_get_num_cpu(ts->parent.t);
1063 // for(i=0; i< num_cpus; i++) {
1064 // g_assert(zombie_process != ts->running_process[i]);
1067 // exit_process(s, zombie_process);
1071 if (process
.getPid().equals(child_pid
)) {
1073 .debug("Unexpected, process pid equal to child pid: "
1076 + trcEvent
.getTimestamp());
1079 // g_assert(process->pid != child_pid);
1080 // FIXME : Add this test in the "known state" section
1081 // g_assert(process->pid == parent_pid);
1082 LttngProcessState child_process
= lttv_state_find_process(
1083 traceSt
, ANY_CPU
, child_pid
);
1084 if (child_process
== null) {
1085 child_process
= create_process(traceSt
, cpu
, child_pid
,
1086 child_tgid
, timeStamp
);
1087 child_process
.setPpid(process
.getPid(), timeStamp
.getValue());
1090 * The process has already been created : due to time
1091 * imprecision between multiple CPUs : it has been scheduled
1092 * in before creation. Note that we shouldn't have this kind
1095 * Simply put a correct parent.
1097 StringBuilder sb
= new StringBuilder("Process " + child_pid
);
1098 sb
.append(" has been created at ["
1099 + child_process
.getCreation_time() + "] ");
1100 sb
.append("and inserted at ["
1101 + child_process
.getInsertion_time() + "] ");
1102 sb
.append("before \nfork on cpu " + cpu
+ " Event time: ["
1103 + trcEvent
+ "]\n.");
1105 .append("Probably an unsynchronized TSD problem on the traced machine.");
1106 TraceDebug
.debug(sb
.toString());
1108 // g_assert(0); /* This is a problematic case : the process
1111 // before the fork event */
1112 child_process
.setPpid(process
.getPid());
1113 child_process
.setTgid(child_tgid
);
1116 if (!child_process
.getName().equals(
1117 ProcessStatus
.LTTV_STATE_UNNAMED
.getInName())) {
1118 TraceDebug
.debug("Unexpected child process status: "
1119 + child_process
.getName());
1122 child_process
.setName(process
.getName());
1123 child_process
.setBrand(process
.getBrand());
1130 public Events
getEventHandleType() {
1139 * Handles: LTT_EVENT_KTHREAD_CREATE
1142 * Fields: LTT_FIELD_PID
1147 final IEventProcessing
getProcessKernelThreadHandler() {
1148 AbsStateUpdate handler
= new AbsStateUpdate() {
1150 private Events eventType
= Events
.LTT_EVENT_KTHREAD_CREATE
;
1153 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
1155 * We stamp a newly created process as kernel_thread. The thread
1156 * should not be running yet.
1159 LttngExecutionState exState
;
1161 LttngProcessState process
;
1164 pid
= getAFieldLong(trcEvent
, traceSt
, Fields
.LTT_FIELD_PID
);
1165 // s->parent.target_pid = pid;
1167 process
= lttv_state_find_process_or_create(traceSt
, ANY_CPU
,
1168 pid
, new TmfTimestamp());
1170 if (!process
.getState().getProc_status().equals(
1171 ProcessStatus
.LTTV_STATE_DEAD
)) {
1172 // Leave only the first element in the stack with execution
1175 exState
= process
.getFirstElementFromExecutionStack();
1176 exState
.setExec_mode(ExecutionMode
.LTTV_STATE_SYSCALL
);
1177 process
.clearExecutionStack();
1178 process
.pushToExecutionStack(exState
);
1181 process
.setType(ProcessType
.LTTV_STATE_KERNEL_THREAD
);
1188 public Events
getEventHandleType() {
1197 * Handles: LTT_EVENT_PROCESS_EXIT
1205 final IEventProcessing
getProcessExitHandler() {
1206 AbsStateUpdate handler
= new AbsStateUpdate() {
1208 private Events eventType
= Events
.LTT_EVENT_PROCESS_EXIT
;
1211 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
1214 LttngProcessState process
;
1216 pid
= getAFieldLong(trcEvent
, traceSt
, Fields
.LTT_FIELD_PID
);
1217 // s->parent.target_pid = pid;
1219 // FIXME : Add this test in the "known state" section
1220 // g_assert(process->pid == pid);
1222 process
= lttv_state_find_process(traceSt
, ANY_CPU
, pid
);
1223 if (process
!= null) {
1224 process
.getState().setProc_status(
1225 ProcessStatus
.LTTV_STATE_EXIT
);
1232 public Events
getEventHandleType() {
1241 * Handles: LTT_EVENT_PROCESS_FREE
1244 * Fields: LTT_FIELD_PID
1249 final IEventProcessing
getProcessFreeHandler() {
1250 AbsStateUpdate handler
= new AbsStateUpdate() {
1252 private Events eventType
= Events
.LTT_EVENT_PROCESS_FREE
;
1255 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
1258 LttngProcessState process
;
1260 /* PID of the process to release */
1261 release_pid
= getAFieldLong(trcEvent
, traceSt
,
1262 Fields
.LTT_FIELD_PID
);
1263 // s->parent.target_pid = release_pid;
1265 if ((release_pid
!= null) && (release_pid
.longValue() == 0L)) {
1266 TraceDebug
.debug("Unexpected release_pid: 0, Event time: "
1267 + trcEvent
.getTimestamp());
1270 process
= lttv_state_find_process(traceSt
, ANY_CPU
, release_pid
);
1271 if (process
!= null) {
1272 exit_process(traceSt
, process
);
1277 // if(process != null) {
1279 * release_task is happening at kernel level : we can now safely
1280 * release the data structure of the process
1282 // This test is fun, though, as it may happen that
1283 // at time t : CPU 0 : process_free
1284 // at time t+150ns : CPU 1 : schedule out
1285 // Clearly due to time imprecision, we disable it. (Mathieu)
1286 // If this weird case happen, we have no choice but to put the
1287 // Currently running process on the cpu to 0.
1288 // I re-enable it following time precision fixes. (Mathieu)
1289 // Well, in the case where an process is freed by a process on
1292 // and still scheduled, it happens that this is the schedchange
1295 // drop the last reference count. Do not free it here!
1297 // int num_cpus = ltt_trace_get_num_cpu(ts->parent.t);
1299 // for(i=0; i< num_cpus; i++) {
1300 // //g_assert(process != ts->running_process[i]);
1301 // if(process == ts->running_process[i]) {
1302 // //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
1306 // if(i == num_cpus) /* process is not scheduled */
1307 // exit_process(s, process);
1315 public Events
getEventHandleType() {
1324 * Handles: LTT_EVENT_EXEC
1327 * FIELDS: LTT_FIELD_FILENAME
1332 final IEventProcessing
getProcessExecHandler() {
1333 AbsStateUpdate handler
= new AbsStateUpdate() {
1335 private Events eventType
= Events
.LTT_EVENT_EXEC
;
1338 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
1340 Long cpu
= trcEvent
.getCpuId();
1341 LttngProcessState process
= traceSt
.getRunning_process().get(
1344 // #if 0//how to use a sequence that must be transformed in a
1346 // /* PID of the process to release */
1347 // guint64 name_len = ltt_event_field_element_number(e,
1348 // lttv_trace_get_hook_field(th, 0));
1349 // //name = ltt_event_get_string(e,
1350 // lttv_trace_get_hook_field(th, 0));
1351 // LttField *child = ltt_event_field_element_select(e,
1352 // lttv_trace_get_hook_field(th, 0), 0);
1353 // gchar *name_begin =
1354 // (gchar*)(ltt_event_data(e)+ltt_event_field_offset(e, child));
1355 // gchar *null_term_name = g_new(gchar, name_len+1);
1356 // memcpy(null_term_name, name_begin, name_len);
1357 // null_term_name[name_len] = '\0';
1358 // process->name = g_quark_from_string(null_term_name);
1361 process
.setName(getAFieldString(trcEvent
, traceSt
,
1362 Fields
.LTT_FIELD_FILENAME
));
1363 process
.setBrand(StateStrings
.LTTV_STATE_UNBRANDED
);
1369 public Events
getEventHandleType() {
1378 * LTT_EVENT_THREAD_BRAND
1381 * FIELDS: LTT_FIELD_NAME
1386 final IEventProcessing
GetThreadBrandHandler() {
1387 AbsStateUpdate handler
= new AbsStateUpdate() {
1389 private Events eventType
= Events
.LTT_EVENT_THREAD_BRAND
;
1392 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
1395 Long cpu
= trcEvent
.getCpuId();
1396 LttngProcessState process
= traceSt
.getRunning_process().get(
1399 name
= getAFieldString(trcEvent
, traceSt
, Fields
.LTT_FIELD_NAME
);
1400 process
.setBrand(name
);
1406 public Events
getEventHandleType() {
1416 final IEventProcessing
getStateDumpEndHandler() {
1417 AbsStateUpdate handler
= new AbsStateUpdate() {
1419 private Events eventType
= Events
.LTT_EVENT_STATEDUMP_END
;
1422 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
1424 /* For all processes */
1426 * if kernel thread, if stack[0] is unknown, set to syscall
1429 /* else, if stack[0] is unknown, set to user mode, running */
1430 LttngProcessState
[] processes
= traceSt
.getProcesses();
1431 TmfTimestamp time
= trcEvent
.getTimestamp();
1433 for (int pos
= 0; pos
< processes
.length
; pos
++) {
1434 fix_process(processes
[pos
], time
);
1442 public Events
getEventHandleType() {
1447 * Private method used to establish the first execution state in the
1448 * stack for a given process
1453 private void fix_process(LttngProcessState process
,
1454 TmfTimestamp timestamp
) {
1456 LttngExecutionState es
;
1458 if (process
.getType() == ProcessType
.LTTV_STATE_KERNEL_THREAD
) {
1459 es
= process
.getFirstElementFromExecutionStack();
1461 if (es
.getExec_mode() == ExecutionMode
.LTTV_STATE_MODE_UNKNOWN
) {
1462 es
.setExec_mode(ExecutionMode
.LTTV_STATE_SYSCALL
);
1464 .setExec_submode(ExecutionSubMode
.LTTV_STATE_SUBMODE_NONE
1466 es
.setEntry_Time(timestamp
.getValue());
1467 es
.setChange_Time(timestamp
.getValue());
1468 es
.setCum_cpu_time(0L);
1469 if (es
.getProc_status() == ProcessStatus
.LTTV_STATE_UNNAMED
) {
1470 es
.setProc_status(ProcessStatus
.LTTV_STATE_WAIT
);
1474 es
= process
.getFirstElementFromExecutionStack();
1475 if (es
.getExec_mode() == ExecutionMode
.LTTV_STATE_MODE_UNKNOWN
) {
1476 es
.setExec_mode(ExecutionMode
.LTTV_STATE_USER_MODE
);
1478 .setExec_submode(ExecutionSubMode
.LTTV_STATE_SUBMODE_NONE
1480 es
.setEntry_Time(timestamp
.getValue());
1481 es
.setChange_Time(timestamp
.getValue());
1482 es
.setCum_cpu_time(0L);
1483 if (es
.getProc_status() == ProcessStatus
.LTTV_STATE_UNNAMED
) {
1484 es
.setProc_status(ProcessStatus
.LTTV_STATE_RUN
);
1487 // If the first element is also the one on top... mean
1488 // we have ONE element on the stack
1489 if (process
.getFirstElementFromExecutionStack() == process
1490 .peekFromExecutionStack()) {
1492 * Still in bottom unknown mode, means never did a
1493 * system call May be either in user mode, syscall
1494 * mode, running or waiting.
1497 * FIXME : we may be tagging syscall mode when being
1500 // Get a new execution State
1501 es
= new LttngExecutionState();
1503 // initialize values
1504 es
.setExec_mode(ExecutionMode
.LTTV_STATE_SYSCALL
);
1506 .setExec_submode(ExecutionSubMode
.LTTV_STATE_SUBMODE_NONE
1508 es
.setEntry_Time(timestamp
.getValue());
1509 es
.setChange_Time(timestamp
.getValue());
1510 es
.setCum_cpu_time(0L);
1511 es
.setProc_status(ProcessStatus
.LTTV_STATE_WAIT
);
1513 // Push the new state to the stack
1514 process
.pushToExecutionStack(es
);
1525 * Handles: LTT_EVENT_PROCESS_STATE
1528 * FIELDS: LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
1529 * LTT_FIELD_TYPE, LTT_FIELD_MODE, LTT_FIELD_SUBMODE, LTT_FIELD_STATUS,
1535 final IEventProcessing
getEnumProcessStateHandler() {
1536 AbsStateUpdate handler
= new AbsStateUpdate() {
1538 private Events eventType
= Events
.LTT_EVENT_PROCESS_STATE
;
1541 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
1547 Long cpu
= trcEvent
.getCpuId();
1549 LttngProcessState process
= traceSt
.getRunning_process().get(
1551 LttngProcessState parent_process
;
1553 // String mode, submode, status;
1554 LttngExecutionState es
;
1557 pid
= getAFieldLong(trcEvent
, traceSt
, Fields
.LTT_FIELD_PID
);
1560 parent_pid
= getAFieldLong(trcEvent
, traceSt
,
1561 Fields
.LTT_FIELD_PARENT_PID
);
1564 command
= getAFieldString(trcEvent
, traceSt
,
1565 Fields
.LTT_FIELD_NAME
);
1567 Long typeVal
= getAFieldLong(trcEvent
, traceSt
,
1568 Fields
.LTT_FIELD_TYPE
);
1570 type
= ProcessType
.LTTV_STATE_KERNEL_THREAD
.getInName();
1571 if ((typeVal
!= null) && (typeVal
.longValue() == 0L)) {
1572 type
= ProcessType
.LTTV_STATE_USER_THREAD
.getInName();
1576 // mode = getAFieldString(trcEvent, traceSt,
1577 // Fields.LTT_FIELD_MODE);
1580 // submode = getAFieldString(trcEvent, traceSt,
1581 // Fields.LTT_FIELD_SUBMODE);
1584 // status = getAFieldString(trcEvent, traceSt,
1585 // Fields.LTT_FIELD_STATUS);
1588 tgid
= getAFieldLong(trcEvent
, traceSt
, Fields
.LTT_FIELD_TGID
);
1593 if ((pid
!= null) && (pid
.longValue() == 0L)) {
1594 for (Long acpu
: traceSt
.getCpu_states().keySet()) {
1595 process
= lttv_state_find_process(traceSt
, acpu
, pid
);
1596 if (process
!= null) {
1597 process
.setPpid(parent_pid
);
1598 process
.setTgid(tgid
);
1599 process
.setName(command
);
1601 .setType(ProcessType
.LTTV_STATE_KERNEL_THREAD
);
1603 StringBuilder sb
= new StringBuilder(
1604 "Unexpected, null process read from the TraceState list of processes, event time: "
1605 + trcEvent
.getTimestamp());
1606 TraceDebug
.debug(sb
.toString());
1611 * The process might exist if a process was forked while
1612 * performing the state dump.
1614 process
= lttv_state_find_process(traceSt
, ANY_CPU
, pid
);
1615 if (process
== null) {
1616 parent_process
= lttv_state_find_process(traceSt
,
1617 ANY_CPU
, parent_pid
);
1618 TmfTimestamp eventTime
= trcEvent
.getTimestamp();
1619 process
= create_process(traceSt
, cpu
, pid
, tgid
,
1620 command
, eventTime
);
1621 if (parent_process
!= null) {
1622 process
.setPpid(parent_process
.getPid(), eventTime
.getValue());
1625 /* Keep the stack bottom : a running user mode */
1627 * Disabled because of inconsistencies in the current
1630 if (type
.equals(ProcessType
.LTTV_STATE_KERNEL_THREAD
1633 * FIXME Kernel thread : can be in syscall or
1634 * interrupt or trap.
1637 * Will cause expected trap when in fact being
1638 * syscall (even after end of statedump event) Will
1639 * cause expected interrupt when being syscall.
1640 * (only before end of statedump event)
1642 // process type is USER_THREAD by default.
1644 .setType(ProcessType
.LTTV_STATE_KERNEL_THREAD
);
1648 //Only one entry needed in the execution stack
1649 process
.popFromExecutionStack();
1650 es
= process
.getState();
1651 es
.setExec_mode(ExecutionMode
.LTTV_STATE_MODE_UNKNOWN
);
1652 es
.setProc_status(ProcessStatus
.LTTV_STATE_UNNAMED
);
1654 .setExec_submode(ExecutionSubMode
.LTTV_STATE_SUBMODE_UNKNOWN
1657 // /* UNKNOWN STATE */
1659 // es = process->state =
1660 // &g_array_index(process->execution_stack,
1661 // LttvExecutionState, 1);
1662 // es->t = LTTV_STATE_MODE_UNKNOWN;
1663 // es->s = LTTV_STATE_UNNAMED;
1664 // es->n = LTTV_STATE_SUBMODE_UNKNOWN;
1669 * The process has already been created : Probably was
1670 * forked while dumping the process state or was simply
1671 * scheduled in prior to get the state dump event.
1673 process
.setPpid(parent_pid
);
1674 process
.setTgid(tgid
);
1675 process
.setName(command
);
1676 if (type
.equals(ProcessType
.LTTV_STATE_KERNEL_THREAD
1679 .setType(ProcessType
.LTTV_STATE_KERNEL_THREAD
);
1681 process
.setType(ProcessType
.LTTV_STATE_USER_THREAD
);
1685 // &g_array_index(process->execution_stack,
1686 // LttvExecutionState,
1689 // if(es->t == LTTV_STATE_MODE_UNKNOWN) {
1690 // if(type == LTTV_STATE_KERNEL_THREAD)
1691 // es->t = LTTV_STATE_SYSCALL;
1693 // es->t = LTTV_STATE_USER_MODE;
1697 * Don't mess around with the stack, it will eventually
1698 * become ok after the end of state dump.
1708 public Events
getEventHandleType() {