Thread Analysis : thread function name and thread class name is shown in the thread... 54/23254/1
authorwoojin <woojin2.jung@samsung.com>
Fri, 20 Jun 2014 11:15:34 +0000 (20:15 +0900)
committerwoojin <woojin2.jung@samsung.com>
Fri, 20 Jun 2014 11:15:34 +0000 (20:15 +0900)
Show thread class name for Tizen Thread.
Show thread function name for other thread (e.g. pthread).

Change-Id: I6a1f8312f3cda5527e4c04dfb543453753f2f0f0
Signed-off-by: woojin <woojin2.jung@samsung.com>
org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/common/SymbolManager.java
org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/nl/ThreadPageLabels.java
org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/nl/ThreadPageLabels.properties
org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/swap/logparser/SWAPLogParser.java
org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/swap/model/data/ThreadData.java
org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/thread/ThreadDetailInfoView.java
org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/thread/thread/ThreadPageThreadData.java
org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/thread/thread/ThreadPageThreadDataManager.java

index 74036b5..9d934d3 100644 (file)
@@ -30,7 +30,9 @@ import java.io.File;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.lang.ref.WeakReference;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfDebugInfoProviderFactory;
@@ -52,6 +54,14 @@ import org.eclipse.cdt.utils.elf.Elf.Symbol;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.Path;
 import org.tizen.dynamicanalyzer.nl.AnalyzerLabels;
+import org.tizen.dynamicanalyzer.nl.InformationViewLabels;
+import org.tizen.dynamicanalyzer.swap.channel.control.BinaryInfo;
+import org.tizen.dynamicanalyzer.swap.channel.data.ApiNameManager;
+import org.tizen.dynamicanalyzer.swap.channel.data.LibraryObject;
+import org.tizen.dynamicanalyzer.swap.channel.data.ProcessInfo;
+import org.tizen.dynamicanalyzer.swap.channel.data.ProcessInfoPackage;
+import org.tizen.dynamicanalyzer.swap.model.data.ProfileData;
+import org.tizen.dynamicanalyzer.swap.platform.BinarySettingManager;
 import org.tizen.dynamicanalyzer.util.DALogger;
 
 public class SymbolManager {
@@ -316,4 +326,141 @@ public class SymbolManager {
                }
                return demangled;
        }
