1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Bug 240507 Fix the cache for the GDBMultiProcesses service. Also clean up the use of thread-info

This commit is contained in:
Marc Khouzam 2008-08-11 13:02:51 +00:00
parent 1fbfd51fac
commit eeb6b080ef
9 changed files with 342 additions and 236 deletions

View file

@ -25,18 +25,20 @@ import org.eclipse.dd.dsf.datamodel.DMContexts;
import org.eclipse.dd.dsf.datamodel.IDMContext; import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.debug.service.IProcesses; import org.eclipse.dd.dsf.debug.service.IProcesses;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext; import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerResumedDMEvent;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerSuspendedDMEvent;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExitedDMEvent; import org.eclipse.dd.dsf.debug.service.IRunControl.IExitedDMEvent;
import org.eclipse.dd.dsf.debug.service.IRunControl.IResumedDMEvent; import org.eclipse.dd.dsf.debug.service.IRunControl.IResumedDMEvent;
import org.eclipse.dd.dsf.debug.service.IRunControl.IStartedDMEvent; import org.eclipse.dd.dsf.debug.service.IRunControl.IStartedDMEvent;
import org.eclipse.dd.dsf.debug.service.IRunControl.ISuspendedDMEvent; import org.eclipse.dd.dsf.debug.service.IRunControl.ISuspendedDMEvent;
import org.eclipse.dd.dsf.debug.service.IRunControl.StateChangeReason;
import org.eclipse.dd.dsf.debug.service.command.CommandCache; import org.eclipse.dd.dsf.debug.service.command.CommandCache;
import org.eclipse.dd.dsf.service.AbstractDsfService; import org.eclipse.dd.dsf.service.AbstractDsfService;
import org.eclipse.dd.dsf.service.DsfServiceEventHandler; import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
import org.eclipse.dd.dsf.service.DsfSession; import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.gdb.internal.GdbPlugin; import org.eclipse.dd.gdb.internal.GdbPlugin;
import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl; import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl;
import org.eclipse.dd.mi.internal.MIPlugin;
import org.eclipse.dd.mi.service.IMIExecutionDMContext; import org.eclipse.dd.mi.service.IMIExecutionDMContext;
import org.eclipse.dd.mi.service.IMIExecutionGroupDMContext; import org.eclipse.dd.mi.service.IMIExecutionGroupDMContext;
import org.eclipse.dd.mi.service.IMIProcessDMContext; import org.eclipse.dd.mi.service.IMIProcessDMContext;
@ -45,12 +47,16 @@ import org.eclipse.dd.mi.service.command.MIControlDMContext;
import org.eclipse.dd.mi.service.command.commands.MIListThreadGroups; import org.eclipse.dd.mi.service.command.commands.MIListThreadGroups;
import org.eclipse.dd.mi.service.command.commands.MITargetAttach; import org.eclipse.dd.mi.service.command.commands.MITargetAttach;
import org.eclipse.dd.mi.service.command.commands.MITargetDetach; import org.eclipse.dd.mi.service.command.commands.MITargetDetach;
import org.eclipse.dd.mi.service.command.commands.MIThreadInfo;
import org.eclipse.dd.mi.service.command.events.IMIDMEvent;
import org.eclipse.dd.mi.service.command.events.MIThreadCreatedEvent;
import org.eclipse.dd.mi.service.command.events.MIThreadGroupCreatedEvent; import org.eclipse.dd.mi.service.command.events.MIThreadGroupCreatedEvent;
import org.eclipse.dd.mi.service.command.events.MIThreadGroupExitedEvent; import org.eclipse.dd.mi.service.command.events.MIThreadGroupExitedEvent;
import org.eclipse.dd.mi.service.command.output.IThreadInfo;
import org.eclipse.dd.mi.service.command.output.MIInfo; import org.eclipse.dd.mi.service.command.output.MIInfo;
import org.eclipse.dd.mi.service.command.output.MIListThreadGroupsInfo; import org.eclipse.dd.mi.service.command.output.MIListThreadGroupsInfo;
import org.eclipse.dd.mi.service.command.output.MIThreadInfoInfo;
import org.eclipse.dd.mi.service.command.output.MIListThreadGroupsInfo.IThreadGroupInfo; import org.eclipse.dd.mi.service.command.output.MIListThreadGroupsInfo.IThreadGroupInfo;
import org.eclipse.dd.mi.service.command.output.MIListThreadGroupsInfo.IThreadInfo;
import org.osgi.framework.BundleContext; import org.osgi.framework.BundleContext;
@ -305,7 +311,12 @@ public class GDBMultiProcesses extends AbstractDsfService implements IMIProcesse
} }
private GDBControl fCommandControl; private GDBControl fCommandControl;
private CommandCache fCommandCache;
// A cache for commands about the threadGroups
private CommandCache fContainerCommandCache;
//A cache for commands about the threads
private CommandCache fThreadCommandCache;
// A map of process id to process names. It is filled when we get all the processes that are running // A map of process id to process names. It is filled when we get all the processes that are running
private Map<String, String> fProcessNames = new HashMap<String, String>(); private Map<String, String> fProcessNames = new HashMap<String, String>();
@ -345,8 +356,11 @@ public class GDBMultiProcesses extends AbstractDsfService implements IMIProcesse
private void doInitialize(RequestMonitor requestMonitor) { private void doInitialize(RequestMonitor requestMonitor) {
fCommandControl = getServicesTracker().getService(GDBControl.class); fCommandControl = getServicesTracker().getService(GDBControl.class);
fCommandCache = new CommandCache(getSession(), fCommandControl); fContainerCommandCache = new CommandCache(getSession(), fCommandControl);
fCommandCache.setContextAvailable(fCommandControl.getControlDMContext(), true); fContainerCommandCache.setContextAvailable(fCommandControl.getControlDMContext(), true);
fThreadCommandCache = new CommandCache(getSession(), fCommandControl);
fThreadCommandCache.setContextAvailable(fCommandControl.getControlDMContext(), true);
getSession().addServiceEventListener(this, null); getSession().addServiceEventListener(this, null);
// Register this service. // Register this service.
@ -431,18 +445,18 @@ public class GDBMultiProcesses extends AbstractDsfService implements IMIProcesse
final MIThreadDMC threadDmc = (MIThreadDMC)dmc; final MIThreadDMC threadDmc = (MIThreadDMC)dmc;
MIControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, MIControlDMContext.class); MIControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, MIControlDMContext.class);
IMIProcessDMContext procDmc = DMContexts.getAncestorOfType(dmc, IMIProcessDMContext.class); fThreadCommandCache.execute(new MIThreadInfo(controlDmc, threadDmc.getId()),
fCommandCache.execute(new MIListThreadGroups(controlDmc, procDmc.getProcId()), new DataRequestMonitor<MIThreadInfoInfo>(getExecutor(), rm) {
new DataRequestMonitor<MIListThreadGroupsInfo>(getExecutor(), rm) {
@Override @Override
protected void handleSuccess() { protected void handleSuccess() {
IThreadDMData threadData = new MIThreadDMData("", ""); //$NON-NLS-1$ //$NON-NLS-2$ IThreadDMData threadData = new MIThreadDMData("", ""); //$NON-NLS-1$ //$NON-NLS-2$
for (IThreadInfo thread : getData().getThreadList()) { if (getData().getThreadList().length != 0) {
IThreadInfo thread = getData().getThreadList()[0];
if (thread.getThreadId().equals(threadDmc.getId())) { if (thread.getThreadId().equals(threadDmc.getId())) {
threadData = new MIThreadDMData("", thread.getOSId()); //$NON-NLS-1$ threadData = new MIThreadDMData("", thread.getOsId()); //$NON-NLS-1$
break;
} }
} }
rm.setData(threadData); rm.setData(threadData);
rm.done(); rm.done();
} }
@ -454,8 +468,18 @@ public class GDBMultiProcesses extends AbstractDsfService implements IMIProcesse
} }
public void getDebuggingContext(IThreadDMContext dmc, DataRequestMonitor<IDMContext> rm) { public void getDebuggingContext(IThreadDMContext dmc, DataRequestMonitor<IDMContext> rm) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, if (dmc instanceof MIProcessDMC) {
NOT_SUPPORTED, "Not supported", null)); //$NON-NLS-1$ MIProcessDMC procDmc = (MIProcessDMC)dmc;
rm.setData(createExecutionGroupContext(procDmc, procDmc.getProcId()));
} else if (dmc instanceof MIThreadDMC) {
MIThreadDMC threadDmc = (MIThreadDMC)dmc;
IMIProcessDMContext procDmc = DMContexts.getAncestorOfType(dmc, IMIProcessDMContext.class);
IMIExecutionGroupDMContext groupDmc = createExecutionGroupContext(procDmc, procDmc.getProcId());
rm.setData(createExecutionContext(groupDmc, threadDmc, threadDmc.getId()));
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid thread context.", null)); //$NON-NLS-1$
}
rm.done(); rm.done();
} }
@ -538,17 +562,17 @@ public class GDBMultiProcesses extends AbstractDsfService implements IMIProcesse
final MIControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, MIControlDMContext.class); final MIControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, MIControlDMContext.class);
final IMIExecutionGroupDMContext groupDmc = DMContexts.getAncestorOfType(dmc, IMIExecutionGroupDMContext.class); final IMIExecutionGroupDMContext groupDmc = DMContexts.getAncestorOfType(dmc, IMIExecutionGroupDMContext.class);
if (groupDmc != null) { if (groupDmc != null) {
fCommandCache.execute( fThreadCommandCache.execute(
new MIListThreadGroups(controlDmc, groupDmc.getGroupId()), new MIListThreadGroups(controlDmc, groupDmc.getGroupId()),
new DataRequestMonitor<MIListThreadGroupsInfo>(getExecutor(), rm) { new DataRequestMonitor<MIListThreadGroupsInfo>(getExecutor(), rm) {
@Override @Override
protected void handleSuccess() { protected void handleSuccess() {
rm.setData(makeExecutionDMCs(groupDmc, getData().getThreadList())); rm.setData(makeExecutionDMCs(groupDmc, getData().getThreadInfo().getThreadList()));
rm.done(); rm.done();
} }
}); });
} else { } else {
fCommandCache.execute( fContainerCommandCache.execute(
new MIListThreadGroups(controlDmc), new MIListThreadGroups(controlDmc),
new DataRequestMonitor<MIListThreadGroupsInfo>(getExecutor(), rm) { new DataRequestMonitor<MIListThreadGroupsInfo>(getExecutor(), rm) {
@Override @Override
@ -603,7 +627,8 @@ public class GDBMultiProcesses extends AbstractDsfService implements IMIProcesse
final MIControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, MIControlDMContext.class); final MIControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, MIControlDMContext.class);
if (controlDmc != null) { if (controlDmc != null) {
fCommandCache.execute( // Don't cache this command since the list can change at any time.
fCommandControl.queueCommand(
new MIListThreadGroups(controlDmc, true), new MIListThreadGroups(controlDmc, true),
new DataRequestMonitor<MIListThreadGroupsInfo>(getExecutor(), rm) { new DataRequestMonitor<MIListThreadGroupsInfo>(getExecutor(), rm) {
@Override @Override
@ -655,32 +680,10 @@ public class GDBMultiProcesses extends AbstractDsfService implements IMIProcesse
public String getExecutionGroupIdFromThread(String threadId) { public String getExecutionGroupIdFromThread(String threadId) {
String groupId = fGroupIdMap.get(threadId); String groupId = fGroupIdMap.get(threadId);
if (groupId == null) return "162"; //$NON-NLS-1$ if (groupId == null) return ""; //$NON-NLS-1$
else return groupId; else return groupId;
} }
@DsfServiceEventHandler
public void eventDispatched(IResumedDMEvent e) {
fCommandCache.setContextAvailable(e.getDMContext(), false);
// I need to put this so that in non-stop mode, we can send the CLIInfo
// command while some threads are running.
// However, in all-stop, this line breaks a thread exiting, and threads running
// because it allows us to send the thread-list-ids although we don't have a prompt
// We need to find a proper solution for the cache.
// fCommandCache.setContextAvailable(fCommandControl.getControlDMContext(), true);
if (e.getReason() != StateChangeReason.STEP) {
fCommandCache.reset();
}
}
@DsfServiceEventHandler
public void eventDispatched(ISuspendedDMEvent e) {
fCommandCache.setContextAvailable(e.getDMContext(), true);
fCommandCache.setContextAvailable(fCommandControl.getControlDMContext(), true);
fCommandCache.reset();
}
@DsfServiceEventHandler @DsfServiceEventHandler
public void eventDispatched(final MIThreadGroupCreatedEvent e) { public void eventDispatched(final MIThreadGroupCreatedEvent e) {
IProcessDMContext procDmc = e.getDMContext(); IProcessDMContext procDmc = e.getDMContext();
@ -695,4 +698,67 @@ public class GDBMultiProcesses extends AbstractDsfService implements IMIProcesse
getSession().dispatchEvent(new ExecutionGroupExitedDMEvent(groupDmc), getProperties()); getSession().dispatchEvent(new ExecutionGroupExitedDMEvent(groupDmc), getProperties());
} }
@DsfServiceEventHandler
public void eventDispatched(IResumedDMEvent e) {
if (e instanceof IContainerResumedDMEvent) {
// This will happen in all-stop mode
fContainerCommandCache.setContextAvailable(e.getDMContext(), false);
fThreadCommandCache.setContextAvailable(e.getDMContext(), false);
} else {
// This will happen in non-stop mode
// Keep target available for Container commands
}
}
@DsfServiceEventHandler
public void eventDispatched(ISuspendedDMEvent e) {
if (e instanceof IContainerSuspendedDMEvent) {
// This will happen in all-stop mode
fContainerCommandCache.setContextAvailable(e.getDMContext(), true);
fThreadCommandCache.setContextAvailable(e.getDMContext(), true);
} else {
// This will happen in non-stop mode
}
}
// Event handler when a thread or threadGroup starts
@DsfServiceEventHandler
public void eventDispatched(IStartedDMEvent e) {
if (e instanceof ExecutionGroupStartedDMEvent) {
fContainerCommandCache.reset();
} else {
// HACK figure out the thread and the group ids
// I had to HACK GDB for this
if (e instanceof IMIDMEvent) {
String threadId = ((MIThreadCreatedEvent)((IMIDMEvent)e).getMIEvent()).getStrId();
IContainerDMContext ctx = ((MIThreadCreatedEvent)((IMIDMEvent)e).getMIEvent()).getDMContext();
if (ctx instanceof IMIExecutionGroupDMContext) {
String groupId = ((IMIExecutionGroupDMContext)ctx).getGroupId();
fGroupIdMap.put(threadId, groupId);
}
}
// END HACK
fThreadCommandCache.reset();
}
}
// Event handler when a thread or a threadGroup exits
@DsfServiceEventHandler
public void eventDispatched(IExitedDMEvent e) {
if (e instanceof ExecutionGroupExitedDMEvent) {
fContainerCommandCache.reset();
} else {
// HACK figure out the thread and the group ids
// I had to HACK GDB for this
if (e instanceof IMIDMEvent) {
String threadId = ((MIThreadCreatedEvent)((IMIDMEvent)e).getMIEvent()).getStrId();
fGroupIdMap.remove(threadId);
}
// END HACK
fThreadCommandCache.reset();
}
}
} }

View file

@ -195,12 +195,7 @@ public class MIRunControlEventProcessor
if (event != null) { if (event != null) {
fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties()); fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties());
} }
} } else if ("thread-group-created".equals(miEvent) || "thread-group-exited".equals(miEvent)) { //$NON-NLS-1$ //$NON-NLS-2$
} else if (oobr instanceof MINotifyAsyncOutput) {
// Parse the string and dispatch the corresponding event
MINotifyAsyncOutput exec = (MINotifyAsyncOutput) oobr;
String miEvent = exec.getAsyncClass();
if ("thread-group-created".equals(miEvent) || "thread-group-exited".equals(miEvent)) { //$NON-NLS-1$ //$NON-NLS-2$
String groupId = null; String groupId = null;

View file

@ -11,7 +11,7 @@
package org.eclipse.dd.mi.service.command.commands; package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext; import org.eclipse.dd.mi.service.command.MIControlDMContext;
import org.eclipse.dd.mi.service.command.output.MIOutput; import org.eclipse.dd.mi.service.command.output.MIOutput;
import org.eclipse.dd.mi.service.command.output.MIThreadInfoInfo; import org.eclipse.dd.mi.service.command.output.MIThreadInfoInfo;
@ -26,12 +26,12 @@ import org.eclipse.dd.mi.service.command.output.MIThreadInfoInfo;
*/ */
public class MIThreadInfo extends MICommand<MIThreadInfoInfo> { public class MIThreadInfo extends MICommand<MIThreadInfoInfo> {
public MIThreadInfo(IContainerDMContext dmc) { public MIThreadInfo(MIControlDMContext dmc) {
super(dmc, "-thread-info"); //$NON-NLS-1$ super(dmc, "-thread-info"); //$NON-NLS-1$
} }
public MIThreadInfo(IContainerDMContext dmc, int threadId) { public MIThreadInfo(MIControlDMContext dmc, String threadId) {
super(dmc, "-thread-info", new String[]{ Integer.toString(threadId) }); //$NON-NLS-1$ super(dmc, "-thread-info", new String[]{ threadId }); //$NON-NLS-1$
} }
@Override @Override

View file

@ -0,0 +1,23 @@
/*******************************************************************************
* Copyright (c) 2008 Ericsson and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Ericsson - Initial API and implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.output;
import java.math.BigInteger;
public interface IThreadFrame {
int getStackLevel();
BigInteger getAddress();
String getFucntion();
Object[] getArgs();
String getFileName();
String getFullName();
int getLineNumber();
}

View file

@ -0,0 +1,21 @@
/*******************************************************************************
* Copyright (c) 2008 Ericsson and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Ericsson - Initial API and implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.output;
public interface IThreadInfo {
String getThreadId();
String getTargetId();
String getOsId();
IThreadFrame getTopFrame();
String getDetails();
String getState();
}

View file

@ -21,15 +21,15 @@ import org.eclipse.dd.dsf.concurrent.Immutable;
* *
* The description field can be different depending on the target we are connected to. * The description field can be different depending on the target we are connected to.
* *
* This output is from -list-thread-groups --available: * -list-thread-groups --available:
* ^done,groups=[{id="160",description="name: JIM_InstallerProcess, type 555481, locked: N, system: N, state: Idle"}, * ^done,groups=[{id="160",description="name: JIM_InstallerProcess, type 555481, locked: N, system: N, state: Idle"},
* {id="161",description="name: JIM_TcpSetupHandlerProcess, type 555505, locked: N, system: N, state: Idle"}, * {id="161",description="name: JIM_TcpSetupHandlerProcess, type 555505, locked: N, system: N, state: Idle"},
* {id="162",description="name: JUnitProcess_PT, type 1094605, locked: N, system: N, state: Idle"}] * {id="162",description="name: JUnitProcess_PT, type 1094605, locked: N, system: N, state: Idle"}]
* *
* This output is from -list-thread-groups: * -list-thread-groups:
* ^done,groups=[{id="162",type="process",pid="162"}] * ^done,groups=[{id="162",type="process",pid="162"}]
* *
* This output is from -list-thread-groups GROUPID, in the case of a running thread or a stopped thread: * list-thread-groups GROUPID, in the case of a running thread or a stopped thread:
* ^done,threads=[{id="1",target-id="Thread 162.32942",details="JUnitProcess_PT (Ready) 1030373359 44441",frame={level="0",addr="0x00000000",func="??",args=[]},state="stopped"}] * ^done,threads=[{id="1",target-id="Thread 162.32942",details="JUnitProcess_PT (Ready) 1030373359 44441",frame={level="0",addr="0x00000000",func="??",args=[]},state="stopped"}]
* ^done,threads=[{id="1",target-id="Thread 162.32942",details="JUnitProcess_PT Idle 981333916 42692",state="running"}] * ^done,threads=[{id="1",target-id="Thread 162.32942",details="JUnitProcess_PT Idle 981333916 42692",state="running"}]
*/ */
@ -77,31 +77,9 @@ public class MIListThreadGroupsInfo extends MIInfo {
public String getDesciption() { return fDescription; } public String getDesciption() { return fDescription; }
} }
public interface IThreadInfo {
String getThreadId();
String getOSId();
String getState();
}
@Immutable private IThreadGroupInfo[] fGroupList;
private static class ThreadInfo implements IThreadInfo { private MIThreadInfoInfo fThreadInfo;
final String fThreadId;
final String fOSId;
final String fState;
public ThreadInfo(String id, String osId, String state) {
fThreadId = id;
fOSId = osId;
fState = state;
}
public String getThreadId() { return fThreadId; }
public String getOSId() { return fOSId; }
public String getState() { return fState; }
}
IThreadGroupInfo[] fGroupList;
IThreadInfo[] fThreadList;
public MIListThreadGroupsInfo(MIOutput out) { public MIListThreadGroupsInfo(MIOutput out) {
super(out); super(out);
@ -109,7 +87,7 @@ public class MIListThreadGroupsInfo extends MIInfo {
} }
public IThreadGroupInfo[] getGroupList() { return fGroupList; } public IThreadGroupInfo[] getGroupList() { return fGroupList; }
public IThreadInfo[] getThreadList() { return fThreadList; } public MIThreadInfoInfo getThreadInfo() { return fThreadInfo; }
private void parse() { private void parse() {
if (isDone()) { if (isDone()) {
@ -125,26 +103,23 @@ public class MIListThreadGroupsInfo extends MIInfo {
parseGroups((MIList)val); parseGroups((MIList)val);
} }
} else if (var.equals("threads")) { //$NON-NLS-1$ } else if (var.equals("threads")) { //$NON-NLS-1$
MIValue val = results[i].getMIValue(); // Re-use the MIThreadInfoInfo parsing
if (val instanceof MIList) { fThreadInfo = new MIThreadInfoInfo(out);
parseThreads((MIList)val);
} }
} }
}
} }
} }
if (fGroupList == null) { if (fGroupList == null) {
fGroupList = new IThreadGroupInfo[0]; fGroupList = new IThreadGroupInfo[0];
} }
if (fThreadList == null) { if (fThreadInfo == null) {
fThreadList = new IThreadInfo[0]; fThreadInfo = new MIThreadInfoInfo(null);
} }
} }
private void parseGroups(MIList list) { private void parseGroups(MIList list) {
MIValue[] values = list.getMIValues(); MIValue[] values = list.getMIValues();
fGroupList = new ThreadGroupInfo[values.length]; fGroupList = new IThreadGroupInfo[values.length];
for (int i = 0; i < values.length; i++) { for (int i = 0; i < values.length; i++) {
MIResult[] results = ((MITuple)values[i]).getMIResults(); MIResult[] results = ((MITuple)values[i]).getMIResults();
String id = "", desc = "";//$NON-NLS-1$//$NON-NLS-2$ String id = "", desc = "";//$NON-NLS-1$//$NON-NLS-2$
@ -169,40 +144,4 @@ public class MIListThreadGroupsInfo extends MIInfo {
fGroupList[i] = new ThreadGroupInfo(id, desc); fGroupList[i] = new ThreadGroupInfo(id, desc);
} }
} }
private void parseThreads(MIList list) {
MIValue[] values = list.getMIValues();
fThreadList = new ThreadInfo[values.length];
for (int i = 0; i < values.length; i++) {
MIResult[] results = ((MITuple)values[i]).getMIResults();
String id = "", osId = "", state = "";//$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
for (MIResult result : results) {
String var = result.getVariable();
if (var.equals("id")) { //$NON-NLS-1$
MIValue value = result.getMIValue();
if (value instanceof MIConst) {
String str = ((MIConst)value).getCString();
id = str.trim();
}
} else if (var.equals("target-id")) { //$NON-NLS-1$
MIValue value = result.getMIValue();
if (value instanceof MIConst) {
String str = ((MIConst)value).getCString();
osId = str.trim();
}
} else if (var.equals("state")) { //$NON-NLS-1$
MIValue value = result.getMIValue();
if (value instanceof MIConst) {
String str = ((MIConst)value).getCString();
state = str.trim();
}
}
}
fThreadList[i] = new ThreadInfo(id, osId, state);
}
}
} }

