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
= traceSt
.getTrap_states().get(trap
);
171 trap_state
.incrementRunning();
178 public Events
getEventHandleType() {
189 final IEventProcessing
getTrapExitHandler() {
190 AbsStateUpdate handler
= new AbsStateUpdate() {
192 private Events eventType
= Events
.LTT_EVENT_TRAP_EXIT
;
195 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
197 Long cpu
= trcEvent
.getCpuId();
198 LTTngCPUState cpust
= traceSt
.getCpu_states().get(cpu
);
199 Long trap
= cpust
.popFromTrapStack();
201 /* update process state */
202 pop_state(cpu
, ExecutionMode
.LTTV_STATE_TRAP
, traceSt
, trcEvent
205 /* update cpu status */
209 traceSt
.getTrap_states().get(trap
).decrementRunning();
212 // TraceDebug.debug("remove this line");
220 public Events
getEventHandleType() {
231 final IEventProcessing
getIrqEntryHandler() {
232 AbsStateUpdate handler
= new AbsStateUpdate() {
234 private Events eventType
= Events
.LTT_EVENT_IRQ_ENTRY
;
237 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
239 Long cpu
= trcEvent
.getCpuId();
241 Long irq
= getAFieldLong(trcEvent
, traceSt
,
242 Fields
.LTT_FIELD_IRQ_ID
);
248 submode
= traceSt
.getIrq_names().get(irq
);
250 if (submode
== null) {
251 submode
= ExecutionSubMode
.LTTV_STATE_SUBMODE_UNKNOWN
256 * Do something with the info about being in user or system mode
259 push_state(cpu
, ExecutionMode
.LTTV_STATE_IRQ
, submode
, trcEvent
260 .getTimestamp(), traceSt
);
262 /* update cpu state */
263 LTTngCPUState cpust
= traceSt
.getCpu_states().get(cpu
);
264 cpu_push_mode(cpust
, CpuMode
.LTTV_CPU_IRQ
); /* mode stack */
265 cpust
.pushToIrqStack(irq
); /* last irq */
267 /* udpate irq state */
268 irq_push_mode(traceSt
.getIrq_states().get(irq
),
269 IRQMode
.LTTV_IRQ_BUSY
);
274 public Events
getEventHandleType() {
285 final IEventProcessing
getSoftIrqExitHandler() {
286 AbsStateUpdate handler
= new AbsStateUpdate() {
288 private Events eventType
= Events
.LTT_EVENT_SOFT_IRQ_EXIT
;
291 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
293 Long cpu
= trcEvent
.getCpuId();
294 LTTngCPUState cpust
= traceSt
.getCpu_states().get(cpu
);
295 Long softirq
= cpust
.popFromSoftIrqStack();
297 // Update process status
298 pop_state(cpu
, ExecutionMode
.LTTV_STATE_SOFT_IRQ
, traceSt
,
299 trcEvent
.getTimestamp());
301 /* update softirq status */
303 LttngSoftIRQState softIrqstate
= traceSt
304 .getSoft_irq_states().get(softirq
);
305 softIrqstate
.decrementRunning();
308 /* update cpu status */
315 public Events
getEventHandleType() {
326 final IEventProcessing
getIrqExitHandler() {
327 AbsStateUpdate handler
= new AbsStateUpdate() {
329 private Events eventType
= Events
.LTT_EVENT_IRQ_EXIT
;
332 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
334 Long cpu
= trcEvent
.getCpuId();
336 /* update process state */
337 pop_state(cpu
, ExecutionMode
.LTTV_STATE_IRQ
, traceSt
, trcEvent
340 /* update cpu status */
341 LTTngCPUState cpust
= traceSt
.getCpu_states().get(cpu
);
344 /* update irq status */
345 Long last_irq
= cpust
.popFromIrqStack();
346 if (last_irq
!= -1L) {
347 LttngIRQState irq_state
= traceSt
.getIrq_states().get(
349 irq_pop_mode(irq_state
);
357 public Events
getEventHandleType() {
368 final IEventProcessing
getSoftIrqRaiseHandler() {
369 AbsStateUpdate handler
= new AbsStateUpdate() {
371 private Events eventType
= Events
.LTT_EVENT_SOFT_IRQ_RAISE
;
374 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
376 // Long cpu = trcEvent.getCpuId();
379 Long softirq
= getAFieldLong(trcEvent
, traceSt
,
380 Fields
.LTT_FIELD_SOFT_IRQ_ID
);
382 if (softirq
== null) {
383 TraceDebug
.debug("Soft_irq_id not found in "
384 + eventType
.getInName() + " time: "
385 + trcEvent
.getTimestamp());
390 // String[] softIrqNames = traceSt.getSoft_irq_names();
391 // if (softirq < softIrqNames.length) {
392 // submode = softIrqNames[softirq];
394 // submode = "softirq " + softirq;
397 /* update softirq status */
398 /* a soft irq raises are not cumulative */
399 LttngSoftIRQState irqState
= traceSt
.getSoft_irq_states().get(
401 if (irqState
!= null) {
402 irqState
.setPending(1L);
405 .debug("unexpected soft irq id value: " + softirq
);
413 public Events
getEventHandleType() {
424 final IEventProcessing
getSoftIrqEntryHandler() {
425 AbsStateUpdate handler
= new AbsStateUpdate() {
427 private Events eventType
= Events
.LTT_EVENT_SOFT_IRQ_ENTRY
;
430 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
433 Long cpu
= trcEvent
.getCpuId();
436 Long softirq
= getAFieldLong(trcEvent
, traceSt
,
437 Fields
.LTT_FIELD_SOFT_IRQ_ID
);
439 if (softirq
== null) {
440 TraceDebug
.debug("Soft IRQ ID not found, eventTime: "
441 + trcEvent
.getTimestamp());
446 Map
<Long
, String
> softIrqNames
= traceSt
.getSoft_irq_names();
447 String submode
= softIrqNames
.get(softirq
);
448 if (submode
== null) {
449 submode
= "softirq " + softirq
;
450 softIrqNames
.put(softirq
, submode
);
453 /* update softirq status */
454 LttngSoftIRQState irqState
= traceSt
.getSoft_irq_states().get(
456 if (irqState
!= null) {
457 irqState
.decrementPending();
458 irqState
.incrementRunning();
461 .debug("unexpected soft irq id value: " + softirq
);
464 /* update cpu state */
465 LTTngCPUState cpu_state
= traceSt
.getCpu_states().get(cpu
);
466 cpu_state
.pushToSoftIrqStack(softirq
);
467 cpu_push_mode(cpu_state
, CpuMode
.LTTV_CPU_SOFT_IRQ
);
469 /* update process execution mode state stack */
470 push_state(cpu
, ExecutionMode
.LTTV_STATE_SOFT_IRQ
, submode
,
471 trcEvent
.getTimestamp(), traceSt
);
478 public Events
getEventHandleType() {
486 * Method to handle the event: LTT_EVENT_LIST_INTERRRUPT
490 final IEventProcessing
getEnumInterruptHandler() {
491 AbsStateUpdate handler
= new AbsStateUpdate() {
493 private Events eventType
= Events
.LTT_EVENT_LIST_INTERRUPT
;
496 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
497 String action
= getAFieldString(trcEvent
, traceSt
,
498 Fields
.LTT_FIELD_ACTION
);
499 Long irq
= getAFieldLong(trcEvent
, traceSt
,
500 Fields
.LTT_FIELD_IRQ_ID
);
502 if (action
== null) {
503 TraceDebug
.debug("Field Action not found in event "
504 + eventType
.getInName() + " time: "
505 + trcEvent
.getTimestamp());
510 TraceDebug
.debug("Field irq_id not found in event "
511 + eventType
.getInName() + " time: "
512 + trcEvent
.getTimestamp());
516 Map
<Long
, String
> irq_names
= traceSt
.getIrq_names();
518 irq_names
.put(irq
, action
);
524 public Events
getEventHandleType() {
532 * Handle the event LTT_EVENT_REQUEST_ISSUE
536 final IEventProcessing
getBdevRequestIssueHandler() {
537 AbsStateUpdate handler
= new AbsStateUpdate() {
539 private Events eventType
= Events
.LTT_EVENT_REQUEST_ISSUE
;
542 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
545 Long major
= getAFieldLong(trcEvent
, traceSt
,
546 Fields
.LTT_FIELD_MAJOR
);
547 Long minor
= getAFieldLong(trcEvent
, traceSt
,
548 Fields
.LTT_FIELD_MINOR
);
549 Long operation
= getAFieldLong(trcEvent
, traceSt
,
550 Fields
.LTT_FIELD_OPERATION
);
552 // calculate bdevcode
553 Long devcode
= mkdev(major
, minor
);
555 if (devcode
== null) {
557 .debug("incorrect calcualtion of bdevcode input( major: "
561 + " operation: " + operation
);
565 Map
<Long
, LttngBdevState
> bdev_states
= traceSt
568 LttngBdevState bdevState
= bdev_states
.get(devcode
);
569 if (bdevState
== null) {
570 bdevState
= new LttngBdevState();
573 // update the mode in the stack
574 if (operation
== 0L) {
575 bdevState
.pushToBdevStack(BdevMode
.LTTV_BDEV_BUSY_READING
);
577 bdevState
.pushToBdevStack(BdevMode
.LTTV_BDEV_BUSY_WRITING
);
580 // make sure it is included in the set
581 bdev_states
.put(devcode
, bdevState
);
587 public Events
getEventHandleType() {
596 * Handling event: LTT_EVENT_REQUEST_COMPLETE
599 * FIELDS(LTT_FIELD_MAJOR, LTT_FIELD_MINOR, LTT_FIELD_OPERATION
604 final IEventProcessing
getBdevRequestCompleteHandler() {
605 AbsStateUpdate handler
= new AbsStateUpdate() {
607 private Events eventType
= Events
.LTT_EVENT_REQUEST_COMPLETE
;
610 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
613 Long major
= getAFieldLong(trcEvent
, traceSt
,
614 Fields
.LTT_FIELD_MAJOR
);
615 Long minor
= getAFieldLong(trcEvent
, traceSt
,
616 Fields
.LTT_FIELD_MINOR
);
617 Long operation
= getAFieldLong(trcEvent
, traceSt
,
618 Fields
.LTT_FIELD_OPERATION
);
620 // calculate bdevcode
621 Long devcode
= mkdev(major
, minor
);
623 if (devcode
== null) {
625 .debug("incorrect calcualtion of bdevcode input( major: "
629 + " operation: " + operation
);
633 Map
<Long
, LttngBdevState
> bdev_states
= traceSt
636 LttngBdevState bdevState
= bdev_states
.get(devcode
);
637 if (bdevState
== null) {
638 bdevState
= new LttngBdevState();
641 /* update block device */
642 bdev_pop_mode(bdevState
);
649 public Events
getEventHandleType() {
658 * Handles event: LTT_EVENT_FUNCTION_ENTRY
661 * FIELDS: LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE
666 final IEventProcessing
getFunctionEntryHandler() {
667 AbsStateUpdate handler
= new AbsStateUpdate() {
669 private Events eventType
= Events
.LTT_EVENT_FUNCTION_ENTRY
;
672 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
673 Long cpu
= trcEvent
.getCpuId();
674 Long funcptr
= getAFieldLong(trcEvent
, traceSt
,
675 Fields
.LTT_FIELD_THIS_FN
);
677 push_function(traceSt
, funcptr
, cpu
);
683 public Events
getEventHandleType() {
694 final IEventProcessing
getFunctionExitHandler() {
695 AbsStateUpdate handler
= new AbsStateUpdate() {
697 private Events eventType
= Events
.LTT_EVENT_FUNCTION_EXIT
;
700 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
702 Long funcptr
= getAFieldLong(trcEvent
, traceSt
,
703 Fields
.LTT_FIELD_THIS_FN
);
705 pop_function(traceSt
, trcEvent
, funcptr
);
711 public Events
getEventHandleType() {
720 * process event: LTT_EVENT_SYS_CALL_TABLE
723 * fields: LTT_FIELD_ID, LTT_FIELD_ADDRESS, LTT_FIELD_SYMBOL
728 final IEventProcessing
getDumpSyscallHandler() {
729 AbsStateUpdate handler
= new AbsStateUpdate() {
731 private Events eventType
= Events
.LTT_EVENT_SYS_CALL_TABLE
;
734 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
735 // obtain the syscall id
736 Long id
= getAFieldLong(trcEvent
, traceSt
, Fields
.LTT_FIELD_ID
);
738 // Long address = getAFieldLong(trcEvent, traceSt,
739 // Fields.LTT_FIELD_ADDRESS);
742 String symbol
= getAFieldString(trcEvent
, traceSt
,
743 Fields
.LTT_FIELD_SYMBOL
);
745 // fill the symbol to the sycall_names collection
746 traceSt
.getSyscall_names().put(id
, symbol
);
752 public Events
getEventHandleType() {
761 * Handles event: LTT_EVENT_KPROBE_TABLE
764 * Fields: LTT_FIELD_IP, LTT_FIELD_SYMBOL
769 final IEventProcessing
getDumpKprobeHandler() {
770 AbsStateUpdate handler
= new AbsStateUpdate() {
772 private Events eventType
= Events
.LTT_EVENT_KPROBE_TABLE
;
775 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
777 Long ip
= getAFieldLong(trcEvent
, traceSt
, Fields
.LTT_FIELD_IP
);
778 String symbol
= getAFieldString(trcEvent
, traceSt
,
779 Fields
.LTT_FIELD_SYMBOL
);
781 traceSt
.getKprobe_table().put(ip
, symbol
);
788 public Events
getEventHandleType() {
797 * Handles: LTT_EVENT_SOFTIRQ_VEC
800 * Fields: LTT_FIELD_ID, LTT_FIELD_ADDRESS, LTT_FIELD_SYMBOL
805 final IEventProcessing
getDumpSoftIrqHandler() {
806 AbsStateUpdate handler
= new AbsStateUpdate() {
808 private Events eventType
= Events
.LTT_EVENT_SOFTIRQ_VEC
;
811 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
814 Long id
= getAFieldLong(trcEvent
, traceSt
, Fields
.LTT_FIELD_ID
);
816 // Address not needed
817 // Long address = ltt_event_get_long_unsigned(e,
818 // lttv_trace_get_hook_field(th,
822 String symbol
= getAFieldString(trcEvent
, traceSt
,
823 Fields
.LTT_FIELD_SYMBOL
);
825 // Register the soft irq name
826 traceSt
.getSoft_irq_names().put(id
, symbol
);
832 public Events
getEventHandleType() {
841 * Handles: LTT_EVENT_SCHED_SCHEDULE
844 * Fields: LTT_FIELD_PREV_PID, LTT_FIELD_NEXT_PID, LTT_FIELD_PREV_STATE
849 final IEventProcessing
getSchedChangeHandler() {
850 AbsStateUpdate handler
= new AbsStateUpdate() {
852 private Events eventType
= Events
.LTT_EVENT_SCHED_SCHEDULE
;
855 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
857 Long cpu
= trcEvent
.getCpuId();
858 TmfTimestamp eventTime
= trcEvent
.getTimestamp();
860 LttngProcessState process
= traceSt
.getRunning_process().get(
863 Long pid_out
= getAFieldLong(trcEvent
, traceSt
,
864 Fields
.LTT_FIELD_PREV_PID
);
865 Long pid_in
= getAFieldLong(trcEvent
, traceSt
,
866 Fields
.LTT_FIELD_NEXT_PID
);
867 Long state_out
= getAFieldLong(trcEvent
, traceSt
,
868 Fields
.LTT_FIELD_PREV_STATE
);
870 if (process
!= null) {
873 * We could not know but it was not the idle process
874 * executing. This should only happen at the beginning,
875 * before the first schedule event, and when the initial
876 * information (current process for each CPU) is missing. It
877 * is not obvious how we could, after the fact, compensate
878 * the wrongly attributed statistics.
881 // This test only makes sense once the state is known and if
884 // missing events. We need to silently ignore schedchange
887 // process_free, or it causes glitches. (FIXME)
888 // if(unlikely(process->pid != pid_out)) {
889 // g_assert(process->pid == 0);
891 if ((process
.getPid().longValue() == 0L)
892 && (process
.getState().getExec_mode() == ExecutionMode
.LTTV_STATE_MODE_UNKNOWN
)) {
893 if ((pid_out
!= null) && (pid_out
.longValue() == 0L)) {
895 * Scheduling out of pid 0 at beginning of the trace
896 * : we know for sure it is in syscall mode at this
900 process
.getState().setExec_mode(
901 ExecutionMode
.LTTV_STATE_SYSCALL
);
902 process
.getState().setProc_status(
903 ProcessStatus
.LTTV_STATE_WAIT
);
904 process
.getState().setChange_Time(
905 trcEvent
.getTimestamp().getValue());
906 process
.getState().setEntry_Time(
907 trcEvent
.getTimestamp().getValue());
910 if (process
.getState().getProc_status() == ProcessStatus
.LTTV_STATE_EXIT
) {
911 process
.getState().setProc_status(
912 ProcessStatus
.LTTV_STATE_ZOMBIE
);
913 process
.getState().setChange_Time(
914 trcEvent
.getTimestamp().getValue());
916 if ((state_out
!= null)
917 && (state_out
.longValue() == 0L)) {
918 process
.getState().setProc_status(
919 ProcessStatus
.LTTV_STATE_WAIT_CPU
);
921 process
.getState().setProc_status(
922 ProcessStatus
.LTTV_STATE_WAIT
);
925 process
.getState().setChange_Time(
926 trcEvent
.getTimestamp().getValue());
929 if ((state_out
!= null)
930 && (state_out
== 32L || state_out
== 64L)) { /*
935 /* see sched.h for states */
936 if (!exit_process(traceSt
, process
)) {
937 process
.getState().setProc_status(
938 ProcessStatus
.LTTV_STATE_DEAD
);
939 process
.getState().setChange_Time(
940 trcEvent
.getTimestamp().getValue());
945 process
= lttv_state_find_process_or_create(traceSt
, cpu
,
948 traceSt
.getRunning_process().put(cpu
, process
);
950 process
.getState().setProc_status(ProcessStatus
.LTTV_STATE_RUN
);
951 process
.getState().setChange_Time(eventTime
.getValue());
953 // process->state->s = LTTV_STATE_RUN;
954 // if(process->usertrace)
955 // process->usertrace->cpu = cpu;
956 // process->last_cpu_index =
957 // ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
959 // process->state->change = s->parent.timestamp;
961 LTTngCPUState cpu_state
= traceSt
.getCpu_states().get(cpu
);
962 /* update cpu status */
963 if ((pid_in
!= null) && (pid_in
.longValue() == 0L)) {
965 /* going to idle task */
966 cpu_set_base_mode(cpu_state
, CpuMode
.LTTV_CPU_IDLE
);
969 * scheduling a real task. we must be careful here: if we
970 * just schedule()'ed to a process that is in a trap, we
971 * must put the cpu in trap mode
973 cpu_set_base_mode(cpu_state
, CpuMode
.LTTV_CPU_BUSY
);
974 if (process
.getState().getExec_mode() == ExecutionMode
.LTTV_STATE_TRAP
) {
975 cpu_push_mode(cpu_state
, CpuMode
.LTTV_CPU_TRAP
);
983 public Events
getEventHandleType() {
992 * Handles: LTT_EVENT_PROCESS_FORK
995 * Fields: FIELD_ARRAY(LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID,
996 * LTT_FIELD_CHILD_TGID)
1001 final IEventProcessing
getProcessForkHandler() {
1002 AbsStateUpdate handler
= new AbsStateUpdate() {
1004 private Events eventType
= Events
.LTT_EVENT_PROCESS_FORK
;
1007 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
1009 Long cpu
= trcEvent
.getCpuId();
1010 LttngProcessState process
= traceSt
.getRunning_process().get(
1012 TmfTimestamp timeStamp
= trcEvent
.getTimestamp();
1015 // Long parent_pid = getAFieldLong(trcEvent, traceSt,
1016 // Fields.LTT_FIELD_PARENT_PID);
1019 /* In the Linux Kernel, there is one PID per thread. */
1020 Long child_pid
= getAFieldLong(trcEvent
, traceSt
,
1021 Fields
.LTT_FIELD_CHILD_PID
);
1024 /* tgid in the Linux kernel is the "real" POSIX PID. */
1025 Long child_tgid
= getAFieldLong(trcEvent
, traceSt
,
1026 Fields
.LTT_FIELD_CHILD_TGID
);
1027 if (child_tgid
== null) {
1032 * Mathieu : it seems like the process might have been scheduled
1033 * in before the fork, and, in a rare case, might be the current
1034 * process. This might happen in a SMP case where we don't have
1035 * enough precision on the clocks.
1037 * Test reenabled after precision fixes on time. (Mathieu)
1040 // zombie_process = lttv_state_find_process(ts, ANY_CPU,
1043 // if(unlikely(zombie_process != NULL)) {
1044 // /* Reutilisation of PID. Only now we are sure that the old
1046 // * has been released. FIXME : should know when release_task
1050 // guint num_cpus = ltt_trace_get_num_cpu(ts->parent.t);
1052 // for(i=0; i< num_cpus; i++) {
1053 // g_assert(zombie_process != ts->running_process[i]);
1056 // exit_process(s, zombie_process);
1060 if (process
.getPid().equals(child_pid
)) {
1062 .debug("Unexpected, process pid equal to child pid: "
1065 + trcEvent
.getTimestamp());
1068 // g_assert(process->pid != child_pid);
1069 // FIXME : Add this test in the "known state" section
1070 // g_assert(process->pid == parent_pid);
1071 LttngProcessState child_process
= lttv_state_find_process(
1072 traceSt
, ANY_CPU
, child_pid
);
1073 if (child_process
== null) {
1074 child_process
= create_process(traceSt
, cpu
, child_pid
,
1075 child_tgid
, timeStamp
);
1076 child_process
.setPpid(process
.getPid(), timeStamp
.getValue());
1079 * The process has already been created : due to time
1080 * imprecision between multiple CPUs : it has been scheduled
1081 * in before creation. Note that we shouldn't have this kind
1084 * Simply put a correct parent.
1086 StringBuilder sb
= new StringBuilder("Process " + child_pid
);
1087 sb
.append(" has been created at ["
1088 + child_process
.getCreation_time() + "] ");
1089 sb
.append("and inserted at ["
1090 + child_process
.getInsertion_time() + "] ");
1091 sb
.append("before \nfork on cpu " + cpu
+ " Event time: ["
1092 + trcEvent
+ "]\n.");
1094 .append("Probably an unsynchronized TSD problem on the traced machine.");
1095 TraceDebug
.debug(sb
.toString());
1097 // g_assert(0); /* This is a problematic case : the process
1100 // before the fork event */
1101 child_process
.setPpid(process
.getPid());
1102 child_process
.setTgid(child_tgid
);
1105 if (!child_process
.getName().equals(
1106 ProcessStatus
.LTTV_STATE_UNNAMED
.getInName())) {
1107 TraceDebug
.debug("Unexpected child process status: "
1108 + child_process
.getName());
1111 child_process
.setName(process
.getName());
1112 child_process
.setBrand(process
.getBrand());
1119 public Events
getEventHandleType() {
1128 * Handles: LTT_EVENT_KTHREAD_CREATE
1131 * Fields: LTT_FIELD_PID
1136 final IEventProcessing
getProcessKernelThreadHandler() {
1137 AbsStateUpdate handler
= new AbsStateUpdate() {
1139 private Events eventType
= Events
.LTT_EVENT_KTHREAD_CREATE
;
1142 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
1144 * We stamp a newly created process as kernel_thread. The thread
1145 * should not be running yet.
1148 LttngExecutionState exState
;
1150 LttngProcessState process
;
1153 pid
= getAFieldLong(trcEvent
, traceSt
, Fields
.LTT_FIELD_PID
);
1154 // s->parent.target_pid = pid;
1156 process
= lttv_state_find_process_or_create(traceSt
, ANY_CPU
,
1157 pid
, new TmfTimestamp());
1159 if (!process
.getState().getProc_status().equals(
1160 ProcessStatus
.LTTV_STATE_DEAD
)) {
1161 // Leave only the first element in the stack with execution
1164 exState
= process
.getFirstElementFromExecutionStack();
1165 exState
.setExec_mode(ExecutionMode
.LTTV_STATE_SYSCALL
);
1166 process
.clearExecutionStack();
1167 process
.pushToExecutionStack(exState
);
1170 process
.setType(ProcessType
.LTTV_STATE_KERNEL_THREAD
);
1177 public Events
getEventHandleType() {
1186 * Handles: LTT_EVENT_PROCESS_EXIT
1194 final IEventProcessing
getProcessExitHandler() {
1195 AbsStateUpdate handler
= new AbsStateUpdate() {
1197 private Events eventType
= Events
.LTT_EVENT_PROCESS_EXIT
;
1200 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
1203 LttngProcessState process
;
1205 pid
= getAFieldLong(trcEvent
, traceSt
, Fields
.LTT_FIELD_PID
);
1206 // s->parent.target_pid = pid;
1208 // FIXME : Add this test in the "known state" section
1209 // g_assert(process->pid == pid);
1211 process
= lttv_state_find_process(traceSt
, ANY_CPU
, pid
);
1212 if (process
!= null) {
1213 process
.getState().setProc_status(
1214 ProcessStatus
.LTTV_STATE_EXIT
);
1221 public Events
getEventHandleType() {
1230 * Handles: LTT_EVENT_PROCESS_FREE
1233 * Fields: LTT_FIELD_PID
1238 final IEventProcessing
getProcessFreeHandler() {
1239 AbsStateUpdate handler
= new AbsStateUpdate() {
1241 private Events eventType
= Events
.LTT_EVENT_PROCESS_FREE
;
1244 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
1247 LttngProcessState process
;
1249 /* PID of the process to release */
1250 release_pid
= getAFieldLong(trcEvent
, traceSt
,
1251 Fields
.LTT_FIELD_PID
);
1252 // s->parent.target_pid = release_pid;
1254 if ((release_pid
!= null) && (release_pid
.longValue() == 0L)) {
1255 TraceDebug
.debug("Unexpected release_pid: 0, Event time: "
1256 + trcEvent
.getTimestamp());
1259 process
= lttv_state_find_process(traceSt
, ANY_CPU
, release_pid
);
1260 if (process
!= null) {
1261 exit_process(traceSt
, process
);
1266 // if(process != null) {
1268 * release_task is happening at kernel level : we can now safely
1269 * release the data structure of the process
1271 // This test is fun, though, as it may happen that
1272 // at time t : CPU 0 : process_free
1273 // at time t+150ns : CPU 1 : schedule out
1274 // Clearly due to time imprecision, we disable it. (Mathieu)
1275 // If this weird case happen, we have no choice but to put the
1276 // Currently running process on the cpu to 0.
1277 // I re-enable it following time precision fixes. (Mathieu)
1278 // Well, in the case where an process is freed by a process on
1281 // and still scheduled, it happens that this is the schedchange
1284 // drop the last reference count. Do not free it here!
1286 // int num_cpus = ltt_trace_get_num_cpu(ts->parent.t);
1288 // for(i=0; i< num_cpus; i++) {
1289 // //g_assert(process != ts->running_process[i]);
1290 // if(process == ts->running_process[i]) {
1291 // //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
1295 // if(i == num_cpus) /* process is not scheduled */
1296 // exit_process(s, process);
1304 public Events
getEventHandleType() {
1313 * Handles: LTT_EVENT_EXEC
1316 * FIELDS: LTT_FIELD_FILENAME
1321 final IEventProcessing
getProcessExecHandler() {
1322 AbsStateUpdate handler
= new AbsStateUpdate() {
1324 private Events eventType
= Events
.LTT_EVENT_EXEC
;
1327 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
1329 Long cpu
= trcEvent
.getCpuId();
1330 LttngProcessState process
= traceSt
.getRunning_process().get(
1333 // #if 0//how to use a sequence that must be transformed in a
1335 // /* PID of the process to release */
1336 // guint64 name_len = ltt_event_field_element_number(e,
1337 // lttv_trace_get_hook_field(th, 0));
1338 // //name = ltt_event_get_string(e,
1339 // lttv_trace_get_hook_field(th, 0));
1340 // LttField *child = ltt_event_field_element_select(e,
1341 // lttv_trace_get_hook_field(th, 0), 0);
1342 // gchar *name_begin =
1343 // (gchar*)(ltt_event_data(e)+ltt_event_field_offset(e, child));
1344 // gchar *null_term_name = g_new(gchar, name_len+1);
1345 // memcpy(null_term_name, name_begin, name_len);
1346 // null_term_name[name_len] = '\0';
1347 // process->name = g_quark_from_string(null_term_name);
1350 process
.setName(getAFieldString(trcEvent
, traceSt
,
1351 Fields
.LTT_FIELD_FILENAME
));
1352 process
.setBrand(StateStrings
.LTTV_STATE_UNBRANDED
);
1358 public Events
getEventHandleType() {
1367 * LTT_EVENT_THREAD_BRAND
1370 * FIELDS: LTT_FIELD_NAME
1375 final IEventProcessing
GetThreadBrandHandler() {
1376 AbsStateUpdate handler
= new AbsStateUpdate() {
1378 private Events eventType
= Events
.LTT_EVENT_THREAD_BRAND
;
1381 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
1384 Long cpu
= trcEvent
.getCpuId();
1385 LttngProcessState process
= traceSt
.getRunning_process().get(
1388 name
= getAFieldString(trcEvent
, traceSt
, Fields
.LTT_FIELD_NAME
);
1389 process
.setBrand(name
);
1395 public Events
getEventHandleType() {
1405 final IEventProcessing
getStateDumpEndHandler() {
1406 AbsStateUpdate handler
= new AbsStateUpdate() {
1408 private Events eventType
= Events
.LTT_EVENT_STATEDUMP_END
;
1411 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
1413 /* For all processes */
1415 * if kernel thread, if stack[0] is unknown, set to syscall
1418 /* else, if stack[0] is unknown, set to user mode, running */
1419 LttngProcessState
[] processes
= traceSt
.getProcesses();
1420 TmfTimestamp time
= trcEvent
.getTimestamp();
1422 for (int pos
= 0; pos
< processes
.length
; pos
++) {
1423 fix_process(processes
[pos
], time
);
1431 public Events
getEventHandleType() {
1436 * Private method used to establish the first execution state in the
1437 * stack for a given process
1442 private void fix_process(LttngProcessState process
,
1443 TmfTimestamp timestamp
) {
1445 LttngExecutionState es
;
1447 if (process
.getType() == ProcessType
.LTTV_STATE_KERNEL_THREAD
) {
1448 es
= process
.getFirstElementFromExecutionStack();
1450 if (es
.getExec_mode() == ExecutionMode
.LTTV_STATE_MODE_UNKNOWN
) {
1451 es
.setExec_mode(ExecutionMode
.LTTV_STATE_SYSCALL
);
1453 .setExec_submode(ExecutionSubMode
.LTTV_STATE_SUBMODE_NONE
1455 es
.setEntry_Time(timestamp
.getValue());
1456 es
.setChange_Time(timestamp
.getValue());
1457 es
.setCum_cpu_time(0L);
1458 if (es
.getProc_status() == ProcessStatus
.LTTV_STATE_UNNAMED
) {
1459 es
.setProc_status(ProcessStatus
.LTTV_STATE_WAIT
);
1463 es
= process
.getFirstElementFromExecutionStack();
1464 if (es
.getExec_mode() == ExecutionMode
.LTTV_STATE_MODE_UNKNOWN
) {
1465 es
.setExec_mode(ExecutionMode
.LTTV_STATE_USER_MODE
);
1467 .setExec_submode(ExecutionSubMode
.LTTV_STATE_SUBMODE_NONE
1469 es
.setEntry_Time(timestamp
.getValue());
1470 es
.setChange_Time(timestamp
.getValue());
1471 es
.setCum_cpu_time(0L);
1472 if (es
.getProc_status() == ProcessStatus
.LTTV_STATE_UNNAMED
) {
1473 es
.setProc_status(ProcessStatus
.LTTV_STATE_RUN
);
1476 // If the first element is also the one on top... mean
1477 // we have ONE element on the stack
1478 if (process
.getFirstElementFromExecutionStack() == process
1479 .peekFromExecutionStack()) {
1481 * Still in bottom unknown mode, means never did a
1482 * system call May be either in user mode, syscall
1483 * mode, running or waiting.
1486 * FIXME : we may be tagging syscall mode when being
1489 // Get a new execution State
1490 es
= new LttngExecutionState();
1492 // initialize values
1493 es
.setExec_mode(ExecutionMode
.LTTV_STATE_SYSCALL
);
1495 .setExec_submode(ExecutionSubMode
.LTTV_STATE_SUBMODE_NONE
1497 es
.setEntry_Time(timestamp
.getValue());
1498 es
.setChange_Time(timestamp
.getValue());
1499 es
.setCum_cpu_time(0L);
1500 es
.setProc_status(ProcessStatus
.LTTV_STATE_WAIT
);
1502 // Push the new state to the stack
1503 process
.pushToExecutionStack(es
);
1514 * Handles: LTT_EVENT_PROCESS_STATE
1517 * FIELDS: LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
1518 * LTT_FIELD_TYPE, LTT_FIELD_MODE, LTT_FIELD_SUBMODE, LTT_FIELD_STATUS,
1524 final IEventProcessing
getEnumProcessStateHandler() {
1525 AbsStateUpdate handler
= new AbsStateUpdate() {
1527 private Events eventType
= Events
.LTT_EVENT_PROCESS_STATE
;
1530 public boolean process(LttngEvent trcEvent
, LttngTraceState traceSt
) {
1536 Long cpu
= trcEvent
.getCpuId();
1538 LttngProcessState process
= traceSt
.getRunning_process().get(
1540 LttngProcessState parent_process
;
1542 // String mode, submode, status;
1543 LttngExecutionState es
;
1546 pid
= getAFieldLong(trcEvent
, traceSt
, Fields
.LTT_FIELD_PID
);
1549 parent_pid
= getAFieldLong(trcEvent
, traceSt
,
1550 Fields
.LTT_FIELD_PARENT_PID
);
1553 command
= getAFieldString(trcEvent
, traceSt
,
1554 Fields
.LTT_FIELD_NAME
);
1556 Long typeVal
= getAFieldLong(trcEvent
, traceSt
,
1557 Fields
.LTT_FIELD_TYPE
);
1559 type
= ProcessType
.LTTV_STATE_KERNEL_THREAD
.getInName();
1560 if ((typeVal
!= null) && (typeVal
.longValue() == 0L)) {
1561 type
= ProcessType
.LTTV_STATE_USER_THREAD
.getInName();
1565 // mode = getAFieldString(trcEvent, traceSt,
1566 // Fields.LTT_FIELD_MODE);
1569 // submode = getAFieldString(trcEvent, traceSt,
1570 // Fields.LTT_FIELD_SUBMODE);
1573 // status = getAFieldString(trcEvent, traceSt,
1574 // Fields.LTT_FIELD_STATUS);
1577 tgid
= getAFieldLong(trcEvent
, traceSt
, Fields
.LTT_FIELD_TGID
);
1582 if ((pid
!= null) && (pid
.longValue() == 0L)) {
1583 for (Long acpu
: traceSt
.getCpu_states().keySet()) {
1584 process
= lttv_state_find_process(traceSt
, acpu
, pid
);
1585 if (process
!= null) {
1586 process
.setPpid(parent_pid
);
1587 process
.setTgid(tgid
);
1588 process
.setName(command
);
1590 .setType(ProcessType
.LTTV_STATE_KERNEL_THREAD
);
1592 StringBuilder sb
= new StringBuilder(
1593 "Unexpected, null process read from the TraceState list of processes, event time: "
1594 + trcEvent
.getTimestamp());
1595 TraceDebug
.debug(sb
.toString());
1600 * The process might exist if a process was forked while
1601 * performing the state dump.
1603 process
= lttv_state_find_process(traceSt
, ANY_CPU
, pid
);
1604 if (process
== null) {
1605 parent_process
= lttv_state_find_process(traceSt
,
1606 ANY_CPU
, parent_pid
);
1607 TmfTimestamp eventTime
= trcEvent
.getTimestamp();
1608 process
= create_process(traceSt
, cpu
, pid
, tgid
,
1609 command
, eventTime
);
1610 if (parent_process
!= null) {
1611 process
.setPpid(parent_process
.getPid(), eventTime
.getValue());
1614 /* Keep the stack bottom : a running user mode */
1616 * Disabled because of inconsistencies in the current
1619 if (type
.equals(ProcessType
.LTTV_STATE_KERNEL_THREAD
1622 * FIXME Kernel thread : can be in syscall or
1623 * interrupt or trap.
1626 * Will cause expected trap when in fact being
1627 * syscall (even after end of statedump event) Will
1628 * cause expected interrupt when being syscall.
1629 * (only before end of statedump event)
1631 // process type is USER_THREAD by default.
1633 .setType(ProcessType
.LTTV_STATE_KERNEL_THREAD
);
1637 //Only one entry needed in the execution stack
1638 process
.popFromExecutionStack();
1639 es
= process
.getState();
1640 es
.setExec_mode(ExecutionMode
.LTTV_STATE_MODE_UNKNOWN
);
1641 es
.setProc_status(ProcessStatus
.LTTV_STATE_UNNAMED
);
1643 .setExec_submode(ExecutionSubMode
.LTTV_STATE_SUBMODE_UNKNOWN
1646 // /* UNKNOWN STATE */
1648 // es = process->state =
1649 // &g_array_index(process->execution_stack,
1650 // LttvExecutionState, 1);
1651 // es->t = LTTV_STATE_MODE_UNKNOWN;
1652 // es->s = LTTV_STATE_UNNAMED;
1653 // es->n = LTTV_STATE_SUBMODE_UNKNOWN;
1658 * The process has already been created : Probably was
1659 * forked while dumping the process state or was simply
1660 * scheduled in prior to get the state dump event.
1662 process
.setPpid(parent_pid
);
1663 process
.setTgid(tgid
);
1664 process
.setName(command
);
1665 if (type
.equals(ProcessType
.LTTV_STATE_KERNEL_THREAD
1668 .setType(ProcessType
.LTTV_STATE_KERNEL_THREAD
);
1670 process
.setType(ProcessType
.LTTV_STATE_USER_THREAD
);
1674 // &g_array_index(process->execution_stack,
1675 // LttvExecutionState,
1678 // if(es->t == LTTV_STATE_MODE_UNKNOWN) {
1679 // if(type == LTTV_STATE_KERNEL_THREAD)
1680 // es->t = LTTV_STATE_SYSCALL;
1682 // es->t = LTTV_STATE_USER_MODE;
1686 * Don't mess around with the stack, it will eventually
1687 * become ok after the end of state dump.
1697 public Events
getEventHandleType() {