| 1 | /******************************************************************************* |
| 2 | * Copyright (c) 2009 Ericsson |
| 3 | * |
| 4 | * All rights reserved. This program and the accompanying materials are |
| 5 | * made available under the terms of the Eclipse Public License v1.0 which |
| 6 | * accompanies this distribution, and is available at |
| 7 | * http://www.eclipse.org/legal/epl-v10.html |
| 8 | * |
| 9 | * Contributors: |
| 10 | * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation |
| 11 | * Michel Dagenais (michel.dagenais@polymtl.ca) - Reference C implementation, used with permission |
| 12 | *******************************************************************************/ |
| 13 | package org.eclipse.linuxtools.lttng.state.evProcessor.state; |
| 14 | |
| 15 | import org.eclipse.linuxtools.lttng.TraceDebug; |
| 16 | import org.eclipse.linuxtools.lttng.event.LttngEvent; |
| 17 | import org.eclipse.linuxtools.lttng.state.StateStrings; |
| 18 | import org.eclipse.linuxtools.lttng.state.StateStrings.ExecutionMode; |
| 19 | import org.eclipse.linuxtools.lttng.state.StateStrings.IRQMode; |
| 20 | import org.eclipse.linuxtools.lttng.state.StateStrings.ProcessStatus; |
| 21 | import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor; |
| 22 | import org.eclipse.linuxtools.lttng.state.model.LTTngCPUState; |
| 23 | import org.eclipse.linuxtools.lttng.state.model.LttngBdevState; |
| 24 | import org.eclipse.linuxtools.lttng.state.model.LttngExecutionState; |
| 25 | import org.eclipse.linuxtools.lttng.state.model.LttngIRQState; |
| 26 | import org.eclipse.linuxtools.lttng.state.model.LttngProcessState; |
| 27 | import org.eclipse.linuxtools.lttng.state.model.LttngTraceState; |
| 28 | import org.eclipse.linuxtools.tmf.event.TmfTimestamp; |
| 29 | |
| 30 | public abstract class AbsStateUpdate extends AbsStateProcessing implements |
| 31 | ILttngEventProcessor { |
| 32 | |
| 33 | // ======================================================================== |
| 34 | // Data |
| 35 | // ======================================================================= |
| 36 | protected static final Long ANY_CPU = 0L; |
| 37 | |
| 38 | // ======================================================================== |
| 39 | // push and pop from stack |
| 40 | // ======================================================================= |
| 41 | protected void push_state(Long cpu, StateStrings.ExecutionMode execMode, |
| 42 | String submode, int subModeId, TmfTimestamp eventTime, LttngTraceState traceSt) { |
| 43 | |
| 44 | LttngProcessState process = traceSt.getRunning_process().get(cpu); |
| 45 | LttngExecutionState exe_state = new LttngExecutionState(); |
| 46 | exe_state.setExec_mode(execMode); |
| 47 | exe_state.setExec_submode(submode); |
| 48 | exe_state.setExec_submode_id(subModeId); |
| 49 | exe_state.setEntry_Time(eventTime.getValue()); |
| 50 | exe_state.setChange_Time(eventTime.getValue()); |
| 51 | exe_state.setCum_cpu_time(0L); |
| 52 | // if (process != null) |
| 53 | exe_state.setProc_status(process.getState().getProc_status()); |
| 54 | process.pushToExecutionStack(exe_state); |
| 55 | } |
| 56 | |
| 57 | protected void pop_state(Long cpu, StateStrings.ExecutionMode execMode, |
| 58 | LttngTraceState traceSt, TmfTimestamp eventTime) { |
| 59 | |
| 60 | LttngProcessState process = traceSt.getRunning_process().get(cpu); |
| 61 | |
| 62 | if (!process.getState().getExec_mode().equals(execMode)) { |
| 63 | // Different execution mode |
| 64 | TraceDebug.debug("Different Execution Mode type \n\tTime:" //$NON-NLS-1$ |
| 65 | + eventTime.toString() + "\n\tprocess state has: \n\t" //$NON-NLS-1$ |
| 66 | + process.getState().getExec_mode().toString() |
| 67 | + "\n\twhen pop_int is:\n\t" + execMode.toString()); //$NON-NLS-1$ |
| 68 | return; |
| 69 | } |
| 70 | |
| 71 | //The process state is updated within the pop method |
| 72 | process.popFromExecutionStack(); |
| 73 | process.getState().setChange_Time(eventTime.getValue()); |
| 74 | } |
| 75 | |
| 76 | protected void irq_push_mode(LttngIRQState irqst, IRQMode state) { |
| 77 | irqst.pushToIrqStack(state); |
| 78 | } |
| 79 | |
| 80 | protected void irq_set_base_mode(LttngIRQState irqst, IRQMode state) { |
| 81 | irqst.clearAndSetBaseToIrqStack(state); |
| 82 | } |
| 83 | |
| 84 | protected void irq_pop_mode(LttngIRQState irqst) { |
| 85 | irqst.popFromIrqStack(); |
| 86 | } |
| 87 | |
| 88 | protected void cpu_push_mode(LTTngCPUState cpust, StateStrings.CpuMode state) { |
| 89 | // The initialization (init) creates a LttngCPUState instance per |
| 90 | // available cpu in the system |
| 91 | cpust.pushToCpuStack(state); |
| 92 | } |
| 93 | |
| 94 | protected void cpu_pop_mode(LTTngCPUState cpust) { |
| 95 | cpust.popFromCpuStack(); |
| 96 | } |
| 97 | |
| 98 | /* clears the stack and sets the state passed as argument */ |
| 99 | protected void cpu_set_base_mode(LTTngCPUState cpust, |
| 100 | StateStrings.CpuMode state) { |
| 101 | cpust.clearAndSetBaseToCpuStack(state); |
| 102 | } |
| 103 | |
| 104 | protected void bdev_pop_mode(LttngBdevState bdevst) { |
| 105 | bdevst.popFromBdevStack(); |
| 106 | } |
| 107 | |
| 108 | /** |
| 109 | * Push a new received function pointer to the user_stack |
| 110 | * |
| 111 | * @param traceSt |
| 112 | * @param funcptr |
| 113 | * @param cpu |
| 114 | */ |
| 115 | protected void push_function(LttngTraceState traceSt, Long funcptr, Long cpu) { |
| 116 | // Get the related process |
| 117 | LttngProcessState process = traceSt.getRunning_process().get(cpu); |
| 118 | |
| 119 | // update stack |
| 120 | process.pushToUserStack(funcptr); |
| 121 | |
| 122 | // update the pointer to the current function on the corresponding |
| 123 | // process |
| 124 | process.setCurrent_function(funcptr); |
| 125 | } |
| 126 | |
| 127 | protected void pop_function(LttngTraceState traceSt, LttngEvent trcEvent, |
| 128 | Long funcptr) { |
| 129 | Long cpu = trcEvent.getCpuId(); |
| 130 | LttngProcessState process = traceSt.getRunning_process().get(cpu); |
| 131 | Long curr_function = process.getCurrent_function(); |
| 132 | |
| 133 | if (curr_function != null && !curr_function.equals(funcptr)) { |
| 134 | TraceDebug.debug("Different functions: " + funcptr + " current: " //$NON-NLS-1$ //$NON-NLS-2$ |
| 135 | + curr_function + " time stamp: " //$NON-NLS-1$ |
| 136 | + trcEvent.getTimestamp().toString()); |
| 137 | |
| 138 | // g_info("Different functions (%lu.%09lu): ignore it\n", |
| 139 | // tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec); |
| 140 | // g_info("process state has %" PRIu64 " when pop_function is %" |
| 141 | // PRIu64 |
| 142 | // "\n", |
| 143 | // process->current_function, funcptr); |
| 144 | // g_info("{ %u, %u, %s, %s, %s }\n", |
| 145 | // process->pid, |
| 146 | // process->ppid, |
| 147 | // g_quark_to_string(process->name), |
| 148 | // g_quark_to_string(process->brand), |
| 149 | // g_quark_to_string(process->state->s)); |
| 150 | return; |
| 151 | } |
| 152 | |
| 153 | process.popFromUserStack(); |
| 154 | process.setCurrent_function(process.peekFromUserStack()); |
| 155 | } |
| 156 | |
| 157 | // ======================================================================== |
| 158 | // General methods |
| 159 | // ======================================================================= |
| 160 | // Adaption from MKDEV macro |
| 161 | protected Long mkdev(Long major, Long minor) { |
| 162 | Long result = null; |
| 163 | if (major != null && minor != null) { |
| 164 | result = (major << 20) | minor; |
| 165 | } |
| 166 | return result; |
| 167 | } |
| 168 | |
| 169 | /* |
| 170 | * FIXME : this function should be called when we receive an event telling |
| 171 | * that release_task has been called in the kernel. In happens generally |
| 172 | * when the parent waits for its child termination, but may also happen in |
| 173 | * special cases in the child's exit : when the parent ignores its children |
| 174 | * SIGCCHLD or has the flag SA_NOCLDWAIT. It can also happen when the child |
| 175 | * is part of a killed thread group, but isn't the leader. |
| 176 | */ |
| 177 | protected boolean exit_process(LttngTraceState ts, LttngProcessState process) { |
| 178 | /* |
| 179 | * Wait for both schedule with exit dead and process free to happen. |
| 180 | * They can happen in any order. |
| 181 | */ |
| 182 | process.incrementFree_events(); |
| 183 | if (process.getFree_events() < 2) { |
| 184 | return false; |
| 185 | } |
| 186 | |
| 187 | process.clearExecutionStack(); |
| 188 | process.clearUserStack(); |
| 189 | ts.removeProcessState(process); |
| 190 | |
| 191 | return true; |
| 192 | } |
| 193 | |
| 194 | /** |
| 195 | * @param traceSt |
| 196 | * @param cpu |
| 197 | * @param pid |
| 198 | * @param tgid |
| 199 | * @param timestamp |
| 200 | * @return |
| 201 | */ |
| 202 | protected LttngProcessState create_process(LttngTraceState traceSt, |
| 203 | Long cpu, Long pid, Long tgid, final TmfTimestamp timestamp) { |
| 204 | LttngProcessState process = create_process(traceSt, cpu, pid, tgid, |
| 205 | ProcessStatus.LTTV_STATE_UNNAMED.getInName(), timestamp); |
| 206 | return process; |
| 207 | } |
| 208 | |
| 209 | /** |
| 210 | * @param traceSt |
| 211 | * @param cpu |
| 212 | * @param pid |
| 213 | * @param tgid |
| 214 | * @param name |
| 215 | * @param timestamp |
| 216 | * @return |
| 217 | */ |
| 218 | protected LttngProcessState create_process(LttngTraceState traceSt, |
| 219 | Long cpu, Long pid, Long tgid, String name, |
| 220 | final TmfTimestamp timestamp) { |
| 221 | LttngProcessState process; |
| 222 | process = new LttngProcessState(cpu, pid, tgid, name, timestamp.getValue(), traceSt.getTraceId()); |
| 223 | traceSt.addProcessState(process); |
| 224 | return process; |
| 225 | } |
| 226 | |
| 227 | /** |
| 228 | * @param ts |
| 229 | * @param cpu |
| 230 | * @param pid |
| 231 | * @param timestamp |
| 232 | * , Used when a new process is needed |
| 233 | * @return |
| 234 | */ |
| 235 | protected LttngProcessState lttv_state_find_process_or_create( |
| 236 | LttngTraceState ts, Long cpu, Long pid, final TmfTimestamp timestamp) { |
| 237 | |
| 238 | LttngProcessState process = lttv_state_find_process(ts, cpu, pid); |
| 239 | /* Put ltt_time_zero creation time for non existing processes */ |
| 240 | if (process == null) { |
| 241 | process = create_process(ts, cpu, pid, 0L, timestamp); |
| 242 | // leave only one entry in the execution stack |
| 243 | process.popFromExecutionStack(); |
| 244 | LttngExecutionState es = process.getState(); |
| 245 | es.setExec_mode(ExecutionMode.LTTV_STATE_MODE_UNKNOWN); |
| 246 | es.setProc_status(ProcessStatus.LTTV_STATE_UNNAMED); |
| 247 | } |
| 248 | |
| 249 | return process; |
| 250 | } |
| 251 | |
| 252 | } |