View file

@ -10,14 +10,10 @@
*******************************************************************************/ *******************************************************************************/
package org.eclipse.dd.mi.service.command.output; package org.eclipse.dd.mi.service.command.output;
import java.math.BigInteger;
import java.util.List;
import java.util.Vector;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.eclipse.dd.dsf.concurrent.Immutable;
/** /**
* GDB/MI thread list parsing. * GDB/MI thread list parsing.
* *
@ -28,14 +24,14 @@ import org.eclipse.dd.dsf.concurrent.Immutable;
* {id="2",target-id="Thread 0xb7c8ab90 (LWP 7010)", * {id="2",target-id="Thread 0xb7c8ab90 (LWP 7010)",
* frame={level="0",addr="0x08048bba",func="my_func",args=[{name="arg",value="0xbff056f5"}], * frame={level="0",addr="0x08048bba",func="my_func",args=[{name="arg",value="0xbff056f5"}],
* file="my_test.cc",fullname="/home/francois/GDB/my_test.cc",line="26"}, * file="my_test.cc",fullname="/home/francois/GDB/my_test.cc",line="26"},
* running="0"}, * state="stopped"},
* {id="1",target-id="Thread 0xb7c8b8d0 (LWP 7007)", * {id="1",target-id="Thread 0xb7c8b8d0 (LWP 7007)",
* frame={level="0",addr="0x08048a77",func="timer",args=[{name="duration",value="0xbff056f5 \"10\""}], * frame={level="0",addr="0x08048a77",func="timer",args=[{name="duration",value="0xbff056f5 \"10\""}],
* file="my_test.cc",fullname="/home/francois/GDB/my_test.cc",line="39"}, * file="my_test.cc",fullname="/home/francois/GDB/my_test.cc",line="39"},
* running="0"} * state="stopped"}
* ],current-thread-id="2" * ],current-thread-id="2"
* *
*
* Example 2: * Example 2:
* *
* -thread-info 2 * -thread-info 2
@ -43,7 +39,7 @@ import org.eclipse.dd.dsf.concurrent.Immutable;
* {id="2",target-id="Thread 0xb7c8ab90 (LWP 7010)", * {id="2",target-id="Thread 0xb7c8ab90 (LWP 7010)",
* frame={level="0",addr="0x08048bba",func="my_func",args=[{name="arg",value="0xbff056f5"}], * frame={level="0",addr="0x08048bba",func="my_func",args=[{name="arg",value="0xbff056f5"}],
* file="my_test.cc",fullname="/home/francois/GDB/my_test.cc",line="26"}, * file="my_test.cc",fullname="/home/francois/GDB/my_test.cc",line="26"},
* running="0"} * state="stopped"}
* ] * ]
* *
* *
@ -51,92 +47,45 @@ import org.eclipse.dd.dsf.concurrent.Immutable;
* *
* -thread-info * -thread-info
* ^done,threads=[ * ^done,threads=[
* {id="2",target-id="Thread 0xb7c8eb90 (LWP 7807)",running="1"}, * {id="2",target-id="Thread 0xb7d6d6b0 (LWP 14494)",state="running"},
* {id="1",target-id="Thread 0xb7c8b8d0 (LWP 7007)", * {id="1",target-id="Thread 0xb7c8b8d0 (LWP 7007)",
* frame={level="0",addr="0x08048a77",func="timer",args=[{name="duration",value="0xbff056f5 \"10\""}], * frame={level="0",addr="0x08048a77",func="timer",args=[{name="duration",value="0xbff056f5 \"10\""}],
* file="my_test.cc",fullname="/home/francois/GDB/my_test.cc",line="39"}, * file="my_test.cc",fullname="/home/francois/GDB/my_test.cc",line="39"},
* running="0"} * state="stopped"}
* ],current-thread-id="1" * ],current-thread-id="1"
*
*
* Example 4 (non-stop):
*
* -thread-info 1
* ^done,threads=[{id="1",target-id="Thread 0xb7d6d6b0 (LWP 14494)",state="running"}]
*
*
* Example 5 (Dicos):
*
* -thread-info 1
* ^done,threads=[
* {id="1",target-id="Thread 162.32942",details="JUnitProcess_PT (Ready) 175417582794 8572423",
* frame={level="0",addr="0x1559a318",func="mainExpressionTestApp",args=[],
* file="/local/home/lmckhou/TSP/TADE/example/JUnitProcess_OU/src/ExpressionTestApp.cc",
* fullname="/local/home/lmckhou/TSP/TADE/example/JUnitProcess_OU/src/ExpressionTestApp.cc",line="279"},
* state="stopped"}]
*/ */
public class MIThreadInfoInfo extends MIInfo { public class MIThreadInfoInfo extends MIInfo {
@Immutable private String fCurrentThread = null;
public class ThreadInfo { private IThreadInfo[] fThreadList = null;
final private String fGdbId;
final private String fTargetId;
final private String fOsId;
final private ThreadFrame fTopFrame;
final private boolean fIsRunning;
public ThreadInfo(String gdbId, String targetId, String osId, ThreadFrame topFrame, boolean isRunning) {
fGdbId = gdbId;
fTargetId = targetId;
fOsId = osId;
fTopFrame = topFrame;
fIsRunning = isRunning;
}
public String getGdbId() { return fGdbId; }
public String getTargetId() { return fTargetId; }
public String getOsId() { return fOsId; }
public ThreadFrame getTopFrame() { return fTopFrame; }
public boolean isRunning() { return fIsRunning; }
}
@Immutable
public class ThreadFrame {
final private int fStackLevel;
final private BigInteger fAddress;
final private String fFunction;
final private ThreadFrameFunctionArgs[] fArgs;
final private String fFileName;
final private String fFullName;
final private int fLineNumber;
public ThreadFrame(int stackLevel, BigInteger address, String function,
ThreadFrameFunctionArgs[] args, String file, String fullName, int line)
{
fStackLevel = stackLevel;
fAddress = address;
fFunction = function;
fArgs = args;
fFileName = file;
fFullName = fullName;
fLineNumber = line;
}
public int getStackLevel() { return fStackLevel; }
public BigInteger getAddress() { return fAddress; }
public String getFucntion() { return fFunction; }
public ThreadFrameFunctionArgs[] getArgs() { return fArgs; }
public String getFileName() { return fFileName; }
public String getFullName() { return fFullName; }
public int getLineNumber() { return fLineNumber; }
}
@Immutable
public class ThreadFrameFunctionArgs {
}
private int fCurrentThread = -1;
private List<ThreadInfo> fThreadInfoList = null;
private int[] fThreadList = null;
public MIThreadInfoInfo(MIOutput out) { public MIThreadInfoInfo(MIOutput out) {
super(out); super(out);
parse(); parse();
} }
public int getCurrentThread() { public String getCurrentThread() {
return fCurrentThread; return fCurrentThread;
} }
public List<ThreadInfo> getThreadInfoList() { public IThreadInfo[] getThreadList() {
return fThreadInfoList;
}
public int[] getThreadList() {
return fThreadList; return fThreadList;
} }
@ -159,40 +108,36 @@ public class MIThreadInfoInfo extends MIInfo {
else if (var.equals("current-thread-id")) { //$NON-NLS-1$ else if (var.equals("current-thread-id")) { //$NON-NLS-1$
MIValue value = results[i].getMIValue(); MIValue value = results[i].getMIValue();
if (value instanceof MIConst) { if (value instanceof MIConst) {
String str = ((MIConst) value).getCString(); fCurrentThread = ((MIConst) value).getCString().trim();
try {
fCurrentThread = Integer.parseInt(str.trim());
} catch (NumberFormatException e) {
fCurrentThread = -1;
} }
} }
} }
} }
} }
} if (fThreadList == null) {
if (fThreadInfoList == null) { fThreadList = new IThreadInfo[0];
fThreadInfoList = new Vector<ThreadInfo>(0);
fThreadList = new int[0];
} }
} }
// General formats: // General formats:
// id="n",target-id="Thread 0xb7c8ab90 (LWP 7010)",frame={...},running="0" // id="n",target-id="Thread 0xb7c8ab90 (LWP 7010)",frame={...},state="stopped"
// id="n",target-id="Thread 0xb7c8eb90 (LWP 7807)",running="1" // id="n",target-id="Thread 0xb7c8eb90 (LWP 7807)",state="running"
// id="n",target-id="Thread 162.32942",details="...",frame={...},state="stopped"
private void parseThreads(MIList list) { private void parseThreads(MIList list) {
MIValue[] values = list.getMIValues(); MIValue[] values = list.getMIValues();
fThreadInfoList = new Vector<ThreadInfo>(values.length); fThreadList = new IThreadInfo[values.length];
fThreadList = new int[values.length];
for (int i = 0; i < values.length; i++) { for (int i = 0; i < values.length; i++) {
MITuple value = (MITuple) values[i]; MITuple value = (MITuple) values[i];
MIResult[] results = value.getMIResults(); MIResult[] results = value.getMIResults();
String gdbId = null; String threadId = null;
String targetId = null; String targetId = null;
String osId = null; String osId = null;
String parentId = null;
ThreadFrame topFrame = null; ThreadFrame topFrame = null;
boolean isRunning = false; String state = null;
String details = null;
for (int j = 0; j < results.length; j++) { for (int j = 0; j < results.length; j++) {
MIResult result = results[j]; MIResult result = results[j];
@ -200,45 +145,68 @@ public class MIThreadInfoInfo extends MIInfo {
if (var.equals("id")) { //$NON-NLS-1$ if (var.equals("id")) { //$NON-NLS-1$
MIValue val = results[j].getMIValue(); MIValue val = results[j].getMIValue();
if (val instanceof MIConst) { if (val instanceof MIConst) {
gdbId = ((MIConst) val).getCString(); threadId = ((MIConst) val).getCString().trim();
} }
} }
else if (var.equals("target-id")) { //$NON-NLS-1$ else if (var.equals("target-id")) { //$NON-NLS-1$
MIValue val = results[j].getMIValue(); MIValue val = results[j].getMIValue();
if (val instanceof MIConst) { if (val instanceof MIConst) {
targetId = ((MIConst) val).getCString(); targetId = ((MIConst) val).getCString().trim();
osId = parseOsId(targetId); osId = parseOsId(targetId);
parentId = parseParentId(targetId);
} }
} }
else if (var.equals("frame")) { //$NON-NLS-1$ else if (var.equals("frame")) { //$NON-NLS-1$
MIValue val = results[j].getMIValue(); MIValue val = results[j].getMIValue();
topFrame = parseFrame(val); topFrame = parseFrame(val);
} }
else if (var.equals("running")) { //$NON-NLS-1$ else if (var.equals("state")) { //$NON-NLS-1$
MIValue val = results[j].getMIValue(); MIValue val = results[j].getMIValue();
if (val instanceof MIConst) { if (val instanceof MIConst) {
String v = ((MIConst) val).getCString(); state = ((MIConst) val).getCString().trim();
isRunning = v.equals("1"); //$NON-NLS-1$ }
}
else if (var.equals("details")) { //$NON-NLS-1$
MIValue val = results[j].getMIValue();
if (val instanceof MIConst) {
details = ((MIConst) val).getCString().trim();
} }
} }
} }
fThreadInfoList.add(new ThreadInfo(gdbId, targetId, osId, topFrame, isRunning)); fThreadList[i] = new ThreadInfo(threadId, targetId, osId, parentId, topFrame, details, state);
try {
fThreadList[i] = Integer.parseInt(gdbId);
} catch (NumberFormatException e) {
}
} }
} }
// General format: // General format:
// "Thread 0xb7c8ab90 (LWP 7010)" // "Thread 0xb7c8ab90 (LWP 7010)"
// "Thread 162.32942"
private String parseOsId(String str) { private String parseOsId(String str) {
Pattern pattern = Pattern.compile("(Thread\\s*)(0x[0-9a-fA-F]+|-?\\d+)(\\s*\\(LWP\\s*)(\\d*)", 0); //$NON-NLS-1$ Pattern pattern = Pattern.compile("(Thread\\s*)(0x[0-9a-fA-F]+|-?\\d+)(\\s*\\(LWP\\s*)(\\d*)", 0); //$NON-NLS-1$
Matcher matcher = pattern.matcher(str); Matcher matcher = pattern.matcher(str);
if (matcher.find()) { if (matcher.find()) {
return matcher.group(4); return matcher.group(4);
} }
pattern = Pattern.compile("Thread\\s*\\d+\\.(\\d+)", 0); //$NON-NLS-1$
matcher = pattern.matcher(str);
if (matcher.find()) {
return matcher.group(1);
}
return null;
}
// General format:
// "Thread 0xb7c8ab90 (LWP 7010)"
// "Thread 162.32942"
private String parseParentId(String str) {
Pattern pattern = Pattern.compile("Thread\\s*(\\d+)\\.\\d+", 0); //$NON-NLS-1$
Matcher matcher = pattern.matcher(str);
if (matcher.find()) {
return matcher.group(1);
}
return null; return null;
} }

