From: Daniel Friederich Date: Wed, 12 Oct 2016 14:41:09 +0000 (-0500) Subject: Support for multiple instances X-Git-Tag: android-x86-8.1-r1~68^2~13^2^2~49^2~14^2~1 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=0e48e18171e17c76834916c2c87360195edf8667;p=android-x86%2Fsystem-extras.git Support for multiple instances Allows to use separate instances for separate perf.datai files (and possibly also separate instances on separate threads) Test: Tested by running report_sample.py Change-Id: I0ebdb3c650a4540f07237b515d451d69ec3810e6 --- diff --git a/simpleperf/report_lib_interface.cpp b/simpleperf/report_lib_interface.cpp index 3653e0d7..cdd9fb1c 100644 --- a/simpleperf/report_lib_interface.cpp +++ b/simpleperf/report_lib_interface.cpp @@ -24,6 +24,8 @@ #include "thread_tree.h" #include "utils.h" +class ReportLib; + extern "C" { #define EXPORT __attribute__((visibility("default"))) @@ -59,17 +61,22 @@ struct CallChain { CallChainEntry* entries; }; +// Create a new instance, +// pass the instance to the other functions below. +ReportLib* CreateReportLib() EXPORT; +void DestroyReportLib(ReportLib* report_lib) EXPORT; + // Set log severity, different levels are: // verbose, debug, info, warning, error, fatal. -bool SetLogSeverity(const char* log_level) EXPORT; -bool SetSymfs(const char* symfs_dir) EXPORT; -bool SetRecordFile(const char* record_file) EXPORT; -void ShowIpForUnknownSymbol() EXPORT; - -Sample* GetNextSample() EXPORT; -Event* GetEventOfCurrentSample() EXPORT; -SymbolEntry* GetSymbolOfCurrentSample() EXPORT; -CallChain* GetCallChainOfCurrentSample() EXPORT; +bool SetLogSeverity(ReportLib* report_lib, const char* log_level) EXPORT; +bool SetSymfs(ReportLib* report_lib, const char* symfs_dir) EXPORT; +bool SetRecordFile(ReportLib* report_lib, const char* record_file) EXPORT; +void ShowIpForUnknownSymbol(ReportLib* report_lib) EXPORT; + +Sample* GetNextSample(ReportLib* report_lib) EXPORT; +Event* GetEventOfCurrentSample(ReportLib* report_lib) EXPORT; +SymbolEntry* GetSymbolOfCurrentSample(ReportLib* report_lib) EXPORT; +CallChain* GetCallChainOfCurrentSample(ReportLib* report_lib) EXPORT; } struct EventAttrWithName { @@ -90,12 +97,9 @@ class ReportLib { : log_severity_( new android::base::ScopedLogSeverity(android::base::INFO)), record_filename_("perf.data"), - update_flag_(0) {} - - static ReportLib& GetInstance() { - static ReportLib lib; - return lib; - } + current_thread_(nullptr), + update_flag_(0) + {} bool SetLogSeverity(const char* log_level); @@ -272,32 +276,43 @@ CallChain* ReportLib::GetCallChainOfCurrentSample() { return ¤t_callchain_; } -bool SetLogSeverity(const char* log_level) { - return ReportLib::GetInstance().SetLogSeverity(log_level); +// Exported methods working with a client created instance +ReportLib* CreateReportLib() { + return new ReportLib(); } -bool SetSymfs(const char* symfs_dir) { - return ReportLib::GetInstance().SetSymfs(symfs_dir); +void DestroyReportLib(ReportLib* report_lib) { + delete report_lib; } -bool SetRecordFile(const char* record_file) { - return ReportLib::GetInstance().SetRecordFile(record_file); +bool SetLogSeverity(ReportLib* report_lib, const char* log_level) { + return report_lib->SetLogSeverity(log_level); } -void ShowIpForUnknownSymbol() { - return ReportLib::GetInstance().ShowIpForUnknownSymbol(); +bool SetSymfs(ReportLib* report_lib, const char* symfs_dir) { + return report_lib->SetSymfs(symfs_dir); } -Sample* GetNextSample() { return ReportLib::GetInstance().GetNextSample(); } +bool SetRecordFile(ReportLib* report_lib, const char* record_file) { + return report_lib->SetRecordFile(record_file); +} + +void ShowIpForUnknownSymbol(ReportLib* report_lib) { + return report_lib->ShowIpForUnknownSymbol(); +} + +Sample* GetNextSample(ReportLib* report_lib) { + return report_lib->GetNextSample(); +} -Event* GetEventOfCurrentSample() { - return ReportLib::GetInstance().GetEventOfCurrentSample(); +Event* GetEventOfCurrentSample(ReportLib* report_lib) { + return report_lib->GetEventOfCurrentSample(); } -SymbolEntry* GetSymbolOfCurrentSample() { - return ReportLib::GetInstance().GetSymbolOfCurrentSample(); +SymbolEntry* GetSymbolOfCurrentSample(ReportLib* report_lib) { + return report_lib->GetSymbolOfCurrentSample(); } -CallChain* GetCallChainOfCurrentSample() { - return ReportLib::GetInstance().GetCallChainOfCurrentSample(); +CallChain* GetCallChainOfCurrentSample(ReportLib* report_lib) { + return report_lib->GetCallChainOfCurrentSample(); } diff --git a/simpleperf/scripts/report_sample.py b/simpleperf/scripts/report_sample.py index d0605cd7..831baeb7 100644 --- a/simpleperf/scripts/report_sample.py +++ b/simpleperf/scripts/report_sample.py @@ -32,6 +32,7 @@ def usage(): def report_sample(record_file, symfs_dir): """ read record_file, and print each sample""" lib = ReportLib() + lib.ShowIpForUnknownSymbol() if symfs_dir is not None: lib.SetSymfs(symfs_dir) @@ -41,6 +42,7 @@ def report_sample(record_file, symfs_dir): while True: sample = lib.GetNextSample() if sample is None: + lib.Close() break event = lib.GetEventOfCurrentSample() symbol = lib.GetSymbolOfCurrentSample() diff --git a/simpleperf/scripts/simpleperf_report_lib.py b/simpleperf/scripts/simpleperf_report_lib.py index d4724b90..8b0e133f 100644 --- a/simpleperf/scripts/simpleperf_report_lib.py +++ b/simpleperf/scripts/simpleperf_report_lib.py @@ -61,6 +61,8 @@ class CallChainStructure(ct.Structure): _fields_ = [('nr', ct.c_uint32), ('entries', ct.POINTER(CallChainEntryStructure))] +class ReportLibStructure(ct.Structure): + _fields_ = [] class ReportLib(object): @@ -68,6 +70,9 @@ class ReportLib(object): if native_lib_path is None: native_lib_path = _get_script_path() + "/libsimpleperf_report.so" self._lib = ct.CDLL(native_lib_path) + self._CreateReportLibFunc = self._lib.CreateReportLib + self._CreateReportLibFunc.restype = ct.POINTER(ReportLibStructure) + self._DestroyReportLibFunc = self._lib.DestroyReportLib self._SetLogSeverityFunc = self._lib.SetLogSeverity self._SetSymfsFunc = self._lib.SetSymfs self._SetRecordFileFunc = self._lib.SetRecordFile @@ -81,39 +86,55 @@ class ReportLib(object): self._GetCallChainOfCurrentSampleFunc = self._lib.GetCallChainOfCurrentSample self._GetCallChainOfCurrentSampleFunc.restype = ct.POINTER( CallChainStructure) + self._instance = self._CreateReportLibFunc() + assert(not _is_null(self._instance)) + + def Close(self): + if self._instance is None: + return + self._DestroyReportLibFunc(self._instance) + self._instance = None def SetLogSeverity(self, log_level='info'): """ Set log severity of native lib, can be verbose,debug,info,error,fatal.""" - assert(self._SetLogSeverityFunc(log_level)) + cond = self._SetLogSeverityFunc(self.getInstance(), log_level) + assert(cond) def SetSymfs(self, symfs_dir): """ Set directory used to find symbols.""" - assert(self._SetSymfsFunc(symfs_dir)) + cond = self._SetSymfsFunc(self.getInstance(), symfs_dir) + assert(cond) def SetRecordFile(self, record_file): """ Set the path of record file, like perf.data.""" - assert(self._SetRecordFileFunc(record_file)) + cond = self._SetRecordFileFunc(self.getInstance(), record_file) + assert(cond) def ShowIpForUnknownSymbol(self): - self._ShowIpForUnknownSymbolFunc() + self._ShowIpForUnknownSymbolFunc(self.getInstance()) def GetNextSample(self): - sample = self._GetNextSampleFunc() + sample = self._GetNextSampleFunc(self.getInstance()) if _is_null(sample): return None return sample def GetEventOfCurrentSample(self): - event = self._GetEventOfCurrentSampleFunc() + event = self._GetEventOfCurrentSampleFunc(self.getInstance()) assert(not _is_null(event)) return event def GetSymbolOfCurrentSample(self): - symbol = self._GetSymbolOfCurrentSampleFunc() + symbol = self._GetSymbolOfCurrentSampleFunc(self.getInstance()) assert(not _is_null(symbol)) return symbol def GetCallChainOfCurrentSample(self): - callchain = self._GetCallChainOfCurrentSampleFunc() + callchain = self._GetCallChainOfCurrentSampleFunc(self.getInstance()) assert(not _is_null(callchain)) return callchain + + def getInstance(self): + if self._instance is None: + raise Exception("Instance is Closed") + return self._instance