diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/CoreInfo.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/CoreInfo.java new file mode 100644 index 00000000000..726a6fd47e6 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/CoreInfo.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2012 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: + * Marc Khouzam (Ericsson) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.internal; + +import org.eclipse.cdt.internal.core.ICoreInfo; + +public class CoreInfo implements ICoreInfo { + private String fId; + private String fPhysicalId; + + public CoreInfo(String id, String pId) { + fId = id; + fPhysicalId = pId; + } + + @Override + public String getId() { + return fId; + } + + @Override + public String getPhysicalId() { + return fPhysicalId; + } +} \ No newline at end of file diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/CoreList.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/CoreList.java index 45e57f2ed43..55007d29bb0 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/CoreList.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/CoreList.java @@ -24,26 +24,6 @@ import org.eclipse.cdt.internal.core.ICoreInfo; */ public class CoreList { - private class CoreInfo implements ICoreInfo { - private String fId; - private String fPhysicalId; - - public CoreInfo(String id, String pId) { - fId = id; - fPhysicalId = pId; - } - - @Override - public String getId() { - return fId; - } - - @Override - public String getPhysicalId() { - return fPhysicalId; - } - } - private ICoreInfo[] fCoreList; private String fCoreFileName; diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBHardware.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBHardware.java index c4c93231669..48d0a69d9ce 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBHardware.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBHardware.java @@ -12,8 +12,11 @@ package org.eclipse.cdt.dsf.gdb.service; import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; import java.util.HashSet; import java.util.Hashtable; +import java.util.List; import java.util.Set; import java.util.Vector; @@ -36,6 +39,7 @@ import org.eclipse.cdt.dsf.debug.service.command.ICommandListener; import org.eclipse.cdt.dsf.debug.service.command.ICommandResult; import org.eclipse.cdt.dsf.debug.service.command.ICommandToken; import org.eclipse.cdt.dsf.debug.service.command.IEventListener; +import org.eclipse.cdt.dsf.gdb.internal.CoreInfo; import org.eclipse.cdt.dsf.gdb.internal.CoreList; import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; import org.eclipse.cdt.dsf.gdb.internal.service.command.commands.MIMetaGetCPUInfo; @@ -44,6 +48,8 @@ import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl; import org.eclipse.cdt.dsf.mi.service.IMICommandControl; import org.eclipse.cdt.dsf.mi.service.command.CommandFactory; import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; +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.service.AbstractDsfService; import org.eclipse.cdt.dsf.service.DsfServiceEventHandler; import org.eclipse.cdt.dsf.service.DsfSession; @@ -378,6 +384,7 @@ public class GDBHardware extends AbstractDsfService implements IGDBHardware, ICa * information we need. */ private class CPUInfoManager implements ICommandControl { + private final List fCommandProcessors = new ArrayList(); @Override public ICommandToken queueCommand(final ICommand command, DataRequestMonitor rm) { @@ -389,6 +396,11 @@ public class GDBHardware extends AbstractDsfService implements IGDBHardware, ICa } }; + // The class does not buffer commands itself, but sends them directly to the real + // MICommandControl service. Therefore, we must immediately tell our calling cache that the command + // has been sent, since we can never cancel it. + processCommandSent(token); + if (command instanceof MIMetaGetCPUInfo) { @SuppressWarnings("unchecked") final DataRequestMonitor drm = (DataRequestMonitor)rm; @@ -407,12 +419,54 @@ public class GDBHardware extends AbstractDsfService implements IGDBHardware, ICa // Now that we processed the file, remove it to avoid polluting the file system new File(localFile).delete(); drm.done(new MIMetaGetCPUInfoInfo(info)); + processCommandDone(token, drm.getData()); + } + @Override + protected void handleError() { + // On some older linux versions, gdbserver is not able to read from /proc + // because it is a pseudo filesystem. + // We need to find some other method of getting the info we need. + + // For a remote session, we can use GDB's -list-thread-groups --available + // command, which shows on which cores a process is running. This does + // not necessarily give the exhaustive list of cores, but that is the best + // we have in this case. + // + // In this case, we don't have knowledge about CPUs, so we lump all cores + // into a single CPU. + + fCommandControl.queueCommand( + fCommandFactory.createMIListThreadGroups(dmc, true), + new ImmediateDataRequestMonitor(drm) { + @Override + protected void handleSuccess() { + // First extract the string id for every core GDB reports + Set coreIds = new HashSet(); + IThreadGroupInfo[] groups = getData().getGroupList(); + for (IThreadGroupInfo group : groups) { + coreIds.addAll(Arrays.asList(group.getCores())); + } + + // Now create the context for each distinct core + // + // We don't have CPU info in this case so let's put them all under a single CPU + final String defaultCPUId = "0"; //$NON-NLS-1$ + ICoreInfo[] info = new ICoreInfo[coreIds.size()]; + int i = 0; + for (String id : coreIds) { + info[i++] = new CoreInfo(id, defaultCPUId); + } + drm.done(new MIMetaGetCPUInfoInfo(info)); + processCommandDone(token, drm.getData()); + } + }); } }); } else { // For a local session, parse /proc/cpuinfo directly. ICoreInfo[] info = new CoreList("/proc/cpuinfo").getCoreList(); //$NON-NLS-1$ drm.done(new MIMetaGetCPUInfoInfo(info)); + processCommandDone(token, drm.getData()); } } else { rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, @@ -422,11 +476,26 @@ public class GDBHardware extends AbstractDsfService implements IGDBHardware, ICa return token; } + // Need to support these as they are used by the commandCache @Override - public void addCommandListener(ICommandListener processor) { assert false : "Not supported"; } //$NON-NLS-1$ + public void addCommandListener(ICommandListener processor) { fCommandProcessors.add(processor); } + @Override + public void removeCommandListener(ICommandListener processor) { fCommandProcessors.remove(processor); } + + + private void processCommandSent(ICommandToken token) { + for (ICommandListener processor : fCommandProcessors) { + processor.commandSent(token); + } + } + + private void processCommandDone(ICommandToken token, ICommandResult result) { + for (ICommandListener processor : fCommandProcessors) { + processor.commandDone(token, result); + } + } + @Override - public void removeCommandListener(ICommandListener processor) { assert false : "Not supported"; } //$NON-NLS-1$ - @Override public void addEventListener(IEventListener processor) { assert false : "Not supported"; } //$NON-NLS-1$ @Override public void removeEventListener(IEventListener processor) { assert false : "Not supported"; } //$NON-NLS-1$