View file

@ -0,0 +1,46 @@
/*******************************************************************************
* Copyright (c) 2008 Ericsson and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Ericsson - Initial API and implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.output;
import java.math.BigInteger;
import org.eclipse.dd.dsf.concurrent.Immutable;
@Immutable
public class ThreadFrame implements IThreadFrame {
final private int fStackLevel;
final private BigInteger fAddress;
final private String fFunction;
final private Object[] fArgs;
final private String fFileName;
final private String fFullName;
final private int fLineNumber;
public ThreadFrame(int stackLevel, BigInteger address, String function,
Object[] args, String file, String fullName, int line)
{
fStackLevel = stackLevel;
fAddress = address;
fFunction = function;
fArgs = args;
fFileName = file;
fFullName = fullName;
fLineNumber = line;
}
public int getStackLevel() { return fStackLevel; }
public BigInteger getAddress() { return fAddress; }
public String getFucntion() { return fFunction; }
public Object[] getArgs() { return fArgs; }
public String getFileName() { return fFileName; }
public String getFullName() { return fFullName; }
public int getLineNumber() { return fLineNumber; }
}

View file

@ -0,0 +1,48 @@
/*******************************************************************************
* Copyright (c) 2008 Ericsson and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Ericsson - Initial API and implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.output;
import org.eclipse.dd.dsf.concurrent.Immutable;
@Immutable
public class ThreadInfo implements IThreadInfo {
final private String fThreadId;
final private String fTargetId;
final private String fOsId;
final private String fParentId;
final private IThreadFrame fTopFrame;
final private String fDetails;
final private String fState;
public ThreadInfo(String threadId, String targetId, String osId, String parentId,
IThreadFrame topFrame, String details, String state) {
fThreadId = threadId;
fTargetId = targetId;
fOsId = osId;
fParentId = parentId;
fTopFrame = topFrame;
fDetails = details;
fState = state;
}
public String getThreadId() { return fThreadId; }
public String getTargetId() { return fTargetId; }
public String getOsId() { return fOsId; }
public String getParentId() { return fParentId; }
public IThreadFrame getTopFrame() { return fTopFrame; }
public String getDetails() { return fDetails; }
public String getState() { return fState; }
}