+       
+
+       /**
+        * getFuncName : returns function name from pc address, pid, time
+        * and set build type and binary path for ProfileData
+        * @param input : can be null. If not null, set build type and binary path for ProfileData
+        * @param address : pc address
+        * @param pid : process id
+        * @param time : time stamp of the function call
+        * @return : function name
+        */
+       // TODO: remove unnecessary code
+       public static String getFuncName(ProfileData input, long address, int pid, long time) {
+               HashMap<Long, String> funcNameMap = AnalyzerManager
+                               .getFuncNameMapByPid(pid);
+               String functionName = funcNameMap.get(address);
+               if (null != functionName) {
+                       return functionName;
+               }
+
+               ProcessInfoPackage processInfoPkg = AnalyzerManager.getProject()
+                               .getProcessInfoPackage(pid);
+               ProcessInfo processInfo = processInfoPkg
+                               .getProcessInfo(time);
+
+               /** for debug */
+               BinaryInfo binInfo1 = processInfo.getTargetBinary(address);
+               if (binInfo1 == null) {
+                       // System.out.println("[Get functino name bug : "
+                       // + "Can't find binary info]");
+                       // System.out
+                       // .println("msg id : "
+                       // + AnalyzerUtil.toHexdecimal(input.getId())
+                       // + " pid : "
+                       // + processInfo.getPid()
+                       // + " low : "
+                       // + AnalyzerUtil.toHexdecimal(processInfo
+                       // .getLowestAddress())
+                       // + " input addr : "
+                       // + AnalyzerUtil.toHexdecimal(input.getPcAddr())
+                       // + "  high : "
+                       // + AnalyzerUtil.toHexdecimal(processInfo
+                       // .getHighestAddress()));
+                       return null;
+               }
+               // String binPath1 = binInfo1.getTargetBinaryPath();
+               // System.out.print("binary : " + binPath1 + " ==> ");
+               // AnalyzerUtil.printHexdecimal(processInfo.getLowestAddress());
+               // System.out.print(" < ");
+               // AnalyzerUtil.printHexdecimal(pcAddr);
+               // System.out.print(" < ");
+               // AnalyzerUtil.printHexdecimal(processInfo.getHighestAddress());
+               // System.out.println();
+
+               if (address >= processInfo.getLowestAddress()
+                               && address <= processInfo.getHighestAddress()) {
+                       String baseAddr = Long.toString(processInfo.getLowestAddress());
+                       String pcStr = Long.toString(address);
+                       BinaryInfo binInfo = processInfo.getTargetBinary(address);
+                       String localPath = binInfo.getTempBinaryPath();
+                       if (null != input) {
+                               input.setBuildType(binInfo.getType());
+                               input.setBinaryPath(binInfo.getTargetBinaryPath());
+                       }
+                       boolean isPieBuild = true;
+                       if (binInfo.getType() != 1) {
+                               isPieBuild = false;
+                       }
+                       functionName = addr2func(localPath, pcStr, isPieBuild, baseAddr);
+               } else {
+                       HashMap<String, BinaryInfo> binInfoMap = BinarySettingManager
+                                       .getInstance().getTargetBinInfoMap();
+                       List<String> binPaths = new ArrayList<String>();
+                       binPaths.addAll(binInfoMap.keySet());
+
+                       HashMap<String, LibraryObject> libHash = processInfo
+                                       .getLibObjHash();
+                       LibraryObject libraryObject = null;
+                       int size = binPaths.size();
+                       for (int i = 0; i < size; i++) {
+                               String binPath = binPaths.get(i);
+                               LibraryObject libObj = libHash.get(binPath);
+                               if (null == libObj) {
+                                       continue;
+                               }
+                               long lowAddr = libObj.getLowestAddress();
+                               long highAddr = libObj.getHighestAddress();
+
+                               /** for debug */
+                               // if (lowAddr > pcAddr || highAddr < pcAddr) {
+                               // System.out.print(input.getId() + " lib : " + binPath
+                               // + " ==> ");
+                               // AnalyzerUtil.printHexdecimal(lowAddr);
+                               // System.out.print(" < ");
+                               // AnalyzerUtil.printHexdecimal(pcAddr);
+                               // System.out.print(" < ");
+                               // AnalyzerUtil.printHexdecimal(highAddr);
+                               // System.out.println();
+                               // }
+
+                               if (address >= lowAddr && address <= highAddr) {
+                                       libraryObject = libObj;
+                                       break;
+                               }
+                       }
+                       if (null != libraryObject) {
+                               String path = libraryObject.getLibPath();
+                               BinaryInfo binInfo = binInfoMap.get(path);
+                               if (null != binInfo) {
+                                       String localPath = binInfo.getTempBinaryPath();
+                                       String baseAddr = Long.toString(libraryObject
+                                                       .getLowestAddress());
+                                       String pcStr = Long.toString(address);
+                                       if (null != input) {
+                                               input.setBinaryPath(binInfo.getTargetBinaryPath());
+                                       }
+                                       boolean isPieBuild = true;
+                                       if (binInfo.getType() != 1) {
+                                               isPieBuild = false;
+                                       }
+                                       functionName = addr2func(localPath, pcStr, isPieBuild, baseAddr);
+                               }
+                       }
+               }
+
+               if (null == functionName || functionName.isEmpty()
+                               || functionName.equals("_end")) { //$NON-NLS-1$
+                       functionName = InformationViewLabels.CALLSTACK_TABLE_UNKNOWN_FUNCTION;
+                       ApiNameManager.getApiId(functionName);
+               } else {
+                       String prevFunctionName = functionName;
+                       functionName = demanglingFunctionName(prevFunctionName);
+                       ApiNameManager.getApiId(functionName);
+               }
+               funcNameMap.put(address, functionName);
+               return functionName;
+       }
 }
