mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-04 14:55:41 +02:00
Bug 337893 - Support concurrent setting of bp on a running target for non-stop mode, single process
This commit is contained in:
parent
a9a26fba14
commit
7edc697389
1 changed files with 305 additions and 36 deletions
|
@ -14,13 +14,15 @@ package org.eclipse.cdt.dsf.gdb.service;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
import org.eclipse.cdt.core.IAddress;
|
import org.eclipse.cdt.core.IAddress;
|
||||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
|
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.Immutable;
|
import org.eclipse.cdt.dsf.concurrent.Immutable;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.MultiRequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.Sequence;
|
import org.eclipse.cdt.dsf.concurrent.Sequence;
|
||||||
import org.eclipse.cdt.dsf.concurrent.Sequence.Step;
|
import org.eclipse.cdt.dsf.concurrent.Sequence.Step;
|
||||||
|
@ -898,25 +900,6 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
threadState.fStateChangeDetails = event.getDetails();
|
threadState.fStateChangeDetails = event.getDetails();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @since 3.0
|
|
||||||
*/
|
|
||||||
public void executeWithTargetAvailable(IDMContext ctx, Sequence.Step[] steps, RequestMonitor rm) {
|
|
||||||
Vector<Step> totalStepsVector = new Vector<Step>();
|
|
||||||
totalStepsVector.add(new IsTargetAvailableStep(ctx));
|
|
||||||
totalStepsVector.add(new MakeTargetAvailableStep());
|
|
||||||
for (Step step : steps) {
|
|
||||||
totalStepsVector.add(step);
|
|
||||||
}
|
|
||||||
totalStepsVector.add(new RestoreTargetStateStep());
|
|
||||||
|
|
||||||
final Step[] totalSteps = totalStepsVector.toArray(new Step[totalStepsVector.size()]);
|
|
||||||
getExecutor().execute(new Sequence(getExecutor(), rm) {
|
|
||||||
@Override public Step[] getSteps() { return totalSteps; }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ******************************************************************************
|
/* ******************************************************************************
|
||||||
* Section to support making operations even when the target is unavailable.
|
* Section to support making operations even when the target is unavailable.
|
||||||
*
|
*
|
||||||
|
@ -925,19 +908,262 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
* like breakpoints. The safe way to do it is to make sure we have at least
|
* like breakpoints. The safe way to do it is to make sure we have at least
|
||||||
* one thread suspended.
|
* one thread suspended.
|
||||||
*
|
*
|
||||||
* Basically, we must make sure one container is suspended before making
|
* Basically, we must make sure one thread is suspended before making
|
||||||
* certain operations (currently breakpoints). If that is not the case, we must
|
* certain operations (currently breakpoints). If that is not the case, we must
|
||||||
* first suspend one thread, then perform the specified operations,
|
* first suspend one thread, then perform the specified operations,
|
||||||
* and finally resume that thread..
|
* and finally resume that thread..
|
||||||
* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=242943
|
* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=242943
|
||||||
* and https://bugs.eclipse.org/bugs/show_bug.cgi?id=282273
|
* and https://bugs.eclipse.org/bugs/show_bug.cgi?id=282273
|
||||||
*
|
|
||||||
* ******************************************************************************/
|
* ******************************************************************************/
|
||||||
private IContainerDMContext fContainerDmcToSuspend = null;
|
|
||||||
private IMIExecutionDMContext fExecutionDmcToSuspend = null;
|
|
||||||
private boolean fTargetAvailable = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Utility class to store the parameters of the executeWithTargetAvailable() operations.
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
protected static class TargetAvailableOperationInfo {
|
||||||
|
public IDMContext ctx;
|
||||||
|
public Sequence.Step[] steps;
|
||||||
|
public RequestMonitor rm;
|
||||||
|
|
||||||
|
public TargetAvailableOperationInfo(IDMContext ctx, Step[] steps, RequestMonitor rm) {
|
||||||
|
super();
|
||||||
|
this.ctx = ctx;
|
||||||
|
this.steps = steps;
|
||||||
|
this.rm = rm;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Keep track of if the target was available or not when we started the operation
|
||||||
|
private boolean fTargetAvailable;
|
||||||
|
// The container that needs to be suspended to perform the steps of the operation
|
||||||
|
private IContainerDMContext fContainerDmcToSuspend;
|
||||||
|
// The thread that we will actually suspend to make the container suspended.
|
||||||
|
private IMIExecutionDMContext fExecutionDmcToSuspend;
|
||||||
|
|
||||||
|
// Do we currently have an executeWithTargetAvailable() operation ongoing?
|
||||||
|
private boolean fOngoingOperation;
|
||||||
|
// Are we currently executing steps passed into executeWithTargetAvailable()?
|
||||||
|
// This allows us to know if we can add more steps to execute or if we missed
|
||||||
|
// our opportunity
|
||||||
|
private boolean fCurrentlyExecutingSteps;
|
||||||
|
|
||||||
|
// MultiRequestMonitor that allows us to track all the different steps we are
|
||||||
|
// executing. Once all steps are executed, we can complete this MultiRM and
|
||||||
|
// allow the global sequence to continue.
|
||||||
|
// Note that we couldn't use a CountingRequestMonitor because that type of RM
|
||||||
|
// needs to know in advance how many subRms it will track; the MultiRM allows us
|
||||||
|
// to receive more steps to execute continuously, and be able to upate the MultiRM.
|
||||||
|
private MultiRequestMonitor<RequestMonitor> fExecuteQueuedOpsStepMonitor;
|
||||||
|
// The number of batches of steps that are still being executing for potentially
|
||||||
|
// concurrent executeWithTargetAvailable() operations.
|
||||||
|
// Once this gets to zero, we know we have executed all the steps we were aware of
|
||||||
|
// and we can complete the operation.
|
||||||
|
private int fNumStepsStillExecuting;
|
||||||
|
// Queue of executeWithTargetAvailable() operations that need to be processed.
|
||||||
|
private LinkedList<TargetAvailableOperationInfo> fOperationsPending = new LinkedList<TargetAvailableOperationInfo>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the target is available to perform operations
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
protected boolean isTargetAvailable() {
|
||||||
|
return fTargetAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 4.0 */
|
||||||
|
protected void setTargetAvailable(boolean available) {
|
||||||
|
fTargetAvailable = available;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the container context that needs to be suspended to perform the
|
||||||
|
* required operation.
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
protected IContainerDMContext getContainerToSuspend() {
|
||||||
|
return fContainerDmcToSuspend;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 4.0 */
|
||||||
|
protected void setContainerToSuspend(IContainerDMContext context) {
|
||||||
|
fContainerDmcToSuspend = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the container context that needs to be suspended to perform the
|
||||||
|
* required operation.
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
protected IMIExecutionDMContext getExecutionToSuspend() {
|
||||||
|
return fExecutionDmcToSuspend;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 4.0 */
|
||||||
|
protected void setExecutionToSuspend(IMIExecutionDMContext context) {
|
||||||
|
fExecutionDmcToSuspend = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether there is currently an ExecuteWithTargetAvailable() operation ongoing.
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
protected boolean isTargetAvailableOperationOngoing() {
|
||||||
|
return fOngoingOperation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 4.0 */
|
||||||
|
protected void setTargetAvailableOperationOngoing(boolean ongoing) {
|
||||||
|
fOngoingOperation = ongoing;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether we are current in the process of executing the steps
|
||||||
|
* that were passed to ExecuteWithTargetAvailable().
|
||||||
|
* When this value is true, we can send more steps to be executed.
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
protected boolean isCurrentlyExecutingSteps() {
|
||||||
|
return fCurrentlyExecutingSteps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 4.0 */
|
||||||
|
protected void setCurrentlyExecutingSteps(boolean executing) {
|
||||||
|
fCurrentlyExecutingSteps = executing;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the requestMonitor that will be run once all steps sent to
|
||||||
|
* ExecuteWithTargetAvailable() have been executed.
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
protected MultiRequestMonitor<RequestMonitor> getExecuteQueuedStepsRM() {
|
||||||
|
return fExecuteQueuedOpsStepMonitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 4.0 */
|
||||||
|
protected void setExecuteQueuedStepsRM(MultiRequestMonitor<RequestMonitor> rm) {
|
||||||
|
fExecuteQueuedOpsStepMonitor = rm;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of batches of steps sent to ExecuteWithTargetAvailable()
|
||||||
|
* that are still executing. Once this number reaches zero, we can complete
|
||||||
|
* the overall ExecuteWithTargetAvailable() operation.
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
protected int getNumStepsStillExecuting() {
|
||||||
|
return fNumStepsStillExecuting;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 4.0 */
|
||||||
|
protected void setNumStepsStillExecuting(int num) {
|
||||||
|
fNumStepsStillExecuting = num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the queue of executeWithTargetAvailable() operations that still need to be processed
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
protected LinkedList<TargetAvailableOperationInfo> getOperationsPending() {
|
||||||
|
return fOperationsPending;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method takes care of executing a batch of steps that were passed to
|
||||||
|
* ExecuteWithTargetAvailable(). The method is used to track the progress
|
||||||
|
* of all these batches of steps, so that we know exactly when all of them
|
||||||
|
* have been completed and the global sequence can be completed.
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
protected void executeSteps(final TargetAvailableOperationInfo info) {
|
||||||
|
fNumStepsStillExecuting++;
|
||||||
|
|
||||||
|
// This RM propagates any error to the original rm of the actual steps.
|
||||||
|
// Even in case of errors for these steps, we want to continue the overall sequence
|
||||||
|
RequestMonitor stepsRm = new RequestMonitor(ImmediateExecutor.getInstance(), null) {
|
||||||
|
@Override
|
||||||
|
protected void handleCompleted() {
|
||||||
|
info.rm.setStatus(getStatus());
|
||||||
|
// It is important to call rm.done() right away.
|
||||||
|
// This is because some other operation we are performing might be waiting
|
||||||
|
// for this one to be done. If we try to wait for the entire sequence to be
|
||||||
|
// done, then we will never finish because one monitor will never show as
|
||||||
|
// done, waiting for the second one.
|
||||||
|
info.rm.done();
|
||||||
|
|
||||||
|
fExecuteQueuedOpsStepMonitor.requestMonitorDone(this);
|
||||||
|
fNumStepsStillExecuting--;
|
||||||
|
if (fNumStepsStillExecuting == 0) {
|
||||||
|
fExecuteQueuedOpsStepMonitor.doneAdding();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fExecuteQueuedOpsStepMonitor.add(stepsRm);
|
||||||
|
|
||||||
|
getExecutor().execute(new Sequence(getExecutor(), stepsRm) {
|
||||||
|
@Override public Step[] getSteps() { return info.steps; }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
public void executeWithTargetAvailable(IDMContext ctx, final Sequence.Step[] steps, final RequestMonitor rm) {
|
||||||
|
if (!fOngoingOperation) {
|
||||||
|
// We are the first operation of this kind currently requested
|
||||||
|
// so we need to start the sequence
|
||||||
|
fOngoingOperation = true;
|
||||||
|
|
||||||
|
// We always go through our queue, even if we only have a single call to this method
|
||||||
|
fOperationsPending.add(new TargetAvailableOperationInfo(ctx, steps, rm));
|
||||||
|
|
||||||
|
// Steps that need to be executed to perform the operation
|
||||||
|
final Step[] sequenceSteps = new Step[] {
|
||||||
|
new IsTargetAvailableStep(ctx),
|
||||||
|
new MakeTargetAvailableStep(),
|
||||||
|
new ExecuteQueuedOperationsStep(),
|
||||||
|
new RestoreTargetStateStep(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Once all the sequence is completed, we need to see if we have received
|
||||||
|
// another request that we now need to process
|
||||||
|
RequestMonitor sequenceCompletedRm = new RequestMonitor(getExecutor(), null) {
|
||||||
|
@Override
|
||||||
|
protected void handleCompleted() {
|
||||||
|
fOngoingOperation = false;
|
||||||
|
|
||||||
|
if (fOperationsPending.size() > 0) {
|
||||||
|
// Darn, more operations came in. Trigger their processing
|
||||||
|
// by calling executeWithTargetAvailable() on the last one
|
||||||
|
TargetAvailableOperationInfo info = fOperationsPending.removeLast();
|
||||||
|
executeWithTargetAvailable(info.ctx, info.steps, info.rm);
|
||||||
|
}
|
||||||
|
// no other rm.done() needs to be called, they have all been handled already
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
getExecutor().execute(new Sequence(getExecutor(), sequenceCompletedRm) {
|
||||||
|
@Override public Step[] getSteps() { return sequenceSteps; }
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// We are currently already executing such an operation
|
||||||
|
// If we are still in the process of executing steps, let's include this new set of steps.
|
||||||
|
// This is important because some steps may depend on these new ones.
|
||||||
|
if (fCurrentlyExecutingSteps) {
|
||||||
|
executeSteps(new TargetAvailableOperationInfo(ctx, steps, rm));
|
||||||
|
} else {
|
||||||
|
// Too late to execute the new steps, so queue them for later
|
||||||
|
fOperationsPending.add(new TargetAvailableOperationInfo(ctx, steps, rm));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This part of the sequence verifies if the execution context of interest
|
||||||
|
* is suspended or not.
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
protected class IsTargetAvailableStep extends Sequence.Step {
|
protected class IsTargetAvailableStep extends Sequence.Step {
|
||||||
|
@ -949,17 +1175,17 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(final RequestMonitor rm) {
|
public void execute(final RequestMonitor rm) {
|
||||||
fContainerDmcToSuspend = DMContexts.getAncestorOfType(fCtx, IContainerDMContext.class);
|
fContainerDmcToSuspend = DMContexts.getAncestorOfType(fCtx, IMIContainerDMContext.class);
|
||||||
if (fContainerDmcToSuspend != null) {
|
if (fContainerDmcToSuspend != null) {
|
||||||
// In non-stop, we don't actually need this particular process to be suspended,
|
String groupId = ((IMIContainerDMContext)fContainerDmcToSuspend).getGroupId();
|
||||||
// all we need is one of any of the processes to be suspended.
|
if (groupId != null && groupId.length() > 0) {
|
||||||
// However, for efficiency, we can first check if the process in question
|
// If we have a fully formed containerDmc, we can use it directly.
|
||||||
// is suspended.
|
fTargetAvailable = isSuspended(fContainerDmcToSuspend);
|
||||||
if (isSuspended(fContainerDmcToSuspend)) {
|
|
||||||
fTargetAvailable = true;
|
|
||||||
rm.done();
|
rm.done();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// else, the container is not fully formed, so let's fetch it below, since
|
||||||
|
// we know we are running single-process and there is only one process
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we get here, we have to get the list of processes to know if any of
|
// If we get here, we have to get the list of processes to know if any of
|
||||||
|
@ -974,7 +1200,7 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
assert getData() != null;
|
assert getData() != null;
|
||||||
|
|
||||||
if (getData().length == 0) {
|
if (getData().length == 0) {
|
||||||
// Happens at startup, starting with GDB 7.0
|
// Happens at startup, starting with GDB 7.0.
|
||||||
// This means the target is available
|
// This means the target is available
|
||||||
fTargetAvailable = true;
|
fTargetAvailable = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -995,12 +1221,14 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* If the execution context of interest is not suspended, this step
|
||||||
|
* will interrupt it.
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
protected class MakeTargetAvailableStep extends Sequence.Step {
|
protected class MakeTargetAvailableStep extends Sequence.Step {
|
||||||
@Override
|
@Override
|
||||||
public void execute(final RequestMonitor rm) {
|
public void execute(final RequestMonitor rm) {
|
||||||
if (!fTargetAvailable) {
|
if (!isTargetAvailable()) {
|
||||||
// Instead of suspending the entire process, let's find its first thread and use that
|
// Instead of suspending the entire process, let's find its first thread and use that
|
||||||
IProcesses processControl = getServicesTracker().getService(IProcesses.class);
|
IProcesses processControl = getServicesTracker().getService(IProcesses.class);
|
||||||
processControl.getProcessesBeingDebugged(
|
processControl.getProcessesBeingDebugged(
|
||||||
|
@ -1028,7 +1256,6 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
super.handleFailure();
|
super.handleFailure();
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -1043,12 +1270,50 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This step of the sequence takes care of executing all the steps that
|
||||||
|
* were passed to ExecuteWithTargetAvailable().
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
protected class ExecuteQueuedOperationsStep extends Sequence.Step {
|
||||||
|
@Override
|
||||||
|
public void execute(final RequestMonitor rm) {
|
||||||
|
fCurrentlyExecutingSteps = true;
|
||||||
|
|
||||||
|
// It is important to use an ImmediateExecutor for this RM, to make sure we don't risk getting a new
|
||||||
|
// call to ExecuteWithTargetAvailable() when we just finished executing the steps.
|
||||||
|
fExecuteQueuedOpsStepMonitor = new MultiRequestMonitor<RequestMonitor>(ImmediateExecutor.getInstance(), rm) {
|
||||||
|
@Override
|
||||||
|
protected void handleCompleted() {
|
||||||
|
assert fOperationsPending.size() == 0;
|
||||||
|
|
||||||
|
// We don't handle errors here. Instead, we have already propagated any
|
||||||
|
// errors to each rm for each set of steps
|
||||||
|
|
||||||
|
fCurrentlyExecutingSteps = false;
|
||||||
|
// Continue the sequence
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Tell the RM that we need to confirm when we are done adding sub-rms
|
||||||
|
fExecuteQueuedOpsStepMonitor.requireDoneAdding();
|
||||||
|
|
||||||
|
// All pending operations are independent of each other so we can
|
||||||
|
// run them concurrently.
|
||||||
|
while (fOperationsPending.size() > 0) {
|
||||||
|
executeSteps(fOperationsPending.poll());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the sequence had to interrupt the execution context of interest,
|
||||||
|
* this step will resume it again to reach the same state as when we started.
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
protected class RestoreTargetStateStep extends Sequence.Step {
|
protected class RestoreTargetStateStep extends Sequence.Step {
|
||||||
@Override
|
@Override
|
||||||
public void execute(final RequestMonitor rm) {
|
public void execute(final RequestMonitor rm) {
|
||||||
if (!fTargetAvailable) {
|
if (!isTargetAvailable()) {
|
||||||
assert fDisableNextRunningEventDmc == null;
|
assert fDisableNextRunningEventDmc == null;
|
||||||
fDisableNextRunningEventDmc = fExecutionDmcToSuspend;
|
fDisableNextRunningEventDmc = fExecutionDmcToSuspend;
|
||||||
|
|
||||||
|
@ -1089,6 +1354,10 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* ******************************************************************************
|
||||||
|
* End of section to support operations even when the target is unavailable.
|
||||||
|
* ******************************************************************************/
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Event handlers
|
// Event handlers
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
Loading…
Add table
Reference in a new issue