From 78669bf6c13c64f097988b234bd84cf9e9ea2195 Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Tue, 6 Jul 2010 20:27:07 +0000 Subject: [PATCH] Bug 318230: Use GDB 7.1 support for displaying cores for threads and processes in a label within the debug view. --- .../ui/viewmodel/launch/ContainerVMNode.java | 67 ++++- .../launch/GdbExecutionContextLabelText.java | 7 +- .../launch/IGdbLaunchVMConstants.java | 8 +- .../launch/MessagesForGdbLaunchVM.java | 4 +- .../launch/MessagesForGdbLaunchVM.properties | 23 +- .../ui/viewmodel/launch/ThreadVMNode.java | 31 ++- .../cdt/dsf/gdb/service/GDBProcesses_7_0.java | 8 +- .../cdt/dsf/gdb/service/GDBProcesses_7_1.java | 238 ++++++++++++++++++ .../gdb/service/GdbDebugServicesFactory.java | 4 + .../cdt/dsf/gdb/service/IGDBProcesses.java | 21 +- .../output/MIListThreadGroupsInfo.java | 12 +- .../mi/service/command/output/MIThread.java | 2 +- 12 files changed, 397 insertions(+), 28 deletions(-) create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_1.java diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/ContainerVMNode.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/ContainerVMNode.java index b082f7a9507..f8943da33b8 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/ContainerVMNode.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/ContainerVMNode.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2009 Ericsson and others. + * Copyright (c) 2006, 2010 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 @@ -27,7 +27,9 @@ import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext; import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService; import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent; import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.AbstractContainerVMNode; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.ExecutionContextLabelText; import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.ILaunchVMConstants; +import org.eclipse.cdt.dsf.gdb.service.IGDBProcesses.IGdbThreadDMData; import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.cdt.dsf.ui.concurrent.ViewerCountingRequestMonitor; @@ -36,18 +38,27 @@ import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelAttribute; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelColumnInfo; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelImage; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelText; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.PropertiesBasedLabelProvider; import org.eclipse.cdt.dsf.ui.viewmodel.properties.VMDelegatingPropertiesUpdate; +import org.eclipse.core.runtime.IStatus; import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest; import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.ui.IMemento; @SuppressWarnings("restriction") public class ContainerVMNode extends AbstractContainerVMNode - implements IElementMementoProvider + implements IElementLabelProvider, IElementMementoProvider { public ContainerVMNode(AbstractDMVMProvider provider, DsfSession session) { super(provider, session); @@ -58,6 +69,37 @@ public class ContainerVMNode extends AbstractContainerVMNode return "ContainerVMNode(" + getSession().getId() + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } + @Override + protected IElementLabelProvider createLabelProvider() { + PropertiesBasedLabelProvider provider = new PropertiesBasedLabelProvider(); + + provider.setColumnInfo( + PropertiesBasedLabelProvider.ID_COLUMN_NO_COLUMNS, + new LabelColumnInfo(new LabelAttribute[] { + new GdbExecutionContextLabelText( + MessagesForGdbLaunchVM.ContainerVMNode_No_columns__text_format, + new String[] { + ExecutionContextLabelText.PROP_NAME_KNOWN, + PROP_NAME, + ExecutionContextLabelText.PROP_ID_KNOWN, + ILaunchVMConstants.PROP_ID, + IGdbLaunchVMConstants.PROP_CORES_ID_KNOWN, + IGdbLaunchVMConstants.PROP_CORES_ID }), + new LabelText(MessagesForGdbLaunchVM.ContainerVMNode_No_columns__Error__label, new String[0]), + new LabelImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_DEBUG_TARGET_SUSPENDED)) { + { setPropertyNames(new String[] { ILaunchVMConstants.PROP_IS_SUSPENDED }); } + + @Override + public boolean isEnabled(IStatus status, java.util.Map properties) { + return Boolean.TRUE.equals(properties.get(ILaunchVMConstants.PROP_IS_SUSPENDED)); + }; + }, + new LabelImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_DEBUG_TARGET)), + })); + + return provider; + } + @Override protected void updateElementsInSessionThread(final IChildrenUpdate update) { IProcesses processService = getServicesTracker().getService(IProcesses.class); @@ -98,6 +140,11 @@ public class ContainerVMNode extends AbstractContainerVMNode parentUpdates[i] = new VMDelegatingPropertiesUpdate(updates[i], countringRm); count++; + if (update.getProperties().contains(PROP_NAME) || + update.getProperties().contains(ILaunchVMConstants.PROP_ID) || + update.getProperties().contains(IGdbLaunchVMConstants.PROP_CORES_ID)) + { + IProcesses processService = getServicesTracker().getService(IProcesses.class); final IProcessDMContext procDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IProcessDMContext.class); @@ -119,6 +166,7 @@ public class ContainerVMNode extends AbstractContainerVMNode }); count++; } + } countringRm.setDoneCount(count); } @@ -129,6 +177,21 @@ public class ContainerVMNode extends AbstractContainerVMNode protected void fillThreadDataProperties(IPropertiesUpdate update, IThreadDMData data) { update.setProperty(PROP_NAME, data.getName()); update.setProperty(ILaunchVMConstants.PROP_ID, data.getId()); + + String coresStr = null; + if (data instanceof IGdbThreadDMData) { + String[] cores = ((IGdbThreadDMData)data).getCores(); + if (cores != null) { + StringBuffer str = new StringBuffer(); + for (String core : cores) { + str.append(core + ","); //$NON-NLS-1$ + } + if (str.length() > 0) { + coresStr = str.substring(0, str.length() - 1); + } + } + } + update.setProperty(IGdbLaunchVMConstants.PROP_CORES_ID, coresStr); } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/GdbExecutionContextLabelText.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/GdbExecutionContextLabelText.java index 9323c714d1f..8f640591a39 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/GdbExecutionContextLabelText.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/GdbExecutionContextLabelText.java @@ -28,6 +28,9 @@ public class GdbExecutionContextLabelText extends ExecutionContextLabelText { protected Object getPropertyValue(String propertyName, IStatus status, Map properties) { if (IGdbLaunchVMConstants.PROP_OS_ID_KNOWN.equals(propertyName)) { return properties.get(IGdbLaunchVMConstants.PROP_OS_ID) != null ? 1 : 0; + } + if (IGdbLaunchVMConstants.PROP_CORES_ID_KNOWN.equals(propertyName)) { + return properties.get(IGdbLaunchVMConstants.PROP_CORES_ID) != null ? 1 : 0; } return super.getPropertyValue(propertyName, status, properties); } @@ -35,7 +38,9 @@ public class GdbExecutionContextLabelText extends ExecutionContextLabelText { @Override protected boolean checkProperty(String propertyName, IStatus status, Map properties) { if (IGdbLaunchVMConstants.PROP_OS_ID_KNOWN.equals(propertyName) || - IGdbLaunchVMConstants.PROP_OS_ID.equals(propertyName)) + IGdbLaunchVMConstants.PROP_OS_ID.equals(propertyName) || + IGdbLaunchVMConstants.PROP_CORES_ID_KNOWN.equals(propertyName) || + IGdbLaunchVMConstants.PROP_CORES_ID.equals(propertyName)) { return true; } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/IGdbLaunchVMConstants.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/IGdbLaunchVMConstants.java index a9890c39c35..a78d5a420db 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/IGdbLaunchVMConstants.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/IGdbLaunchVMConstants.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2009 Wind River Systems and others. + * Copyright (c) 2008, 2010 Wind River Systems 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 @@ -22,5 +22,11 @@ public interface IGdbLaunchVMConstants { */ public static final String PROP_OS_ID_KNOWN = "os_id_known"; //$NON-NLS-1$ + public static final String PROP_CORES_ID = "cores_id"; //$NON-NLS-1$ + + /** + * Value 0 means it's not known. Value 1, means it's known. + */ + public static final String PROP_CORES_ID_KNOWN = "cores_id_known"; //$NON-NLS-1$ } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/MessagesForGdbLaunchVM.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/MessagesForGdbLaunchVM.java index 8d8f09727ca..df30252d9a9 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/MessagesForGdbLaunchVM.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/MessagesForGdbLaunchVM.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2009 Wind River Systems and others. + * Copyright (c) 2008, 2010 Wind River Systems 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 @@ -19,6 +19,8 @@ import org.eclipse.osgi.util.NLS; public class MessagesForGdbLaunchVM extends NLS { public static String ThreadVMNode_No_columns__text_format; public static String ThreadVMNode_No_columns__Error__label; + public static String ContainerVMNode_No_columns__text_format; + public static String ContainerVMNode_No_columns__Error__label; static { // initialize resource bundle diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/MessagesForGdbLaunchVM.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/MessagesForGdbLaunchVM.properties index ca90ff3d56b..9372518493b 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/MessagesForGdbLaunchVM.properties +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/MessagesForGdbLaunchVM.properties @@ -15,12 +15,23 @@ # {3} - ID # {4} - OS Thread ID available, 0=not available/1=available # {5} - OS Thread ID -# {6} - 0=running/1=suspended -# {7} - state change reason available, 0=not available/1=available -# {8} - state change reason -# {9} - state change details available, 0=not available/1=available -# {10}- state change details -ThreadVMNode_No_columns__text_format={0,choice,0#Thread|1#{1}}{2,choice,0#|1# [{3}]}{4,choice,0#|1# {5}} ({6,choice,0#Running|1#Suspended}{7,choice,0#|1# : {8}}{9,choice,0#|1# : {10}}) +# {6} - Core available, 0=not available/1=available +# {7} - Core +# {8} - 0=running/1=suspended +# {9} - state change reason available, 0=not available/1=available +# {10} - state change reason +# {11} - state change details available, 0=not available/1=available +# {12} - state change details +ThreadVMNode_No_columns__text_format={0,choice,0#Thread|1#{1}}{2,choice,0#|1# [{3}]}{4,choice,0#|1# {5}}{6,choice,0#|1# [core: {7}]} ({8,choice,0#Running|1#Suspended}{9,choice,0#|1# : {10}}{11,choice,0#|1# : {12}}) ThreadVMNode_No_columns__Error__label= +# {0} - name available, 0=not available/1=available +# {1} - name +# {2} - ID available, 0=not available/1=available +# {3} - ID +# {4} - Cores available, 0=not available/1=available +# {5} - Cores +ContainerVMNode_No_columns__text_format={0,choice,0#Process|1#{1}}{2,choice,0#|1# [{3}]}{4,choice,0#|1# [cores: {5}]} + +ContainerVMNode_No_columns__Error__label= diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/ThreadVMNode.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/ThreadVMNode.java index cf8f2935e67..9627a4bf39d 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/ThreadVMNode.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/ThreadVMNode.java @@ -20,6 +20,7 @@ import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMData; import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.AbstractThreadVMNode; import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.ExecutionContextLabelText; import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.ILaunchVMConstants; +import org.eclipse.cdt.dsf.gdb.service.IGDBProcesses.IGdbThreadDMData; import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext; import org.eclipse.cdt.dsf.service.DsfSession; @@ -74,7 +75,9 @@ public class ThreadVMNode extends AbstractThreadVMNode ILaunchVMConstants.PROP_ID, IGdbLaunchVMConstants.PROP_OS_ID_KNOWN, IGdbLaunchVMConstants.PROP_OS_ID, - ILaunchVMConstants.PROP_IS_SUSPENDED, + IGdbLaunchVMConstants.PROP_CORES_ID_KNOWN, + IGdbLaunchVMConstants.PROP_CORES_ID, + ILaunchVMConstants.PROP_IS_SUSPENDED, ExecutionContextLabelText.PROP_STATE_CHANGE_REASON_KNOWN, ILaunchVMConstants.PROP_STATE_CHANGE_REASON, ExecutionContextLabelText.PROP_STATE_CHANGE_DETAILS_KNOWN, @@ -117,14 +120,14 @@ public class ThreadVMNode extends AbstractThreadVMNode update.setProperty(ILaunchVMConstants.PROP_ID, Integer.toString(execDmc.getThreadId())); } - IProcesses processService = getServicesTracker().getService(IProcesses.class); - final IThreadDMContext threadDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IThreadDMContext.class); - if (update.getProperties().contains(PROP_NAME) || - update.getProperties().contains(IGdbLaunchVMConstants.PROP_OS_ID)) + update.getProperties().contains(IGdbLaunchVMConstants.PROP_OS_ID) || + update.getProperties().contains(IGdbLaunchVMConstants.PROP_CORES_ID)) { - // - if (processService == null || threadDmc == null) { + IProcesses processService = getServicesTracker().getService(IProcesses.class); + final IThreadDMContext threadDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IThreadDMContext.class); + + if (processService == null || threadDmc == null) { update.setStatus(DsfUIPlugin.newErrorStatus(IDsfStatusConstants.INVALID_HANDLE, "Service or handle invalid", null)); //$NON-NLS-1$ } else { processService.getExecutionData( @@ -153,6 +156,20 @@ public class ThreadVMNode extends AbstractThreadVMNode update.setProperty(PROP_NAME, data.getName()); } update.setProperty(IGdbLaunchVMConstants.PROP_OS_ID, data.getId()); + + if (data instanceof IGdbThreadDMData) { + String[] cores = ((IGdbThreadDMData)data).getCores(); + if (cores != null) { + StringBuffer str = new StringBuffer(); + for (String core : cores) { + str.append(core + ","); //$NON-NLS-1$ + } + if (str.length() > 0) { + String coresStr = str.substring(0, str.length() - 1); + update.setProperty(IGdbLaunchVMConstants.PROP_CORES_ID, coresStr); + } + } + } } private String produceThreadElementName(String viewName, IMIExecutionDMContext execCtx) { diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_0.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_0.java index 1e19d6f476a..5d6d481e7c9 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_0.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_0.java @@ -75,10 +75,7 @@ import org.osgi.framework.BundleContext; /** * This class implements the IProcesses interface for GDB 7.0 - * Actually, I'm not sure what the next version of GDB will be, so technically, - * it is the one after GDB 6.8, as long as it contains multi-process support, - * which really mean it supports the new -list-thread-groups command. - * + * which supports the new -list-thread-groups command. */ public class GDBProcesses_7_0 extends AbstractDsfService implements IGDBProcesses, ICachingService, IEventListener { @@ -216,9 +213,10 @@ public class GDBProcesses_7_0 extends AbstractDsfService /** * Context representing a thread. + * @since 3.1 */ @Immutable - private static class MIThreadDMC extends AbstractDMContext + protected static class MIThreadDMC extends AbstractDMContext implements IThreadDMContext { /** diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_1.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_1.java new file mode 100644 index 00000000000..a91ee6140fa --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_1.java @@ -0,0 +1,238 @@ +/******************************************************************************* + * Copyright (c) 2010 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.cdt.dsf.gdb.service; + +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; +import org.eclipse.cdt.dsf.concurrent.Immutable; +import org.eclipse.cdt.dsf.concurrent.RequestMonitor; +import org.eclipse.cdt.dsf.datamodel.DMContexts; +import org.eclipse.cdt.dsf.datamodel.IDMContext; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerResumedDMEvent; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerSuspendedDMEvent; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IExitedDMEvent; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IResumedDMEvent; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IStartedDMEvent; +import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent; +import org.eclipse.cdt.dsf.debug.service.command.BufferedCommandControl; +import org.eclipse.cdt.dsf.debug.service.command.CommandCache; +import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext; +import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; +import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl; +import org.eclipse.cdt.dsf.mi.service.IMICommandControl; +import org.eclipse.cdt.dsf.mi.service.IMIProcessDMContext; +import org.eclipse.cdt.dsf.mi.service.command.CommandFactory; +import org.eclipse.cdt.dsf.mi.service.command.output.MIListThreadGroupsInfo; +import org.eclipse.cdt.dsf.mi.service.command.output.MIListThreadGroupsInfo.IThreadGroupInfo; +import org.eclipse.cdt.dsf.mi.service.command.output.MIListThreadGroupsInfo.IThreadGroupInfoExtension; +import org.eclipse.cdt.dsf.mi.service.command.output.MIThread; +import org.eclipse.cdt.dsf.mi.service.command.output.MIThreadInfoInfo; +import org.eclipse.cdt.dsf.service.DsfServiceEventHandler; +import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +/** + * This class implements the IProcesses interface for GDB 7.1 + * which provides new information about cores for threads and processes. + * + * @since 3.1 + */ +public class GDBProcesses_7_1 extends GDBProcesses_7_0 { + + @Immutable + protected static class MIThreadDMData_7_1 extends MIThreadDMData implements IGdbThreadDMData { + final String[] fCores; + + public MIThreadDMData_7_1(String name, String id, String[] cores) { + super(name, id); + fCores = cores; + } + + public String[] getCores() { return fCores; } + } + + private CommandFactory fCommandFactory; + // This cache is used when we send command to get the cores. + // The value of the cores can change at any time, but we provide + // an updated value whenever there is a suspended event. + private CommandCache fCommandForCoresCache; + private IGDBControl fCommandControl; + + public GDBProcesses_7_1(DsfSession session) { + super(session); + } + + @Override + public void initialize(final RequestMonitor requestMonitor) { + super.initialize(new RequestMonitor(getExecutor(), requestMonitor) { + @Override + protected void handleSuccess() { + doInitialize(requestMonitor); + } + }); + } + + /** + * This method initializes this service after our superclass's initialize() + * method succeeds. + * + * @param requestMonitor + * The call-back object to notify when this service's + * initialization is done. + */ + private void doInitialize(RequestMonitor requestMonitor) { + fCommandControl = getServicesTracker().getService(IGDBControl.class); + + // This caches stores the result of a command when received; also, this cache + // is manipulated when receiving events. Currently, events are received after + // three scheduling of the executor, while command results after only one. This + // can cause problems because command results might be processed before an event + // that actually arrived before the command result. + // To solve this, we use a bufferedCommandControl that will delay the command + // result by two scheduling of the executor. + // See bug 280461 + fCommandForCoresCache = new CommandCache(getSession(), + new BufferedCommandControl(fCommandControl, getExecutor(), 2)); + fCommandForCoresCache.setContextAvailable(fCommandControl.getContext(), true); + + fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory(); + getSession().addServiceEventListener(this, null); + + requestMonitor.done(); + } + + @Override + public void shutdown(RequestMonitor requestMonitor) { + getSession().removeServiceEventListener(this); + + super.shutdown(requestMonitor); + } + + @Override + public void getExecutionData(final IThreadDMContext dmc, final DataRequestMonitor rm) { + if (dmc instanceof IMIProcessDMContext) { + // Starting with GDB 7.1, we can obtain the list of cores a process is currently + // running on (each core that has a thread of that process). + // We have to use -list-thread-groups to obtain that information + super.getExecutionData(dmc, new DataRequestMonitor(ImmediateExecutor.getInstance(), rm) { + @Override + protected void handleSuccess() { + final IThreadDMData firstLevelData = getData(); + + ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, ICommandControlDMContext.class); + final String groupId = ((IMIProcessDMContext)dmc).getProcId(); + fCommandForCoresCache.execute( + fCommandFactory.createMIListThreadGroups(controlDmc), + new DataRequestMonitor(ImmediateExecutor.getInstance(), rm) { + @Override + protected void handleCompleted() { + String[] cores = null; + if (isSuccess()) { + IThreadGroupInfo[] groups = getData().getGroupList(); + if (groups != null) { + for (IThreadGroupInfo group : groups) { + if (group.getGroupId().equals(groupId)) { + if (group instanceof IThreadGroupInfoExtension) { + cores = ((IThreadGroupInfoExtension)group).getCores(); + } + break; + } + } + } + } + rm.setData(new MIThreadDMData_7_1(firstLevelData.getName(), + firstLevelData.getId(), + cores)); + rm.done(); + } + }); + } + }); + } else if (dmc instanceof MIThreadDMC) { + // Starting with GDB 7.1, we can obtain the core on which a thread + // is currently located. The info is a new field in -thread-info + final MIThreadDMC threadDmc = (MIThreadDMC)dmc; + + ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, ICommandControlDMContext.class); + fCommandForCoresCache.execute(fCommandFactory.createMIThreadInfo(controlDmc, threadDmc.getId()), + new DataRequestMonitor(ImmediateExecutor.getInstance(), rm) { + @Override + protected void handleSuccess() { + IThreadDMData threadData = null; + if (getData().getThreadList().length != 0) { + MIThread thread = getData().getThreadList()[0]; + if (thread.getThreadId().equals(threadDmc.getId())) { + String core = thread.getCore(); + threadData = new MIThreadDMData_7_1("", thread.getOsId(), //$NON-NLS-1$ + core == null ? null : new String[] { core }); + } + } + + if (threadData != null) { + rm.setData(threadData); + } else { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Could not get thread info", null)); //$NON-NLS-1$ + } + rm.done(); + } + }); + } else { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } + + @DsfServiceEventHandler + public void eventDispatched_7_1(IResumedDMEvent e) { + if (e instanceof IContainerResumedDMEvent) { + // This will happen in all-stop mode + fCommandForCoresCache.setContextAvailable(e.getDMContext(), false); + } else { + // This will happen in non-stop mode + // Keep target available for Container commands + } + } + + // Something has suspended, core allocation could have changed + // during the time it was running. + @DsfServiceEventHandler + public void eventDispatched_7_1(ISuspendedDMEvent e) { + if (e instanceof IContainerSuspendedDMEvent) { + // This will happen in all-stop mode + fCommandForCoresCache.setContextAvailable(fCommandControl.getContext(), true); + } else { + // This will happen in non-stop mode + } + + fCommandForCoresCache.reset(); + } + + // Event handler when a thread or threadGroup starts, core allocation + // could have changed + @DsfServiceEventHandler + public void eventDispatched_7_1(IStartedDMEvent e) { + fCommandForCoresCache.reset(); + } + + // Event handler when a thread or a threadGroup exits, core allocation + // could have changed + @DsfServiceEventHandler + public void eventDispatched_7_1(IExitedDMEvent e) { + fCommandForCoresCache.reset(); + } + + @Override + public void flushCache(IDMContext context) { + fCommandForCoresCache.reset(context); + super.flushCache(context); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java index c4d8515845c..0bc2fc6befc 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java @@ -44,6 +44,7 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory { // This should eventually be "7.0" once GDB 7.0 is released private static final String GDB_7_0_VERSION = "6.8.50.20090218"; //$NON-NLS-1$ + private static final String GDB_7_1_VERSION = "7.1"; //$NON-NLS-1$ private static final String GDB_7_2_VERSION = "7.1.50"; //$NON-NLS-1$ private final String fVersion; @@ -133,6 +134,9 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory { @Override protected IProcesses createProcessesService(DsfSession session) { + if (GDB_7_1_VERSION.compareTo(fVersion) <= 0) { + return new GDBProcesses_7_1(session); + } if (GDB_7_0_VERSION.compareTo(fVersion) <= 0) { return new GDBProcesses_7_0(session); } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBProcesses.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBProcesses.java index 9d4cfb2aecb..8705a8b2053 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBProcesses.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBProcesses.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2009 Ericsson and others. + * Copyright (c) 2008, 2010 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 @@ -7,6 +7,7 @@ * * Contributors: * Ericsson - initial API and implementation + * Ericsson - added support for core-awareness *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.service; @@ -15,6 +16,24 @@ import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext; import org.eclipse.cdt.dsf.mi.service.IMIProcesses; public interface IGDBProcesses extends IMIProcesses { + + /** + * This interface extends the DSF ThreadDMData to provide + * the cores on which a process or a thread is located. + * + * @since 3.1 + */ + public interface IGdbThreadDMData extends IThreadDMData { + /** + * @return The list of identifiers of the cores on which the thread + * or process is currently located. A thread will typically + * be located on a single core at a time, while a process will + * be located on all cores on which one of the process' threads + * is located. Returns null if the information is not available. + */ + String[] getCores(); + } + /** * Get a list of all execution contexts belonging to a container. This call is synchronous, * unlike the call to getProcessesBeingDebugged(). However, some services may not be able diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MIListThreadGroupsInfo.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MIListThreadGroupsInfo.java index 59a029d2db1..a9e3133afb1 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MIListThreadGroupsInfo.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MIListThreadGroupsInfo.java @@ -158,9 +158,16 @@ public class MIListThreadGroupsInfo extends MIInfo { String getName(); String getDesciption(); } + + /** + * @since 3.1 + */ + public interface IThreadGroupInfoExtension extends IThreadGroupInfo { + String[] getCores(); + } @Immutable - private static class ThreadGroupInfo implements IThreadGroupInfo { + private static class ThreadGroupInfo implements IThreadGroupInfoExtension { final String fGroupId; final String fDescription; final String fName; @@ -208,6 +215,7 @@ public class MIListThreadGroupsInfo extends MIInfo { public String getName() { return fName; } public String getDesciption() { return fDescription; } + public String[] getCores() { return fCores; } // The following are not used yet, but it's good to keep // them as a way to document what is available from GDB. @@ -216,8 +224,6 @@ public class MIListThreadGroupsInfo extends MIInfo { @SuppressWarnings("unused") public String getUser() { return fUser; } @SuppressWarnings("unused") - public String[] getCores() { return fCores; } - @SuppressWarnings("unused") public String getExecutable() { return fExecutable; } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MIThread.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MIThread.java index dacacb6ce2f..456efac4d8e 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MIThread.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MIThread.java @@ -56,7 +56,7 @@ public class MIThread { * Available since GDB 7.1 * @since 3.1 */ - public String getCore() { return fCore; } + public String getCore() { return fCore; } public static MIThread parse(MITuple tuple) { MIResult[] results = tuple.getMIResults();