index 0b9a376..9c7bb2e 100644 (file)
@@ -101,6 +101,8 @@ public class ThreadPageLabels extends NLS {
        public static String THREAD_DETAILS_TID;
        public static String THREAD_DETAILS_TTYPE;
        public static String THREAD_DETAILS_TATTRTYPE;
+       public static String THREAD_DETAILS_FUNCNAME;
+       public static String THREAD_DETAILS_CLASSNAME;
        public static String THREAD_DETAILS_STARTTIME;
        public static String THREAD_DETAILS_ENDTIME;
        
index 40960ee..c72030e 100644 (file)
@@ -64,9 +64,11 @@ THREAD_API_LIST_VIEW_THREAD_ID=TID
 THREAD_API_LIST_VIEW_RETURN=Return
 THREAD_API_LIST_VIEW_ERRNO=Error Code
 
-THREAD_DETAILS_TID=Thread ID :
+THREAD_DETAILS_TID=Thread ID : 
 THREAD_DETAILS_TTYPE=Type : 
 THREAD_DETAILS_TATTRTYPE=Attr Type : 
+THREAD_DETAILS_FUNCNAME=Thread Function : 
+THREAD_DETAILS_CLASSNAME=Thread Class : 
 THREAD_DETAILS_STARTTIME=Start Time : 
 THREAD_DETAILS_ENDTIME=End Time : 
 
index a5c4d93..92cdca2 100755 (executable)
@@ -144,7 +144,6 @@ public class SWAPLogParser implements Runnable {
                        }
                        LogData log = logLumb.get(i);
                        int id = log.getId();
-                       int seqNum = log.getSeq();
                        if (log instanceof SystemData) {
                                // System.out
                                // .println("=========systemData is slicing===========\n");
@@ -165,9 +164,13 @@ public class SWAPLogParser implements Runnable {
                                                                .getProject().getProcessInfoPackage(pData.getPid());
        
                                                String apiName = pData.getApiName();
+                                               // _end indicates end of BSS (uninitialized data) section
+                                               // function entry of _end is considered as bad data
+                                               // TODO: test and remove _end condition
                                                if (null == apiName || apiName.isEmpty()
                                                                || apiName.equals("_end")) { //$NON-NLS-1$
-                                                       apiName = getFuncName(pData);
+                                                       apiName = SymbolManager.getFuncName(pData, pData.getPcAddr(),
+                                                                       pData.getPid(), pData.getTime());
                                                        if (apiName == null
                                                                        || apiName.equals("<unknown function>")) {
                                                                continue;
@@ -420,132 +423,4 @@ public class SWAPLogParser implements Runnable {
        // + "  time " + input.getTime());
        // System.out.println(" ]");
        // }
-
-       // TODO: remove unnecessary code
-       private String getFuncName(ProfileData input) {
-               long pcAddr = input.getPcAddr();
-               HashMap<Long, String> funcNameMap = AnalyzerManager
-                               .getFuncNameMapByPid(input.getPid());
-               String functionName = funcNameMap.get(pcAddr);
-               if (null != functionName) {
-                       return functionName;
-               }
-
-               // String functionName = null;
-               ProcessInfoPackage processInfoPkg = AnalyzerManager.getProject()
-                               .getProcessInfoPackage(input.getPid());
-               ProcessInfo processInfo = processInfoPkg
-                               .getProcessInfo(input.getTime());
-
-               /** for debug */
-               BinaryInfo binInfo1 = processInfo.getTargetBinary(input.getPcAddr());
-               if (binInfo1 == null) {
-                       // System.out.println("[Get functino name bug : "
-                       // + "Can't find binary info]");
-                       // System.out
-                       // .println("msg id : "
-                       // + AnalyzerUtil.toHexdecimal(input.getId())
-                       // + " pid : "
-                       // + processInfo.getPid()
-                       // + " low : "
-                       // + AnalyzerUtil.toHexdecimal(processInfo
-                       // .getLowestAddress())
-                       // + " input addr : "
-                       // + AnalyzerUtil.toHexdecimal(input.getPcAddr())
-                       // + "  high : "
-                       // + AnalyzerUtil.toHexdecimal(processInfo
-                       // .getHighestAddress()));
-                       return null;
-               }
-               // String binPath1 = binInfo1.getTargetBinaryPath();
-               // System.out.print("binary : " + binPath1 + " ==> ");
-               // AnalyzerUtil.printHexdecimal(processInfo.getLowestAddress());
-               // System.out.print(" < ");
-               // AnalyzerUtil.printHexdecimal(pcAddr);
-               // System.out.print(" < ");
-               // AnalyzerUtil.printHexdecimal(processInfo.getHighestAddress());
-               // System.out.println();
-
-               if (pcAddr >= processInfo.getLowestAddress()
-                               && pcAddr <= processInfo.getHighestAddress()) {
-                       String baseAddr = Long.toString(processInfo.getLowestAddress());
-                       String pcStr = Long.toString(pcAddr);
-                       BinaryInfo binInfo = processInfo.getTargetBinary(pcAddr);
-                       String localPath = binInfo.getTempBinaryPath();
-                       input.setBuildType(binInfo.getType());
-                       input.setBinaryPath(binInfo.getTargetBinaryPath());
-                       boolean isPieBuild = true;
-                       if (binInfo.getType() != 1) {
-                               isPieBuild = false;
-                       }
-                       functionName = SymbolManager.addr2func(localPath, pcStr,
-                                       isPieBuild, baseAddr);
-               } else {
-                       HashMap<String, BinaryInfo> binInfoMap = BinarySettingManager
-                                       .getInstance().getTargetBinInfoMap();
-                       List<String> binPaths = new ArrayList<String>();
-                       binPaths.addAll(binInfoMap.keySet());
-
-                       HashMap<String, LibraryObject> libHash = processInfo
-                                       .getLibObjHash();
-                       LibraryObject libraryObject = null;
-                       int size = binPaths.size();
-                       for (int i = 0; i < size; i++) {
-                               String binPath = binPaths.get(i);
-                               LibraryObject libObj = libHash.get(binPath);
-                               if (null == libObj) {
-                                       continue;
-                               }
-                               long lowAddr = libObj.getLowestAddress();
-                               long highAddr = libObj.getHighestAddress();
-
-                               /** for debug */
-                               // if (lowAddr > pcAddr || highAddr < pcAddr) {
-                               // System.out.print(input.getId() + " lib : " + binPath
-                               // + " ==> ");
-                               // AnalyzerUtil.printHexdecimal(lowAddr);
-                               // System.out.print(" < ");
-                               // AnalyzerUtil.printHexdecimal(pcAddr);
-                               // System.out.print(" < ");
-                               // AnalyzerUtil.printHexdecimal(highAddr);
-                               // System.out.println();
-                               // }
-
-                               if (pcAddr >= lowAddr && pcAddr <= highAddr) {
-                                       libraryObject = libObj;
-                                       break;
-                               }
-                       }
-                       if (null != libraryObject) {
-                               String path = libraryObject.getLibPath();
-                               BinaryInfo binInfo = binInfoMap.get(path);
-                               if (null != binInfo) {
-                                       String localPath = binInfo.getTempBinaryPath();
-                                       String baseAddr = Long.toString(libraryObject
-                                                       .getLowestAddress());
-                                       String pcStr = Long.toString(pcAddr);
-                                       input.setBinaryPath(binInfo.getTargetBinaryPath());                                     
-                                       boolean isPieBuild = true;
-                                       if (binInfo.getType() != 1) {
-                                               isPieBuild = false;
-                                       }
-                                       functionName = SymbolManager.addr2func(localPath, pcStr,
-                                                       isPieBuild, baseAddr);
-                               }
-                       }
-               }
-
-               if (null == functionName || functionName.isEmpty()
-                               || functionName.equals("_end")) { //$NON-NLS-1$
-                       functionName = InformationViewLabels.CALLSTACK_TABLE_UNKNOWN_FUNCTION;
-                       ApiNameManager.getApiId(functionName);
-               } else {
-                       String prevFunctionName = functionName;
-                       functionName = SymbolManager
-                                       .demanglingFunctionName(prevFunctionName);
-                       ApiNameManager.getApiId(functionName);
-               }
-               funcNameMap.put(pcAddr, functionName);
-               return functionName;
-       }
 }
index 9b4289e..51a965d 100644 (file)
@@ -39,6 +39,7 @@ public class ThreadData extends ProbeCommonData {
        long ospThreadId = 0;
        int threadType = 0; // TODO: short
        int apiType = 0;// TODO: short
+       String className = null;
 
        public ThreadData(){}
        
@@ -55,6 +56,9 @@ public class ThreadData extends ProbeCommonData {
                index += INT_SIZE;
 
                apiType = ByteUtil.toInt(data, index);
+               index += INT_SIZE;
+               
+               className = ByteUtil.getString(data, index);
        }
 
        public long getPThreadId() {
@@ -89,6 +93,14 @@ public class ThreadData extends ProbeCommonData {
                this.apiType = apiType;
        }
 
+       public String getClassName() {
+               return className;
+       }
+       
+       public void setClassName(String className) {
+               this.className = className;
+       }
+       
        @Override
        public void makePreparedStatement(PreparedStatement prep)
                        throws SQLException {
index e6b2dda..26d3e0c 100644 (file)
@@ -55,6 +55,8 @@ public class ThreadDetailInfoView extends DAViewComposite {
        private Canvas canvas = null;
        private String tid = AnalyzerLabels.EMPTY_STRING;
        private String type = AnalyzerLabels.EMPTY_STRING;
+       private String funcName = AnalyzerLabels.EMPTY_STRING;
+       private String className = AnalyzerLabels.EMPTY_STRING; 
        private String startTime = AnalyzerLabels.EMPTY_STRING;
        private String endTime = AnalyzerLabels.EMPTY_STRING;
        private String attrType = AnalyzerLabels.EMPTY_STRING;
@@ -64,6 +66,8 @@ public class ThreadDetailInfoView extends DAViewComposite {
        private void init() {
                tid = AnalyzerLabels.EMPTY_STRING;
                type = AnalyzerLabels.EMPTY_STRING;
+               funcName = AnalyzerLabels.EMPTY_STRING;
+               className = AnalyzerLabels.EMPTY_STRING;
                startTime = AnalyzerLabels.EMPTY_STRING;
                endTime = AnalyzerLabels.EMPTY_STRING;
                attrType = AnalyzerLabels.EMPTY_STRING;
@@ -106,6 +110,23 @@ public class ThreadDetailInfoView extends DAViewComposite {
                                        p = e.gc.textExtent(tid, SWT.DRAW_MNEMONIC);
                                        y += (p.y + HEIGHT_MARGIN);
                                }
+                               // tizen thread : show thread class name
+                               // other thread (e.g. pthread) : show thread function name
+                               if (type.equals(ThreadPageLabels.THREAD_ITEM_TYPE_TIZEN)) {
+                                       if (null != className && !(className.equals(CommonConstants.EMPTY))) {
+                                               e.gc.drawText(ThreadPageLabels.THREAD_DETAILS_CLASSNAME + className,
+                                                               LEFT_MARGIN, y);
+                                               p = e.gc.textExtent(tid, SWT.DRAW_MNEMONIC);
+                                               y += (p.y + HEIGHT_MARGIN);
+                                       }                                               
+                               } else {
+                                       if (null != funcName && !(funcName.equals(CommonConstants.EMPTY))) {
+                                               e.gc.drawText(ThreadPageLabels.THREAD_DETAILS_FUNCNAME + funcName,
+                                                               LEFT_MARGIN, y);
+                                               p = e.gc.textExtent(tid, SWT.DRAW_MNEMONIC);
+                                               y += (p.y + HEIGHT_MARGIN);
+                                       }
+                               }
 
                                if (null != startTime
                                                && !(startTime.equals(CommonConstants.EMPTY))) {
@@ -139,6 +160,14 @@ public class ThreadDetailInfoView extends DAViewComposite {
                if (item instanceof ThreadPageThreadData) {
                        tid = item.getTid();
                        type = item.getType();
+                       str = ((ThreadPageThreadData) item).getThreadFuncName();
+                       if (null != str && !(str.equals(CommonConstants.EMPTY))) {
+                               funcName = str;
+                       }
+                       str = ((ThreadPageThreadData) item).getThreadClassName();
+                       if (null != str && !(str.equals(CommonConstants.EMPTY))) {
+                               className = str;
+                       }
                        str = ((ThreadPageThreadData) item).getStartTime();
                        if (null != str && !(str.equals(CommonConstants.EMPTY))) {
                                startTime = str;
@@ -176,6 +205,12 @@ public class ThreadDetailInfoView extends DAViewComposite {
                        if (!type.equals(item.getType())) {
                                return true;
                        }
+                       if (!funcName.equals(((ThreadPageThreadData) item).getThreadFuncName())) {
+                               return true;
+                       }
+                       if (!className.equals(((ThreadPageThreadData) item).getThreadClassName())) {
+                               return true;
+                       }
                        if (!startTime.equals(((ThreadPageThreadData) item).getStartTime())) {
                                return true;
                        }
index 1ad826e..7df646e 100644 (file)
@@ -45,17 +45,33 @@ public class ThreadPageThreadData extends ThreadPageData {
        private List<ThreadPageSyncData> syncs = new ArrayList<ThreadPageSyncData>();
        private String StartTime;
        private String EndTime;
+       private String threadFuncName;
+       private String threadClassName;
        private DAChartSeries loadSeries;
        private DAChartSeries eventSeries;
        private DAChartSeries apiSeries;
 
-       public ThreadPageThreadData(String type, String pid, String tid, String attrType) {
+       public ThreadPageThreadData(String type, String pid, String tid, String attrType,
+                       String funcName) {
                super(type, String.valueOf(tid), pid, tid, attrType);
+               this.threadFuncName = funcName;
        }
 
        public void addDataEvent(ThreadPageThreadDataEvent dataEvent) {
                contentsQueue.add(dataEvent);
        }
+       
+       public String getThreadFuncName() {
+               return threadFuncName;
+       }
+       
+       public String getThreadClassName() {
+               return threadClassName;
+       }
+       
+       public void setThreadClassName(String className) {
+               threadClassName = className;
+       }
 
        public void setItem(DAChartBoardItem item) {
                this.item = item;
index 6180957..08ba159 100644 (file)
@@ -32,6 +32,7 @@ import java.util.List;
 import java.util.Comparator;
 
 import org.tizen.dynamicanalyzer.common.AnalyzerManager;
+import org.tizen.dynamicanalyzer.common.SymbolManager;
 import org.tizen.dynamicanalyzer.constant.CommonConstants;
 import org.tizen.dynamicanalyzer.logparser.LogCenterConstants;
 import org.tizen.dynamicanalyzer.nl.ThreadPageLabels;
@@ -87,6 +88,8 @@ public class ThreadPageThreadDataManager {
        private List<ThreadPageThreadDataEvent> callEventQueue = new ArrayList<ThreadPageThreadDataEvent>();
        private HashMap<String, Integer> threadAttrMap = new HashMap<String, Integer>();
        private HashMap<String, Integer> syncAttrMap = new HashMap<String, Integer>();
+       // threadFuncMap : (pthreadId, function address)
+       private HashMap<String, Long> threadFuncMap = new HashMap<String, Long>();
        private int preSelectionPid = -1;
        
        public static final int PTHREAD_CREATE_JOINABLE = 0;
@@ -339,7 +342,7 @@ public class ThreadPageThreadDataManager {
        public void createMainThreadItem(int tid) {
                ThreadPageThreadData mainData = new ThreadPageThreadData(
                                ThreadPageLabels.THREAD_ITEM_TYPE_MAIN, String.valueOf(tid),
-                               String.valueOf(tid), CommonConstants.EMPTY);
+                               String.valueOf(tid), CommonConstants.EMPTY, "main");
                pushRow(mainData);
        }
                
@@ -482,6 +485,7 @@ public class ThreadPageThreadDataManager {
                case LogCenterConstants.THREAD_API_TYPE_START:
                        if (apiName.equals(ThreadPageLabels.THREAD_API_PTHREAD_CREATE)) {
                                checkThreadType(input.getArgs(), pthreadId);
+                               checkThreadFunc(input.getArgs(), pthreadId);
                        }
                        event = new ThreadPageThreadDataEvent(
                                        ThreadPageThreadDataEvent.TYPE_API,
@@ -530,16 +534,20 @@ public class ThreadPageThreadDataManager {
                case LogCenterConstants.THREAD_API_TYPE_INTERNAL_START:
                        Integer threadAttrTypeInt = threadAttrMap.get(pthreadId);
                        String threadAttrType;
+                       String funcName;
                        
                        if (null != threadAttrTypeInt) {
                                threadAttrType = getAttrTypeByTypeInt(threadAttrTypeInt);
                        } else {
                                threadAttrType = ThreadPageLabels.THREAD_ATTR_TYPE_JOINABLE;
                        }
+                       // get thread function name for this pthread
+                       funcName = SymbolManager.getFuncName(null, threadFuncMap.get(pthreadId),
+                                       input.getPid(), input.getTime());
                        
                        ThreadPageThreadData data = new ThreadPageThreadData(
                                        ThreadPageLabels.THREAD_ITEM_TYPE_PTHREAD, pid, tid,
-                                       threadAttrType);
+                                       threadAttrType, funcName);
                        pushRow(data);
                        event = new ThreadPageThreadDataEvent(
                                        ThreadPageThreadDataEvent.TYPE_EVENT,
@@ -560,6 +568,7 @@ public class ThreadPageThreadDataManager {
                int apiType = input.getApiType();
                String apiName = input.getApiName();
                String callID = Long.toString(input.getOspThreadId());
+               String className = null;
                ThreadPageThreadData data;
                ThreadPageThreadDataEvent event;
                long errorNum = input.getErrno();
@@ -584,6 +593,7 @@ public class ThreadPageThreadDataManager {
                        event.setCallID(callID);
                        data = findCallQueue(callID);
                        if (null != data) {
+                               data.setThreadClassName(input.getClassName());
                                pushRow(data);
                        }
                        pushEvent(event);
@@ -629,10 +639,11 @@ public class ThreadPageThreadDataManager {
                case LogCenterConstants.THREAD_API_TYPE_INTERNAL_START:
                        data = new ThreadPageThreadData(
                                        ThreadPageLabels.THREAD_ITEM_TYPE_TIZEN, pid, tid,
-                                       ThreadPageLabels.THREAD_ATTR_TYPE_JOINABLE);
+                                       ThreadPageLabels.THREAD_ATTR_TYPE_JOINABLE, CommonConstants.EMPTY);
                        // TIZEN thread includes the internal thread
-                       if (true == checkCalledThread(callID)) {
-                               pushRow(data);
+                       if ((className = checkCalledThread(callID)) != null) {
+                                       data.setThreadClassName(className);
+                                       pushRow(data);
                        } else {
                                pushCallRow(data);
                        }
@@ -648,7 +659,6 @@ public class ThreadPageThreadDataManager {
        }
 
        public void parseAPI(LogData input) {
-
                if (null == input) {
                        return;
                }
@@ -830,10 +840,12 @@ public class ThreadPageThreadDataManager {
                parseSync(logPack);
                hasUpdate = true;
        }
-
-       private boolean checkCalledThread(String callId) {
+       // when INTERNAL_START log comes after START log, 
+       // this method finds matching START log (for TIZEN thread only) 
+       // return class name from the START log
+       private String checkCalledThread(String callId) {
                if (null == callId) {
-                       return false;
+                       return null;
                }
                int callEventQueueSize = callEventQueue.size();
                ThreadPageThreadDataEvent callEvent;
@@ -843,10 +855,11 @@ public class ThreadPageThreadDataManager {
                                continue;
                        }
                        if (callId.equals(callEvent.getCallID())) {
-                               return true;
+                               ThreadData threadData = (ThreadData) callEvent.getContents();
+                               return threadData.getClassName();
                        }
                }
-               return false;
+               return null;
        }
 
        private String getCallEventID(String callID) {
@@ -934,6 +947,20 @@ public class ThreadPageThreadDataManager {
                        threadAttrMap.put(pthreadId, attrType);
                }
        }
+       // extract function address from arguments of thread create function,
+       // (e.g. int pthread_create(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *); )
+       // put (pthreadId, function address) in the map 
+       private void checkThreadFunc(String args, String pthreadId) {
+               String[] temp = args.split(",");
+               if (temp.length != 4) {
+                       return;
+               }
+               // 3rd argument is function address
+               String strFuncAddr = temp[2].trim();
+               Long funcAddr = Long.decode(strFuncAddr);
+               
+               threadFuncMap.put(pthreadId, funcAddr);
+       }
        
        private void checkMutexAttrType(String input) {
                String[] temp = input.split(",");