From f4953626d5a8db84aea98ae2e2624dac3dde36f8 Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Mon, 28 Jun 2010 19:38:26 +0000 Subject: [PATCH] Bug 318230: Add infrastructure to read the new core field from the -list-thread-groups and -thread-info commands --- .../command/commands/MIListThreadGroups.java | 26 ++- .../output/MIListThreadGroupsInfo.java | 202 +++++++++++++++++- .../mi/service/command/output/MIThread.java | 22 +- .../command/output/MIThreadInfoInfo.java | 15 +- 4 files changed, 250 insertions(+), 15 deletions(-) diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIListThreadGroups.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIListThreadGroups.java index a4c5f583353..d08be578832 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIListThreadGroups.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIListThreadGroups.java @@ -17,7 +17,7 @@ import org.eclipse.cdt.dsf.mi.service.command.output.MIListThreadGroupsInfo; import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput; /** - * -list-thread-groups [--available | GROUP] + * -list-thread-groups [--available | GROUP] [ --recurse 1 ] * * When used without GROUP parameter, this will list top-level * thread groups that are being debugged. When used with the GROUP @@ -37,9 +37,31 @@ import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput; * * where each thread group is like this: * - * {id="xxx",type="process",pid="yyy",num_children="1"} + * {id="xxx",type="process",pid="yyy",num_children="1",cores=[1,2]} * * The id of a thread group should be considered an opaque string. + * + * As of GDB 7.1, the --recurse option has been added. If this option is + * present, then every reported thread group will also include its children, + * either as `group' or `threads' field. + * + * In general, any combination of option and parameters is permitted, with + * the following caveats: + * - When a single thread group is passed, the output will typically be the + * `threads' result. Because threads may not contain anything, the + * `recurse' option will be ignored. + * - When the `--available' option is passed, limited information may be + * available. In particular, the list of threads of a process might be + * inaccessible. Further, specifying specific thread groups might not give + * any performance advantage over listing all thread groups. The frontend + * should assume that `-list-thread-groups --available' is always an + * expensive operation and cache the results. + * + * As of GDB 7.1, the 'core' output field has been added. + * - cores This field is a list of integers, each identifying a core that one + * thread of the group is running on. This field may be absent if such + * information is not available. + * * @since 1.1 * */ 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 a03a7e9e8d4..7bad1d93943 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 @@ -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 @@ -11,6 +11,8 @@ package org.eclipse.cdt.dsf.mi.service.command.output; +import java.util.ArrayList; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -28,14 +30,126 @@ import org.eclipse.cdt.dsf.concurrent.Immutable; * {id="166",type="process",description="name: JUnitProcess_PT, type 1094605, locked: N, system: N, state: Idle"}] * * {id="3602",type="process",description="/usr/sbin/dhcdbd --system",user="root"} + * * -list-thread-groups: * ^done,groups=[{id="162",type="process",pid="162"}] * - * 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 Idle 981333916 42692",state="running"}] + * + * As of GDB 7.1, a new 'core' output field has been added. This field is a list + * of integers, each identifying a core that one thread of the group is running on. + * This field may be absent if such information is not available. + * + * -list-thread-groups + * ^done,groups=[{id="12779",type="process",pid="12779",cores=["3"]}] + * + * -list-thread-groups 12779 + * ^done,threads=[{id="10", + * target-id="Thread 0xb3d58ba0 (LWP 12876)", + * frame={level="0",addr="0xb7e21b88",func="clone",args=[],from="/lib/libc.so.6"}, + * state="stopped", + * core="3"}, + * {id="3", + * target-id="Thread 0xb755fba0 (LWP 12811)", + * frame={level="0",addr="0xffffe410",func="__kernel_vsyscall",args=[]}, + * state="stopped", + * core="3"}, + * {id="2", + * target-id="Thread 0xb7d60ba0 (LWP 12810)", + * frame={level="0",addr="0xffffe410",func="__kernel_vsyscall",args=[]}, + * state="stopped", + * core="3"}, + * {id="1", + * target-id="Thread 0xb7d616b0 (LWP 12779)", + * frame={level="0",addr="0x08048609",func="main",args=[],file="../src/NonStop.cpp",fullname="/local/runtime-TestDSF/NonStop/src/NonStop.cpp",line="44"}, + * state="stopped", + * core="3"}] + * + * As of GDB 7.1, the --recurse option has been added and causes a different output + * + * -list-thread-groups --recurse 1 + * ^done,groups=[{id="12779", + * type="process", + * pid="12779", + * cores=["3"], + * threads=[{id="10", + * target-id="Thread 0xb3d58ba0 (LWP 12876)", + * frame={level="0",addr="0xb7e21b88",func="clone",args=[],from="/lib/libc.so.6"}, + * state="stopped", + * core="3"}, + * {id="3", + * target-id="Thread 0xb755fba0 (LWP 12811)", + * frame={level="0",addr="0xffffe410",func="__kernel_vsyscall",args=[]}, + * state="stopped", + * core="3"}, + * {id="2", + * target-id="Thread 0xb7d60ba0 (LWP 12810)", + * frame={level="0",addr="0xffffe410",func="__kernel_vsyscall",args=[]}, + * state="stopped", + * core="3"}, + * {id="1", + * target-id="Thread 0xb7d616b0 (LWP 12779)", + * frame={level="0",addr="0x08048609",func="main",args=[],file="../src/NonStop.cpp",fullname="/local/runtime-TestDSF/NonStop/src/NonStop.cpp",line="44"}, + * state="stopped", + * core="3"} + * ] + * }] + * + * Example of outputs by version on Linux + * + * GDB 7.0 + * + * (when no inferior is running) + * -list-thread-groups + * ^done,groups=[] + * + * (with an inferior running) + * -list-thread-groups + * ^done,groups=[{id="19386",type="process",pid="19386"}] + * + * -list-thread-groups 19386 + * ^done,threads=[{id="1",target-id="process 19386",frame={level="0",addr="0x08048618",func="main",args=[],file="a.cc",fullname="/local/lmckhou/testing/a.cc",line="9"},state="stopped"}] + * + * -list-thread-groups --available + * ^done,groups=[{id="19371",type="process",description="gdb.7.0 -i mi testing/a.out",user="lmckhou"},{id="19386",type="process",description="/local/lmckhou/testing/a.out",user="lmckhou"},{id="19413",type="process",description="sleep 5",user="lmckhou"}] + * + * GDB 7.1 + * + * (when no inferior is running) + * -list-thread-groups + * ^done,groups=[{id="0",type="process",pid="0"}] + * + * (with an inferior running) + * -list-thread-groups + * ^done,groups=[{id="19424",type="process",pid="19424",cores=["3"]}] + * + * -list-thread-groups 19424 + * ^done,threads=[{id="1",target-id="process 19424",frame={level="0",addr="0x08048618",func="main",args=[],file="a.cc",fullname="/local/lmckhou/testing/a.cc",line="9"},state="stopped",core="3"}] + * + * -list-thread-groups --available + * ^done,groups=[{id="19418",type="process",description="gdb.7.1 -i mi testing/a.out",user="lmckhou"},{id="19424",type="process",description="/local/lmckhou/testing/a.out",user="lmckhou"},{id="19438",type="process",description="sleep 5",user="lmckhou"}] + * + * GDB 7.2 + * + * (when no inferior is running) + * -list-thread-groups + * ^done,groups=[{id="i1",type="process",executable="/local/lmckhou/testing/a.out"}] + * + * (with an inferior running) + * -list-thread-groups + * ^done,groups=[{id="i1",type="process",pid="19451",executable="/local/lmckhou/testing/a.out",cores=["2"]}] + * + * -list-thread-groups i1 + * ^done,threads=[{id="1",target-id="process 19451",frame={level="0",addr="0x08048618",func="main",args=[],file="a.cc",fullname="/local/lmckhou/testing/a.cc",line="9"},state="stopped",core="2"}] + * + * -list-thread-groups --available + * ^done,groups=[{id="19445",type="process",description="gdb.7.2 -i mi testing/a.out",user="lmckhou"},{id="19451",type="process",description="/local/lmckhou/testing/a.out",user="lmckhou"},{id="19462",type="process",description="sleep 5",user="lmckhou"}] + * * @since 1.1 */ + public class MIListThreadGroupsInfo extends MIInfo { public interface IThreadGroupInfo { @@ -50,11 +164,23 @@ public class MIListThreadGroupsInfo extends MIInfo { final String fGroupId; final String fDescription; final String fName; + final String fType; + final String fUser; + final String fPid; + final String[] fCores; + final String fExecutable; - public ThreadGroupInfo(String id, String description) { + public ThreadGroupInfo(String id, String description, String type, String pid, + String user, String[] cores, String exec) { fGroupId = id; fDescription = description; - + fType = type; + fUser = user; + fPid = pid; + fCores = cores; + + fExecutable = exec; + fName = parseName(fDescription); } @@ -77,11 +203,22 @@ public class MIListThreadGroupsInfo extends MIInfo { } public String getGroupId() { return fGroupId; } - public String getPid() { return fGroupId; } + public String getPid() { return fPid; } public String getName() { return fName; } public String getDesciption() { return fDescription; } + + // The following are not used yet, but it's good to keep + // them as a way to document what is available from GDB. + @SuppressWarnings("unused") + public String getType() { return fType; } + @SuppressWarnings("unused") + public String getUser() { return fUser; } + @SuppressWarnings("unused") + public String[] getCores() { return fCores; } + @SuppressWarnings("unused") + public String getExecutable() { return fExecutable; } } @@ -129,7 +266,10 @@ public class MIListThreadGroupsInfo extends MIInfo { fGroupList = new IThreadGroupInfo[values.length]; for (int i = 0; i < values.length; i++) { MIResult[] results = ((MITuple)values[i]).getMIResults(); - String id = "", desc = "";//$NON-NLS-1$//$NON-NLS-2$ + String id, desc, type, pid, exec, user; + id = desc = type = pid = exec = user = "";//$NON-NLS-1$ + + String[] cores = null; for (MIResult result : results) { String var = result.getVariable(); @@ -144,11 +284,57 @@ public class MIListThreadGroupsInfo extends MIInfo { if (value instanceof MIConst) { String str = ((MIConst)value).getCString(); desc = str.trim(); - + } + } else if (var.equals("type")) { //$NON-NLS-1$ + MIValue value = result.getMIValue(); + if (value instanceof MIConst) { + String str = ((MIConst)value).getCString(); + type = str.trim(); + } + } else if (var.equals("pid")) { //$NON-NLS-1$ + MIValue value = result.getMIValue(); + if (value instanceof MIConst) { + String str = ((MIConst)value).getCString(); + pid = str.trim(); + } + } else if (var.equals("user")) { //$NON-NLS-1$ + MIValue value = result.getMIValue(); + if (value instanceof MIConst) { + String str = ((MIConst)value).getCString(); + user = str.trim(); + } + } else if (var.equals("cores")) { //$NON-NLS-1$ + // Staring with GDB 7.1 + MIValue value = result.getMIValue(); + if (value instanceof MIList) { + cores = parseCores((MIList)value); + } + } else if (var.equals("executable")) { //$NON-NLS-1$ + // Staring with GDB 7.2 + MIValue value = result.getMIValue(); + if (value instanceof MIConst) { + String str = ((MIConst)value).getCString(); + exec = str.trim(); } } } - fGroupList[i] = new ThreadGroupInfo(id, desc); + // In the case of -list-thread-groups --available, we can use the id as the pid + if (pid.equals("")) { //$NON-NLS-1$ + pid = id; + } + fGroupList[i] = new ThreadGroupInfo(id, desc, type, pid, user, cores, exec); } } + + private String[] parseCores(MIList list) { + List cores = new ArrayList(); + + MIValue[] values = list.getMIValues(); + for (int i = 0; i < values.length; i++) { + if (values[i] instanceof MIConst) { + cores.add(((MIConst)values[i]).getCString()); + } + } + return cores.toArray(new String[cores.size()]); + } } 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 f976ea154eb..dacacb6ce2f 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 @@ -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 @@ -28,12 +28,13 @@ public class MIThread { final private String fTargetId; final private String fOsId; final private String fParentId; - final private MIFrame fTopFrame; + final private MIFrame fTopFrame; final private String fDetails; final private String fState; + final private String fCore; private MIThread(String threadId, String targetId, String osId, String parentId, - MIFrame topFrame, String details, String state) { + MIFrame topFrame, String details, String state, String core) { fThreadId = threadId; fTargetId = targetId; fOsId = osId; @@ -41,6 +42,7 @@ public class MIThread { fTopFrame = topFrame; fDetails = details; fState = state; + fCore = core; } public String getThreadId() { return fThreadId; } @@ -50,6 +52,11 @@ public class MIThread { public MIFrame getTopFrame() { return fTopFrame; } public String getDetails() { return fDetails; } public String getState() { return fState; } + /** + * Available since GDB 7.1 + * @since 3.1 + */ + public String getCore() { return fCore; } public static MIThread parse(MITuple tuple) { MIResult[] results = tuple.getMIResults(); @@ -61,6 +68,7 @@ public class MIThread { MIFrame topFrame = null; String state = null; String details = null; + String core = null; for (int j = 0; j < results.length; j++) { MIResult result = results[j]; @@ -95,9 +103,15 @@ public class MIThread { details = ((MIConst) val).getCString().trim(); } } + else if (var.equals("core")) { //$NON-NLS-1$ + MIValue val = results[j].getMIValue(); + if (val instanceof MIConst) { + core = ((MIConst) val).getCString().trim(); + } + } } - return new MIThread(threadId, targetId, osId, parentId, topFrame, details, state); + return new MIThread(threadId, targetId, osId, parentId, topFrame, details, state, core); } private static Pattern fgOsIdPattern1 = Pattern.compile("(Thread\\s*)(0x[0-9a-fA-F]+|-?\\d+)(\\s*\\(LWP\\s*)(\\d*)", 0); //$NON-NLS-1$ diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MIThreadInfoInfo.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MIThreadInfoInfo.java index 295699e2e3d..9163acd275e 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MIThreadInfoInfo.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MIThreadInfoInfo.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 @@ -69,6 +69,19 @@ package org.eclipse.cdt.dsf.mi.service.command.output; * 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"}] + * + * With GDB 7.1, a new 'core' field is present to indicate which core the thread is on. + * The parsing of this new field is handled by {@link MIThread} + * + * -thread-info + * ^done,threads=[ + * {id="1",target-id="process 1307", + * frame={level="0",addr="0x08048618",func="main",args=[], + * file="a.cc",fullname="/local/lmckhou/testing/a.cc",line="9"}, + * state="stopped", + * core="2"}], + * current-thread-id="1" + * * @since 1.1 */ public class MIThreadInfoInfo extends MIInfo {