|
Lines 14-26
Link Here
|
| 14 |
|
14 |
|
| 15 |
import java.util.HashMap; |
15 |
import java.util.HashMap; |
| 16 |
import java.util.Hashtable; |
16 |
import java.util.Hashtable; |
|
|
17 |
import java.util.LinkedList; |
| 17 |
import java.util.Map; |
18 |
import java.util.Map; |
| 18 |
import java.util.Vector; |
|
|
| 19 |
|
19 |
|
| 20 |
import org.eclipse.cdt.core.IAddress; |
20 |
import org.eclipse.cdt.core.IAddress; |
| 21 |
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; |
21 |
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; |
| 22 |
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; |
22 |
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; |
|
|
23 |
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; |
| 23 |
import org.eclipse.cdt.dsf.concurrent.Immutable; |
24 |
import org.eclipse.cdt.dsf.concurrent.Immutable; |
|
|
25 |
import org.eclipse.cdt.dsf.concurrent.MultiRequestMonitor; |
| 24 |
import org.eclipse.cdt.dsf.concurrent.RequestMonitor; |
26 |
import org.eclipse.cdt.dsf.concurrent.RequestMonitor; |
| 25 |
import org.eclipse.cdt.dsf.concurrent.Sequence; |
27 |
import org.eclipse.cdt.dsf.concurrent.Sequence; |
| 26 |
import org.eclipse.cdt.dsf.concurrent.Sequence.Step; |
28 |
import org.eclipse.cdt.dsf.concurrent.Sequence.Step; |
|
Lines 898-922
Link Here
|
| 898 |
threadState.fStateChangeDetails = event.getDetails(); |
900 |
threadState.fStateChangeDetails = event.getDetails(); |
| 899 |
} |
901 |
} |
| 900 |
|
902 |
|
| 901 |
|
|
|
| 902 |
/** |
| 903 |
* @since 3.0 |
| 904 |
*/ |
| 905 |
public void executeWithTargetAvailable(IDMContext ctx, Sequence.Step[] steps, RequestMonitor rm) { |
| 906 |
Vector<Step> totalStepsVector = new Vector<Step>(); |
| 907 |
totalStepsVector.add(new IsTargetAvailableStep(ctx)); |
| 908 |
totalStepsVector.add(new MakeTargetAvailableStep()); |
| 909 |
for (Step step : steps) { |
| 910 |
totalStepsVector.add(step); |
| 911 |
} |
| 912 |
totalStepsVector.add(new RestoreTargetStateStep()); |
| 913 |
|
| 914 |
final Step[] totalSteps = totalStepsVector.toArray(new Step[totalStepsVector.size()]); |
| 915 |
getExecutor().execute(new Sequence(getExecutor(), rm) { |
| 916 |
@Override public Step[] getSteps() { return totalSteps; } |
| 917 |
}); |
| 918 |
} |
| 919 |
|
| 920 |
/* ****************************************************************************** |
903 |
/* ****************************************************************************** |
| 921 |
* Section to support making operations even when the target is unavailable. |
904 |
* Section to support making operations even when the target is unavailable. |
| 922 |
* |
905 |
* |
|
Lines 925-945
Link Here
|
| 925 |
* like breakpoints. The safe way to do it is to make sure we have at least |
908 |
* like breakpoints. The safe way to do it is to make sure we have at least |
| 926 |
* one thread suspended. |
909 |
* one thread suspended. |
| 927 |
* |
910 |
* |
| 928 |
* Basically, we must make sure one container is suspended before making |
911 |
* Basically, we must make sure one thread is suspended before making |
| 929 |
* certain operations (currently breakpoints). If that is not the case, we must |
912 |
* certain operations (currently breakpoints). If that is not the case, we must |
| 930 |
* first suspend one thread, then perform the specified operations, |
913 |
* first suspend one thread, then perform the specified operations, |
| 931 |
* and finally resume that thread.. |
914 |
* and finally resume that thread.. |
| 932 |
* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=242943 |
915 |
* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=242943 |
| 933 |
* and https://bugs.eclipse.org/bugs/show_bug.cgi?id=282273 |
916 |
* and https://bugs.eclipse.org/bugs/show_bug.cgi?id=282273 |
| 934 |
* |
|
|
| 935 |
* ******************************************************************************/ |
917 |
* ******************************************************************************/ |
| 936 |
private IContainerDMContext fContainerDmcToSuspend = null; |
918 |
|
| 937 |
private IMIExecutionDMContext fExecutionDmcToSuspend = null; |
919 |
/** |
| 938 |
private boolean fTargetAvailable = false; |
920 |
* Utility class to store the parameters of the executeWithTargetAvailable() operations. |
|
|
921 |
* @since 4.0 |
| 922 |
*/ |
| 923 |
protected static class TargetAvailableOperationInfo { |
| 924 |
public IDMContext ctx; |
| 925 |
public Sequence.Step[] steps; |
| 926 |
public RequestMonitor rm; |
| 927 |
|
| 928 |
public TargetAvailableOperationInfo(IDMContext ctx, Step[] steps, RequestMonitor rm) { |
| 929 |
super(); |
| 930 |
this.ctx = ctx; |
| 931 |
this.steps = steps; |
| 932 |
this.rm = rm; |
| 933 |
} |
| 934 |
}; |
| 935 |
|
| 936 |
// Keep track of if the target was available or not when we started the operation |
| 937 |
private boolean fTargetAvailable; |
| 938 |
// The container that needs to be suspended to perform the steps of the operation |
| 939 |
private IContainerDMContext fContainerDmcToSuspend; |
| 940 |
// The thread that we will actually suspend to make the container suspended. |
| 941 |
private IMIExecutionDMContext fExecutionDmcToSuspend; |
| 942 |
|
| 943 |
// Do we currently have an executeWithTargetAvailable() operation ongoing? |
| 944 |
private boolean fOngoingOperation; |
| 945 |
// Are we currently executing steps passed into executeWithTargetAvailable()? |
| 946 |
// This allows us to know if we can add more steps to execute or if we missed |
| 947 |
// our opportunity |
| 948 |
private boolean fCurrentlyExecutingSteps; |
| 949 |
|
| 950 |
// MultiRequestMonitor that allows us to track all the different steps we are |
| 951 |
// executing. Once all steps are executed, we can complete this MultiRM and |
| 952 |
// allow the global sequence to continue. |
| 953 |
// Note that we couldn't use a CountingRequestMonitor because that type of RM |
| 954 |
// needs to know in advance how many subRms it will track; the MultiRM allows us |
| 955 |
// to receive more steps to execute continuously, and be able to upate the MultiRM. |
| 956 |
private MultiRequestMonitor<RequestMonitor> fExecuteQueuedOpsStepMonitor; |
| 957 |
// The number of batches of steps that are still being executing for potentially |
| 958 |
// concurrent executeWithTargetAvailable() operations. |
| 959 |
// Once this gets to zero, we know we have executed all the steps we were aware of |
| 960 |
// and we can complete the operation. |
| 961 |
private int fNumStepsStillExecuting; |
| 962 |
// Queue of executeWithTargetAvailable() operations that need to be processed. |
| 963 |
private LinkedList<TargetAvailableOperationInfo> fOperationsPending = new LinkedList<TargetAvailableOperationInfo>(); |
| 964 |
|
| 965 |
/** |
| 966 |
* Returns whether the target is available to perform operations |
| 967 |
* @since 4.0 |
| 968 |
*/ |
| 969 |
protected boolean isTargetAvailable() { |
| 970 |
return fTargetAvailable; |
| 971 |
} |
| 972 |
|
| 973 |
/** @since 4.0 */ |
| 974 |
protected void setTargetAvailable(boolean available) { |
| 975 |
fTargetAvailable = available; |
| 976 |
} |
| 977 |
|
| 978 |
/** |
| 979 |
* Returns the container context that needs to be suspended to perform the |
| 980 |
* required operation. |
| 981 |
* @since 4.0 |
| 982 |
*/ |
| 983 |
protected IContainerDMContext getContainerToSuspend() { |
| 984 |
return fContainerDmcToSuspend; |
| 985 |
} |
| 986 |
|
| 987 |
/** @since 4.0 */ |
| 988 |
protected void setContainerToSuspend(IContainerDMContext context) { |
| 989 |
fContainerDmcToSuspend = context; |
| 990 |
} |
| 991 |
|
| 992 |
/** |
| 993 |
* Returns the container context that needs to be suspended to perform the |
| 994 |
* required operation. |
| 995 |
* @since 4.0 |
| 996 |
*/ |
| 997 |
protected IMIExecutionDMContext getExecutionToSuspend() { |
| 998 |
return fExecutionDmcToSuspend; |
| 999 |
} |
| 1000 |
|
| 1001 |
/** @since 4.0 */ |
| 1002 |
protected void setExecutionToSuspend(IMIExecutionDMContext context) { |
| 1003 |
fExecutionDmcToSuspend = context; |
| 1004 |
} |
| 1005 |
|
| 1006 |
/** |
| 1007 |
* Returns whether there is currently an ExecuteWithTargetAvailable() operation ongoing. |
| 1008 |
* @since 4.0 |
| 1009 |
*/ |
| 1010 |
protected boolean isTargetAvailableOperationOngoing() { |
| 1011 |
return fOngoingOperation; |
| 1012 |
} |
| 1013 |
|
| 1014 |
/** @since 4.0 */ |
| 1015 |
protected void setTargetAvailableOperationOngoing(boolean ongoing) { |
| 1016 |
fOngoingOperation = ongoing; |
| 1017 |
} |
| 1018 |
|
| 1019 |
/** |
| 1020 |
* Returns whether we are current in the process of executing the steps |
| 1021 |
* that were passed to ExecuteWithTargetAvailable(). |
| 1022 |
* When this value is true, we can send more steps to be executed. |
| 1023 |
* @since 4.0 |
| 1024 |
*/ |
| 1025 |
protected boolean isCurrentlyExecutingSteps() { |
| 1026 |
return fCurrentlyExecutingSteps; |
| 1027 |
} |
| 1028 |
|
| 1029 |
/** @since 4.0 */ |
| 1030 |
protected void setCurrentlyExecutingSteps(boolean executing) { |
| 1031 |
fCurrentlyExecutingSteps = executing; |
| 1032 |
} |
| 1033 |
|
| 1034 |
/** |
| 1035 |
* Returns the requestMonitor that will be run once all steps sent to |
| 1036 |
* ExecuteWithTargetAvailable() have been executed. |
| 1037 |
* @since 4.0 |
| 1038 |
*/ |
| 1039 |
protected MultiRequestMonitor<RequestMonitor> getExecuteQueuedStepsRM() { |
| 1040 |
return fExecuteQueuedOpsStepMonitor; |
| 1041 |
} |
| 1042 |
|
| 1043 |
/** @since 4.0 */ |
| 1044 |
protected void setExecuteQueuedStepsRM(MultiRequestMonitor<RequestMonitor> rm) { |
| 1045 |
fExecuteQueuedOpsStepMonitor = rm; |
| 1046 |
} |
| 1047 |
|
| 1048 |
|
| 1049 |
/** |
| 1050 |
* Returns the number of batches of steps sent to ExecuteWithTargetAvailable() |
| 1051 |
* that are still executing. Once this number reaches zero, we can complete |
| 1052 |
* the overall ExecuteWithTargetAvailable() operation. |
| 1053 |
* @since 4.0 |
| 1054 |
*/ |
| 1055 |
protected int getNumStepsStillExecuting() { |
| 1056 |
return fNumStepsStillExecuting; |
| 1057 |
} |
| 1058 |
|
| 1059 |
/** @since 4.0 */ |
| 1060 |
protected void setNumStepsStillExecuting(int num) { |
| 1061 |
fNumStepsStillExecuting = num; |
| 1062 |
} |
| 1063 |
|
| 1064 |
/** |
| 1065 |
* Returns the queue of executeWithTargetAvailable() operations that still need to be processed |
| 1066 |
* @since 4.0 |
| 1067 |
*/ |
| 1068 |
protected LinkedList<TargetAvailableOperationInfo> getOperationsPending() { |
| 1069 |
return fOperationsPending; |
| 1070 |
} |
| 1071 |
|
| 1072 |
/** |
| 1073 |
* This method takes care of executing a batch of steps that were passed to |
| 1074 |
* ExecuteWithTargetAvailable(). The method is used to track the progress |
| 1075 |
* of all these batches of steps, so that we know exactly when all of them |
| 1076 |
* have been completed and the global sequence can be completed. |
| 1077 |
* @since 4.0 |
| 1078 |
*/ |
| 1079 |
protected void executeSteps(final TargetAvailableOperationInfo info) { |
| 1080 |
fNumStepsStillExecuting++; |
| 1081 |
|
| 1082 |
// This RM propagates any error to the original rm of the actual steps. |
| 1083 |
// Even in case of errors for these steps, we want to continue the overall sequence |
| 1084 |
RequestMonitor stepsRm = new RequestMonitor(ImmediateExecutor.getInstance(), null) { |
| 1085 |
@Override |
| 1086 |
protected void handleCompleted() { |
| 1087 |
info.rm.setStatus(getStatus()); |
| 1088 |
// It is important to call rm.done() right away. |
| 1089 |
// This is because some other operation we are performing might be waiting |
| 1090 |
// for this one to be done. If we try to wait for the entire sequence to be |
| 1091 |
// done, then we will never finish because one monitor will never show as |
| 1092 |
// done, waiting for the second one. |
| 1093 |
info.rm.done(); |
| 1094 |
|
| 1095 |
fExecuteQueuedOpsStepMonitor.requestMonitorDone(this); |
| 1096 |
fNumStepsStillExecuting--; |
| 1097 |
if (fNumStepsStillExecuting == 0) { |
| 1098 |
fExecuteQueuedOpsStepMonitor.doneAdding(); |
| 1099 |
} |
| 1100 |
} |
| 1101 |
}; |
| 1102 |
|
| 1103 |
fExecuteQueuedOpsStepMonitor.add(stepsRm); |
| 939 |
|
1104 |
|
|
|
1105 |
getExecutor().execute(new Sequence(getExecutor(), stepsRm) { |
| 1106 |
@Override public Step[] getSteps() { return info.steps; } |
| 1107 |
}); |
| 1108 |
} |
| 1109 |
|
| 940 |
/** |
1110 |
/** |
| 941 |
* @since 3.0 |
1111 |
* @since 3.0 |
| 942 |
*/ |
1112 |
*/ |
|
|
1113 |
public void executeWithTargetAvailable(IDMContext ctx, final Sequence.Step[] steps, final RequestMonitor rm) { |
| 1114 |
if (!fOngoingOperation) { |
| 1115 |
// We are the first operation of this kind currently requested |
| 1116 |
// so we need to start the sequence |
| 1117 |
fOngoingOperation = true; |
| 1118 |
|
| 1119 |
// We always go through our queue, even if we only have a single call to this method |
| 1120 |
fOperationsPending.add(new TargetAvailableOperationInfo(ctx, steps, rm)); |
| 1121 |
|
| 1122 |
// Steps that need to be executed to perform the operation |
| 1123 |
final Step[] sequenceSteps = new Step[] { |
| 1124 |
new IsTargetAvailableStep(ctx), |
| 1125 |
new MakeTargetAvailableStep(), |
| 1126 |
new ExecuteQueuedOperationsStep(), |
| 1127 |
new RestoreTargetStateStep(), |
| 1128 |
}; |
| 1129 |
|
| 1130 |
// Once all the sequence is completed, we need to see if we have received |
| 1131 |
// another request that we now need to process |
| 1132 |
RequestMonitor sequenceCompletedRm = new RequestMonitor(getExecutor(), null) { |
| 1133 |
@Override |
| 1134 |
protected void handleCompleted() { |
| 1135 |
fOngoingOperation = false; |
| 1136 |
|
| 1137 |
if (fOperationsPending.size() > 0) { |
| 1138 |
// Darn, more operations came in. Trigger their processing |
| 1139 |
// by calling executeWithTargetAvailable() on the last one |
| 1140 |
TargetAvailableOperationInfo info = fOperationsPending.removeLast(); |
| 1141 |
executeWithTargetAvailable(info.ctx, info.steps, info.rm); |
| 1142 |
} |
| 1143 |
// no other rm.done() needs to be called, they have all been handled already |
| 1144 |
} |
| 1145 |
}; |
| 1146 |
|
| 1147 |
getExecutor().execute(new Sequence(getExecutor(), sequenceCompletedRm) { |
| 1148 |
@Override public Step[] getSteps() { return sequenceSteps; } |
| 1149 |
}); |
| 1150 |
} else { |
| 1151 |
// We are currently already executing such an operation |
| 1152 |
// If we are still in the process of executing steps, let's include this new set of steps. |
| 1153 |
// This is important because some steps may depend on these new ones. |
| 1154 |
if (fCurrentlyExecutingSteps) { |
| 1155 |
executeSteps(new TargetAvailableOperationInfo(ctx, steps, rm)); |
| 1156 |
} else { |
| 1157 |
// Too late to execute the new steps, so queue them for later |
| 1158 |
fOperationsPending.add(new TargetAvailableOperationInfo(ctx, steps, rm)); |
| 1159 |
} |
| 1160 |
} |
| 1161 |
} |
| 1162 |
|
| 1163 |
|
| 1164 |
/** |
| 1165 |
* This part of the sequence verifies if the execution context of interest |
| 1166 |
* is suspended or not. |
| 1167 |
* @since 3.0 |
| 1168 |
*/ |
| 943 |
protected class IsTargetAvailableStep extends Sequence.Step { |
1169 |
protected class IsTargetAvailableStep extends Sequence.Step { |
| 944 |
final IDMContext fCtx; |
1170 |
final IDMContext fCtx; |
| 945 |
|
1171 |
|
|
Lines 949-965
Link Here
|
| 949 |
|
1175 |
|
| 950 |
@Override |
1176 |
@Override |
| 951 |
public void execute(final RequestMonitor rm) { |
1177 |
public void execute(final RequestMonitor rm) { |
| 952 |
fContainerDmcToSuspend = DMContexts.getAncestorOfType(fCtx, IContainerDMContext.class); |
1178 |
fContainerDmcToSuspend = DMContexts.getAncestorOfType(fCtx, IMIContainerDMContext.class); |
| 953 |
if (fContainerDmcToSuspend != null) { |
1179 |
if (fContainerDmcToSuspend != null) { |
| 954 |
// In non-stop, we don't actually need this particular process to be suspended, |
1180 |
String groupId = ((IMIContainerDMContext)fContainerDmcToSuspend).getGroupId(); |
| 955 |
// all we need is one of any of the processes to be suspended. |
1181 |
if (groupId != null && groupId.length() > 0) { |
| 956 |
// However, for efficiency, we can first check if the process in question |
1182 |
// If we have a fully formed containerDmc, we can use it directly. |
| 957 |
// is suspended. |
1183 |
fTargetAvailable = isSuspended(fContainerDmcToSuspend); |
| 958 |
if (isSuspended(fContainerDmcToSuspend)) { |
|
|
| 959 |
fTargetAvailable = true; |
| 960 |
rm.done(); |
1184 |
rm.done(); |
| 961 |
return; |
1185 |
return; |
| 962 |
} |
1186 |
} |
|
|
1187 |
// else, the container is not fully formed, so let's fetch it below, since |
| 1188 |
// we know we are running single-process and there is only one process |
| 963 |
} |
1189 |
} |
| 964 |
|
1190 |
|
| 965 |
// If we get here, we have to get the list of processes to know if any of |
1191 |
// If we get here, we have to get the list of processes to know if any of |
|
Lines 974-980
Link Here
|
| 974 |
assert getData() != null; |
1200 |
assert getData() != null; |
| 975 |
|
1201 |
|
| 976 |
if (getData().length == 0) { |
1202 |
if (getData().length == 0) { |
| 977 |
// Happens at startup, starting with GDB 7.0 |
1203 |
// Happens at startup, starting with GDB 7.0. |
| 978 |
// This means the target is available |
1204 |
// This means the target is available |
| 979 |
fTargetAvailable = true; |
1205 |
fTargetAvailable = true; |
| 980 |
} else { |
1206 |
} else { |
|
Lines 995-1006
Link Here
|
| 995 |
}; |
1221 |
}; |
| 996 |
|
1222 |
|
| 997 |
/** |
1223 |
/** |
|
|
1224 |
* If the execution context of interest is not suspended, this step |
| 1225 |
* will interrupt it. |
| 998 |
* @since 3.0 |
1226 |
* @since 3.0 |
| 999 |
*/ |
1227 |
*/ |
| 1000 |
protected class MakeTargetAvailableStep extends Sequence.Step { |
1228 |
protected class MakeTargetAvailableStep extends Sequence.Step { |
| 1001 |
@Override |
1229 |
@Override |
| 1002 |
public void execute(final RequestMonitor rm) { |
1230 |
public void execute(final RequestMonitor rm) { |
| 1003 |
if (!fTargetAvailable) { |
1231 |
if (!isTargetAvailable()) { |
| 1004 |
// Instead of suspending the entire process, let's find its first thread and use that |
1232 |
// Instead of suspending the entire process, let's find its first thread and use that |
| 1005 |
IProcesses processControl = getServicesTracker().getService(IProcesses.class); |
1233 |
IProcesses processControl = getServicesTracker().getService(IProcesses.class); |
| 1006 |
processControl.getProcessesBeingDebugged( |
1234 |
processControl.getProcessesBeingDebugged( |
|
Lines 1028-1034
Link Here
|
| 1028 |
super.handleFailure(); |
1256 |
super.handleFailure(); |
| 1029 |
}; |
1257 |
}; |
| 1030 |
}); |
1258 |
}); |
| 1031 |
|
|
|
| 1032 |
} |
1259 |
} |
| 1033 |
}); |
1260 |
}); |
| 1034 |
} else { |
1261 |
} else { |
|
Lines 1043-1054
Link Here
|
| 1043 |
}; |
1270 |
}; |
| 1044 |
|
1271 |
|
| 1045 |
/** |
1272 |
/** |
|
|
1273 |
* This step of the sequence takes care of executing all the steps that |
| 1274 |
* were passed to ExecuteWithTargetAvailable(). |
| 1275 |
* @since 4.0 |
| 1276 |
*/ |
| 1277 |
protected class ExecuteQueuedOperationsStep extends Sequence.Step { |
| 1278 |
@Override |
| 1279 |
public void execute(final RequestMonitor rm) { |
| 1280 |
fCurrentlyExecutingSteps = true; |
| 1281 |
|
| 1282 |
// It is important to use an ImmediateExecutor for this RM, to make sure we don't risk getting a new |
| 1283 |
// call to ExecuteWithTargetAvailable() when we just finished executing the steps. |
| 1284 |
fExecuteQueuedOpsStepMonitor = new MultiRequestMonitor<RequestMonitor>(ImmediateExecutor.getInstance(), rm) { |
| 1285 |
@Override |
| 1286 |
protected void handleCompleted() { |
| 1287 |
assert fOperationsPending.size() == 0; |
| 1288 |
|
| 1289 |
// We don't handle errors here. Instead, we have already propagated any |
| 1290 |
// errors to each rm for each set of steps |
| 1291 |
|
| 1292 |
fCurrentlyExecutingSteps = false; |
| 1293 |
// Continue the sequence |
| 1294 |
rm.done(); |
| 1295 |
} |
| 1296 |
}; |
| 1297 |
// Tell the RM that we need to confirm when we are done adding sub-rms |
| 1298 |
fExecuteQueuedOpsStepMonitor.requireDoneAdding(); |
| 1299 |
|
| 1300 |
// All pending operations are independent of each other so we can |
| 1301 |
// run them concurrently. |
| 1302 |
while (fOperationsPending.size() > 0) { |
| 1303 |
executeSteps(fOperationsPending.poll()); |
| 1304 |
} |
| 1305 |
} |
| 1306 |
}; |
| 1307 |
|
| 1308 |
/** |
| 1309 |
* If the sequence had to interrupt the execution context of interest, |
| 1310 |
* this step will resume it again to reach the same state as when we started. |
| 1046 |
* @since 3.0 |
1311 |
* @since 3.0 |
| 1047 |
*/ |
1312 |
*/ |
| 1048 |
protected class RestoreTargetStateStep extends Sequence.Step { |
1313 |
protected class RestoreTargetStateStep extends Sequence.Step { |
| 1049 |
@Override |
1314 |
@Override |
| 1050 |
public void execute(final RequestMonitor rm) { |
1315 |
public void execute(final RequestMonitor rm) { |
| 1051 |
if (!fTargetAvailable) { |
1316 |
if (!isTargetAvailable()) { |
| 1052 |
assert fDisableNextRunningEventDmc == null; |
1317 |
assert fDisableNextRunningEventDmc == null; |
| 1053 |
fDisableNextRunningEventDmc = fExecutionDmcToSuspend; |
1318 |
fDisableNextRunningEventDmc = fExecutionDmcToSuspend; |
| 1054 |
|
1319 |
|
|
Lines 1089-1094
Link Here
|
| 1089 |
} |
1354 |
} |
| 1090 |
}; |
1355 |
}; |
| 1091 |
|
1356 |
|
|
|
1357 |
/* ****************************************************************************** |
| 1358 |
* End of section to support operations even when the target is unavailable. |
| 1359 |
* ******************************************************************************/ |
| 1360 |
|
| 1092 |
/////////////////////////////////////////////////////////////////////////// |
1361 |
/////////////////////////////////////////////////////////////////////////// |
| 1093 |
// Event handlers |
1362 |
// Event handlers |
| 1094 |
/////////////////////////////////////////////////////////////////////////// |
1363 |
/////////////////////////////////////////////////////////////////////////// |