From b1d07441d04e4116638a1fc162cb7c6e55b2915a Mon Sep 17 00:00:00 2001 From: Jon Medhurst Date: Fri, 8 May 2015 12:04:18 +0100 Subject: gator: Version 5.21.1 Signed-off-by: Drew Richardson Signed-off-by: Jon Medhurst --- drivers/gator/COPYING | 339 +++++++++++++++++++++ drivers/gator/LICENSE | 339 --------------------- drivers/gator/Makefile | 18 +- drivers/gator/gator.h | 41 +-- drivers/gator/gator_annotate.c | 2 +- drivers/gator/gator_annotate_kernel.c | 2 +- drivers/gator/gator_backtrace.c | 2 +- drivers/gator/gator_buffer.c | 2 +- drivers/gator/gator_buffer_write.c | 2 +- drivers/gator/gator_cookies.c | 2 +- drivers/gator/gator_events_armv6.c | 2 +- drivers/gator/gator_events_armv7.c | 2 +- drivers/gator/gator_events_block.c | 2 +- drivers/gator/gator_events_irq.c | 2 +- drivers/gator/gator_events_l2c-310.c | 2 +- drivers/gator/gator_events_mali_4xx.c | 2 +- drivers/gator/gator_events_mali_4xx.h | 2 +- drivers/gator/gator_events_mali_common.c | 2 +- drivers/gator/gator_events_mali_common.h | 2 +- drivers/gator/gator_events_mali_midgard.c | 2 +- drivers/gator/gator_events_mali_midgard_hw.c | 31 +- drivers/gator/gator_events_mali_midgard_hw_test.c | 2 +- drivers/gator/gator_events_meminfo.c | 5 +- drivers/gator/gator_events_mmapped.c | 2 +- drivers/gator/gator_events_net.c | 2 +- drivers/gator/gator_events_perf_pmu.c | 47 +-- drivers/gator/gator_events_sched.c | 2 +- drivers/gator/gator_events_scorpion.c | 2 +- drivers/gator/gator_hrtimer_gator.c | 2 +- drivers/gator/gator_iks.c | 2 +- drivers/gator/gator_main.c | 42 ++- drivers/gator/gator_marshaling.c | 16 +- drivers/gator/gator_trace_gpu.c | 2 +- drivers/gator/gator_trace_power.c | 10 +- drivers/gator/gator_trace_sched.c | 2 +- drivers/gator/mali/mali_kbase_gator_api.h | 219 ------------- .../gator/mali/mali_mjollnir_profiling_gator_api.h | 2 +- .../gator/mali/mali_utgard_profiling_gator_api.h | 2 +- drivers/gator/mali_midgard.mk | 1 + tools/gator/daemon/Android.mk | 4 +- tools/gator/daemon/AnnotateListener.cpp | 30 +- tools/gator/daemon/AnnotateListener.h | 16 +- tools/gator/daemon/Application.mk | 2 +- tools/gator/daemon/Buffer.cpp | 77 +++-- tools/gator/daemon/Buffer.h | 25 +- tools/gator/daemon/CCNDriver.cpp | 5 +- tools/gator/daemon/CCNDriver.h | 2 +- tools/gator/daemon/COPYING | 339 +++++++++++++++++++++ tools/gator/daemon/CPUFreqDriver.cpp | 58 ---- tools/gator/daemon/CPUFreqDriver.h | 34 --- tools/gator/daemon/CapturedXML.cpp | 5 +- tools/gator/daemon/CapturedXML.h | 2 +- tools/gator/daemon/Child.cpp | 49 +-- tools/gator/daemon/Child.h | 2 +- tools/gator/daemon/Command.cpp | 12 +- tools/gator/daemon/Command.h | 2 +- tools/gator/daemon/Config.h | 2 +- tools/gator/daemon/ConfigurationXML.cpp | 10 +- tools/gator/daemon/ConfigurationXML.h | 2 +- tools/gator/daemon/Counter.h | 2 +- tools/gator/daemon/DiskIODriver.cpp | 20 +- tools/gator/daemon/DiskIODriver.h | 2 +- tools/gator/daemon/Driver.cpp | 2 +- tools/gator/daemon/Driver.h | 2 +- tools/gator/daemon/DriverSource.cpp | 33 +- tools/gator/daemon/DriverSource.h | 2 +- tools/gator/daemon/DynBuf.cpp | 16 +- tools/gator/daemon/DynBuf.h | 2 +- tools/gator/daemon/EventsXML.cpp | 179 ++++++++++- tools/gator/daemon/EventsXML.h | 9 +- tools/gator/daemon/ExternalSource.cpp | 59 ++-- tools/gator/daemon/ExternalSource.h | 3 +- tools/gator/daemon/FSDriver.cpp | 32 +- tools/gator/daemon/FSDriver.h | 2 +- tools/gator/daemon/Fifo.cpp | 6 +- tools/gator/daemon/Fifo.h | 2 +- tools/gator/daemon/FtraceDriver.cpp | 119 ++++++-- tools/gator/daemon/FtraceDriver.h | 4 +- tools/gator/daemon/FtraceSource.cpp | 56 +++- tools/gator/daemon/FtraceSource.h | 2 +- tools/gator/daemon/HwmonDriver.cpp | 158 +++++----- tools/gator/daemon/HwmonDriver.h | 2 +- tools/gator/daemon/KMod.cpp | 6 +- tools/gator/daemon/KMod.h | 2 +- tools/gator/daemon/LocalCapture.cpp | 8 +- tools/gator/daemon/LocalCapture.h | 2 +- tools/gator/daemon/Logging.cpp | 10 +- tools/gator/daemon/Logging.h | 16 +- tools/gator/daemon/MaliVideoDriver.cpp | 4 +- tools/gator/daemon/MaliVideoDriver.h | 2 +- tools/gator/daemon/MemInfoDriver.cpp | 4 +- tools/gator/daemon/MemInfoDriver.h | 2 +- tools/gator/daemon/Monitor.cpp | 20 +- tools/gator/daemon/Monitor.h | 2 +- tools/gator/daemon/NetDriver.cpp | 6 +- tools/gator/daemon/NetDriver.h | 2 +- tools/gator/daemon/OlySocket.cpp | 51 ++-- tools/gator/daemon/OlySocket.h | 8 +- tools/gator/daemon/OlyUtility.cpp | 2 +- tools/gator/daemon/OlyUtility.h | 2 +- tools/gator/daemon/PerfBuffer.cpp | 129 ++++++-- tools/gator/daemon/PerfBuffer.h | 3 +- tools/gator/daemon/PerfDriver.cpp | 180 +++++++---- tools/gator/daemon/PerfDriver.h | 8 +- tools/gator/daemon/PerfGroup.cpp | 234 ++++++++++---- tools/gator/daemon/PerfGroup.h | 23 +- tools/gator/daemon/PerfSource.cpp | 210 +++++++------ tools/gator/daemon/PerfSource.h | 5 +- tools/gator/daemon/Proc.cpp | 62 ++-- tools/gator/daemon/Proc.h | 2 +- tools/gator/daemon/Sender.cpp | 8 +- tools/gator/daemon/Sender.h | 2 +- tools/gator/daemon/SessionData.cpp | 67 ++-- tools/gator/daemon/SessionData.h | 11 +- tools/gator/daemon/SessionXML.cpp | 8 +- tools/gator/daemon/SessionXML.h | 2 +- tools/gator/daemon/Setup.cpp | 202 ++++++++---- tools/gator/daemon/Setup.h | 4 +- tools/gator/daemon/Source.cpp | 4 +- tools/gator/daemon/Source.h | 2 +- tools/gator/daemon/StreamlineSetup.cpp | 22 +- tools/gator/daemon/StreamlineSetup.h | 2 +- tools/gator/daemon/UEvent.cpp | 9 +- tools/gator/daemon/UEvent.h | 2 +- tools/gator/daemon/UserSpaceSource.cpp | 37 +-- tools/gator/daemon/UserSpaceSource.h | 2 +- tools/gator/daemon/c++.cpp | 2 +- tools/gator/daemon/common.mk | 9 +- tools/gator/daemon/defaults.xml | 21 +- tools/gator/daemon/escape.c | 2 +- tools/gator/daemon/events-ARM11.xml | 2 +- tools/gator/daemon/events-CCI-400.xml | 4 +- tools/gator/daemon/events-CCI-500.xml | 75 +++++ tools/gator/daemon/events-Cortex-A15.xml | 100 +++--- tools/gator/daemon/events-Cortex-A17.xml | 79 +++-- tools/gator/daemon/events-Cortex-A5.xml | 52 ++-- tools/gator/daemon/events-Cortex-A53.xml | 117 +++---- tools/gator/daemon/events-Cortex-A57.xml | 58 ++-- tools/gator/daemon/events-Cortex-A7.xml | 65 ++-- tools/gator/daemon/events-Cortex-A72.xml | 87 ++++++ tools/gator/daemon/events-Cortex-A8.xml | 44 +-- tools/gator/daemon/events-Cortex-A9.xml | 66 ++-- tools/gator/daemon/events-Filesystem.xml | 3 +- tools/gator/daemon/events-L2C-310.xml | 4 +- tools/gator/daemon/events-Linux.xml | 4 +- tools/gator/daemon/events-Mali-4xx.xml | 4 +- tools/gator/daemon/events-Mali-Midgard.xml | 17 +- tools/gator/daemon/events-Mali-Midgard_hw.xml | 75 ++--- tools/gator/daemon/events-Mali-T60x_hw.xml | 66 ++-- tools/gator/daemon/events-Mali-T62x_hw.xml | 65 ++-- tools/gator/daemon/events-Mali-T72x_hw.xml | 56 ++-- tools/gator/daemon/events-Mali-T76x_hw.xml | 67 ++-- tools/gator/daemon/events-Mali-T82x_hw.xml | 108 +++++++ tools/gator/daemon/events-Mali-T83x_hw.xml | 108 +++++++ tools/gator/daemon/events-Mali-T86x_hw.xml | 117 +++++++ tools/gator/daemon/events-Mali-T88x_hw.xml | 117 +++++++ tools/gator/daemon/events-Other.xml | 33 ++ tools/gator/daemon/events-ftrace.xml | 21 +- tools/gator/daemon/main.cpp | 100 ++++-- 159 files changed, 3600 insertions(+), 2091 deletions(-) create mode 100644 drivers/gator/COPYING delete mode 100644 drivers/gator/LICENSE delete mode 100644 drivers/gator/mali/mali_kbase_gator_api.h create mode 100644 tools/gator/daemon/COPYING delete mode 100644 tools/gator/daemon/CPUFreqDriver.cpp delete mode 100644 tools/gator/daemon/CPUFreqDriver.h create mode 100644 tools/gator/daemon/events-CCI-500.xml create mode 100644 tools/gator/daemon/events-Cortex-A72.xml create mode 100644 tools/gator/daemon/events-Mali-T82x_hw.xml create mode 100644 tools/gator/daemon/events-Mali-T83x_hw.xml create mode 100644 tools/gator/daemon/events-Mali-T86x_hw.xml create mode 100644 tools/gator/daemon/events-Mali-T88x_hw.xml create mode 100644 tools/gator/daemon/events-Other.xml diff --git a/drivers/gator/COPYING b/drivers/gator/COPYING new file mode 100644 index 000000000000..d159169d1050 --- /dev/null +++ b/drivers/gator/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/drivers/gator/LICENSE b/drivers/gator/LICENSE deleted file mode 100644 index d159169d1050..000000000000 --- a/drivers/gator/LICENSE +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/drivers/gator/Makefile b/drivers/gator/Makefile index 28d2070b11d5..d14e2a02fee0 100644 --- a/drivers/gator/Makefile +++ b/drivers/gator/Makefile @@ -63,6 +63,22 @@ gator-$(CONFIG_ARM) += gator_events_armv6.o \ gator-$(CONFIG_ARM64) += +$(obj)/gator_main.o: $(obj)/gator_src_md5.h + +clean-files := gator_src_md5.h + +# Note, in the recipe below we use "cd $(srctree) && cd $(src)" rather than +# "cd $(srctree)/$(src)" because under DKMS $(src) is an absolute path, and we +# can't just use $(src) because for normal kernel builds this is relative to +# $(srctree) + + chk_events.h = : + quiet_chk_events.h = echo ' CHK $@' +silent_chk_events.h = : +$(obj)/gator_src_md5.h: FORCE + @$($(quiet)chk_events.h) + $(Q)cd $(srctree) && cd $(src) ; $(CONFIG_SHELL) -c "echo 'static char *gator_src_md5 = \"'\`ls *.c *.h mali/*.h | grep -Ev '^(gator_src_md5\.c|gator\.mod\.c)$$' | LC_ALL=C sort | xargs cat | md5sum | cut -b 1-32\`'\";'" > $(abspath $@) + else all: @@ -73,7 +89,7 @@ all: $(error) clean: - rm -f *.o .*.cmd modules.order Module.symvers gator.ko gator.mod.c + rm -f *.o .*.cmd gator_src_md5.h modules.order Module.symvers gator.ko gator.mod.c rm -rf .tmp_versions endif diff --git a/drivers/gator/gator.h b/drivers/gator/gator.h index 5cc73a388c4f..202eb41c485b 100644 --- a/drivers/gator/gator.h +++ b/drivers/gator/gator.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -21,25 +21,26 @@ #define GATOR_IKS_SUPPORT defined(CONFIG_BL_SWITCHER) /* cpu ids */ -#define ARM1136 0xb36 -#define ARM1156 0xb56 -#define ARM1176 0xb76 -#define ARM11MPCORE 0xb02 -#define CORTEX_A5 0xc05 -#define CORTEX_A7 0xc07 -#define CORTEX_A8 0xc08 -#define CORTEX_A9 0xc09 -#define CORTEX_A15 0xc0f -#define CORTEX_A17 0xc0e -#define SCORPION 0x00f -#define SCORPIONMP 0x02d -#define KRAITSIM 0x049 -#define KRAIT 0x04d -#define KRAIT_S4_PRO 0x06f -#define CORTEX_A53 0xd03 -#define CORTEX_A57 0xd07 -#define AARCH64 0xd0f -#define OTHER 0xfff +#define ARM1136 0x41b36 +#define ARM1156 0x41b56 +#define ARM1176 0x41b76 +#define ARM11MPCORE 0x41b02 +#define CORTEX_A5 0x41c05 +#define CORTEX_A7 0x41c07 +#define CORTEX_A8 0x41c08 +#define CORTEX_A9 0x41c09 +#define CORTEX_A15 0x41c0f +#define CORTEX_A12 0x41c0d +#define CORTEX_A17 0x41c0e +#define SCORPION 0x5100f +#define SCORPIONMP 0x5102d +#define KRAITSIM 0x51049 +#define KRAIT 0x5104d +#define KRAIT_S4_PRO 0x5106f +#define CORTEX_A53 0x41d03 +#define CORTEX_A57 0x41d07 +#define CORTEX_A72 0x41d08 +#define OTHER 0xfffff /* gpu enums */ #define MALI_4xx 1 diff --git a/drivers/gator/gator_annotate.c b/drivers/gator/gator_annotate.c index ff9a3cef7b2e..cc9ae02e5fba 100644 --- a/drivers/gator/gator_annotate.c +++ b/drivers/gator/gator_annotate.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/gator_annotate_kernel.c b/drivers/gator/gator_annotate_kernel.c index 69471f99e5fb..54e8e86e34cf 100644 --- a/drivers/gator/gator_annotate_kernel.c +++ b/drivers/gator/gator_annotate_kernel.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2012-2014. All rights reserved. + * Copyright (C) ARM Limited 2012-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/gator_backtrace.c b/drivers/gator/gator_backtrace.c index 76c941d009a9..5557ec0b29ca 100644 --- a/drivers/gator/gator_backtrace.c +++ b/drivers/gator/gator_backtrace.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/gator_buffer.c b/drivers/gator/gator_buffer.c index 910d5aa15066..f335457638ae 100644 --- a/drivers/gator/gator_buffer.c +++ b/drivers/gator/gator_buffer.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/gator_buffer_write.c b/drivers/gator/gator_buffer_write.c index 654ec606cfad..b731e6a414d2 100644 --- a/drivers/gator/gator_buffer_write.c +++ b/drivers/gator/gator_buffer_write.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/gator_cookies.c b/drivers/gator/gator_cookies.c index c43cce815226..9bd4c8b98c9e 100644 --- a/drivers/gator/gator_cookies.c +++ b/drivers/gator/gator_cookies.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/gator_events_armv6.c b/drivers/gator/gator_events_armv6.c index a157a0013302..178397033e2c 100644 --- a/drivers/gator/gator_events_armv6.c +++ b/drivers/gator/gator_events_armv6.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/gator_events_armv7.c b/drivers/gator/gator_events_armv7.c index 09c94220114c..e1f6a5fa9997 100644 --- a/drivers/gator/gator_events_armv7.c +++ b/drivers/gator/gator_events_armv7.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/gator_events_block.c b/drivers/gator/gator_events_block.c index a352a54afa02..b3467b133712 100644 --- a/drivers/gator/gator_events_block.c +++ b/drivers/gator/gator_events_block.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/gator_events_irq.c b/drivers/gator/gator_events_irq.c index 5221aac581b3..81b976a9b282 100644 --- a/drivers/gator/gator_events_irq.c +++ b/drivers/gator/gator_events_irq.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/gator_events_l2c-310.c b/drivers/gator/gator_events_l2c-310.c index 73aaac32327e..063a06079c74 100644 --- a/drivers/gator/gator_events_l2c-310.c +++ b/drivers/gator/gator_events_l2c-310.c @@ -1,7 +1,7 @@ /** * l2c310 (L2 Cache Controller) event counters for gator * - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/gator_events_mali_4xx.c b/drivers/gator/gator_events_mali_4xx.c index 9cf43fe2c29b..423b4e08e8cc 100644 --- a/drivers/gator/gator_events_mali_4xx.c +++ b/drivers/gator/gator_events_mali_4xx.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/gator_events_mali_4xx.h b/drivers/gator/gator_events_mali_4xx.h index 976ca8c4cfa1..8f6a870e6d0c 100644 --- a/drivers/gator/gator_events_mali_4xx.h +++ b/drivers/gator/gator_events_mali_4xx.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2011-2014. All rights reserved. + * Copyright (C) ARM Limited 2011-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/gator_events_mali_common.c b/drivers/gator/gator_events_mali_common.c index 1af87d649afe..7741f2575542 100644 --- a/drivers/gator/gator_events_mali_common.c +++ b/drivers/gator/gator_events_mali_common.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2012-2014. All rights reserved. + * Copyright (C) ARM Limited 2012-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/gator_events_mali_common.h b/drivers/gator/gator_events_mali_common.h index e7082e62fe88..a4fc9d7d4cf6 100644 --- a/drivers/gator/gator_events_mali_common.h +++ b/drivers/gator/gator_events_mali_common.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2012-2014. All rights reserved. + * Copyright (C) ARM Limited 2012-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/gator_events_mali_midgard.c b/drivers/gator/gator_events_mali_midgard.c index 0aec906d7ae5..3b0963a8de21 100644 --- a/drivers/gator/gator_events_mali_midgard.c +++ b/drivers/gator/gator_events_mali_midgard.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2011-2014. All rights reserved. + * Copyright (C) ARM Limited 2011-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/gator_events_mali_midgard_hw.c b/drivers/gator/gator_events_mali_midgard_hw.c index c8065da56815..7e1eee30026d 100644 --- a/drivers/gator/gator_events_mali_midgard_hw.c +++ b/drivers/gator/gator_events_mali_midgard_hw.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2012-2014. All rights reserved. + * Copyright (C) ARM Limited 2012-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -18,7 +18,7 @@ /* Mali Midgard DDK includes */ #if defined(MALI_SIMPLE_API) /* Header with wrapper functions to kbase structures and functions */ -#include "mali/mali_kbase_gator_api.h" +#include "mali_kbase_gator_api.h" #elif defined(MALI_DIR_MIDGARD) /* New DDK Directory structure with kernel/drivers/gpu/arm/midgard */ #include "mali_linux_trace.h" @@ -40,6 +40,10 @@ #error MALI_DDK_GATOR_API_VERSION is invalid (must be 1 for r1/r2 DDK, or 2 for r3/r4 DDK, or 3 for r5 and later DDK). #endif +#if !defined(CONFIG_MALI_GATOR_SUPPORT) +#error CONFIG_MALI_GATOR_SUPPORT is required for GPU activity and software counters +#endif + #include "gator_events_mali_common.h" /* @@ -748,12 +752,12 @@ static int read_counter(const int cnt, const int len, const struct mali_counter { const int block = GET_HW_BLOCK(cnt); const int counter_offset = GET_COUNTER_OFFSET(cnt); + u32 value = 0; #if MALI_DDK_GATOR_API_VERSION == 3 const char *block_base_address = (char *)in_out_info->kernel_dump_buffer; int i; int shader_core_count = 0; - u32 value = 0; for (i = 0; i < in_out_info->nr_hwc_blocks; i++) { if (block == in_out_info->hwc_layout[i]) { @@ -766,6 +770,12 @@ static int read_counter(const int cnt, const int len, const struct mali_counter if (shader_core_count > 1) value /= shader_core_count; #else + const unsigned int vithar_blocks[] = { + 0x700, /* VITHAR_JOB_MANAGER, Block 0 */ + 0x400, /* VITHAR_TILER, Block 1 */ + 0x000, /* VITHAR_SHADER_CORE, Block 2 */ + 0x500 /* VITHAR_MEMORY_SYSTEM, Block 3 */ + }; const char *block_base_address = (char *)kernel_dump_buffer + vithar_blocks[block]; /* If counter belongs to shader block need to take into account all cores */ @@ -831,31 +841,22 @@ static int read(int **buffer, bool sched_switch) * Only process hardware counters if at least one of the hardware counters is enabled. */ if (num_hardware_counters_enabled > 0) { -#if MALI_DDK_GATOR_API_VERSION != 3 - const unsigned int vithar_blocks[] = { - 0x700, /* VITHAR_JOB_MANAGER, Block 0 */ - 0x400, /* VITHAR_TILER, Block 1 */ - 0x000, /* VITHAR_SHADER_CORE, Block 2 */ - 0x500 /* VITHAR_MEMORY_SYSTEM, Block 3 */ - }; -#endif - #if MALI_DDK_GATOR_API_VERSION == 3 if (!handles) return -1; /* Mali symbols can be called safely since a kbcontext is valid */ - if (kbase_gator_instr_hwcnt_dump_complete_symbol(handles, &success) == MALI_TRUE) { + if (kbase_gator_instr_hwcnt_dump_complete_symbol(handles, &success)) { #else if (!kbcontext) return -1; /* Mali symbols can be called safely since a kbcontext is valid */ - if (kbase_instr_hwcnt_dump_complete_symbol(kbcontext, &success) == MALI_TRUE) { + if (kbase_instr_hwcnt_dump_complete_symbol(kbcontext, &success)) { #endif kbase_device_busy = false; - if (success == MALI_TRUE) { + if (success) { /* Cycle through hardware counters and accumulate totals */ for (cnt = 0; cnt < number_of_hardware_counters; cnt++) { const struct mali_counter *counter = &counters[cnt]; diff --git a/drivers/gator/gator_events_mali_midgard_hw_test.c b/drivers/gator/gator_events_mali_midgard_hw_test.c index 31a91e1c72b2..87c569cabf53 100644 --- a/drivers/gator/gator_events_mali_midgard_hw_test.c +++ b/drivers/gator/gator_events_mali_midgard_hw_test.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2012-2014. All rights reserved. + * Copyright (C) ARM Limited 2012-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/gator_events_meminfo.c b/drivers/gator/gator_events_meminfo.c index c625ac5af9cd..985b312ab92b 100644 --- a/drivers/gator/gator_events_meminfo.c +++ b/drivers/gator/gator_events_meminfo.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -58,6 +58,8 @@ static ulong proc_enabled[PROC_COUNT]; static ulong proc_keys[PROC_COUNT]; static DEFINE_PER_CPU(long long, proc_buffer[2 * (PROC_COUNT + 3)]); +static void do_read(void); + #if USE_THREAD static int gator_meminfo_func(void *data); @@ -177,6 +179,7 @@ static int gator_events_meminfo_start(void) if (GATOR_REGISTER_TRACE(mm_page_alloc)) goto mm_page_alloc_exit; + do_read(); #if USE_THREAD /* Start worker thread */ gator_meminfo_run = true; diff --git a/drivers/gator/gator_events_mmapped.c b/drivers/gator/gator_events_mmapped.c index 6b2af995ed41..7b517611f8ec 100644 --- a/drivers/gator/gator_events_mmapped.c +++ b/drivers/gator/gator_events_mmapped.c @@ -1,7 +1,7 @@ /* * Example events provider * - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/gator_events_net.c b/drivers/gator/gator_events_net.c index d21b4db7b77c..1e36731479d2 100644 --- a/drivers/gator/gator_events_net.c +++ b/drivers/gator/gator_events_net.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/gator_events_perf_pmu.c b/drivers/gator/gator_events_perf_pmu.c index 47cf278e508b..f6b4f18ad11a 100644 --- a/drivers/gator/gator_events_perf_pmu.c +++ b/drivers/gator/gator_events_perf_pmu.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -23,11 +23,13 @@ extern bool event_based_sampling; /* Maximum number of per-core counters - currently reserves enough space for two full hardware PMUs for big.LITTLE */ #define CNTMAX 16 #define CCI_400 4 +#define CCI_500 8 #define CCN_5XX 8 /* Maximum number of uncore counters */ /* + 1 for the cci-400 cycles counter */ +/* cci-500 has no cycles counter */ /* + 1 for the CCN-5xx cycles counter */ -#define UCCNT (CCI_400 + 1 + CCN_5XX + 1) +#define UCCNT (CCI_400 + 1 + CCI_500 + CCN_5XX + 1) /* Default to 0 if unable to probe the revision which was the previous behavior */ #define DEFAULT_CCI_REVISION 0 @@ -58,9 +60,9 @@ static struct gator_attr uc_attrs[UCCNT]; static int uc_attr_count; struct gator_event { - int curr; - int prev; - int prev_delta; + uint32_t curr; + uint32_t prev; + uint32_t prev_delta; bool zero; struct perf_event *pevent; struct perf_event_attr *pevent_attr; @@ -315,7 +317,7 @@ static void gator_events_perf_pmu_stop(void) static void __read(int *const len, int cpu, struct gator_attr *const attr, struct gator_event *const event) { - int delta; + uint32_t delta; struct perf_event *const ev = event->pevent; if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) { @@ -341,8 +343,6 @@ static void __read(int *const len, int cpu, struct gator_attr *const attr, struc event->prev_delta = delta; event->prev = event->curr; per_cpu(perf_cnt, cpu)[(*len)++] = attr->key; - if (delta < 0) - delta *= -1; per_cpu(perf_cnt, cpu)[(*len)++] = delta; } } @@ -436,13 +436,15 @@ static int probe_cci_revision(void) #endif -static void gator_events_perf_pmu_uncore_init(const char *const name, const int type, const int count) +static void gator_events_perf_pmu_uncore_init(const char *const name, const int type, const int count, const bool has_cycles_counter) { int cnt; - snprintf(uc_attrs[uc_attr_count].name, sizeof(uc_attrs[uc_attr_count].name), "%s_ccnt", name); - uc_attrs[uc_attr_count].type = type; - ++uc_attr_count; + if (has_cycles_counter) { + snprintf(uc_attrs[uc_attr_count].name, sizeof(uc_attrs[uc_attr_count].name), "%s_ccnt", name); + uc_attrs[uc_attr_count].type = type; + ++uc_attr_count; + } for (cnt = 0; cnt < count; ++cnt, ++uc_attr_count) { struct gator_attr *const attr = &uc_attrs[uc_attr_count]; @@ -452,7 +454,7 @@ static void gator_events_perf_pmu_uncore_init(const char *const name, const int } } -static void gator_events_perf_pmu_cci_init(const int type) +static void gator_events_perf_pmu_cci_400_init(const int type) { const char *cci_name; @@ -468,7 +470,7 @@ static void gator_events_perf_pmu_cci_init(const int type) return; } - gator_events_perf_pmu_uncore_init(cci_name, type, CCI_400); + gator_events_perf_pmu_uncore_init(cci_name, type, CCI_400, true); } static void gator_events_perf_pmu_cpu_init(const struct gator_cpu *const gator_cpu, const int type) @@ -535,9 +537,11 @@ int gator_events_perf_pmu_init(void) if (pe->pmu != NULL && type == pe->pmu->type) { if (strcmp("CCI", pe->pmu->name) == 0 || strcmp("CCI_400", pe->pmu->name) == 0 || strcmp("CCI_400-r1", pe->pmu->name) == 0) { - gator_events_perf_pmu_cci_init(type); + gator_events_perf_pmu_cci_400_init(type); + } else if (strcmp("CCI_500", pe->pmu->name) == 0) { + gator_events_perf_pmu_uncore_init("CCI_500", type, CCI_500, false); } else if (strcmp("ccn", pe->pmu->name) == 0) { - gator_events_perf_pmu_uncore_init("ARM_CCN_5XX", type, CCN_5XX); + gator_events_perf_pmu_uncore_init("ARM_CCN_5XX", type, CCN_5XX, true); } else if ((gator_cpu = gator_find_cpu_by_pmu_name(pe->pmu->name)) != NULL) { found_cpu = true; gator_events_perf_pmu_cpu_init(gator_cpu, type); @@ -549,10 +553,15 @@ int gator_events_perf_pmu_init(void) } if (!found_cpu) { - const struct gator_cpu *const gator_cpu = gator_find_cpu_by_cpuid(gator_cpuid()); + const struct gator_cpu *gator_cpu = gator_find_cpu_by_cpuid(gator_cpuid()); - if (gator_cpu == NULL) - return -1; + if (gator_cpu == NULL) { + gator_cpu = gator_find_cpu_by_cpuid(OTHER); + if (gator_cpu == NULL) { + pr_err("gator: Didn't find cpu\n"); + return -1; + } + } gator_events_perf_pmu_cpu_init(gator_cpu, PERF_TYPE_RAW); } diff --git a/drivers/gator/gator_events_sched.c b/drivers/gator/gator_events_sched.c index 637107d6af1d..463d83496073 100644 --- a/drivers/gator/gator_events_sched.c +++ b/drivers/gator/gator_events_sched.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/gator_events_scorpion.c b/drivers/gator/gator_events_scorpion.c index 49219362db09..b51dcd39a8e1 100644 --- a/drivers/gator/gator_events_scorpion.c +++ b/drivers/gator/gator_events_scorpion.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2011-2014. All rights reserved. + * Copyright (C) ARM Limited 2011-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/gator_hrtimer_gator.c b/drivers/gator/gator_hrtimer_gator.c index c1525e10a8da..36961f85b62a 100644 --- a/drivers/gator/gator_hrtimer_gator.c +++ b/drivers/gator/gator_hrtimer_gator.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2011-2014. All rights reserved. + * Copyright (C) ARM Limited 2011-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/gator_iks.c b/drivers/gator/gator_iks.c index fb78c10fd987..80535c7b2b6e 100644 --- a/drivers/gator/gator_iks.c +++ b/drivers/gator/gator_iks.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/gator_main.c b/drivers/gator/gator_main.c index 30bf60d95286..affa1dc312e4 100644 --- a/drivers/gator/gator_main.c +++ b/drivers/gator/gator_main.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -8,7 +8,7 @@ */ /* This version must match the gator daemon version */ -#define PROTOCOL_VERSION 20 +#define PROTOCOL_VERSION 21 static unsigned long gator_protocol_version = PROTOCOL_VERSION; #include @@ -28,6 +28,7 @@ static unsigned long gator_protocol_version = PROTOCOL_VERSION; #include #include "gator.h" +#include "gator_src_md5.h" #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32) #error kernels prior to 2.6.32 are not supported @@ -92,21 +93,17 @@ static unsigned long gator_protocol_version = PROTOCOL_VERSION; /* Name Frame Messages */ #define MESSAGE_COOKIE 1 #define MESSAGE_THREAD_NAME 2 -#define MESSAGE_LINK 4 /* Scheduler Trace Frame Messages */ #define MESSAGE_SCHED_SWITCH 1 #define MESSAGE_SCHED_EXIT 2 -/* Idle Frame Messages */ -#define MESSAGE_IDLE_ENTER 1 -#define MESSAGE_IDLE_EXIT 2 - /* Summary Frame Messages */ #define MESSAGE_SUMMARY 1 #define MESSAGE_CORE_NAME 3 /* Activity Frame Messages */ +#define MESSAGE_LINK 1 #define MESSAGE_SWITCH 2 #define MESSAGE_EXIT 3 @@ -267,6 +264,9 @@ GATOR_EVENTS_LIST * Misc ******************************************************************************/ +MODULE_PARM_DESC(gator_src_md5, "Gator driver source code md5sum"); +module_param_named(src_md5, gator_src_md5, charp, 0444); + static const struct gator_cpu gator_cpus[] = { { .cpuid = ARM1136, @@ -331,6 +331,13 @@ static const struct gator_cpu gator_cpus[] = { .dt_name = "arm,cortex-a15", .pmnc_counters = 6, }, + { + .cpuid = CORTEX_A12, + .core_name = "Cortex-A17", + .pmnc_name = "ARMv7_Cortex_A17", + .dt_name = "arm,cortex-a17", + .pmnc_counters = 6, + }, { .cpuid = CORTEX_A17, .core_name = "Cortex-A17", @@ -383,9 +390,10 @@ static const struct gator_cpu gator_cpus[] = { .pmnc_counters = 6, }, { - .cpuid = AARCH64, - .core_name = "AArch64", - .pmnc_name = "ARM_AArch64", + .cpuid = CORTEX_A72, + .core_name = "Cortex-A72", + .pmnc_name = "ARM_Cortex-A72", + .dt_name = "arm,cortex-a72", .pmnc_counters = 6, }, { @@ -443,7 +451,7 @@ u32 gator_cpuid(void) #else asm volatile("mrs %0, midr_el1" : "=r" (val)); #endif - return (val >> 4) & 0xfff; + return ((val & 0xff000000) >> 12) | ((val & 0xfff0) >> 4); #else return OTHER; #endif @@ -597,7 +605,7 @@ static void gator_send_core_name(const int cpu, const u32 cpuid) if (cpuid == -1) snprintf(core_name_buf, sizeof(core_name_buf), "Unknown"); else - snprintf(core_name_buf, sizeof(core_name_buf), "Unknown (0x%.3x)", cpuid); + snprintf(core_name_buf, sizeof(core_name_buf), "Unknown (0x%.5x)", cpuid); core_name = core_name_buf; } @@ -729,11 +737,11 @@ static void gator_emit_perf_time(u64 time) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) if (time >= gator_sync_time) { - int cpu = get_physical_cpu(); - marshal_event_single64(0, -1, local_clock()); gator_sync_time += NSEC_PER_SEC; - gator_commit_buffer(cpu, COUNTER_BUF, time); + if (gator_live_rate <= 0) { + gator_commit_buffer(get_physical_cpu(), COUNTER_BUF, time); + } } #endif } @@ -867,7 +875,9 @@ static void gator_summary(void) marshal_summary(timestamp, uptime, gator_monotonic_started, uname_buf); gator_sync_time = 0; - gator_emit_perf_time(gator_monotonic_started); + gator_emit_perf_time(gator_monotonic_started); + /* Always flush COUNTER_BUF so that the initial perf_time is received before it's used */ + gator_commit_buffer(get_physical_cpu(), COUNTER_BUF, 0); preempt_enable(); } diff --git a/drivers/gator/gator_marshaling.c b/drivers/gator/gator_marshaling.c index 0d1167643642..f5b81843d1c4 100644 --- a/drivers/gator/gator_marshaling.c +++ b/drivers/gator/gator_marshaling.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2012-2014. All rights reserved. + * Copyright (C) ARM Limited 2012-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -107,16 +107,16 @@ static void marshal_link(int cookie, int tgid, int pid) local_irq_save(flags); time = gator_get_time(); - if (buffer_check_space(cpu, NAME_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) { - gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_LINK); - gator_buffer_write_packed_int64(cpu, NAME_BUF, time); - gator_buffer_write_packed_int(cpu, NAME_BUF, cookie); - gator_buffer_write_packed_int(cpu, NAME_BUF, tgid); - gator_buffer_write_packed_int(cpu, NAME_BUF, pid); + if (buffer_check_space(cpu, ACTIVITY_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) { + gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, MESSAGE_LINK); + gator_buffer_write_packed_int64(cpu, ACTIVITY_BUF, time); + gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, cookie); + gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, tgid); + gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, pid); } local_irq_restore(flags); /* Check and commit; commit is set to occur once buffer is 3/4 full */ - buffer_check(cpu, NAME_BUF, time); + buffer_check(cpu, ACTIVITY_BUF, time); } static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, u64 time) diff --git a/drivers/gator/gator_trace_gpu.c b/drivers/gator/gator_trace_gpu.c index 5de9152e365a..d9b82ee1857f 100644 --- a/drivers/gator/gator_trace_gpu.c +++ b/drivers/gator/gator_trace_gpu.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/gator_trace_power.c b/drivers/gator/gator_trace_power.c index 46e04b29a187..aaa8f8636c83 100644 --- a/drivers/gator/gator_trace_power.c +++ b/drivers/gator/gator_trace_power.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2011-2014. All rights reserved. + * Copyright (C) ARM Limited 2011-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -80,13 +80,7 @@ GATOR_DEFINE_PROBE(cpu_idle, TP_PROTO(unsigned int state, unsigned int cpu)) return; if (implements_wfi()) { - if (state == PWR_EVENT_EXIT) { - /* transition from wfi to non-wfi */ - marshal_idle(cpu, MESSAGE_IDLE_EXIT); - } else { - /* transition from non-wfi to wfi */ - marshal_idle(cpu, MESSAGE_IDLE_ENTER); - } + marshal_idle(cpu, state); } per_cpu(idle_prev_state, cpu) = state; diff --git a/drivers/gator/gator_trace_sched.c b/drivers/gator/gator_trace_sched.c index 6d7cbd7348e1..ad7c39e14a17 100644 --- a/drivers/gator/gator_trace_sched.c +++ b/drivers/gator/gator_trace_sched.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/mali/mali_kbase_gator_api.h b/drivers/gator/mali/mali_kbase_gator_api.h deleted file mode 100644 index 5ed069797e36..000000000000 --- a/drivers/gator/mali/mali_kbase_gator_api.h +++ /dev/null @@ -1,219 +0,0 @@ -/** - * Copyright (C) ARM Limited 2014. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#ifndef _KBASE_GATOR_API_H_ -#define _KBASE_GATOR_API_H_ - -/** - * @brief This file describes the API used by Gator to collect hardware counters data from a Mali device. - */ - -/* This define is used by the gator kernel module compile to select which DDK - * API calling convention to use. If not defined (legacy DDK) gator assumes - * version 1. The version to DDK release mapping is: - * Version 1 API: DDK versions r1px, r2px - * Version 2 API: DDK versions r3px, r4px - * Version 3 API: DDK version r5p0 and newer - * - * API Usage - * ========= - * - * 1] Call kbase_gator_hwcnt_init_names() to return the list of short counter - * names for the GPU present in this device. - * - * 2] Create a kbase_gator_hwcnt_info structure and set the counter enables for - * the counters you want enabled. The enables can all be set for simplicity in - * most use cases, but disabling some will let you minimize bandwidth impact. - * - * 3] Call kbase_gator_hwcnt_init() using the above structure, to create a - * counter context. On successful return the DDK will have populated the - * structure with a variety of useful information. - * - * 4] Call kbase_gator_hwcnt_dump_irq() to queue a non-blocking request for a - * counter dump. If this returns a non-zero value the request has been queued, - * otherwise the driver has been unable to do so (typically because of another - * user of the instrumentation exists concurrently). - * - * 5] Call kbase_gator_hwcnt_dump_complete() to test whether the previously - * requested dump has been succesful. If this returns non-zero the counter dump - * has resolved, but the value of *success must also be tested as the dump - * may have not been successful. If it returns zero the counter dump was - * abandoned due to the device being busy (typically because of another - * user of the instrumentation exists concurrently). - * - * 6] Process the counters stored in the buffer pointed to by ... - * - * kbase_gator_hwcnt_info->kernel_dump_buffer - * - * In pseudo code you can find all of the counters via this approach: - * - * - * hwcnt_info # pointer to kbase_gator_hwcnt_info structure - * hwcnt_name # pointer to name list - * - * u32 * hwcnt_data = (u32*)hwcnt_info->kernel_dump_buffer - * - * # Iterate over each 64-counter block in this GPU configuration - * for( i = 0; i < hwcnt_info->nr_hwc_blocks; i++) { - * hwc_type type = hwcnt_info->hwc_layout[i]; - * - * # Skip reserved type blocks - they contain no counters at all - * if( type == RESERVED_BLOCK ) { - * continue; - * } - * - * size_t name_offset = type * 64; - * size_t data_offset = i * 64; - * - * # Iterate over the names of the counters in this block type - * for( j = 0; j < 64; j++) { - * const char * name = hwcnt_name[name_offset+j]; - * - * # Skip empty name strings - there is no counter here - * if( name[0] == '\0' ) { - * continue; - * } - * - * u32 data = hwcnt_data[data_offset+j]; - * - * printk( "COUNTER: %s DATA: %u\n", name, data ); - * } - * } - * - * - * Note that in most implementations you typically want to either SUM or - * AVERAGE multiple instances of the same counter if, for example, you have - * multiple shader cores or multiple L2 caches. The most sensible view for - * analysis is to AVERAGE shader core counters, but SUM L2 cache and MMU - * counters. - * - * 7] Goto 4, repeating until you want to stop collecting counters. - * - * 8] Release the dump resources by calling kbase_gator_hwcnt_term(). - * - * 9] Release the name table resources by calling kbase_gator_hwcnt_term_names(). - * This function must only be called if init_names() returned a non-NULL value. - **/ - -#define MALI_DDK_GATOR_API_VERSION 3 - -#if !defined(MALI_TRUE) - #define MALI_TRUE ((uint32_t)1) -#endif - -#if !defined(MALI_FALSE) - #define MALI_FALSE ((uint32_t)0) -#endif - -enum hwc_type { - JM_BLOCK = 0, - TILER_BLOCK, - SHADER_BLOCK, - MMU_L2_BLOCK, - RESERVED_BLOCK -}; - -struct kbase_gator_hwcnt_info { - - /* Passed from Gator to kbase */ - - /* the bitmask of enabled hardware counters for each counter block */ - uint16_t bitmask[4]; - - /* Passed from kbase to Gator */ - - /* ptr to counter dump memory */ - void *kernel_dump_buffer; - - /* size of counter dump memory */ - uint32_t size; - - /* the ID of the Mali device */ - uint32_t gpu_id; - - /* the number of shader cores in the GPU */ - uint32_t nr_cores; - - /* the number of core groups */ - uint32_t nr_core_groups; - - /* the memory layout of the performance counters */ - enum hwc_type *hwc_layout; - - /* the total number of hardware couter blocks */ - uint32_t nr_hwc_blocks; -}; - -/** - * @brief Opaque block of Mali data which Gator needs to return to the API later. - */ -struct kbase_gator_hwcnt_handles; - -/** - * @brief Initialize the resources Gator needs for performance profiling. - * - * @param in_out_info A pointer to a structure containing the enabled counters passed from Gator and all the Mali - * specific information that will be returned to Gator. On entry Gator must have populated the - * 'bitmask' field with the counters it wishes to enable for each class of counter block. - * Each entry in the array corresponds to a single counter class based on the "hwc_type" - * enumeration, and each bit corresponds to an enable for 4 sequential counters (LSB enables - * the first 4 counters in the block, and so on). See the GPU counter array as returned by - * kbase_gator_hwcnt_get_names() for the index values of each counter for the curernt GPU. - * - * @return Pointer to an opaque handle block on success, NULL on error. - */ -extern struct kbase_gator_hwcnt_handles *kbase_gator_hwcnt_init(struct kbase_gator_hwcnt_info *in_out_info); - -/** - * @brief Free all resources once Gator has finished using performance counters. - * - * @param in_out_info A pointer to a structure containing the enabled counters passed from Gator and all the - * Mali specific information that will be returned to Gator. - * @param opaque_handles A wrapper structure for kbase structures. - */ -extern void kbase_gator_hwcnt_term(struct kbase_gator_hwcnt_info *in_out_info, struct kbase_gator_hwcnt_handles *opaque_handles); - -/** - * @brief Poll whether a counter dump is successful. - * - * @param opaque_handles A wrapper structure for kbase structures. - * @param[out] success Non-zero on success, zero on failure. - * - * @return Zero if the dump is still pending, non-zero if the dump has completed. Note that a - * completed dump may not have dumped succesfully, so the caller must test for both - * a completed and successful dump before processing counters. - */ -extern uint32_t kbase_gator_instr_hwcnt_dump_complete(struct kbase_gator_hwcnt_handles *opaque_handles, uint32_t * const success); - -/** - * @brief Request the generation of a new counter dump. - * - * @param opaque_handles A wrapper structure for kbase structures. - * - * @return Zero if the hardware device is busy and cannot handle the request, non-zero otherwise. - */ -extern uint32_t kbase_gator_instr_hwcnt_dump_irq(struct kbase_gator_hwcnt_handles *opaque_handles); - -/** - * @brief This function is used to fetch the names table based on the Mali device in use. - * - * @param[out] total_number_of_counters The total number of counters short names in the Mali devices' list. - * - * @return Pointer to an array of strings of length *total_number_of_counters. - */ -extern const char * const *kbase_gator_hwcnt_init_names(uint32_t *total_number_of_counters); - -/** - * @brief This function is used to terminate the use of the names table. - * - * This function must only be called if the initial call to kbase_gator_hwcnt_init_names returned a non-NULL value. - */ -extern void kbase_gator_hwcnt_term_names(void); - -#endif diff --git a/drivers/gator/mali/mali_mjollnir_profiling_gator_api.h b/drivers/gator/mali/mali_mjollnir_profiling_gator_api.h index 2bc0b037eee6..a5d165157396 100644 --- a/drivers/gator/mali/mali_mjollnir_profiling_gator_api.h +++ b/drivers/gator/mali/mali_mjollnir_profiling_gator_api.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/mali/mali_utgard_profiling_gator_api.h b/drivers/gator/mali/mali_utgard_profiling_gator_api.h index d6465312628e..f550490c2c39 100644 --- a/drivers/gator/mali/mali_utgard_profiling_gator_api.h +++ b/drivers/gator/mali/mali_utgard_profiling_gator_api.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/gator/mali_midgard.mk b/drivers/gator/mali_midgard.mk index 1b784d5c3d58..b0076c22da6b 100644 --- a/drivers/gator/mali_midgard.mk +++ b/drivers/gator/mali_midgard.mk @@ -23,6 +23,7 @@ endif ifneq ($(wildcard $(DDK_DIR)/drivers/gpu/arm/midgard/mali_kbase_gator_api.h),) EXTRA_CFLAGS += -DMALI_SIMPLE_API=1 +EXTRA_CFLAGS += -I$(DDK_DIR)/drivers/gpu/arm/midgard endif UMP_DIR = $(DDK_DIR)/include/linux diff --git a/tools/gator/daemon/Android.mk b/tools/gator/daemon/Android.mk index 970ac6946150..68f4a8397379 100644 --- a/tools/gator/daemon/Android.mk +++ b/tools/gator/daemon/Android.mk @@ -1,13 +1,12 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) -XML_H := $(shell cd $(LOCAL_PATH) && make events_xml.h defaults_xml.h) +XML_H := $(shell cd $(LOCAL_PATH) && make events_xml.h defaults_xml.h SrcMd5.cpp) LOCAL_SRC_FILES := \ AnnotateListener.cpp \ Buffer.cpp \ CCNDriver.cpp \ - CPUFreqDriver.cpp \ CapturedXML.cpp \ Child.cpp \ Command.cpp \ @@ -43,6 +42,7 @@ LOCAL_SRC_FILES := \ SessionXML.cpp \ Setup.cpp \ Source.cpp \ + SrcMd5.cpp \ StreamlineSetup.cpp \ UEvent.cpp \ UserSpaceSource.cpp \ diff --git a/tools/gator/daemon/AnnotateListener.cpp b/tools/gator/daemon/AnnotateListener.cpp index 50110b4dc84c..5966cbea8d13 100644 --- a/tools/gator/daemon/AnnotateListener.cpp +++ b/tools/gator/daemon/AnnotateListener.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2014. All rights reserved. + * Copyright (C) ARM Limited 2014-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -12,36 +12,56 @@ #include "OlySocket.h" +static const char STREAMLINE_ANNOTATE_PARENT[] = "\0streamline-annotate-parent"; + struct AnnotateClient { AnnotateClient *next; int fd; }; -AnnotateListener::AnnotateListener() : mClients(NULL), mSock(NULL) { +AnnotateListener::AnnotateListener() : mClients(NULL), mSock(NULL), mUds(NULL) { } AnnotateListener::~AnnotateListener() { close(); + delete mUds; delete mSock; } void AnnotateListener::setup() { mSock = new OlyServerSocket(8082); + mUds = new OlyServerSocket(STREAMLINE_ANNOTATE_PARENT, sizeof(STREAMLINE_ANNOTATE_PARENT), true); } -int AnnotateListener::getFd() { +int AnnotateListener::getSockFd() { return mSock->getFd(); } -void AnnotateListener::handle() { +void AnnotateListener::handleSock() { AnnotateClient *const client = new AnnotateClient(); client->fd = mSock->acceptConnection(); client->next = mClients; mClients = client; } +int AnnotateListener::getUdsFd() { + return mUds->getFd(); +} + +void AnnotateListener::handleUds() { + AnnotateClient *const client = new AnnotateClient(); + client->fd = mUds->acceptConnection(); + client->next = mClients; + mClients = client; +} + void AnnotateListener::close() { - mSock->closeServerSocket(); + if (mUds != NULL) { + mUds->closeServerSocket(); + } + if (mSock != NULL) { + mSock->closeServerSocket(); + } while (mClients != NULL) { ::close(mClients->fd); AnnotateClient *next = mClients->next; diff --git a/tools/gator/daemon/AnnotateListener.h b/tools/gator/daemon/AnnotateListener.h index cdefef12db22..6bc747d42d18 100644 --- a/tools/gator/daemon/AnnotateListener.h +++ b/tools/gator/daemon/AnnotateListener.h @@ -1,12 +1,15 @@ /** - * Copyright (C) ARM Limited 2014. All rights reserved. + * Copyright (C) ARM Limited 2014-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -class AnnotateClient; +#ifndef ANNOTATELISTENER_H +#define ANNOTATELISTENER_H + +struct AnnotateClient; class OlyServerSocket; class AnnotateListener { @@ -15,17 +18,22 @@ public: ~AnnotateListener(); void setup(); - int getFd(); + int getSockFd(); + int getUdsFd(); - void handle(); + void handleSock(); + void handleUds(); void close(); void signal(); private: AnnotateClient *mClients; OlyServerSocket *mSock; + OlyServerSocket *mUds; // Intentionally unimplemented AnnotateListener(const AnnotateListener &); AnnotateListener &operator=(const AnnotateListener &); }; + +#endif // ANNOTATELISTENER_H diff --git a/tools/gator/daemon/Application.mk b/tools/gator/daemon/Application.mk index 3ada471cac19..8b0a7882e938 100644 --- a/tools/gator/daemon/Application.mk +++ b/tools/gator/daemon/Application.mk @@ -1,3 +1,3 @@ -APP_PLATFORM := android-8 +APP_PLATFORM := android-9 # Replace armeabi-v7a with arm64-v8a to build an arm64 gatord or with armeabi to build an ARM11 gatord APP_ABI := armeabi-v7a diff --git a/tools/gator/daemon/Buffer.cpp b/tools/gator/daemon/Buffer.cpp index 8fa628015069..c4ced9f607f9 100644 --- a/tools/gator/daemon/Buffer.cpp +++ b/tools/gator/daemon/Buffer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -13,17 +13,19 @@ #include "SessionData.h" #define mask (mSize - 1) +#define FRAME_HEADER_SIZE 3 enum { - CODE_PEA = 1, - CODE_KEYS = 2, - CODE_FORMAT = 3, - CODE_MAPS = 4, - CODE_COMM = 5, - CODE_KEYS_OLD = 6, - CODE_ONLINE_CPU = 7, - CODE_OFFLINE_CPU = 8, - CODE_KALLSYMS = 9, + CODE_PEA = 1, + CODE_KEYS = 2, + CODE_FORMAT = 3, + CODE_MAPS = 4, + CODE_COMM = 5, + CODE_KEYS_OLD = 6, + CODE_ONLINE_CPU = 7, + CODE_OFFLINE_CPU = 8, + CODE_KALLSYMS = 9, + CODE_COUNTERS = 10, }; // Summary Frame Messages @@ -47,7 +49,7 @@ enum { Buffer::Buffer(const int32_t core, const int32_t buftype, const int size, sem_t *const readerSem) : mBuf(new char[size]), mReaderSem(readerSem), mCommitTime(gSessionData->mLiveRate), mSize(size), mReadPos(0), mWritePos(0), mCommitPos(0), mAvailable(true), mIsDone(false), mCore(core), mBufType(buftype) { if ((mSize & mask) != 0) { - logg->logError(__FILE__, __LINE__, "Buffer size is not a power of 2"); + logg->logError("Buffer size is not a power of 2"); handleException(); } sem_init(&mWriterSem, 0, 0); @@ -141,7 +143,7 @@ int Buffer::contiguousSpaceAvailable() const { } } -void Buffer::commit(const uint64_t time) { +void Buffer::commit(const uint64_t time, const bool force) { // post-populate the length, which does not include the response type length nor the length itself, i.e. only the length of the payload const int typeLength = gSessionData->mLocalCapture ? 0 : 1; int length = mWritePos - mCommitPos; @@ -149,6 +151,10 @@ void Buffer::commit(const uint64_t time) { length += mSize; } length = length - typeLength - sizeof(int32_t); + if (!force && !mIsDone && length <= FRAME_HEADER_SIZE) { + // Nothing to write, only the frame header is present + return; + } for (size_t byte = 0; byte < sizeof(int32_t); byte++) { mBuf[(mCommitPos + typeLength + byte) & mask] = (length >> byte * 8) & 0xFF; } @@ -317,7 +323,7 @@ void Buffer::event64(const int key, const int64_t value) { } } -void Buffer::pea(const uint64_t currTime, const struct perf_event_attr *const pea, int key) { +void Buffer::marshalPea(const uint64_t currTime, const struct perf_event_attr *const pea, int key) { while (!checkSpace(2 * MAXSIZE_PACK32 + pea->size)) { sem_wait(&mWriterSem); } @@ -327,7 +333,7 @@ void Buffer::pea(const uint64_t currTime, const struct perf_event_attr *const pe check(currTime); } -void Buffer::keys(const uint64_t currTime, const int count, const __u64 *const ids, const int *const keys) { +void Buffer::marshalKeys(const uint64_t currTime, const int count, const __u64 *const ids, const int *const keys) { while (!checkSpace(2 * MAXSIZE_PACK32 + count * (MAXSIZE_PACK32 + MAXSIZE_PACK64))) { sem_wait(&mWriterSem); } @@ -340,7 +346,7 @@ void Buffer::keys(const uint64_t currTime, const int count, const __u64 *const i check(currTime); } -void Buffer::keysOld(const uint64_t currTime, const int keyCount, const int *const keys, const int bytes, const char *const buf) { +void Buffer::marshalKeysOld(const uint64_t currTime, const int keyCount, const int *const keys, const int bytes, const char *const buf) { while (!checkSpace((2 + keyCount) * MAXSIZE_PACK32 + bytes)) { sem_wait(&mWriterSem); } @@ -353,7 +359,7 @@ void Buffer::keysOld(const uint64_t currTime, const int keyCount, const int *con check(currTime); } -void Buffer::format(const uint64_t currTime, const int length, const char *const format) { +void Buffer::marshalFormat(const uint64_t currTime, const int length, const char *const format) { while (!checkSpace(MAXSIZE_PACK32 + length + 1)) { sem_wait(&mWriterSem); } @@ -362,7 +368,7 @@ void Buffer::format(const uint64_t currTime, const int length, const char *const check(currTime); } -void Buffer::maps(const uint64_t currTime, const int pid, const int tid, const char *const maps) { +void Buffer::marshalMaps(const uint64_t currTime, const int pid, const int tid, const char *const maps) { const int mapsLen = strlen(maps) + 1; while (!checkSpace(3 * MAXSIZE_PACK32 + mapsLen)) { sem_wait(&mWriterSem); @@ -374,7 +380,7 @@ void Buffer::maps(const uint64_t currTime, const int pid, const int tid, const c check(currTime); } -void Buffer::comm(const uint64_t currTime, const int pid, const int tid, const char *const image, const char *const comm) { +void Buffer::marshalComm(const uint64_t currTime, const int pid, const int tid, const char *const image, const char *const comm) { const int imageLen = strlen(image) + 1; const int commLen = strlen(comm) + 1; while (!checkSpace(3 * MAXSIZE_PACK32 + imageLen + commLen)) { @@ -388,27 +394,27 @@ void Buffer::comm(const uint64_t currTime, const int pid, const int tid, const c check(currTime); } -void Buffer::onlineCPU(const uint64_t currTime, const uint64_t time, const int cpu) { +void Buffer::onlineCPU(const uint64_t currTime, const int cpu) { while (!checkSpace(MAXSIZE_PACK32 + MAXSIZE_PACK64)) { sem_wait(&mWriterSem); } packInt(CODE_ONLINE_CPU); - packInt64(time); + packInt64(currTime); packInt(cpu); check(currTime); } -void Buffer::offlineCPU(const uint64_t currTime, const uint64_t time, const int cpu) { +void Buffer::offlineCPU(const uint64_t currTime, const int cpu) { while (!checkSpace(MAXSIZE_PACK32 + MAXSIZE_PACK64)) { sem_wait(&mWriterSem); } packInt(CODE_OFFLINE_CPU); - packInt64(time); + packInt64(currTime); packInt(cpu); check(currTime); } -void Buffer::kallsyms(const uint64_t currTime, const char *const kallsyms) { +void Buffer::marshalKallsyms(const uint64_t currTime, const char *const kallsyms) { const int kallsymsLen = strlen(kallsyms) + 1; while (!checkSpace(3 * MAXSIZE_PACK32 + kallsymsLen)) { sem_wait(&mWriterSem); @@ -418,6 +424,31 @@ void Buffer::kallsyms(const uint64_t currTime, const char *const kallsyms) { check(currTime); } +void Buffer::perfCounterHeader(const uint64_t time) { + while (!checkSpace(MAXSIZE_PACK32 + MAXSIZE_PACK64)) { + sem_wait(&mWriterSem); + } + packInt(CODE_COUNTERS); + packInt64(time); +} + +void Buffer::perfCounter(const int core, const int key, const int64_t value) { + while (!checkSpace(2*MAXSIZE_PACK32 + MAXSIZE_PACK64)) { + sem_wait(&mWriterSem); + } + packInt(core); + packInt(key); + packInt64(value); +} + +void Buffer::perfCounterFooter(const uint64_t currTime) { + while (!checkSpace(MAXSIZE_PACK32)) { + sem_wait(&mWriterSem); + } + packInt(-1); + check(currTime); +} + void Buffer::setDone() { mIsDone = true; commit(0); diff --git a/tools/gator/daemon/Buffer.h b/tools/gator/daemon/Buffer.h index 6cffd8e39a36..13c44e1fd359 100644 --- a/tools/gator/daemon/Buffer.h +++ b/tools/gator/daemon/Buffer.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -36,7 +36,7 @@ public: int bytesAvailable() const; int contiguousSpaceAvailable() const; - void commit(const uint64_t time); + void commit(const uint64_t time, const bool force = false); void check(const uint64_t time); // Summary messages @@ -50,15 +50,18 @@ public: void event64(int key, int64_t value); // Perf Attrs messages - void pea(const uint64_t currTime, const struct perf_event_attr *const pea, int key); - void keys(const uint64_t currTime, const int count, const __u64 *const ids, const int *const keys); - void keysOld(const uint64_t currTime, const int keyCount, const int *const keys, const int bytes, const char *const buf); - void format(const uint64_t currTime, const int length, const char *const format); - void maps(const uint64_t currTime, const int pid, const int tid, const char *const maps); - void comm(const uint64_t currTime, const int pid, const int tid, const char *const image, const char *const comm); - void onlineCPU(const uint64_t currTime, const uint64_t time, const int cpu); - void offlineCPU(const uint64_t currTime, const uint64_t time, const int cpu); - void kallsyms(const uint64_t currTime, const char *const kallsyms); + void marshalPea(const uint64_t currTime, const struct perf_event_attr *const pea, int key); + void marshalKeys(const uint64_t currTime, const int count, const __u64 *const ids, const int *const keys); + void marshalKeysOld(const uint64_t currTime, const int keyCount, const int *const keys, const int bytes, const char *const buf); + void marshalFormat(const uint64_t currTime, const int length, const char *const format); + void marshalMaps(const uint64_t currTime, const int pid, const int tid, const char *const maps); + void marshalComm(const uint64_t currTime, const int pid, const int tid, const char *const image, const char *const comm); + void onlineCPU(const uint64_t currTime, const int cpu); + void offlineCPU(const uint64_t currTime, const int cpu); + void marshalKallsyms(const uint64_t currTime, const char *const kallsyms); + void perfCounterHeader(const uint64_t time); + void perfCounter(const int core, const int key, const int64_t value); + void perfCounterFooter(const uint64_t currTime); void setDone(); bool isDone() const; diff --git a/tools/gator/daemon/CCNDriver.cpp b/tools/gator/daemon/CCNDriver.cpp index dd1a2b133842..d77513acc4e4 100644 --- a/tools/gator/daemon/CCNDriver.cpp +++ b/tools/gator/daemon/CCNDriver.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2014. All rights reserved. + * Copyright (C) ARM Limited 2014-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -28,7 +28,6 @@ static const char TAG_OPTION_SET[] = "option_set"; static const char ATTR_AVERAGE_SELECTION[] = "average_selection"; static const char ATTR_COUNTER[] = "counter"; -static const char ATTR_COUNTER_SET[] = "counter_set"; static const char ATTR_COUNT[] = "count"; static const char ATTR_DESCRIPTION[] = "description"; static const char ATTR_DISPLAY[] = "display"; @@ -110,7 +109,7 @@ void CCNDriver::readEvents(mxml_node_t *const) { int type; if (DriverSource::readIntDriver("/sys/bus/event_source/devices/ccn/type", &type) != 0) { - logg->logError(__FILE__, __LINE__, "Unable to read CCN-5xx type"); + logg->logError("Unable to read CCN-5xx type"); handleException(); } diff --git a/tools/gator/daemon/CCNDriver.h b/tools/gator/daemon/CCNDriver.h index fb4c717e969a..06ac33f07a36 100644 --- a/tools/gator/daemon/CCNDriver.h +++ b/tools/gator/daemon/CCNDriver.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2014. All rights reserved. + * Copyright (C) ARM Limited 2014-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/COPYING b/tools/gator/daemon/COPYING new file mode 100644 index 000000000000..d159169d1050 --- /dev/null +++ b/tools/gator/daemon/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/tools/gator/daemon/CPUFreqDriver.cpp b/tools/gator/daemon/CPUFreqDriver.cpp deleted file mode 100644 index 41f9d6f2b3f4..000000000000 --- a/tools/gator/daemon/CPUFreqDriver.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include "CPUFreqDriver.h" - -#include "Buffer.h" -#include "DriverSource.h" -#include "Logging.h" -#include "SessionData.h" - -CPUFreqDriver::CPUFreqDriver() : mPrev() { -} - -CPUFreqDriver::~CPUFreqDriver() { -} - -void CPUFreqDriver::readEvents(mxml_node_t *const) { - // Only for use with perf - if (!gSessionData->perf.isSetup()) { - return; - } - - setCounters(new DriverCounter(getCounters(), strdup("Linux_power_cpu_freq"))); -} - -void CPUFreqDriver::read(Buffer *const buffer) { - char buf[64]; - const DriverCounter *const counter = getCounters(); - if ((counter == NULL) || !counter->isEnabled()) { - return; - } - - const int key = getCounters()->getKey(); - bool resetCores = false; - for (int i = 0; i < gSessionData->mCores; ++i) { - snprintf(buf, sizeof(buf), "/sys/devices/system/cpu/cpu%i/cpufreq/cpuinfo_cur_freq", i); - int64_t freq; - if (DriverSource::readInt64Driver(buf, &freq) != 0) { - freq = 0; - } - if (mPrev[i] != freq) { - mPrev[i] = freq; - // Change cores - buffer->event64(2, i); - resetCores = true; - buffer->event64(key, 1000*freq); - } - } - if (resetCores) { - // Revert cores, UserSpaceSource is all on core 0 - buffer->event64(2, 0); - } -} diff --git a/tools/gator/daemon/CPUFreqDriver.h b/tools/gator/daemon/CPUFreqDriver.h deleted file mode 100644 index ad8c9aaa9e7d..000000000000 --- a/tools/gator/daemon/CPUFreqDriver.h +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef CPUFREQDRIVER_H -#define CPUFREQDRIVER_H - -#include "Config.h" -#include "Driver.h" - -class CPUFreqDriver : public PolledDriver { -private: - typedef PolledDriver super; - -public: - CPUFreqDriver(); - ~CPUFreqDriver(); - - void readEvents(mxml_node_t *const root); - void read(Buffer *const buffer); - -private: - int64_t mPrev[NR_CPUS]; - - // Intentionally unimplemented - CPUFreqDriver(const CPUFreqDriver &); - CPUFreqDriver &operator=(const CPUFreqDriver &); -}; - -#endif // CPUFREQDRIVER_H diff --git a/tools/gator/daemon/CapturedXML.cpp b/tools/gator/daemon/CapturedXML.cpp index 0b5802c893bb..1854c77dcb0e 100644 --- a/tools/gator/daemon/CapturedXML.cpp +++ b/tools/gator/daemon/CapturedXML.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -34,7 +34,6 @@ mxml_node_t* CapturedXML::getTree(bool includeTime) { mxmlElementSetAttr(captured, "version", "1"); if (gSessionData->perf.isSetup()) { mxmlElementSetAttr(captured, "type", "Perf"); - mxmlElementSetAttr(captured, "perf_beta", "yes"); } mxmlElementSetAttrf(captured, "protocol", "%d", PROTOCOL_VERSION); if (includeTime) { // Send the following only after the capture is complete @@ -98,7 +97,7 @@ void CapturedXML::write(char* path) { char* xml = getXML(true); if (util->writeToDisk(file, xml) < 0) { - logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file); + logg->logError("Error writing %s\nPlease verify the path.", file); handleException(); } diff --git a/tools/gator/daemon/CapturedXML.h b/tools/gator/daemon/CapturedXML.h index b704f6e53bb5..69d80c09b514 100644 --- a/tools/gator/daemon/CapturedXML.h +++ b/tools/gator/daemon/CapturedXML.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/Child.cpp b/tools/gator/daemon/Child.cpp index 6b5bbb3bf6af..a19e9cf86805 100644 --- a/tools/gator/daemon/Child.cpp +++ b/tools/gator/daemon/Child.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -150,13 +150,12 @@ static void *senderThread(void *) { prctl(PR_SET_NAME, (unsigned long)&"gatord-sender", 0, 0, 0); sem_wait(&haltPipeline); - while (!primarySource->isDone() || - !externalSource->isDone() || + while (!externalSource->isDone() || (userSpaceSource != NULL && !userSpaceSource->isDone()) || - (ftraceSource != NULL && !ftraceSource->isDone())) { + (ftraceSource != NULL && !ftraceSource->isDone()) || + !primarySource->isDone()) { sem_wait(&senderSem); - primarySource->write(sender); externalSource->write(sender); if (userSpaceSource != NULL) { userSpaceSource->write(sender); @@ -164,6 +163,7 @@ static void *senderThread(void *) { if (ftraceSource != NULL) { ftraceSource->write(sender); } + primarySource->write(sender); } // write end-of-capture sequence @@ -232,7 +232,7 @@ void Child::run() { sender = new Sender(socket); if (mNumConnections > 1) { - logg->logError(__FILE__, __LINE__, "Session already in progress"); + logg->logError("Session already in progress"); handleException(); } @@ -267,7 +267,7 @@ void Child::run() { char* xmlString; xmlString = util->readFromDisk(gSessionData->mSessionXMLPath); if (xmlString == 0) { - logg->logError(__FILE__, __LINE__, "Unable to read session xml file: %s", gSessionData->mSessionXMLPath); + logg->logError("Unable to read session xml file: %s", gSessionData->mSessionXMLPath); handleException(); } gSessionData->parseSessionXML(xmlString); @@ -280,16 +280,27 @@ void Child::run() { } if (gSessionData->kmod.isMaliCapture() && (gSessionData->mSampleRate == 0)) { - logg->logError(__FILE__, __LINE__, "Mali counters are not supported with Sample Rate: None."); + logg->logError("Mali counters are not supported with Sample Rate: None."); handleException(); } + // Initialize ftrace source before child as it's slow and dependens on nothing else + // If initialized later, us gator with ftrace has time sync issues + if (gSessionData->ftraceDriver.countersEnabled()) { + ftraceSource = new FtraceSource(&senderSem); + if (!ftraceSource->prepare()) { + logg->logError("Unable to prepare userspace source for capture"); + handleException(); + } + ftraceSource->start(); + } + // Must be after session XML is parsed if (!primarySource->prepare()) { if (gSessionData->perf.isSetup()) { - logg->logError(__FILE__, __LINE__, "Unable to prepare gator driver for capture"); + logg->logError("Unable to communicate with the perf API, please ensure that CONFIG_TRACING and CONFIG_CONTEXT_SWITCH_TRACER are enabled. Please refer to README_Streamline.txt for more information."); } else { - logg->logError(__FILE__, __LINE__, "Unable to communicate with the perf API, please ensure that CONFIG_TRACING and CONFIG_CONTEXT_SWITCH_TRACER are enabled. Please refer to README_Streamline.txt for more information."); + logg->logError("Unable to prepare gator driver for capture"); } handleException(); } @@ -300,7 +311,7 @@ void Child::run() { // Must be initialized before senderThread is started as senderThread checks externalSource externalSource = new ExternalSource(&senderSem); if (!externalSource->prepare()) { - logg->logError(__FILE__, __LINE__, "Unable to prepare external source for capture"); + logg->logError("Unable to prepare external source for capture"); handleException(); } externalSource->start(); @@ -324,21 +335,12 @@ void Child::run() { if (startUSSource) { userSpaceSource = new UserSpaceSource(&senderSem); if (!userSpaceSource->prepare()) { - logg->logError(__FILE__, __LINE__, "Unable to prepare userspace source for capture"); + logg->logError("Unable to prepare userspace source for capture"); handleException(); } userSpaceSource->start(); } - if (gSessionData->ftraceDriver.countersEnabled()) { - ftraceSource = new FtraceSource(&senderSem); - if (!ftraceSource->prepare()) { - logg->logError(__FILE__, __LINE__, "Unable to prepare userspace source for capture"); - handleException(); - } - ftraceSource->start(); - } - if (gSessionData->mAllowCommands && (gSessionData->mCaptureCommand != NULL)) { pthread_t thread; if (pthread_create(&thread, NULL, commandThread, NULL)) { @@ -347,7 +349,7 @@ void Child::run() { } if (!thread_creation_success) { - logg->logError(__FILE__, __LINE__, "Failed to create gator threads"); + logg->logError("Failed to create gator threads"); handleException(); } @@ -357,6 +359,7 @@ void Child::run() { // Start profiling primarySource->run(); + // Wait for the other threads to exit if (ftraceSource != NULL) { ftraceSource->join(); } @@ -364,8 +367,6 @@ void Child::run() { userSpaceSource->join(); } externalSource->join(); - - // Wait for the other threads to exit pthread_join(senderThreadID, NULL); // Shutting down the connection should break the stop thread which is stalling on the socket recv() function diff --git a/tools/gator/daemon/Child.h b/tools/gator/daemon/Child.h index cc78202ceb5c..a6c54db70a70 100644 --- a/tools/gator/daemon/Child.h +++ b/tools/gator/daemon/Child.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/Command.cpp b/tools/gator/daemon/Command.cpp index 28d73cf5a905..0a6e3b9901ee 100644 --- a/tools/gator/daemon/Command.cpp +++ b/tools/gator/daemon/Command.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2014. All rights reserved. + * Copyright (C) ARM Limited 2014-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -39,7 +39,7 @@ static int getUid(const char *const name, char *const shPath, const char *const const int pid = fork(); if (pid < 0) { - logg->logError(__FILE__, __LINE__, "fork failed"); + logg->logError("fork failed"); handleException(); } if (pid == 0) { @@ -94,7 +94,7 @@ void *commandThread(void *) { const char *const name = gSessionData->mCaptureUser == NULL ? "nobody" : gSessionData->mCaptureUser; const int uid = getUid(name); if (uid < 0) { - logg->logError(__FILE__, __LINE__, "Unable to lookup the user %s, please double check that the user exists", name); + logg->logError("Unable to look up the user %s, please double check that the user exists", name); handleException(); } @@ -103,13 +103,13 @@ void *commandThread(void *) { char buf[128]; int pipefd[2]; if (pipe_cloexec(pipefd) != 0) { - logg->logError(__FILE__, __LINE__, "pipe failed"); + logg->logError("pipe failed"); handleException(); } const int pid = fork(); if (pid < 0) { - logg->logError(__FILE__, __LINE__, "fork failed"); + logg->logError("fork failed"); handleException(); } if (pid == 0) { @@ -163,7 +163,7 @@ void *commandThread(void *) { close(pipefd[1]); const ssize_t bytes = read(pipefd[0], buf, sizeof(buf)); if (bytes > 0) { - logg->logError(__FILE__, __LINE__, buf); + logg->logError("%s", buf); handleException(); } close(pipefd[0]); diff --git a/tools/gator/daemon/Command.h b/tools/gator/daemon/Command.h index 17244b7aaebc..2838adcec661 100644 --- a/tools/gator/daemon/Command.h +++ b/tools/gator/daemon/Command.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2014. All rights reserved. + * Copyright (C) ARM Limited 2014-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/Config.h b/tools/gator/daemon/Config.h index bee383a1c797..eb31556e6426 100644 --- a/tools/gator/daemon/Config.h +++ b/tools/gator/daemon/Config.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/ConfigurationXML.cpp b/tools/gator/daemon/ConfigurationXML.cpp index 6590dd389196..be224a4f2b1f 100644 --- a/tools/gator/daemon/ConfigurationXML.cpp +++ b/tools/gator/daemon/ConfigurationXML.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -106,7 +106,7 @@ void ConfigurationXML::validate(void) { const Counter & counter = gSessionData->mCounters[i]; if (counter.isEnabled()) { if (strcmp(counter.getType(), "") == 0) { - logg->logError(__FILE__, __LINE__, "Invalid required attribute in configuration.xml:\n counter=\"%s\"\n event=%d\n", counter.getType(), counter.getEvent()); + logg->logError("Invalid required attribute in configuration.xml:\n counter=\"%s\"\n event=%d\n", counter.getType(), counter.getEvent()); handleException(); } @@ -116,7 +116,7 @@ void ConfigurationXML::validate(void) { if (counter2.isEnabled()) { // check if the types are the same if (strcmp(counter.getType(), counter2.getType()) == 0) { - logg->logError(__FILE__, __LINE__, "Duplicate performance counter type in configuration.xml: %s", counter.getType()); + logg->logError("Duplicate performance counter type in configuration.xml: %s", counter.getType()); handleException(); } } @@ -169,7 +169,7 @@ void ConfigurationXML::configurationTag(mxml_node_t *node) { for (Driver *driver = Driver::getHead(); driver != NULL; driver = driver->getNext()) { if (driver->claimCounter(counter)) { if (counter.getDriver() != NULL) { - logg->logError(__FILE__, __LINE__, "More than one driver has claimed %s:%i", counter.getType(), counter.getEvent()); + logg->logError("More than one driver has claimed %s:%i", counter.getType(), counter.getEvent()); handleException(); } counter.setDriver(driver); @@ -210,7 +210,7 @@ void ConfigurationXML::remove() { getPath(path); if (::remove(path) != 0) { - logg->logError(__FILE__, __LINE__, "Invalid configuration.xml file detected and unable to delete it. To resolve, delete configuration.xml on disk"); + logg->logError("Invalid configuration.xml file detected and unable to delete it. To resolve, delete configuration.xml on disk"); handleException(); } logg->logMessage("Invalid configuration.xml file detected and removed"); diff --git a/tools/gator/daemon/ConfigurationXML.h b/tools/gator/daemon/ConfigurationXML.h index efa415e508b6..a986ce99381b 100644 --- a/tools/gator/daemon/ConfigurationXML.h +++ b/tools/gator/daemon/ConfigurationXML.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/Counter.h b/tools/gator/daemon/Counter.h index 5202aa046362..a4c22f571342 100644 --- a/tools/gator/daemon/Counter.h +++ b/tools/gator/daemon/Counter.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/DiskIODriver.cpp b/tools/gator/daemon/DiskIODriver.cpp index 5deb0f375f3a..af62bb9a95bd 100644 --- a/tools/gator/daemon/DiskIODriver.cpp +++ b/tools/gator/daemon/DiskIODriver.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -67,7 +67,7 @@ void DiskIODriver::doRead() { } if (!mBuf.read("/proc/diskstats")) { - logg->logError(__FILE__, __LINE__, "Unable to read /proc/diskstats"); + logg->logError("Unable to read /proc/diskstats"); handleException(); } @@ -76,9 +76,9 @@ void DiskIODriver::doRead() { char *lastName = NULL; int lastNameLen = -1; - char *start = mBuf.getBuf(); - while (*start != '\0') { - char *end = strchr(start, '\n'); + char *line = mBuf.getBuf(); + while (*line != '\0') { + char *end = strchr(line, '\n'); if (end != NULL) { *end = '\0'; } @@ -87,15 +87,15 @@ void DiskIODriver::doRead() { int nameEnd = -1; int64_t readBytes = -1; int64_t writeBytes = -1; - const int count = sscanf(start, "%*d %*d %n%*s%n %*u %*u %" SCNu64 " %*u %*u %*u %" SCNu64, &nameStart, &nameEnd, &readBytes, &writeBytes); + const int count = sscanf(line, "%*d %*d %n%*s%n %*u %*u %" SCNu64 " %*u %*u %*u %" SCNu64, &nameStart, &nameEnd, &readBytes, &writeBytes); if (count != 2) { - logg->logError(__FILE__, __LINE__, "Unable to parse /proc/diskstats"); + logg->logError("Unable to parse /proc/diskstats"); handleException(); } // Skip partitions which are identified if the name is a substring of the last non-partition - if ((lastName == NULL) || (strncmp(lastName, start + nameStart, lastNameLen) != 0)) { - lastName = start + nameStart; + if ((lastName == NULL) || (strncmp(lastName, line + nameStart, lastNameLen) != 0)) { + lastName = line + nameStart; lastNameLen = nameEnd - nameStart; mReadBytes += readBytes; mWriteBytes += writeBytes; @@ -104,7 +104,7 @@ void DiskIODriver::doRead() { if (end == NULL) { break; } - start = end + 1; + line = end + 1; } } diff --git a/tools/gator/daemon/DiskIODriver.h b/tools/gator/daemon/DiskIODriver.h index d0db18c77d04..6ecda5afc25a 100644 --- a/tools/gator/daemon/DiskIODriver.h +++ b/tools/gator/daemon/DiskIODriver.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/Driver.cpp b/tools/gator/daemon/Driver.cpp index 275da31c7a0d..72c731424bde 100644 --- a/tools/gator/daemon/Driver.cpp +++ b/tools/gator/daemon/Driver.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/Driver.h b/tools/gator/daemon/Driver.h index 72870e3dbca1..19ec12775a39 100644 --- a/tools/gator/daemon/Driver.h +++ b/tools/gator/daemon/Driver.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/DriverSource.cpp b/tools/gator/daemon/DriverSource.cpp index 7f299b646952..34920cee92fb 100644 --- a/tools/gator/daemon/DriverSource.cpp +++ b/tools/gator/daemon/DriverSource.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -32,7 +32,7 @@ DriverSource::DriverSource(sem_t *senderSem, sem_t *startProfile) : mBuffer(NULL mBuffer = new Buffer(0, FRAME_PERF_ATTRS, 4*1024*1024, senderSem); if (readIntDriver("/dev/gator/version", &driver_version) == -1) { - logg->logError(__FILE__, __LINE__, "Error reading gator driver version"); + logg->logError("Error reading gator driver version"); handleException(); } @@ -40,7 +40,7 @@ DriverSource::DriverSource(sem_t *senderSem, sem_t *startProfile) : mBuffer(NULL if (driver_version != PROTOCOL_VERSION) { if ((driver_version > PROTOCOL_DEV) || (PROTOCOL_VERSION > PROTOCOL_DEV)) { // One of the mismatched versions is development version - logg->logError(__FILE__, __LINE__, + logg->logError( "DEVELOPMENT BUILD MISMATCH: gator driver version \"%d\" is not in sync with gator daemon version \"%d\".\n" ">> The following must be synchronized from engineering repository:\n" ">> * gator driver\n" @@ -49,7 +49,7 @@ DriverSource::DriverSource(sem_t *senderSem, sem_t *startProfile) : mBuffer(NULL handleException(); } else { // Release version mismatch - logg->logError(__FILE__, __LINE__, + logg->logError( "gator driver version \"%d\" is different than gator daemon version \"%d\".\n" ">> Please upgrade the driver and daemon to the latest versions.", driver_version, PROTOCOL_VERSION); handleException(); @@ -58,7 +58,7 @@ DriverSource::DriverSource(sem_t *senderSem, sem_t *startProfile) : mBuffer(NULL int enable = -1; if (readIntDriver("/dev/gator/enable", &enable) != 0 || enable != 0) { - logg->logError(__FILE__, __LINE__, "Driver already enabled, possibly a session is already in progress."); + logg->logError("Driver already enabled, possibly a session is already in progress."); handleException(); } @@ -68,7 +68,7 @@ DriverSource::DriverSource(sem_t *senderSem, sem_t *startProfile) : mBuffer(NULL } if (readIntDriver("/dev/gator/buffer_size", &mBufferSize) || mBufferSize <= 0) { - logg->logError(__FILE__, __LINE__, "Unable to read the driver buffer size"); + logg->logError("Unable to read the driver buffer size"); handleException(); } } @@ -99,10 +99,11 @@ void DriverSource::bootstrapThread() { DynBuf printb; DynBuf b1; DynBuf b2; - const uint64_t currTime = getTime(); + // MonotonicStarted may not be not assigned yet + const uint64_t currTime = 0;//getTime() - gSessionData->mMonotonicStarted; if (!readProcComms(currTime, mBuffer, &printb, &b1, &b2)) { - logg->logError(__FILE__, __LINE__, "readProcComms failed"); + logg->logError("readProcComms failed"); handleException(); } @@ -124,33 +125,33 @@ void DriverSource::run() { // Set the maximum backtrace depth if (writeReadDriver("/dev/gator/backtrace_depth", &gSessionData->mBacktraceDepth)) { - logg->logError(__FILE__, __LINE__, "Unable to set the driver backtrace depth"); + logg->logError("Unable to set the driver backtrace depth"); handleException(); } // open the buffer which calls userspace_buffer_open() in the driver mBufferFD = open("/dev/gator/buffer", O_RDONLY | O_CLOEXEC); if (mBufferFD < 0) { - logg->logError(__FILE__, __LINE__, "The gator driver did not set up properly. Please view the linux console or dmesg log for more information on the failure."); + logg->logError("The gator driver did not set up properly. Please view the linux console or dmesg log for more information on the failure."); handleException(); } // set the tick rate of the profiling timer if (writeReadDriver("/dev/gator/tick", &gSessionData->mSampleRate) != 0) { - logg->logError(__FILE__, __LINE__, "Unable to set the driver tick"); + logg->logError("Unable to set the driver tick"); handleException(); } // notify the kernel of the response type int response_type = gSessionData->mLocalCapture ? 0 : RESPONSE_APC_DATA; if (writeDriver("/dev/gator/response_type", response_type)) { - logg->logError(__FILE__, __LINE__, "Unable to write the response type"); + logg->logError("Unable to write the response type"); handleException(); } // Set the live rate if (writeReadDriver("/dev/gator/live_rate", &gSessionData->mLiveRate)) { - logg->logError(__FILE__, __LINE__, "Unable to set the driver live rate"); + logg->logError("Unable to set the driver live rate"); handleException(); } @@ -158,7 +159,7 @@ void DriverSource::run() { // This command makes the driver start profiling by calling gator_op_start() in the driver if (writeDriver("/dev/gator/enable", "1") != 0) { - logg->logError(__FILE__, __LINE__, "The gator driver did not start properly. Please view the linux console or dmesg log for more information on the failure."); + logg->logError("The gator driver did not start properly. Please view the linux console or dmesg log for more information on the failure."); handleException(); } @@ -168,7 +169,7 @@ void DriverSource::run() { pthread_t bootstrapThreadID; if (pthread_create(&bootstrapThreadID, NULL, bootstrapThreadStatic, this) != 0) { - logg->logError(__FILE__, __LINE__, "Unable to start the gator_bootstrap thread"); + logg->logError("Unable to start the gator_bootstrap thread"); handleException(); } @@ -190,7 +191,7 @@ void DriverSource::run() { // In one shot mode, stop collection once all the buffers are filled if (gSessionData->mOneShot && gSessionData->mSessionIsActive) { if (bytesCollected == -1 || mFifo->willFill(bytesCollected)) { - logg->logMessage("One shot"); + logg->logMessage("One shot (gator.ko)"); child->endSession(); } } diff --git a/tools/gator/daemon/DriverSource.h b/tools/gator/daemon/DriverSource.h index ec27b0815bbf..32d983d6d036 100644 --- a/tools/gator/daemon/DriverSource.h +++ b/tools/gator/daemon/DriverSource.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/DynBuf.cpp b/tools/gator/daemon/DynBuf.cpp index df20713ad63c..690cbcb94293 100644 --- a/tools/gator/daemon/DynBuf.cpp +++ b/tools/gator/daemon/DynBuf.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -42,7 +42,7 @@ bool DynBuf::read(const char *const path) { const int fd = open(path, O_RDONLY | O_CLOEXEC); if (fd < 0) { - logg->logMessage("%s(%s:%i): open failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("open failed"); return false; } @@ -52,14 +52,14 @@ bool DynBuf::read(const char *const path) { const size_t minCapacity = length + MIN_BUFFER_FREE + 1; if (capacity < minCapacity) { if (resize(minCapacity) != 0) { - logg->logMessage("%s(%s:%i): DynBuf::resize failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("DynBuf::resize failed"); goto fail; } } const ssize_t bytes = ::read(fd, buf + length, capacity - length - 1); if (bytes < 0) { - logg->logMessage("%s(%s:%i): read failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("read failed"); goto fail; } else if (bytes == 0) { break; @@ -105,7 +105,7 @@ bool DynBuf::printf(const char *format, ...) { if (capacity <= 0) { if (resize(2 * MIN_BUFFER_FREE) != 0) { - logg->logMessage("%s(%s:%i): DynBuf::resize failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("DynBuf::resize failed"); return false; } } @@ -114,13 +114,13 @@ bool DynBuf::printf(const char *format, ...) { int bytes = vsnprintf(buf, capacity, format, ap); va_end(ap); if (bytes < 0) { - logg->logMessage("%s(%s:%i): fsnprintf failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("fsnprintf failed"); return false; } if (static_cast(bytes) > capacity) { if (resize(bytes + 1) != 0) { - logg->logMessage("%s(%s:%i): DynBuf::resize failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("DynBuf::resize failed"); return false; } @@ -128,7 +128,7 @@ bool DynBuf::printf(const char *format, ...) { bytes = vsnprintf(buf, capacity, format, ap); va_end(ap); if (bytes < 0) { - logg->logMessage("%s(%s:%i): fsnprintf failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("fsnprintf failed"); return false; } } diff --git a/tools/gator/daemon/DynBuf.h b/tools/gator/daemon/DynBuf.h index 2f4554ab2e49..da83cd65ca3e 100644 --- a/tools/gator/daemon/DynBuf.h +++ b/tools/gator/daemon/DynBuf.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/EventsXML.cpp b/tools/gator/daemon/EventsXML.cpp index d905bbabe988..cec08d5a6fff 100644 --- a/tools/gator/daemon/EventsXML.cpp +++ b/tools/gator/daemon/EventsXML.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -13,10 +13,35 @@ #include "OlyUtility.h" #include "SessionData.h" +class XMLList { +public: + XMLList(XMLList *const prev, mxml_node_t *const node) : mPrev(prev), mNode(node) {} + + XMLList *getPrev() { return mPrev; } + mxml_node_t *getNode() const { return mNode; } + void setNode(mxml_node_t *const node) { mNode = node; } + + static void free(XMLList *list) { + while (list != NULL) { + XMLList *prev = list->getPrev(); + delete list; + list = prev; + } + } + +private: + XMLList *const mPrev; + mxml_node_t *mNode; + + // Intentionally unimplemented + XMLList(const XMLList &); + XMLList &operator=(const XMLList &); +}; + mxml_node_t *EventsXML::getTree() { #include "events_xml.h" // defines and initializes char events_xml[] and int events_xml_len char path[PATH_MAX]; - mxml_node_t *xml; + mxml_node_t *xml = NULL; FILE *fl; // Avoid unused variable warning @@ -25,19 +50,147 @@ mxml_node_t *EventsXML::getTree() { // Load the provided or default events xml if (gSessionData->mEventsXMLPath) { strncpy(path, gSessionData->mEventsXMLPath, PATH_MAX); - } else { - util->getApplicationFullPath(path, PATH_MAX); - strncat(path, "events.xml", PATH_MAX - strlen(path) - 1); + fl = fopen(path, "r"); + if (fl) { + xml = mxmlLoadFile(NULL, fl, MXML_NO_CALLBACK); + fclose(fl); + } } - fl = fopen(path, "r"); - if (fl) { - xml = mxmlLoadFile(NULL, fl, MXML_NO_CALLBACK); - fclose(fl); - } else { + if (xml == NULL) { logg->logMessage("Unable to locate events.xml, using default"); xml = mxmlLoadString(NULL, (const char *)events_xml, MXML_NO_CALLBACK); } + // Append additional events XML + if (gSessionData->mEventsXMLAppend) { + fl = fopen(gSessionData->mEventsXMLAppend, "r"); + if (fl == NULL) { + logg->logError("Unable to open additional events XML %s", gSessionData->mEventsXMLAppend); + handleException(); + } + mxml_node_t *append = mxmlLoadFile(NULL, fl, MXML_NO_CALLBACK); + fclose(fl); + + mxml_node_t *events = mxmlFindElement(xml, xml, "events", NULL, NULL, MXML_DESCEND); + if (!events) { + logg->logError("Unable to find node in the events.xml, please ensure the first two lines of events XML starts with:\n" + "\n" + ""); + handleException(); + } + + XMLList *categoryList = NULL; + XMLList *eventList = NULL; + { + // Make list of all categories in xml + mxml_node_t *node = xml; + while (true) { + node = mxmlFindElement(node, xml, "category", NULL, NULL, MXML_DESCEND); + if (node == NULL) { + break; + } + categoryList = new XMLList(categoryList, node); + } + + // Make list of all events in xml + node = xml; + while (true) { + node = mxmlFindElement(node, xml, "event", NULL, NULL, MXML_DESCEND); + if (node == NULL) { + break; + } + eventList = new XMLList(eventList, node); + } + } + + // Handle events + for (mxml_node_t *node = mxmlFindElement(append, append, "event", NULL, NULL, MXML_DESCEND), + *next = mxmlFindElement(node, append, "event", NULL, NULL, MXML_DESCEND); + node != NULL; + node = next, next = mxmlFindElement(node, append, "event", NULL, NULL, MXML_DESCEND)) { + const char *const category = mxmlElementGetAttr(mxmlGetParent(node), "name"); + const char *const title = mxmlElementGetAttr(node, "title"); + const char *const name = mxmlElementGetAttr(node, "name"); + if (category == NULL || title == NULL || name == NULL) { + logg->logError("Not all event XML nodes have the required title and name and parent name attributes"); + handleException(); + } + + // Replace any duplicate events + for (XMLList *event = eventList; event != NULL; event = event->getPrev()) { + const char *const category2 = mxmlElementGetAttr(mxmlGetParent(event->getNode()), "name"); + const char *const title2 = mxmlElementGetAttr(event->getNode(), "title"); + const char *const name2 = mxmlElementGetAttr(event->getNode(), "name"); + if (category2 == NULL || title2 == NULL || name2 == NULL) { + logg->logError("Not all event XML nodes have the required title and name and parent name attributes"); + handleException(); + } + + if (strcmp(category, category2) == 0 && strcmp(title, title2) == 0 && strcmp(name, name2) == 0) { + logg->logMessage("Replacing counter %s %s: %s", category, title, name); + mxml_node_t *parent = mxmlGetParent(event->getNode()); + mxmlDelete(event->getNode()); + mxmlAdd(parent, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, node); + event->setNode(node); + break; + } + } + } + + // Handle categories + for (mxml_node_t *node = strcmp(mxmlGetElement(append), "category") == 0 ? append : mxmlFindElement(append, append, "category", NULL, NULL, MXML_DESCEND), + *next = mxmlFindElement(node, append, "category", NULL, NULL, MXML_DESCEND); + node != NULL; + node = next, next = mxmlFindElement(node, append, "category", NULL, NULL, MXML_DESCEND)) { + // After replacing duplicate events, a category may be empty + if (mxmlGetFirstChild(node) == NULL) { + continue; + } + + const char *const name = mxmlElementGetAttr(node, "name"); + if (name == NULL) { + logg->logError("Not all event XML categories have the required name attribute"); + handleException(); + } + + // Merge identically named categories + bool merged = false; + for (XMLList *category = categoryList; category != NULL; category = category->getPrev()) { + const char *const name2 = mxmlElementGetAttr(category->getNode(), "name"); + if (name2 == NULL) { + logg->logError("Not all event XML categories have the required name attribute"); + handleException(); + } + + if (strcmp(name, name2) == 0) { + logg->logMessage("Merging category %s", name); + while (true) { + mxml_node_t *child = mxmlGetFirstChild(node); + if (child == NULL) { + break; + } + mxmlAdd(category->getNode(), MXML_ADD_AFTER, mxmlGetLastChild(category->getNode()), child); + } + merged = true; + break; + } + } + + if (merged) { + continue; + } + + // Add new categories + logg->logMessage("Appending category %s", name); + mxmlAdd(events, MXML_ADD_AFTER, mxmlGetLastChild(events), node); + } + + XMLList::free(eventList); + XMLList::free(categoryList); + + mxmlDelete(append); + } + return xml; } @@ -47,7 +200,9 @@ char *EventsXML::getXML() { // Add dynamic events from the drivers mxml_node_t *events = mxmlFindElement(xml, xml, "events", NULL, NULL, MXML_DESCEND); if (!events) { - logg->logError(__FILE__, __LINE__, "Unable to find node in the events.xml"); + logg->logError("Unable to find node in the events.xml, please ensure the first two lines of events XML are:\n" + "\n" + ""); handleException(); } for (Driver *driver = Driver::getHead(); driver != NULL; driver = driver->getNext()) { @@ -68,7 +223,7 @@ void EventsXML::write(const char *path) { char *buf = getXML(); if (util->writeToDisk(file, buf) < 0) { - logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file); + logg->logError("Error writing %s\nPlease verify the path.", file); handleException(); } diff --git a/tools/gator/daemon/EventsXML.h b/tools/gator/daemon/EventsXML.h index ff7a02fd3c78..2b38fa4364e0 100644 --- a/tools/gator/daemon/EventsXML.h +++ b/tools/gator/daemon/EventsXML.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -13,9 +13,16 @@ class EventsXML { public: + EventsXML() {} + mxml_node_t *getTree(); char *getXML(); void write(const char* path); + +private: + // Intentionally unimplemented + EventsXML(const EventsXML &); + EventsXML &operator=(const EventsXML &); }; #endif // EVENTS_XML diff --git a/tools/gator/daemon/ExternalSource.cpp b/tools/gator/daemon/ExternalSource.cpp index 8f5e6b684c53..8d71b6de3d5e 100644 --- a/tools/gator/daemon/ExternalSource.cpp +++ b/tools/gator/daemon/ExternalSource.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -12,10 +12,14 @@ #include #include +#include "Child.h" #include "Logging.h" #include "OlySocket.h" #include "SessionData.h" +extern Child *child; + +static const char STREAMLINE_ANNOTATE[] = "\0streamline-annotate"; static const char MALI_VIDEO[] = "\0mali-video"; static const char MALI_VIDEO_STARTUP[] = "\0mali-video-startup"; static const char MALI_VIDEO_V1[] = "MALI_VIDEO 1\n"; @@ -40,7 +44,7 @@ static bool setNonblock(const int fd) { return true; } -ExternalSource::ExternalSource(sem_t *senderSem) : mBuffer(0, FRAME_EXTERNAL, 128*1024, senderSem), mMonitor(), mMveStartupUds(MALI_VIDEO_STARTUP, sizeof(MALI_VIDEO_STARTUP)), mMaliStartupUds(MALI_GRAPHICS_STARTUP, sizeof(MALI_GRAPHICS_STARTUP)), mAnnotate(8083), mInterruptFd(-1), mMaliUds(-1), mMveUds(-1) { +ExternalSource::ExternalSource(sem_t *senderSem) : mBuffer(0, FRAME_EXTERNAL, 128*1024, senderSem), mMonitor(), mMveStartupUds(MALI_VIDEO_STARTUP, sizeof(MALI_VIDEO_STARTUP)), mMaliStartupUds(MALI_GRAPHICS_STARTUP, sizeof(MALI_GRAPHICS_STARTUP)), mAnnotate(8083), mAnnotateUds(STREAMLINE_ANNOTATE, sizeof(STREAMLINE_ANNOTATE), true), mInterruptFd(-1), mMaliUds(-1), mMveUds(-1) { sem_init(&mBufferSem, 0, 0); } @@ -49,18 +53,22 @@ ExternalSource::~ExternalSource() { void ExternalSource::waitFor(const int bytes) { while (mBuffer.bytesAvailable() <= bytes) { + if (gSessionData->mOneShot && gSessionData->mSessionIsActive) { + logg->logMessage("One shot (external)"); + child->endSession(); + } sem_wait(&mBufferSem); } } void ExternalSource::configureConnection(const int fd, const char *const handshake, size_t size) { if (!setNonblock(fd)) { - logg->logError(__FILE__, __LINE__, "Unable to set nonblock on fh"); + logg->logError("Unable to set nonblock on fh"); handleException(); } if (!mMonitor.add(fd)) { - logg->logError(__FILE__, __LINE__, "Unable to add fh to monitor"); + logg->logError("Unable to add fh to monitor"); handleException(); } @@ -68,7 +76,7 @@ void ExternalSource::configureConnection(const int fd, const char *const handsha waitFor(Buffer::MAXSIZE_PACK32 + size - 1); mBuffer.packInt(fd); mBuffer.writeBytes(handshake, size - 1); - mBuffer.commit(1); + mBuffer.commit(1, true); } bool ExternalSource::connectMali() { @@ -106,6 +114,7 @@ bool ExternalSource::prepare() { !setNonblock(mMveStartupUds.getFd()) || !mMonitor.add(mMveStartupUds.getFd()) || !setNonblock(mMaliStartupUds.getFd()) || !mMonitor.add(mMaliStartupUds.getFd()) || !setNonblock(mAnnotate.getFd()) || !mMonitor.add(mAnnotate.getFd()) || + !setNonblock(mAnnotateUds.getFd()) || !mMonitor.add(mAnnotateUds.getFd()) || false) { return false; } @@ -122,18 +131,21 @@ void ExternalSource::run() { prctl(PR_SET_NAME, (unsigned long)&"gatord-external", 0, 0, 0); if (pipe_cloexec(pipefd) != 0) { - logg->logError(__FILE__, __LINE__, "pipe failed"); + logg->logError("pipe failed"); handleException(); } mInterruptFd = pipefd[1]; if (!mMonitor.add(pipefd[0])) { - logg->logError(__FILE__, __LINE__, "Monitor::add failed"); + logg->logError("Monitor::add failed"); handleException(); } // Notify annotate clients to retry connecting to gatord - gSessionData->annotateListener.signal(); + uint64_t val = 1; + if (::write(gSessionData->mAnnotateStart, &val, sizeof(val)) != sizeof(val)) { + logg->logMessage("Writing to annotate pipe failed"); + } while (gSessionData->mSessionIsActive) { struct epoll_event events[16]; @@ -141,11 +153,11 @@ void ExternalSource::run() { while (sem_trywait(&mBufferSem) == 0); int ready = mMonitor.wait(events, ARRAY_LENGTH(events), -1); if (ready < 0) { - logg->logError(__FILE__, __LINE__, "Monitor::wait failed"); + logg->logError("Monitor::wait failed"); handleException(); } - const uint64_t currTime = getTime(); + const uint64_t currTime = getTime() - gSessionData->mMonotonicStarted; for (int i = 0; i < ready; ++i) { const int fd = events[i].data.fd; @@ -155,7 +167,7 @@ void ExternalSource::run() { // Don't read from this connection, establish a new connection to Mali-V500 close(client); if (!connectMve()) { - logg->logError(__FILE__, __LINE__, "Unable to configure incoming Mali video connection"); + logg->logError("Unable to configure incoming Mali video connection"); handleException(); } } else if (fd == mMaliStartupUds.getFd()) { @@ -164,13 +176,19 @@ void ExternalSource::run() { // Don't read from this connection, establish a new connection to Mali Graphics close(client); if (!connectMali()) { - logg->logError(__FILE__, __LINE__, "Unable to configure incoming Mali graphics connection"); + logg->logError("Unable to configure incoming Mali graphics connection"); handleException(); } } else if (fd == mAnnotate.getFd()) { int client = mAnnotate.acceptConnection(); if (!setNonblock(client) || !mMonitor.add(client)) { - logg->logError(__FILE__, __LINE__, "Unable to set socket options on incoming annotation connection"); + logg->logError("Unable to set socket options on incoming annotation connection"); + handleException(); + } + } else if (fd == mAnnotateUds.getFd()) { + int client = mAnnotateUds.acceptConnection(); + if (!setNonblock(client) || !mMonitor.add(client)) { + logg->logError("Unable to set socket options on incoming annotation connection"); handleException(); } } else if (fd == pipefd[0]) { @@ -190,28 +208,29 @@ void ExternalSource::run() { if (bytes < 0) { if (errno == EAGAIN) { // Nothing left to read - mBuffer.commit(currTime); + mBuffer.commit(currTime, true); break; } // Something else failed, close the socket - mBuffer.commit(currTime); + mBuffer.commit(currTime, true); mBuffer.packInt(-1); mBuffer.packInt(fd); - mBuffer.commit(currTime); + // Here and other commits, always force-flush the buffer as this frame don't work like others + mBuffer.commit(currTime, true); close(fd); break; } else if (bytes == 0) { // The other side is closed - mBuffer.commit(currTime); + mBuffer.commit(currTime, true); mBuffer.packInt(-1); mBuffer.packInt(fd); - mBuffer.commit(currTime); + mBuffer.commit(currTime, true); close(fd); break; } mBuffer.advanceWrite(bytes); - mBuffer.commit(currTime); + mBuffer.commit(currTime, true); // Short reads also mean nothing is left to read if (bytes < contiguous) { @@ -238,7 +257,7 @@ void ExternalSource::interrupt() { int8_t c = 0; // Write to the pipe to wake the monitor which will cause mSessionIsActive to be reread if (::write(mInterruptFd, &c, sizeof(c)) != sizeof(c)) { - logg->logError(__FILE__, __LINE__, "write failed"); + logg->logError("write failed"); handleException(); } } diff --git a/tools/gator/daemon/ExternalSource.h b/tools/gator/daemon/ExternalSource.h index 919e75e8a41a..25ae7cd4c4ab 100644 --- a/tools/gator/daemon/ExternalSource.h +++ b/tools/gator/daemon/ExternalSource.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -41,6 +41,7 @@ private: OlyServerSocket mMveStartupUds; OlyServerSocket mMaliStartupUds; OlyServerSocket mAnnotate; + OlyServerSocket mAnnotateUds; int mInterruptFd; int mMaliUds; int mMveUds; diff --git a/tools/gator/daemon/FSDriver.cpp b/tools/gator/daemon/FSDriver.cpp index dd8eb804dc99..afac9dfb6761 100644 --- a/tools/gator/daemon/FSDriver.cpp +++ b/tools/gator/daemon/FSDriver.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2014. All rights reserved. + * Copyright (C) ARM Limited 2014-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -42,7 +42,7 @@ FSCounter::FSCounter(DriverCounter *next, char *name, char *path, const char *re if (result != 0) { char buf[128]; regerror(result, &mReg, buf, sizeof(buf)); - logg->logError(__FILE__, __LINE__, "Invalid regex '%s': %s", regex, buf); + logg->logError("Invalid regex '%s': %s", regex, buf); handleException(); } } @@ -79,21 +79,19 @@ int64_t FSCounter::read() { regmatch_t match[2]; int result = regexec(&mReg, buf, 2, match, 0); if (result != 0) { - regerror(result, &mReg, buf, sizeof(buf)); - logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", mPath, buf); - handleException(); + // No match + return 0; } if (match[1].rm_so < 0) { - logg->logError(__FILE__, __LINE__, "Parsing %s failed", mPath); - handleException(); - } - - errno = 0; - value = strtoll(buf + match[1].rm_so, NULL, 0); - if (errno != 0) { - logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", mPath, strerror(errno)); - handleException(); + value = 1; + } else { + errno = 0; + value = strtoll(buf + match[1].rm_so, NULL, 0); + if (errno != 0) { + logg->logError("Parsing %s failed: %s", mPath, strerror(errno)); + handleException(); + } } } else { if (DriverSource::readInt64Driver(mPath, &value) != 0) { @@ -103,7 +101,7 @@ int64_t FSCounter::read() { return value; fail: - logg->logError(__FILE__, __LINE__, "Unable to read %s", mPath); + logg->logError("Unable to read %s", mPath); handleException(); } @@ -126,7 +124,7 @@ void FSDriver::readEvents(mxml_node_t *const xml) { } if (counter[0] == '/') { - logg->logError(__FILE__, __LINE__, "Old style filesystem counter (%s) detected, please create a new unique counter value and move the filename into the path attribute, see events-Filesystem.xml for examples", counter); + logg->logError("Old style filesystem counter (%s) detected, please create a new unique counter value and move the filename into the path attribute, see events-Filesystem.xml for examples", counter); handleException(); } @@ -136,7 +134,7 @@ void FSDriver::readEvents(mxml_node_t *const xml) { const char *path = mxmlElementGetAttr(node, "path"); if (path == NULL) { - logg->logError(__FILE__, __LINE__, "The filesystem counter %s is missing the required path attribute", counter); + logg->logError("The filesystem counter %s is missing the required path attribute", counter); handleException(); } const char *regex = mxmlElementGetAttr(node, "regex"); diff --git a/tools/gator/daemon/FSDriver.h b/tools/gator/daemon/FSDriver.h index a7dc8b4df9dd..63a4e90a2b46 100644 --- a/tools/gator/daemon/FSDriver.h +++ b/tools/gator/daemon/FSDriver.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2014. All rights reserved. + * Copyright (C) ARM Limited 2014-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/Fifo.cpp b/tools/gator/daemon/Fifo.cpp index 41275fd287b8..8d3b9ff8d385 100644 --- a/tools/gator/daemon/Fifo.cpp +++ b/tools/gator/daemon/Fifo.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -24,12 +24,12 @@ Fifo::Fifo(int singleBufferSize, int bufferSize, sem_t* readerSem) { mEnd = false; if (mBuffer == NULL) { - logg->logError(__FILE__, __LINE__, "failed to allocate %d bytes", bufferSize + singleBufferSize); + logg->logError("failed to allocate %d bytes", bufferSize + singleBufferSize); handleException(); } if (sem_init(&mWaitForSpaceSem, 0, 0)) { - logg->logError(__FILE__, __LINE__, "sem_init() failed"); + logg->logError("sem_init() failed"); handleException(); } } diff --git a/tools/gator/daemon/Fifo.h b/tools/gator/daemon/Fifo.h index 21c8d8580391..01fa11b2f2c4 100644 --- a/tools/gator/daemon/Fifo.h +++ b/tools/gator/daemon/Fifo.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/FtraceDriver.cpp b/tools/gator/daemon/FtraceDriver.cpp index b156f1c0b8b4..98bd0a5d9eec 100644 --- a/tools/gator/daemon/FtraceDriver.cpp +++ b/tools/gator/daemon/FtraceDriver.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2014. All rights reserved. + * Copyright (C) ARM Limited 2014-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -9,56 +9,80 @@ #include "FtraceDriver.h" #include +#include +#include "DriverSource.h" #include "Logging.h" +#include "Setup.h" class FtraceCounter : public DriverCounter { public: - FtraceCounter(DriverCounter *next, char *name, const char *regex); + FtraceCounter(DriverCounter *next, char *name, const char *regex, const char *enable); ~FtraceCounter(); + void prepare(); int read(const char *const line, int64_t *values); + void stop(); private: - regex_t reg; + regex_t mReg; + char *const mEnable; + int mWasEnabled; // Intentionally unimplemented FtraceCounter(const FtraceCounter &); FtraceCounter &operator=(const FtraceCounter &); }; -FtraceCounter::FtraceCounter(DriverCounter *next, char *name, const char *regex) : DriverCounter(next, name) { - int result = regcomp(®, regex, REG_EXTENDED); +FtraceCounter::FtraceCounter(DriverCounter *next, char *name, const char *regex, const char *enable) : DriverCounter(next, name), mEnable(enable == NULL ? NULL : strdup(enable)) { + int result = regcomp(&mReg, regex, REG_EXTENDED); if (result != 0) { char buf[128]; - regerror(result, ®, buf, sizeof(buf)); - logg->logError(__FILE__, __LINE__, "Invalid regex '%s': %s", regex, buf); + regerror(result, &mReg, buf, sizeof(buf)); + logg->logError("Invalid regex '%s': %s", regex, buf); handleException(); } } FtraceCounter::~FtraceCounter() { - regfree(®); + regfree(&mReg); + if (mEnable != NULL) { + free(mEnable); + } +} + +void FtraceCounter::prepare() { + if (mEnable == NULL) { + return; + } + + char buf[1<<10]; + snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/events/%s/enable", mEnable); + if ((DriverSource::readIntDriver(buf, &mWasEnabled) != 0) || + (DriverSource::writeDriver(buf, 1) != 0)) { + logg->logError("Unable to read or write to %s", buf); + handleException(); + } } int FtraceCounter::read(const char *const line, int64_t *values) { regmatch_t match[2]; - int result = regexec(®, line, 2, match, 0); + int result = regexec(&mReg, line, 2, match, 0); if (result != 0) { // No match return 0; } + int64_t value; if (match[1].rm_so < 0) { - logg->logError(__FILE__, __LINE__, "Parsing %s failed", getName()); - handleException(); - } - - errno = 0; - int64_t value = strtoll(line + match[1].rm_so, NULL, 0); - if (errno != 0) { - logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", getName(), strerror(errno)); - handleException(); + value = 1; + } else { + errno = 0; + value = strtoll(line + match[1].rm_so, NULL, 0); + if (errno != 0) { + logg->logError("Parsing %s failed: %s", getName(), strerror(errno)); + handleException(); + } } values[0] = getKey(); @@ -67,6 +91,16 @@ int FtraceCounter::read(const char *const line, int64_t *values) { return 1; } +void FtraceCounter::stop() { + if (mEnable == NULL) { + return; + } + + char buf[1<<10]; + snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/events/%s/enable", mEnable); + DriverSource::writeDriver(buf, mWasEnabled); +} + FtraceDriver::FtraceDriver() : mValues(NULL) { } @@ -75,6 +109,19 @@ FtraceDriver::~FtraceDriver() { } void FtraceDriver::readEvents(mxml_node_t *const xml) { + // Check the kernel version + int release[3]; + if (!getLinuxVersion(release)) { + logg->logError("getLinuxVersion failed"); + handleException(); + } + + // The perf clock was added in 3.10 + if (KERNEL_VERSION(release[0], release[1], release[2]) < KERNEL_VERSION(3, 10, 0)) { + logg->logMessage("Unsupported kernel version, to use ftrace please upgrade to Linux 3.10 or later"); + return; + } + mxml_node_t *node = xml; int count = 0; while (true) { @@ -93,16 +140,37 @@ void FtraceDriver::readEvents(mxml_node_t *const xml) { const char *regex = mxmlElementGetAttr(node, "regex"); if (regex == NULL) { - logg->logError(__FILE__, __LINE__, "The regex counter %s is missing the required regex attribute", counter); + logg->logError("The regex counter %s is missing the required regex attribute", counter); handleException(); } - setCounters(new FtraceCounter(getCounters(), strdup(counter), regex)); - ++count; + bool addCounter = true; + const char *enable = mxmlElementGetAttr(node, "enable"); + if (enable != NULL) { + char buf[1<<10]; + snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/events/%s/enable", enable); + if (access(buf, W_OK) != 0) { + logg->logMessage("Disabling counter %s, %s not found", counter, buf); + addCounter = false; + } + } + if (addCounter) { + setCounters(new FtraceCounter(getCounters(), strdup(counter), regex, enable)); + ++count; + } } mValues = new int64_t[2*count]; } +void FtraceDriver::prepare() { + for (FtraceCounter *counter = static_cast(getCounters()); counter != NULL; counter = static_cast(counter->getNext())) { + if (!counter->isEnabled()) { + continue; + } + counter->prepare(); + } +} + int FtraceDriver::read(const char *line, int64_t **buf) { int count = 0; @@ -116,3 +184,12 @@ int FtraceDriver::read(const char *line, int64_t **buf) { *buf = mValues; return count; } + +void FtraceDriver::stop() { + for (FtraceCounter *counter = static_cast(getCounters()); counter != NULL; counter = static_cast(counter->getNext())) { + if (!counter->isEnabled()) { + continue; + } + counter->stop(); + } +} diff --git a/tools/gator/daemon/FtraceDriver.h b/tools/gator/daemon/FtraceDriver.h index 5f958bec672c..b79dc9149d6a 100644 --- a/tools/gator/daemon/FtraceDriver.h +++ b/tools/gator/daemon/FtraceDriver.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2014. All rights reserved. + * Copyright (C) ARM Limited 2014-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -18,7 +18,9 @@ public: void readEvents(mxml_node_t *const xml); + void prepare(); int read(const char *line, int64_t **buf); + void stop(); private: int64_t *mValues; diff --git a/tools/gator/daemon/FtraceSource.cpp b/tools/gator/daemon/FtraceSource.cpp index 521633357417..14a48b3b870c 100644 --- a/tools/gator/daemon/FtraceSource.cpp +++ b/tools/gator/daemon/FtraceSource.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -14,10 +14,13 @@ #include #include +#include "Child.h" #include "DriverSource.h" #include "Logging.h" #include "SessionData.h" +extern Child *child; + static void handler(int signum) { (void)signum; @@ -35,18 +38,20 @@ bool FtraceSource::prepare() { act.sa_handler = handler; act.sa_flags = (int)SA_RESETHAND; if (sigaction(SIGUSR1, &act, NULL) != 0) { - logg->logError(__FILE__, __LINE__, "sigaction failed: %s\n", strerror(errno)); + logg->logError("sigaction failed: %s\n", strerror(errno)); handleException(); } } + gSessionData->ftraceDriver.prepare(); + if (DriverSource::readIntDriver("/sys/kernel/debug/tracing/tracing_on", &mTracingOn)) { - logg->logError(__FILE__, __LINE__, "Unable to read if ftrace is enabled"); + logg->logError("Unable to read if ftrace is enabled"); handleException(); } if (DriverSource::writeDriver("/sys/kernel/debug/tracing/tracing_on", "0") != 0) { - logg->logError(__FILE__, __LINE__, "Unable to turn ftrace off before truncating the buffer"); + logg->logError("Unable to turn ftrace off before truncating the buffer"); handleException(); } @@ -54,20 +59,20 @@ bool FtraceSource::prepare() { int fd; fd = open("/sys/kernel/debug/tracing/trace", O_WRONLY | O_TRUNC | O_CLOEXEC, 0666); if (fd < 0) { - logg->logError(__FILE__, __LINE__, "Unable truncate ftrace buffer: %s", strerror(errno)); + logg->logError("Unable truncate ftrace buffer: %s", strerror(errno)); handleException(); } close(fd); } if (DriverSource::writeDriver("/sys/kernel/debug/tracing/trace_clock", "perf") != 0) { - logg->logError(__FILE__, __LINE__, "Unable to switch ftrace to the perf clock, please ensure you are running Linux 3.10 or later"); + logg->logError("Unable to switch ftrace to the perf clock, please ensure you are running Linux 3.10 or later"); handleException(); } mFtraceFh = fopen_cloexec("/sys/kernel/debug/tracing/trace_pipe", "rb"); if (mFtraceFh == NULL) { - logg->logError(__FILE__, __LINE__, "Unable to open trace_pipe"); + logg->logError("Unable to open trace_pipe"); handleException(); } @@ -79,10 +84,25 @@ void FtraceSource::run() { mTid = syscall(__NR_gettid); if (DriverSource::writeDriver("/sys/kernel/debug/tracing/tracing_on", "1") != 0) { - logg->logError(__FILE__, __LINE__, "Unable to turn ftrace on"); + logg->logError("Unable to turn ftrace on"); handleException(); } + // Wait until monotonicStarted is set before sending data + int64_t monotonicStarted = 0; + while (monotonicStarted <= 0 && gSessionData->mSessionIsActive) { + usleep(10); + + if (gSessionData->perf.isSetup()) { + monotonicStarted = gSessionData->mMonotonicStarted; + } else { + if (DriverSource::readInt64Driver("/dev/gator/started", &monotonicStarted) == -1) { + logg->logError("Error reading gator driver start time"); + handleException(); + } + } + } + while (gSessionData->mSessionIsActive) { char buf[1<<12]; @@ -91,22 +111,26 @@ void FtraceSource::run() { // Interrupted by interrupt - likely user request to terminate break; } - logg->logError(__FILE__, __LINE__, "Unable read trace data: %s", strerror(errno)); + logg->logError("Unable read trace data: %s", strerror(errno)); handleException(); } - const uint64_t currTime = getTime(); + const uint64_t currTime = getTime() - gSessionData->mMonotonicStarted; char *const colon = strstr(buf, ": "); if (colon == NULL) { - logg->logError(__FILE__, __LINE__, "Unable find colon: %s", buf); + if (strstr(buf, " [LOST ") != NULL) { + logg->logError("Ftrace events lost, aborting the capture. It is recommended to discard this report and collect a new capture. If this error occurs often, please reduce the number of ftrace counters selected or the amount of ftrace events generated."); + } else { + logg->logError("Unable to find colon: %s", buf); + } handleException(); } *colon = '\0'; char *const space = strrchr(buf, ' '); if (space == NULL) { - logg->logError(__FILE__, __LINE__, "Unable find space: %s", buf); + logg->logError("Unable to find space: %s", buf); handleException(); } *colon = ':'; @@ -117,7 +141,7 @@ void FtraceSource::run() { errno = 0; const long long time = strtod(space, NULL) * 1000000000; if (errno != 0) { - logg->logError(__FILE__, __LINE__, "Unable to parse time: %s", strerror(errno)); + logg->logError("Unable to parse time: %s", strerror(errno)); handleException(); } mBuffer.event64(-1, time); @@ -127,6 +151,11 @@ void FtraceSource::run() { } mBuffer.check(currTime); + + if (gSessionData->mOneShot && gSessionData->mSessionIsActive && (mBuffer.bytesAvailable() <= 0)) { + logg->logMessage("One shot (ftrace)"); + child->endSession(); + } } } @@ -136,6 +165,7 @@ void FtraceSource::run() { DriverSource::writeDriver("/sys/kernel/debug/tracing/tracing_on", mTracingOn); fclose(mFtraceFh); DriverSource::writeDriver("/sys/kernel/debug/tracing/trace_clock", "local"); + gSessionData->ftraceDriver.stop(); } void FtraceSource::interrupt() { diff --git a/tools/gator/daemon/FtraceSource.h b/tools/gator/daemon/FtraceSource.h index 2391b881494e..bc068d266654 100644 --- a/tools/gator/daemon/FtraceSource.h +++ b/tools/gator/daemon/FtraceSource.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/HwmonDriver.cpp b/tools/gator/daemon/HwmonDriver.cpp index 9d161ae5ac56..d8353b006e63 100644 --- a/tools/gator/daemon/HwmonDriver.cpp +++ b/tools/gator/daemon/HwmonDriver.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -23,7 +23,7 @@ static sensors_subfeature_type getInput(const sensors_feature_type type) { case SENSORS_FEATURE_CURR: return SENSORS_SUBFEATURE_CURR_INPUT; case SENSORS_FEATURE_HUMIDITY: return SENSORS_SUBFEATURE_HUMIDITY_INPUT; default: - logg->logError(__FILE__, __LINE__, "Unsupported hwmon feature %i", type); + logg->logError("Unsupported hwmon feature %i", type); handleException(); } }; @@ -33,112 +33,112 @@ public: HwmonCounter(DriverCounter *next, char *const name, const sensors_chip_name *chip, const sensors_feature *feature); ~HwmonCounter(); - const char *getLabel() const { return label; } - const char *getTitle() const { return title; } - bool isDuplicate() const { return duplicate; } - const char *getDisplay() const { return display; } - const char *getCounterClass() const { return counter_class; } - const char *getUnit() const { return unit; } - int getModifier() const { return modifier; } + const char *getLabel() const { return mLabel; } + const char *getTitle() const { return mTitle; } + bool isDuplicate() const { return mDuplicate; } + const char *getDisplay() const { return mDisplay; } + const char *getCounterClass() const { return mCounterClass; } + const char *getUnit() const { return mUnit; } + double getMultiplier() const { return mMultiplier; } int64_t read(); private: void init(const sensors_chip_name *chip, const sensors_feature *feature); - const sensors_chip_name *chip; - const sensors_feature *feature; - char *label; - const char *title; - const char *display; - const char *counter_class; - const char *unit; - double previous_value; - int modifier; - int monotonic: 1, - duplicate : 1; + const sensors_chip_name *mChip; + const sensors_feature *mFeature; + char *mLabel; + const char *mTitle; + const char *mDisplay; + const char *mCounterClass; + const char *mUnit; + double mPreviousValue; + double mMultiplier; + int mMonotonic: 1, + mDuplicate : 1; // Intentionally unimplemented HwmonCounter(const HwmonCounter &); HwmonCounter &operator=(const HwmonCounter &); }; -HwmonCounter::HwmonCounter(DriverCounter *next, char *const name, const sensors_chip_name *chip, const sensors_feature *feature) : DriverCounter(next, name), chip(chip), feature(feature), duplicate(false) { - label = sensors_get_label(chip, feature); +HwmonCounter::HwmonCounter(DriverCounter *next, char *const name, const sensors_chip_name *const chip, const sensors_feature *feature) : DriverCounter(next, name), mChip(chip), mFeature(feature), mDuplicate(false) { + mLabel = sensors_get_label(mChip, mFeature); - switch (feature->type) { + switch (mFeature->type) { case SENSORS_FEATURE_IN: - title = "Voltage"; - display = "maximum"; - counter_class = "absolute"; - unit = "V"; - modifier = 1000; - monotonic = false; + mTitle = "Voltage"; + mDisplay = "maximum"; + mCounterClass = "absolute"; + mUnit = "V"; + mMultiplier = 0.001; + mMonotonic = false; break; case SENSORS_FEATURE_FAN: - title = "Fan"; - display = "average"; - counter_class = "absolute"; - unit = "RPM"; - modifier = 1; - monotonic = false; + mTitle = "Fan"; + mDisplay = "average"; + mCounterClass = "absolute"; + mUnit = "RPM"; + mMultiplier = 1.0; + mMonotonic = false; break; case SENSORS_FEATURE_TEMP: - title = "Temperature"; - display = "maximum"; - counter_class = "absolute"; - unit = "°C"; - modifier = 1000; - monotonic = false; + mTitle = "Temperature"; + mDisplay = "maximum"; + mCounterClass = "absolute"; + mUnit = "°C"; + mMultiplier = 0.001; + mMonotonic = false; break; case SENSORS_FEATURE_POWER: - title = "Power"; - display = "maximum"; - counter_class = "absolute"; - unit = "W"; - modifier = 1000000; - monotonic = false; + mTitle = "Power"; + mDisplay = "maximum"; + mCounterClass = "absolute"; + mUnit = "W"; + mMultiplier = 0.000001; + mMonotonic = false; break; case SENSORS_FEATURE_ENERGY: - title = "Energy"; - display = "accumulate"; - counter_class = "delta"; - unit = "J"; - modifier = 1000000; - monotonic = true; + mTitle = "Energy"; + mDisplay = "accumulate"; + mCounterClass = "delta"; + mUnit = "J"; + mMultiplier = 0.000001; + mMonotonic = true; break; case SENSORS_FEATURE_CURR: - title = "Current"; - display = "maximum"; - counter_class = "absolute"; - unit = "A"; - modifier = 1000; - monotonic = false; + mTitle = "Current"; + mDisplay = "maximum"; + mCounterClass = "absolute"; + mUnit = "A"; + mMultiplier = 0.001; + mMonotonic = false; break; case SENSORS_FEATURE_HUMIDITY: - title = "Humidity"; - display = "average"; - counter_class = "absolute"; - unit = "%"; - modifier = 1000; - monotonic = false; + mTitle = "Humidity"; + mDisplay = "average"; + mCounterClass = "absolute"; + mUnit = "%"; + mMultiplier = 0.001; + mMonotonic = false; break; default: - logg->logError(__FILE__, __LINE__, "Unsupported hwmon feature %i", feature->type); + logg->logError("Unsupported hwmon feature %i", mFeature->type); handleException(); } for (HwmonCounter * counter = static_cast(next); counter != NULL; counter = static_cast(counter->getNext())) { - if (strcmp(label, counter->getLabel()) == 0 && strcmp(title, counter->getTitle()) == 0) { - duplicate = true; - counter->duplicate = true; + if (strcmp(mLabel, counter->getLabel()) == 0 && strcmp(mTitle, counter->getTitle()) == 0) { + mDuplicate = true; + counter->mDuplicate = true; break; } } } HwmonCounter::~HwmonCounter() { - free((void *)label); + free((void *)mLabel); } int64_t HwmonCounter::read() { @@ -147,19 +147,19 @@ int64_t HwmonCounter::read() { const sensors_subfeature *subfeature; // Keep in sync with the read check in HwmonDriver::readEvents - subfeature = sensors_get_subfeature(chip, feature, getInput(feature->type)); + subfeature = sensors_get_subfeature(mChip, mFeature, getInput(mFeature->type)); if (!subfeature) { - logg->logError(__FILE__, __LINE__, "No input value for hwmon sensor %s", label); + logg->logError("No input value for hwmon sensor %s", mLabel); handleException(); } - if (sensors_get_value(chip, subfeature->number, &value) != 0) { - logg->logError(__FILE__, __LINE__, "Can't get input value for hwmon sensor %s", label); + if (sensors_get_value(mChip, subfeature->number, &value) != 0) { + logg->logError("Can't get input value for hwmon sensor %s", mLabel); handleException(); } - result = (monotonic ? value - previous_value : value); - previous_value = value; + result = (mMonotonic ? value - mPreviousValue : value); + mPreviousValue = value; return result; } @@ -209,7 +209,7 @@ void HwmonDriver::readEvents(mxml_node_t *const) { void HwmonDriver::writeEvents(mxml_node_t *root) const { root = mxmlNewElement(root, "category"); - mxmlElementSetAttr(root, "name", "hwmon"); + mxmlElementSetAttr(root, "name", "Hardware Monitor"); char buf[1024]; for (HwmonCounter *counter = static_cast(getCounters()); counter != NULL; counter = static_cast(counter->getNext())) { @@ -224,8 +224,8 @@ void HwmonDriver::writeEvents(mxml_node_t *root) const { mxmlElementSetAttr(node, "display", counter->getDisplay()); mxmlElementSetAttr(node, "class", counter->getCounterClass()); mxmlElementSetAttr(node, "units", counter->getUnit()); - if (counter->getModifier() != 1) { - mxmlElementSetAttrf(node, "modifier", "%d", counter->getModifier()); + if (counter->getMultiplier() != 1.0) { + mxmlElementSetAttrf(node, "multiplier", "%lf", counter->getMultiplier()); } if (strcmp(counter->getDisplay(), "average") == 0 || strcmp(counter->getDisplay(), "maximum") == 0) { mxmlElementSetAttr(node, "average_selection", "yes"); diff --git a/tools/gator/daemon/HwmonDriver.h b/tools/gator/daemon/HwmonDriver.h index f28d825e3b7b..f15d557051dc 100644 --- a/tools/gator/daemon/HwmonDriver.h +++ b/tools/gator/daemon/HwmonDriver.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/KMod.cpp b/tools/gator/daemon/KMod.cpp index fe9dc6a7e4f7..e33b499d831b 100644 --- a/tools/gator/daemon/KMod.cpp +++ b/tools/gator/daemon/KMod.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -83,13 +83,13 @@ void KMod::setupCounter(Counter &counter) { if (access(text, F_OK) == 0) { int count = counter.getCount(); if (DriverSource::writeReadDriver(text, &count) && counter.getCount() > 0) { - logg->logError(__FILE__, __LINE__, "Cannot enable EBS for %s:%i with a count of %d\n", counter.getType(), counter.getEvent(), counter.getCount()); + logg->logError("Cannot enable EBS for %s:%i with a count of %d\n", counter.getType(), counter.getEvent(), counter.getCount()); handleException(); } counter.setCount(count); } else if (counter.getCount() > 0) { ConfigurationXML::remove(); - logg->logError(__FILE__, __LINE__, "Event Based Sampling is only supported with kernel versions 3.0.0 and higher with CONFIG_PERF_EVENTS=y, and CONFIG_HW_PERF_EVENTS=y. The invalid configuration.xml has been removed.\n"); + logg->logError("Event Based Sampling is only supported with kernel versions 3.0.0 and higher with CONFIG_PERF_EVENTS=y, and CONFIG_HW_PERF_EVENTS=y. The invalid configuration.xml has been removed.\n"); handleException(); } } diff --git a/tools/gator/daemon/KMod.h b/tools/gator/daemon/KMod.h index 900a60e87d24..7f06b4b34b5d 100644 --- a/tools/gator/daemon/KMod.h +++ b/tools/gator/daemon/KMod.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/LocalCapture.cpp b/tools/gator/daemon/LocalCapture.cpp index d2a4b799d7ac..56899871c03a 100644 --- a/tools/gator/daemon/LocalCapture.cpp +++ b/tools/gator/daemon/LocalCapture.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -27,7 +27,7 @@ LocalCapture::~LocalCapture() {} void LocalCapture::createAPCDirectory(char* target_path) { gSessionData->mAPCDir = createUniqueDirectory(target_path, ".apc"); if ((removeDirAndAllContents(gSessionData->mAPCDir) != 0 || mkdir(gSessionData->mAPCDir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)) { - logg->logError(__FILE__, __LINE__, "Unable to create directory %s", gSessionData->mAPCDir); + logg->logError("Unable to create directory %s", gSessionData->mAPCDir); handleException(); } } @@ -40,7 +40,7 @@ void LocalCapture::write(char* string) { // Write the file if (util->writeToDisk(file, string) < 0) { - logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file); + logg->logError("Error writing %s\nPlease verify the path.", file); handleException(); } @@ -55,7 +55,7 @@ char* LocalCapture::createUniqueDirectory(const char* initialPath, const char* e // Ensure the path is an absolute path, i.e. starts with a slash if (initialPath == 0 || strlen(initialPath) == 0) { - logg->logError(__FILE__, __LINE__, "Missing -o command line option required for a local capture."); + logg->logError("Missing -o command line option required for a local capture."); handleException(); } else if (initialPath[0] != '/') { if (getcwd(path, PATH_MAX) == 0) { diff --git a/tools/gator/daemon/LocalCapture.h b/tools/gator/daemon/LocalCapture.h index 25d281f8328b..807f49d16845 100644 --- a/tools/gator/daemon/LocalCapture.h +++ b/tools/gator/daemon/LocalCapture.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/Logging.cpp b/tools/gator/daemon/Logging.cpp index 41ffa1a45151..8846622d950f 100644 --- a/tools/gator/daemon/Logging.cpp +++ b/tools/gator/daemon/Logging.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -39,12 +39,12 @@ Logging::Logging(bool debug) { Logging::~Logging() { } -void Logging::logError(const char* file, int line, const char* fmt, ...) { +void Logging::_logError(const char *function, const char *file, int line, const char *fmt, ...) { va_list args; MUTEX_LOCK(); if (mDebug) { - snprintf(mErrBuf, sizeof(mErrBuf), "ERROR[%s:%d]: ", file, line); + snprintf(mErrBuf, sizeof(mErrBuf), "ERROR: %s(%s:%i): ", function, file, line); } else { mErrBuf[0] = 0; } @@ -59,12 +59,12 @@ void Logging::logError(const char* file, int line, const char* fmt, ...) { MUTEX_UNLOCK(); } -void Logging::logMessage(const char* fmt, ...) { +void Logging::_logMessage(const char *function, const char *file, int line, const char *fmt, ...) { if (mDebug) { va_list args; MUTEX_LOCK(); - strcpy(mLogBuf, "INFO: "); + snprintf(mLogBuf, sizeof(mLogBuf), "INFO: %s(%s:%i): ", function, file, line); va_start(args, fmt); vsnprintf(mLogBuf + strlen(mLogBuf), sizeof(mLogBuf) - 2 - strlen(mLogBuf), fmt, args); // subtract 2 for \n and \0 diff --git a/tools/gator/daemon/Logging.h b/tools/gator/daemon/Logging.h index 09e93ff13f7a..a7b45239f5d8 100644 --- a/tools/gator/daemon/Logging.h +++ b/tools/gator/daemon/Logging.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -17,10 +17,14 @@ class Logging { public: Logging(bool debug); ~Logging(); - void logError(const char* file, int line, const char* fmt, ...); - void logMessage(const char* fmt, ...); - char* getLastError() {return mErrBuf;} - char* getLastMessage() {return mLogBuf;} +#define logError(...) _logError(__func__, __FILE__, __LINE__, __VA_ARGS__) + __attribute__ ((format (printf, 5, 6))) + void _logError(const char *function, const char *file, int line, const char *fmt, ...); +#define logMessage(...) _logMessage(__func__, __FILE__, __LINE__, __VA_ARGS__) + __attribute__ ((format (printf, 5, 6))) + void _logMessage(const char *function, const char *file, int line, const char *fmt, ...); + char *getLastError() {return mErrBuf;} + char *getLastMessage() {return mLogBuf;} private: char mErrBuf[4096]; // Arbitrarily large buffer to hold a string @@ -29,7 +33,7 @@ private: pthread_mutex_t mLoggingMutex; }; -extern Logging* logg; +extern Logging *logg; extern void handleException() __attribute__ ((noreturn)); diff --git a/tools/gator/daemon/MaliVideoDriver.cpp b/tools/gator/daemon/MaliVideoDriver.cpp index 5eef2643ab15..2db332d3e2e4 100644 --- a/tools/gator/daemon/MaliVideoDriver.cpp +++ b/tools/gator/daemon/MaliVideoDriver.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2014. All rights reserved. + * Copyright (C) ARM Limited 2014-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -109,7 +109,7 @@ static bool writeAll(const int mveUds, const char *const buf, const int pos) { while (written < pos) { size_t bytes = ::write(mveUds, buf + written, pos - written); if (bytes <= 0) { - logg->logMessage("%s(%s:%i): write failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("write failed"); return false; } written += bytes; diff --git a/tools/gator/daemon/MaliVideoDriver.h b/tools/gator/daemon/MaliVideoDriver.h index 204a57a447ac..35b0558e390b 100644 --- a/tools/gator/daemon/MaliVideoDriver.h +++ b/tools/gator/daemon/MaliVideoDriver.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2014. All rights reserved. + * Copyright (C) ARM Limited 2014-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/MemInfoDriver.cpp b/tools/gator/daemon/MemInfoDriver.cpp index cce15c16fcdc..6818b978dc5b 100644 --- a/tools/gator/daemon/MemInfoDriver.cpp +++ b/tools/gator/daemon/MemInfoDriver.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -59,7 +59,7 @@ void MemInfoDriver::read(Buffer *const buffer) { } if (!mBuf.read("/proc/meminfo")) { - logg->logError(__FILE__, __LINE__, "Failed to read /proc/meminfo"); + logg->logError("Failed to read /proc/meminfo"); handleException(); } diff --git a/tools/gator/daemon/MemInfoDriver.h b/tools/gator/daemon/MemInfoDriver.h index eb1b0417f309..ffeaf3009e93 100644 --- a/tools/gator/daemon/MemInfoDriver.h +++ b/tools/gator/daemon/MemInfoDriver.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/Monitor.cpp b/tools/gator/daemon/Monitor.cpp index 74f22ee29fec..04288872f515 100644 --- a/tools/gator/daemon/Monitor.cpp +++ b/tools/gator/daemon/Monitor.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -38,17 +38,17 @@ bool Monitor::init() { mFd = epoll_create(16); #endif if (mFd < 0) { - logg->logMessage("%s(%s:%i): epoll_create1 failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("epoll_create1 failed"); return false; } #ifndef EPOLL_CLOEXEC - int fdf = fcntl(mFd, F_GETFD); - if ((fdf == -1) || (fcntl(mFd, F_SETFD, fdf | FD_CLOEXEC) != 0)) { - logg->logMessage("%s(%s:%i): fcntl failed", __FUNCTION__, __FILE__, __LINE__); - ::close(mFd); - return -1; - } + int fdf = fcntl(mFd, F_GETFD); + if ((fdf == -1) || (fcntl(mFd, F_SETFD, fdf | FD_CLOEXEC) != 0)) { + logg->logMessage("fcntl failed"); + ::close(mFd); + return -1; + } #endif return true; @@ -60,7 +60,7 @@ bool Monitor::add(const int fd) { event.data.fd = fd; event.events = EPOLLIN; if (epoll_ctl(mFd, EPOLL_CTL_ADD, fd, &event) != 0) { - logg->logMessage("%s(%s:%i): epoll_ctl failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("epoll_ctl failed"); return false; } @@ -74,7 +74,7 @@ int Monitor::wait(struct epoll_event *const events, int maxevents, int timeout) if (errno == EINTR) { result = 0; } else { - logg->logMessage("%s(%s:%i): epoll_wait failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("epoll_wait failed"); } } diff --git a/tools/gator/daemon/Monitor.h b/tools/gator/daemon/Monitor.h index 7194e0e4ca50..55368fca3e0a 100644 --- a/tools/gator/daemon/Monitor.h +++ b/tools/gator/daemon/Monitor.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/NetDriver.cpp b/tools/gator/daemon/NetDriver.cpp index e75c0695779a..56b25e0cfa63 100644 --- a/tools/gator/daemon/NetDriver.cpp +++ b/tools/gator/daemon/NetDriver.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -108,7 +108,7 @@ bool NetDriver::doRead() { void NetDriver::start() { if (!doRead()) { - logg->logError(__FILE__, __LINE__, "Unable to read network stats"); + logg->logError("Unable to read network stats"); handleException(); } // Initialize previous values @@ -122,7 +122,7 @@ void NetDriver::start() { void NetDriver::read(Buffer *const buffer) { if (!doRead()) { - logg->logError(__FILE__, __LINE__, "Unable to read network stats"); + logg->logError("Unable to read network stats"); handleException(); } super::read(buffer); diff --git a/tools/gator/daemon/NetDriver.h b/tools/gator/daemon/NetDriver.h index 50ff850bfc6d..5f722800f75f 100644 --- a/tools/gator/daemon/NetDriver.h +++ b/tools/gator/daemon/NetDriver.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/OlySocket.cpp b/tools/gator/daemon/OlySocket.cpp index aa0ce4929916..078d20209226 100644 --- a/tools/gator/daemon/OlySocket.cpp +++ b/tools/gator/daemon/OlySocket.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -19,6 +19,7 @@ #include #include #include +#include #endif #include "Logging.h" @@ -78,7 +79,7 @@ OlyServerSocket::OlyServerSocket(int port) { #ifdef WIN32 WSADATA wsaData; if (WSAStartup(0x0202, &wsaData) != 0) { - logg->logError(__FILE__, __LINE__, "Windows socket initialization failed"); + logg->logError("Windows socket initialization failed"); handleException(); } #endif @@ -97,11 +98,11 @@ OlySocket::OlySocket(int socketID) : mSocketID(socketID) { __a > __b ? __b : __a; \ }) -OlyServerSocket::OlyServerSocket(const char* path, const size_t pathSize) { +OlyServerSocket::OlyServerSocket(const char* path, const size_t pathSize, const bool calculateAddrlen) { // Create socket mFDServer = socket_cloexec(PF_UNIX, SOCK_STREAM, 0); if (mFDServer < 0) { - logg->logError(__FILE__, __LINE__, "Error creating server socket"); + logg->logError("Error creating server socket"); handleException(); } @@ -113,19 +114,19 @@ OlyServerSocket::OlyServerSocket(const char* path, const size_t pathSize) { sockaddr.sun_path[sizeof(sockaddr.sun_path) - 1] = '\0'; // Bind the socket to an address - if (bind(mFDServer, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) { - logg->logError(__FILE__, __LINE__, "Binding of server socket failed."); + if (bind(mFDServer, (const struct sockaddr*)&sockaddr, calculateAddrlen ? offsetof(struct sockaddr_un, sun_path) + pathSize - 1 : sizeof(sockaddr)) < 0) { + logg->logError("Binding of server socket failed."); handleException(); } // Listen for connections on this socket if (listen(mFDServer, 1) < 0) { - logg->logError(__FILE__, __LINE__, "Listening of server socket failed"); + logg->logError("Listening of server socket failed"); handleException(); } } -int OlySocket::connect(const char* path, const size_t pathSize) { +int OlySocket::connect(const char* path, const size_t pathSize, const bool calculateAddrlen) { int fd = socket_cloexec(PF_UNIX, SOCK_STREAM, 0); if (fd < 0) { return -1; @@ -138,7 +139,7 @@ int OlySocket::connect(const char* path, const size_t pathSize) { memcpy(sockaddr.sun_path, path, MIN(pathSize, sizeof(sockaddr.sun_path))); sockaddr.sun_path[sizeof(sockaddr.sun_path) - 1] = '\0'; - if (::connect(fd, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) { + if (::connect(fd, (const struct sockaddr*)&sockaddr, calculateAddrlen ? offsetof(struct sockaddr_un, sun_path) + pathSize - 1 : sizeof(sockaddr)) < 0) { close(fd); return -1; } @@ -174,11 +175,11 @@ void OlySocket::closeSocket() { } void OlyServerSocket::closeServerSocket() { - if (CLOSE_SOCKET(mFDServer) != 0) { - logg->logError(__FILE__, __LINE__, "Failed to close server socket."); + if (mFDServer > 0 && CLOSE_SOCKET(mFDServer) != 0) { + logg->logError("Failed to close server socket."); handleException(); } - mFDServer = 0; + mFDServer = -1; } void OlyServerSocket::createServerSocket(int port) { @@ -190,7 +191,7 @@ void OlyServerSocket::createServerSocket(int port) { family = AF_INET; mFDServer = socket_cloexec(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (mFDServer < 0) { - logg->logError(__FILE__, __LINE__, "Error creating server socket"); + logg->logError("Error creating server socket"); handleException(); } } @@ -198,10 +199,16 @@ void OlyServerSocket::createServerSocket(int port) { // Enable address reuse, another solution would be to create the server socket once and only close it when the object exits int on = 1; if (setsockopt(mFDServer, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) != 0) { - logg->logError(__FILE__, __LINE__, "Setting server socket options failed"); + logg->logError("Setting server socket reuse option failed"); handleException(); } + // Listen on both IPv4 and IPv6 + on = 0; + if (setsockopt(mFDServer, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&on, sizeof(on)) != 0) { + logg->logMessage("setsockopt IPV6_V6ONLY failed"); + } + // Create sockaddr_in structure, ensuring non-populated fields are zero struct sockaddr_in6 sockaddr; memset((void*)&sockaddr, 0, sizeof(sockaddr)); @@ -211,13 +218,13 @@ void OlyServerSocket::createServerSocket(int port) { // Bind the socket to an address if (bind(mFDServer, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) { - logg->logError(__FILE__, __LINE__, "Binding of server socket failed.\nIs an instance already running?"); + logg->logError("Binding of server socket on port %i failed.\nIs an instance already running or is another application using that port?", port); handleException(); } // Listen for connections on this socket if (listen(mFDServer, 1) < 0) { - logg->logError(__FILE__, __LINE__, "Listening of server socket failed"); + logg->logError("Listening of server socket failed"); handleException(); } } @@ -227,14 +234,14 @@ void OlyServerSocket::createServerSocket(int port) { int OlyServerSocket::acceptConnection() { int socketID; if (mFDServer <= 0) { - logg->logError(__FILE__, __LINE__, "Attempting multiple connections on a single connection server socket or attempting to accept on a client socket"); + logg->logError("Attempting multiple connections on a single connection server socket or attempting to accept on a client socket"); handleException(); } // Accept a connection, note that this call blocks until a client connects socketID = accept_cloexec(mFDServer, NULL, NULL); if (socketID < 0) { - logg->logError(__FILE__, __LINE__, "Socket acceptance failed"); + logg->logError("Socket acceptance failed"); handleException(); } return socketID; @@ -248,7 +255,7 @@ void OlySocket::send(const char* buffer, int size) { while (size > 0) { int n = ::send(mSocketID, buffer, size, 0); if (n < 0) { - logg->logError(__FILE__, __LINE__, "Socket send error"); + logg->logError("Socket send error"); handleException(); } size -= n; @@ -264,7 +271,7 @@ int OlySocket::receive(char* buffer, int size) { int bytes = recv(mSocketID, buffer, size, 0); if (bytes < 0) { - logg->logError(__FILE__, __LINE__, "Socket receive error"); + logg->logError("Socket receive error"); handleException(); } else if (bytes == 0) { logg->logMessage("Socket disconnected"); @@ -279,7 +286,7 @@ int OlySocket::receiveNBytes(char* buffer, int size) { while (size > 0 && buffer != NULL) { bytes = recv(mSocketID, buffer, size, 0); if (bytes < 0) { - logg->logError(__FILE__, __LINE__, "Socket receive error"); + logg->logError("Socket receive error"); handleException(); } else if (bytes == 0) { logg->logMessage("Socket disconnected"); @@ -304,7 +311,7 @@ int OlySocket::receiveString(char* buffer, int size) { // Receive a single character int bytes = recv(mSocketID, &buffer[bytes_received], 1, 0); if (bytes < 0) { - logg->logError(__FILE__, __LINE__, "Socket receive error"); + logg->logError("Socket receive error"); handleException(); } else if (bytes == 0) { logg->logMessage("Socket disconnected"); diff --git a/tools/gator/daemon/OlySocket.h b/tools/gator/daemon/OlySocket.h index 6b53b01fc3ee..757a2522f926 100644 --- a/tools/gator/daemon/OlySocket.h +++ b/tools/gator/daemon/OlySocket.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -12,7 +12,7 @@ #include #ifdef WIN32 -typedef socklen_t int; +typedef int socklen_t; #else #include #endif @@ -20,7 +20,7 @@ typedef socklen_t int; class OlySocket { public: #ifndef WIN32 - static int connect(const char* path, const size_t pathSize); + static int connect(const char* path, const size_t pathSize, const bool calculateAddrlen = false); #endif OlySocket(int socketID); @@ -43,7 +43,7 @@ class OlyServerSocket { public: OlyServerSocket(int port); #ifndef WIN32 - OlyServerSocket(const char* path, const size_t pathSize); + OlyServerSocket(const char* path, const size_t pathSize, const bool calculateAddrlen = false); #endif ~OlyServerSocket(); diff --git a/tools/gator/daemon/OlyUtility.cpp b/tools/gator/daemon/OlyUtility.cpp index 45340a27d9fa..6f40168c1ee0 100644 --- a/tools/gator/daemon/OlyUtility.cpp +++ b/tools/gator/daemon/OlyUtility.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/OlyUtility.h b/tools/gator/daemon/OlyUtility.h index 1d26beb596fa..1525081a97a3 100644 --- a/tools/gator/daemon/OlyUtility.h +++ b/tools/gator/daemon/OlyUtility.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/PerfBuffer.cpp b/tools/gator/daemon/PerfBuffer.cpp index f127c996d43b..3b9da1dc6592 100644 --- a/tools/gator/daemon/PerfBuffer.cpp +++ b/tools/gator/daemon/PerfBuffer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -35,14 +35,14 @@ PerfBuffer::~PerfBuffer() { bool PerfBuffer::useFd(const int cpu, const int fd) { if (mFds[cpu] < 0) { if (mBuf[cpu] != MAP_FAILED) { - logg->logMessage("%s(%s:%i): cpu %i already online or not correctly cleaned up", __FUNCTION__, __FILE__, __LINE__, cpu); + logg->logMessage("cpu %i already online or not correctly cleaned up", cpu); return false; } // The buffer isn't mapped yet mBuf[cpu] = mmap(NULL, gSessionData->mPageSize + BUF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (mBuf[cpu] == MAP_FAILED) { - logg->logMessage("%s(%s:%i): mmap failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("mmap failed"); return false; } mFds[cpu] = fd; @@ -50,17 +50,17 @@ bool PerfBuffer::useFd(const int cpu, const int fd) { // Check the version struct perf_event_mmap_page *pemp = static_cast(mBuf[cpu]); if (pemp->compat_version != 0) { - logg->logMessage("%s(%s:%i): Incompatible perf_event_mmap_page compat_version", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("Incompatible perf_event_mmap_page compat_version"); return false; } } else { if (mBuf[cpu] == MAP_FAILED) { - logg->logMessage("%s(%s:%i): cpu already online or not correctly cleaned up", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("cpu already online or not correctly cleaned up"); return false; } if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, mFds[cpu]) < 0) { - logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("ioctl failed"); return false; } } @@ -79,8 +79,8 @@ bool PerfBuffer::isEmpty() { if (mBuf[cpu] != MAP_FAILED) { // Take a snapshot of the positions struct perf_event_mmap_page *pemp = static_cast(mBuf[cpu]); - const __u64 head = pemp->data_head; - const __u64 tail = pemp->data_tail; + const __u64 head = ACCESS_ONCE(pemp->data_head); + const __u64 tail = ACCESS_ONCE(pemp->data_tail); if (head != tail) { return false; @@ -91,42 +91,105 @@ bool PerfBuffer::isEmpty() { return true; } -static void compressAndSend(const int cpu, const __u64 head, __u64 tail, const uint8_t *const b, Sender *const sender) { - // Pick a big size but something smaller than the chunkSize in Sender::writeData which is 100k - char buf[1<<16]; - int writePos = 0; - const int typeLength = gSessionData->mLocalCapture ? 0 : 1; +bool PerfBuffer::isFull() { + for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) { + if (mBuf[cpu] != MAP_FAILED) { + // Take a snapshot of the positions + struct perf_event_mmap_page *pemp = static_cast(mBuf[cpu]); + const __u64 head = ACCESS_ONCE(pemp->data_head); - while (head > tail) { - writePos = 0; - if (!gSessionData->mLocalCapture) { - buf[writePos++] = RESPONSE_APC_DATA; + if (head + 2000 <= (unsigned int)BUF_SIZE) { + return true; + } } - // Reserve space for size - writePos += sizeof(uint32_t); - Buffer::packInt(buf, sizeof(buf), writePos, FRAME_PERF); - Buffer::packInt(buf, sizeof(buf), writePos, cpu); + } + + return false; +} + +class PerfFrame { +public: + PerfFrame(Sender *const sender) : mSender(sender), mWritePos(-1), mCpuSizePos(-1) {} + + void add(const int cpu, const __u64 head, __u64 tail, const uint8_t *const b) { + cpuHeader(cpu); while (head > tail) { const int count = reinterpret_cast(b + (tail & BUF_MASK))->size/sizeof(uint64_t); // Can this whole message be written as Streamline assumes events are not split between frames - if (sizeof(buf) <= writePos + count*Buffer::MAXSIZE_PACK64) { - break; + if (sizeof(mBuf) <= mWritePos + count*Buffer::MAXSIZE_PACK64) { + send(); + cpuHeader(cpu); } for (int i = 0; i < count; ++i) { // Must account for message size - Buffer::packInt64(buf, sizeof(buf), writePos, *reinterpret_cast(b + (tail & BUF_MASK))); + Buffer::packInt64(mBuf, sizeof(mBuf), mWritePos, *reinterpret_cast(b + (tail & BUF_MASK))); tail += sizeof(uint64_t); } } + } + + void send() { + if (mWritePos > 0) { + writeFrameSize(); + mSender->writeData(mBuf, mWritePos, RESPONSE_APC_DATA); + mWritePos = -1; + mCpuSizePos = -1; + } + } - // Write size - Buffer::writeLEInt(reinterpret_cast(buf + typeLength), writePos - typeLength - sizeof(uint32_t)); - sender->writeData(buf, writePos, RESPONSE_APC_DATA); +private: + void writeFrameSize() { + writeCpuSize(); + const int typeLength = gSessionData->mLocalCapture ? 0 : 1; + Buffer::writeLEInt(reinterpret_cast(mBuf + typeLength), mWritePos - typeLength - sizeof(uint32_t)); } -} + + void frameHeader() { + if (mWritePos < 0) { + mWritePos = 0; + mCpuSizePos = -1; + if (!gSessionData->mLocalCapture) { + mBuf[mWritePos++] = RESPONSE_APC_DATA; + } + // Reserve space for frame size + mWritePos += sizeof(uint32_t); + Buffer::packInt(mBuf, sizeof(mBuf), mWritePos, FRAME_PERF); + } + } + + void writeCpuSize() { + if (mCpuSizePos >= 0) { + Buffer::writeLEInt(reinterpret_cast(mBuf + mCpuSizePos), mWritePos - mCpuSizePos - sizeof(uint32_t)); + } + } + + void cpuHeader(const int cpu) { + if (sizeof(mBuf) <= mWritePos + Buffer::MAXSIZE_PACK32 + sizeof(uint32_t)) { + send(); + } + frameHeader(); + writeCpuSize(); + Buffer::packInt(mBuf, sizeof(mBuf), mWritePos, cpu); + mCpuSizePos = mWritePos; + // Reserve space for cpu size + mWritePos += sizeof(uint32_t); + } + + // Pick a big size but something smaller than the chunkSize in Sender::writeData which is 100k + char mBuf[1<<16]; + Sender *const mSender; + int mWritePos; + int mCpuSizePos; + + // Intentionally unimplemented + PerfFrame(const PerfFrame &); + PerfFrame& operator=(const PerfFrame &); +}; bool PerfBuffer::send(Sender *const sender) { + PerfFrame frame(sender); + for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) { if (mBuf[cpu] == MAP_FAILED) { continue; @@ -134,12 +197,12 @@ bool PerfBuffer::send(Sender *const sender) { // Take a snapshot of the positions struct perf_event_mmap_page *pemp = static_cast(mBuf[cpu]); - const __u64 head = pemp->data_head; - const __u64 tail = pemp->data_tail; + const __u64 head = ACCESS_ONCE(pemp->data_head); + const __u64 tail = ACCESS_ONCE(pemp->data_tail); if (head > tail) { const uint8_t *const b = static_cast(mBuf[cpu]) + gSessionData->mPageSize; - compressAndSend(cpu, head, tail, b, sender); + frame.add(cpu, head, tail, b); // Update tail with the data read pemp->data_tail = head; @@ -150,9 +213,11 @@ bool PerfBuffer::send(Sender *const sender) { mBuf[cpu] = MAP_FAILED; mDiscard[cpu] = false; mFds[cpu] = -1; - logg->logMessage("%s(%s:%i): Unmaped cpu %i", __FUNCTION__, __FILE__, __LINE__, cpu); + logg->logMessage("Unmaped cpu %i", cpu); } } + frame.send(); + return true; } diff --git a/tools/gator/daemon/PerfBuffer.h b/tools/gator/daemon/PerfBuffer.h index 25a10625a9e8..a2d0e9b44725 100644 --- a/tools/gator/daemon/PerfBuffer.h +++ b/tools/gator/daemon/PerfBuffer.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -24,6 +24,7 @@ public: bool useFd(const int cpu, const int fd); void discard(const int cpu); bool isEmpty(); + bool isFull(); bool send(Sender *const sender); private: diff --git a/tools/gator/daemon/PerfDriver.cpp b/tools/gator/daemon/PerfDriver.cpp index ee90284cee41..796ee7564c66 100644 --- a/tools/gator/daemon/PerfDriver.cpp +++ b/tools/gator/daemon/PerfDriver.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -40,24 +40,25 @@ struct gator_cpu { // From gator_main.c static const struct gator_cpu gator_cpus[] = { - { 0xb36, "ARM1136", "ARM_ARM11", 3 }, - { 0xb56, "ARM1156", "ARM_ARM11", 3 }, - { 0xb76, "ARM1176", "ARM_ARM11", 3 }, - { 0xb02, "ARM11MPCore", "ARM_ARM11MPCore", 3 }, - { 0xc05, "Cortex-A5", "ARMv7_Cortex_A5", 2 }, - { 0xc07, "Cortex-A7", "ARMv7_Cortex_A7", 4 }, - { 0xc08, "Cortex-A8", "ARMv7_Cortex_A8", 4 }, - { 0xc09, "Cortex-A9", "ARMv7_Cortex_A9", 6 }, - { 0xc0f, "Cortex-A15", "ARMv7_Cortex_A15", 6 }, - { 0xc0e, "Cortex-A17", "ARMv7_Cortex_A17", 6 }, - { 0x00f, "Scorpion", "Scorpion", 4 }, - { 0x02d, "ScorpionMP", "ScorpionMP", 4 }, - { 0x049, "KraitSIM", "Krait", 4 }, - { 0x04d, "Krait", "Krait", 4 }, - { 0x06f, "Krait S4 Pro", "Krait", 4 }, - { 0xd03, "Cortex-A53", "ARM_Cortex-A53", 6 }, - { 0xd07, "Cortex-A57", "ARM_Cortex-A57", 6 }, - { 0xd0f, "AArch64", "ARM_AArch64", 6 }, + { 0x41b36, "ARM1136", "ARM_ARM11", 3 }, + { 0x41b56, "ARM1156", "ARM_ARM11", 3 }, + { 0x41b76, "ARM1176", "ARM_ARM11", 3 }, + { 0x41b02, "ARM11MPCore", "ARM_ARM11MPCore", 3 }, + { 0x41c05, "Cortex-A5", "ARMv7_Cortex_A5", 2 }, + { 0x41c07, "Cortex-A7", "ARMv7_Cortex_A7", 4 }, + { 0x41c08, "Cortex-A8", "ARMv7_Cortex_A8", 4 }, + { 0x41c09, "Cortex-A9", "ARMv7_Cortex_A9", 6 }, + { 0x41c0f, "Cortex-A15", "ARMv7_Cortex_A15", 6 }, + { 0x41c0d, "Cortex-A17", "ARMv7_Cortex_A17", 6 }, + { 0x41c0e, "Cortex-A17", "ARMv7_Cortex_A17", 6 }, + { 0x5100f, "Scorpion", "Scorpion", 4 }, + { 0x5102d, "ScorpionMP", "ScorpionMP", 4 }, + { 0x51049, "KraitSIM", "Krait", 4 }, + { 0x5104d, "Krait", "Krait", 4 }, + { 0x5106f, "Krait S4 Pro", "Krait", 4 }, + { 0x41d03, "Cortex-A53", "ARM_Cortex-A53", 6 }, + { 0x41d07, "Cortex-A57", "ARM_Cortex-A57", 6 }, + { 0x41d08, "Cortex-A72", "ARM_Cortex-A72", 6 }, }; static const char OLD_PMU_PREFIX[] = "ARMv7 Cortex-"; @@ -69,17 +70,19 @@ struct uncore_counter { // gatorfs event name const char *const gatorName; const int count; + const bool hasCyclesCounter; }; static const struct uncore_counter uncore_counters[] = { - { "CCI_400", "CCI_400", 4 }, - { "CCI_400-r1", "CCI_400-r1", 4 }, - { "ccn", "ARM_CCN_5XX", 8 }, + { "CCI_400", "CCI_400", 4, true }, + { "CCI_400-r1", "CCI_400-r1", 4, true }, + { "CCI_500", "CCI_500", 8, false }, + { "ccn", "ARM_CCN_5XX", 8, true }, }; class PerfCounter : public DriverCounter { public: - PerfCounter(DriverCounter *next, const char *name, uint32_t type, uint64_t config, bool perCpu) : DriverCounter(next, name), mType(type), mCount(0), mConfig(config), mPerCpu(perCpu) {} + PerfCounter(DriverCounter *next, const char *name, uint32_t type, uint64_t config, uint64_t sampleType, uint64_t flags) : DriverCounter(next, name), mType(type), mConfig(config), mSampleType(sampleType), mFlags(flags), mCount(0) {} ~PerfCounter() { } @@ -89,13 +92,41 @@ public: void setCount(const int count) { mCount = count; } uint64_t getConfig() const { return mConfig; } void setConfig(const uint64_t config) { mConfig = config; } - bool isPerCpu() const { return mPerCpu; } + uint64_t getSampleType() const { return mSampleType; } + uint64_t getFlags() const { return mFlags; } + virtual void read(Buffer *const, const int) {} private: const uint32_t mType; - int mCount; uint64_t mConfig; - bool mPerCpu; + const uint64_t mSampleType; + const uint64_t mFlags; + int mCount; + + // Intentionally undefined + PerfCounter(const PerfCounter &); + PerfCounter &operator=(const PerfCounter &); +}; + +class CPUFreqDriver : public PerfCounter { +public: + CPUFreqDriver(DriverCounter *next, uint64_t id) : PerfCounter(next, "Linux_power_cpu_freq", PERF_TYPE_TRACEPOINT, id, PERF_SAMPLE_RAW, PERF_GROUP_LEADER | PERF_GROUP_PER_CPU) {} + + void read(Buffer *const buffer, const int cpu) { + char buf[64]; + + snprintf(buf, sizeof(buf), "/sys/devices/system/cpu/cpu%i/cpufreq/cpuinfo_cur_freq", cpu); + int64_t freq; + if (DriverSource::readInt64Driver(buf, &freq) != 0) { + freq = 0; + } + buffer->perfCounter(cpu, getKey(), 1000*freq); + } + +private: + // Intentionally undefined + CPUFreqDriver(const CPUFreqDriver &); + CPUFreqDriver &operator=(const CPUFreqDriver &); }; PerfDriver::PerfDriver() : mIsSetup(false), mLegacySupport(false) { @@ -108,27 +139,32 @@ void PerfDriver::addCpuCounters(const char *const counterName, const int type, c int len = snprintf(NULL, 0, "%s_ccnt", counterName) + 1; char *name = new char[len]; snprintf(name, len, "%s_ccnt", counterName); - setCounters(new PerfCounter(getCounters(), name, type, -1, true)); + setCounters(new PerfCounter(getCounters(), name, type, -1, PERF_SAMPLE_READ, PERF_GROUP_PER_CPU | PERF_GROUP_CPU)); for (int j = 0; j < numCounters; ++j) { len = snprintf(NULL, 0, "%s_cnt%d", counterName, j) + 1; name = new char[len]; snprintf(name, len, "%s_cnt%d", counterName, j); - setCounters(new PerfCounter(getCounters(), name, type, -1, true)); + setCounters(new PerfCounter(getCounters(), name, type, -1, PERF_SAMPLE_READ, PERF_GROUP_PER_CPU | PERF_GROUP_CPU)); } } -void PerfDriver::addUncoreCounters(const char *const counterName, const int type, const int numCounters) { - int len = snprintf(NULL, 0, "%s_ccnt", counterName) + 1; - char *name = new char[len]; - snprintf(name, len, "%s_ccnt", counterName); - setCounters(new PerfCounter(getCounters(), name, type, -1, false)); +void PerfDriver::addUncoreCounters(const char *const counterName, const int type, const int numCounters, const bool hasCyclesCounter) { + int len; + char *name; + + if (hasCyclesCounter) { + len = snprintf(NULL, 0, "%s_ccnt", counterName) + 1; + name = new char[len]; + snprintf(name, len, "%s_ccnt", counterName); + setCounters(new PerfCounter(getCounters(), name, type, -1, PERF_SAMPLE_READ, 0)); + } for (int j = 0; j < numCounters; ++j) { len = snprintf(NULL, 0, "%s_cnt%d", counterName, j) + 1; name = new char[len]; snprintf(name, len, "%s_cnt%d", counterName, j); - setCounters(new PerfCounter(getCounters(), name, type, -1, false)); + setCounters(new PerfCounter(getCounters(), name, type, -1, PERF_SAMPLE_READ, 0)); } } @@ -136,18 +172,18 @@ bool PerfDriver::setup() { // Check the kernel version int release[3]; if (!getLinuxVersion(release)) { - logg->logMessage("%s(%s:%i): getLinuxVersion failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("getLinuxVersion failed"); return false; } if (KERNEL_VERSION(release[0], release[1], release[2]) < KERNEL_VERSION(3, 4, 0)) { - logg->logMessage("%s(%s:%i): Unsupported kernel version", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("Unsupported kernel version"); return false; } mLegacySupport = KERNEL_VERSION(release[0], release[1], release[2]) < KERNEL_VERSION(3, 12, 0); if (access(EVENTS_PATH, R_OK) != 0) { - logg->logMessage("%s(%s:%i): " EVENTS_PATH " does not exist, is CONFIG_TRACING and CONFIG_CONTEXT_SWITCH_TRACER enabled?", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage(EVENTS_PATH " does not exist, is CONFIG_TRACING and CONFIG_CONTEXT_SWITCH_TRACER enabled?"); return false; } @@ -155,7 +191,7 @@ bool PerfDriver::setup() { bool foundCpu = false; DIR *dir = opendir(PERF_DEVICES); if (dir == NULL) { - logg->logMessage("%s(%s:%i): opendif failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("opendir failed"); return false; } @@ -198,7 +234,7 @@ bool PerfDriver::setup() { } logg->logMessage("Adding uncore counters for %s", uncore_counters[i].gatorName); - addUncoreCounters(uncore_counters[i].gatorName, type, uncore_counters[i].count); + addUncoreCounters(uncore_counters[i].gatorName, type, uncore_counters[i].count, uncore_counters[i].hasCyclesCounter); } } closedir(dir); @@ -216,13 +252,11 @@ bool PerfDriver::setup() { } } - /* if (!foundCpu) { - // If all else fails, use the perf architected counters - // 9 because that's how many are in events-Perf-Hardware.xml - assume they can all be enabled at once - addCpuCounters("Perf_Hardware", PERF_TYPE_HARDWARE, 9); + // If all else fails, use the ARM architected counters + logg->logMessage("Using Other cpu"); + addCpuCounters("Other", PERF_TYPE_RAW, 6); } - */ // Add supported software counters long long id; @@ -230,20 +264,25 @@ bool PerfDriver::setup() { id = getTracepointId("irq/softirq_exit", &printb); if (id >= 0) { - setCounters(new PerfCounter(getCounters(), "Linux_irq_softirq", PERF_TYPE_TRACEPOINT, id, true)); + setCounters(new PerfCounter(getCounters(), "Linux_irq_softirq", PERF_TYPE_TRACEPOINT, id, PERF_SAMPLE_READ, PERF_GROUP_PER_CPU | PERF_GROUP_CPU)); } id = getTracepointId("irq/irq_handler_exit", &printb); if (id >= 0) { - setCounters(new PerfCounter(getCounters(), "Linux_irq_irq", PERF_TYPE_TRACEPOINT, id, true)); + setCounters(new PerfCounter(getCounters(), "Linux_irq_irq", PERF_TYPE_TRACEPOINT, id, PERF_SAMPLE_READ, PERF_GROUP_PER_CPU | PERF_GROUP_CPU)); } id = getTracepointId(SCHED_SWITCH, &printb); if (id >= 0) { - setCounters(new PerfCounter(getCounters(), "Linux_sched_switch", PERF_TYPE_TRACEPOINT, id, true)); + setCounters(new PerfCounter(getCounters(), "Linux_sched_switch", PERF_TYPE_TRACEPOINT, id, PERF_SAMPLE_READ, PERF_GROUP_PER_CPU | PERF_GROUP_CPU)); + } + + id = getTracepointId(CPU_FREQUENCY, &printb); + if (id >= 0) { + setCounters(new CPUFreqDriver(getCounters(), id)); } - setCounters(new PerfCounter(getCounters(), "Linux_cpu_wait_contention", TYPE_DERIVED, -1, false)); + setCounters(new PerfCounter(getCounters(), "Linux_cpu_wait_contention", TYPE_DERIVED, -1, 0, 0)); //Linux_cpu_wait_io @@ -254,7 +293,7 @@ bool PerfDriver::setup() { bool PerfDriver::summary(Buffer *const buffer) { struct utsname utsname; if (uname(&utsname) != 0) { - logg->logMessage("%s(%s:%i): uname failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("uname failed"); return false; } @@ -263,25 +302,26 @@ bool PerfDriver::summary(Buffer *const buffer) { struct timespec ts; if (clock_gettime(CLOCK_REALTIME, &ts) != 0) { - logg->logMessage("%s(%s:%i): clock_gettime failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("clock_gettime failed"); return false; } const int64_t timestamp = (int64_t)ts.tv_sec * NS_PER_S + ts.tv_nsec; const uint64_t monotonicStarted = getTime(); gSessionData->mMonotonicStarted = monotonicStarted; + const uint64_t currTime = 0;//getTime() - gSessionData->mMonotonicStarted; - buffer->summary(monotonicStarted, timestamp, monotonicStarted, monotonicStarted, buf); + buffer->summary(currTime, timestamp, monotonicStarted, monotonicStarted, buf); for (int i = 0; i < gSessionData->mCores; ++i) { - coreName(monotonicStarted, buffer, i); + coreName(currTime, buffer, i); } - buffer->commit(monotonicStarted); + buffer->commit(currTime); return true; } -void PerfDriver::coreName(const uint32_t startTime, Buffer *const buffer, const int cpu) { +void PerfDriver::coreName(const uint64_t currTime, Buffer *const buffer, const int cpu) { // Don't send information on a cpu we know nothing about if (gSessionData->mCpuIds[cpu] == -1) { return; @@ -293,8 +333,8 @@ void PerfDriver::coreName(const uint32_t startTime, Buffer *const buffer, const break; } } - if (gator_cpus[j].cpuid == gSessionData->mCpuIds[cpu]) { - buffer->coreName(startTime, cpu, gSessionData->mCpuIds[cpu], gator_cpus[j].core_name); + if (j < ARRAY_LENGTH(gator_cpus) && gator_cpus[j].cpuid == gSessionData->mCpuIds[cpu]) { + buffer->coreName(currTime, cpu, gSessionData->mCpuIds[cpu], gator_cpus[j].core_name); } else { char buf[32]; if (gSessionData->mCpuIds[cpu] == -1) { @@ -302,7 +342,7 @@ void PerfDriver::coreName(const uint32_t startTime, Buffer *const buffer, const } else { snprintf(buf, sizeof(buf), "Unknown (0x%.3x)", gSessionData->mCpuIds[cpu]); } - buffer->coreName(startTime, cpu, gSessionData->mCpuIds[cpu], buf); + buffer->coreName(currTime, cpu, gSessionData->mCpuIds[cpu], buf); } } @@ -325,8 +365,17 @@ void PerfDriver::setupCounter(Counter &counter) { bool PerfDriver::enable(const uint64_t currTime, PerfGroup *const group, Buffer *const buffer) const { for (PerfCounter *counter = static_cast(getCounters()); counter != NULL; counter = static_cast(counter->getNext())) { if (counter->isEnabled() && (counter->getType() != TYPE_DERIVED)) { - if (!group->add(currTime, buffer, counter->getKey(), counter->getType(), counter->getConfig(), counter->getCount(), counter->getCount() > 0 ? PERF_SAMPLE_TID | PERF_SAMPLE_IP : 0, counter->isPerCpu() ? PERF_GROUP_PER_CPU : 0)) { - logg->logMessage("%s(%s:%i): PerfGroup::add failed", __FUNCTION__, __FILE__, __LINE__); + int count = counter->getCount(); + uint64_t sampleType = counter->getSampleType(); + if (sampleType & PERF_SAMPLE_RAW) { + // If raw is enabled, every sample is needed + count = 1; + } + if (!group->add(currTime, buffer, counter->getKey(), counter->getType(), counter->getConfig(), count, + // use getCount instead of count as EBS counters need TID and IP but RAW tracepoints don't + (counter->getCount() > 0 ? PERF_SAMPLE_TID | PERF_SAMPLE_IP : 0) | sampleType, + counter->getFlags())) { + logg->logMessage("PerfGroup::add failed"); return false; } } @@ -335,15 +384,24 @@ bool PerfDriver::enable(const uint64_t currTime, PerfGroup *const group, Buffer return true; } +void PerfDriver::read(Buffer *const buffer, const int cpu) { + for (PerfCounter *counter = static_cast(getCounters()); counter != NULL; counter = static_cast(counter->getNext())) { + if (!counter->isEnabled()) { + continue; + } + counter->read(buffer, cpu); + } +} + long long PerfDriver::getTracepointId(const char *const name, DynBuf *const printb) { if (!printb->printf(EVENTS_PATH "/%s/id", name)) { - logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("DynBuf::printf failed"); return -1; } int64_t result; if (DriverSource::readInt64Driver(printb->getBuf(), &result) != 0) { - logg->logMessage("%s(%s:%i): DriverSource::readInt64Driver failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("DriverSource::readInt64Driver failed"); return -1; } diff --git a/tools/gator/daemon/PerfDriver.h b/tools/gator/daemon/PerfDriver.h index 846203a9e18b..95b42bfa30c0 100644 --- a/tools/gator/daemon/PerfDriver.h +++ b/tools/gator/daemon/PerfDriver.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -19,6 +19,7 @@ #define SCHED_SWITCH "sched/sched_switch" #define CPU_IDLE "power/cpu_idle" +#define CPU_FREQUENCY "power/cpu_frequency" class Buffer; class DynBuf; @@ -33,18 +34,19 @@ public: bool setup(); bool summary(Buffer *const buffer); - void coreName(const uint32_t startTime, Buffer *const buffer, const int cpu); + void coreName(const uint64_t currTime, Buffer *const buffer, const int cpu); bool isSetup() const { return mIsSetup; } void setupCounter(Counter &counter); bool enable(const uint64_t currTime, PerfGroup *const group, Buffer *const buffer) const; + void read(Buffer *const buffer, const int cpu); static long long getTracepointId(const char *const name, DynBuf *const printb); private: void addCpuCounters(const char *const counterName, const int type, const int numCounters); - void addUncoreCounters(const char *const counterName, const int type, const int numCounters); + void addUncoreCounters(const char *const counterName, const int type, const int numCounters, const bool hasCyclesCounter); bool mIsSetup; bool mLegacySupport; diff --git a/tools/gator/daemon/PerfGroup.cpp b/tools/gator/daemon/PerfGroup.cpp index 4fd960a9058c..cfc62e4cc77e 100644 --- a/tools/gator/daemon/PerfGroup.cpp +++ b/tools/gator/daemon/PerfGroup.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -16,17 +16,21 @@ #include #include "Buffer.h" +#include "DynBuf.h" #include "Logging.h" #include "Monitor.h" #include "PerfBuffer.h" #include "SessionData.h" +static const int schedSwitchKey = getEventKey(); +static const int clockKey = getEventKey(); + #define DEFAULT_PEA_ARGS(pea, additionalSampleType) \ pea.size = sizeof(pea); \ /* Emit time, read_format below, group leader id, and raw tracepoint info */ \ pea.sample_type = (gSessionData->perf.getLegacySupport() \ - ? PERF_SAMPLE_TID | PERF_SAMPLE_IP | PERF_SAMPLE_TIME | PERF_SAMPLE_READ | PERF_SAMPLE_ID \ - : PERF_SAMPLE_TIME | PERF_SAMPLE_READ | PERF_SAMPLE_IDENTIFIER ) | additionalSampleType; \ + ? PERF_SAMPLE_TID | PERF_SAMPLE_IP | PERF_SAMPLE_ID \ + : PERF_SAMPLE_IDENTIFIER ) | PERF_SAMPLE_TIME | additionalSampleType; \ /* Emit emit value in group format */ \ pea.read_format = PERF_FORMAT_ID | PERF_FORMAT_GROUP; \ /* start out disabled */ \ @@ -49,11 +53,12 @@ static int sys_perf_event_open(struct perf_event_attr *const attr, const pid_t p return fd; } -PerfGroup::PerfGroup(PerfBuffer *const pb) : mPb(pb) { +PerfGroup::PerfGroup(PerfBuffer *const pb) : mPb(pb), mSchedSwitchId(-1) { memset(&mAttrs, 0, sizeof(mAttrs)); - memset(&mPerCpu, 0, sizeof(mPerCpu)); + memset(&mFlags, 0, sizeof(mFlags)); memset(&mKeys, -1, sizeof(mKeys)); memset(&mFds, -1, sizeof(mFds)); + memset(&mLeaders, -1, sizeof(mLeaders)); } PerfGroup::~PerfGroup() { @@ -64,7 +69,7 @@ PerfGroup::~PerfGroup() { } } -bool PerfGroup::add(const uint64_t currTime, Buffer *const buffer, const int key, const __u32 type, const __u64 config, const __u64 sample, const __u64 sampleType, const int flags) { +int PerfGroup::doAdd(const uint64_t currTime, Buffer *const buffer, const int key, const __u32 type, const __u64 config, const __u64 sample, const __u64 sampleType, const int flags) { int i; for (i = 0; i < ARRAY_LENGTH(mKeys); ++i) { if (mKeys[i] < 0) { @@ -73,8 +78,8 @@ bool PerfGroup::add(const uint64_t currTime, Buffer *const buffer, const int key } if (i >= ARRAY_LENGTH(mKeys)) { - logg->logMessage("%s(%s:%i): Too many counters", __FUNCTION__, __FILE__, __LINE__); - return false; + logg->logMessage("Too many counters"); + return -1; } DEFAULT_PEA_ARGS(mAttrs[i], sampleType); @@ -82,121 +87,230 @@ bool PerfGroup::add(const uint64_t currTime, Buffer *const buffer, const int key mAttrs[i].config = config; mAttrs[i].sample_period = sample; // always be on the CPU but only a group leader can be pinned - mAttrs[i].pinned = (i == 0 ? 1 : 0); + mAttrs[i].pinned = (flags & PERF_GROUP_LEADER ? 1 : 0); mAttrs[i].mmap = (flags & PERF_GROUP_MMAP ? 1 : 0); mAttrs[i].comm = (flags & PERF_GROUP_COMM ? 1 : 0); mAttrs[i].freq = (flags & PERF_GROUP_FREQ ? 1 : 0); mAttrs[i].task = (flags & PERF_GROUP_TASK ? 1 : 0); mAttrs[i].sample_id_all = (flags & PERF_GROUP_SAMPLE_ID_ALL ? 1 : 0); - mPerCpu[i] = (flags & PERF_GROUP_PER_CPU); + mFlags[i] = flags; mKeys[i] = key; - buffer->pea(currTime, &mAttrs[i], key); + buffer->marshalPea(currTime, &mAttrs[i], key); + + return i; +} + +/* Counters from different hardware PMUs need to be in different + * groups. Software counters can be in the same group as the CPU and + * should be marked as PERF_GROUP_CPU. The big and little clusters can + * be in the same group as only one or the other will be available on + * a given CPU. + */ +int PerfGroup::getEffectiveType(const int type, const int flags) { + const int effectiveType = flags & PERF_GROUP_CPU ? (int)PERF_TYPE_HARDWARE : type; + if (effectiveType >= ARRAY_LENGTH(mLeaders)) { + logg->logError("perf type is too large, please increase the size of PerfGroup::mLeaders"); + handleException(); + } + return effectiveType; +} + +bool PerfGroup::createCpuGroup(const uint64_t currTime, Buffer *const buffer) { + if (mSchedSwitchId < 0) { + DynBuf b; + mSchedSwitchId = PerfDriver::getTracepointId(SCHED_SWITCH, &b); + if (mSchedSwitchId < 0) { + logg->logMessage("Unable to read sched_switch id"); + return false; + } + } + + mLeaders[PERF_TYPE_HARDWARE] = doAdd(currTime, buffer, schedSwitchKey, PERF_TYPE_TRACEPOINT, mSchedSwitchId, 1, PERF_SAMPLE_READ | PERF_SAMPLE_RAW, PERF_GROUP_MMAP | PERF_GROUP_COMM | PERF_GROUP_TASK | PERF_GROUP_SAMPLE_ID_ALL | PERF_GROUP_PER_CPU | PERF_GROUP_LEADER | PERF_GROUP_CPU); + if (mLeaders[PERF_TYPE_HARDWARE] < 0) { + return false; + } + + if (gSessionData->mSampleRate > 0 && !gSessionData->mIsEBS && doAdd(currTime, buffer, clockKey, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK, 1000000000UL / gSessionData->mSampleRate, PERF_SAMPLE_TID | PERF_SAMPLE_IP | PERF_SAMPLE_READ, PERF_GROUP_PER_CPU | PERF_GROUP_CPU) < 0) { + return false; + } return true; } +bool PerfGroup::add(const uint64_t currTime, Buffer *const buffer, const int key, const __u32 type, const __u64 config, const __u64 sample, const __u64 sampleType, const int flags) { + const int effectiveType = getEffectiveType(type, flags); + + // Does a group exist for this already? + if (!(flags & PERF_GROUP_LEADER) && mLeaders[effectiveType] < 0) { + // Create it + if (effectiveType == PERF_TYPE_HARDWARE) { + if (!createCpuGroup(currTime, buffer)) { + return false; + } + } else { + // Non-CPU PMUs are sampled every 100ms for Sample Rate: None and EBS, otherwise they would never be sampled + const uint64_t timeout = gSessionData->mSampleRate > 0 && !gSessionData->mIsEBS ? 1000000000UL / gSessionData->mSampleRate : 100000000UL; + // PERF_SAMPLE_TID | PERF_SAMPLE_IP aren't helpful on non-CPU or 'uncore' PMUs - which CPU is the right one to sample? But removing it causes problems, remove it later. + mLeaders[effectiveType] = doAdd(currTime, buffer, clockKey, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK, timeout, PERF_SAMPLE_TID | PERF_SAMPLE_IP | PERF_SAMPLE_READ, PERF_GROUP_LEADER); + if (mLeaders[effectiveType] < 0) { + return false; + } + } + } + + if (!(flags & PERF_GROUP_LEADER) && effectiveType != PERF_TYPE_HARDWARE && (flags & PERF_GROUP_PER_CPU)) { + logg->logError("'uncore' counters are not permitted to be per-cpu"); + handleException(); + } + + return doAdd(currTime, buffer, key, type, config, sample, sampleType, flags) >= 0; +} + int PerfGroup::prepareCPU(const int cpu, Monitor *const monitor) { - logg->logMessage("%s(%s:%i): Onlining cpu %i", __FUNCTION__, __FILE__, __LINE__, cpu); + logg->logMessage("Onlining cpu %i", cpu); for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) { if (mKeys[i] < 0) { continue; } - if ((cpu != 0) && !mPerCpu[i]) { + if ((cpu != 0) && !(mFlags[i] & PERF_GROUP_PER_CPU)) { continue; } - const int offset = i * gSessionData->mCores; - if (mFds[cpu + offset] >= 0) { - logg->logMessage("%s(%s:%i): cpu already online or not correctly cleaned up", __FUNCTION__, __FILE__, __LINE__); + const int offset = i * gSessionData->mCores + cpu; + if (mFds[offset] >= 0) { + logg->logMessage("cpu already online or not correctly cleaned up"); return PG_FAILURE; } - logg->logMessage("%s(%s:%i): perf_event_open cpu: %i type: %lli config: %lli sample: %lli sample_type: 0x%llx pinned: %i mmap: %i comm: %i freq: %i task: %i sample_id_all: %i", __FUNCTION__, __FILE__, __LINE__, cpu, (long long)mAttrs[i].type, (long long)mAttrs[i].config, (long long)mAttrs[i].sample_period, (long long)mAttrs[i].sample_type, mAttrs[i].pinned, mAttrs[i].mmap, mAttrs[i].comm, mAttrs[i].freq, mAttrs[i].task, mAttrs[i].sample_id_all); - mFds[cpu + offset] = sys_perf_event_open(&mAttrs[i], -1, cpu, i == 0 ? -1 : mFds[cpu], i == 0 ? 0 : PERF_FLAG_FD_OUTPUT); - if (mFds[cpu + offset] < 0) { - logg->logMessage("%s(%s:%i): failed %s", __FUNCTION__, __FILE__, __LINE__, strerror(errno)); + logg->logMessage("perf_event_open cpu: %i type: %i config: %lli sample: %lli sample_type: 0x%llx pinned: %lli mmap: %lli comm: %lli freq: %lli task: %lli sample_id_all: %lli", cpu, mAttrs[i].type, mAttrs[i].config, mAttrs[i].sample_period, mAttrs[i].sample_type, mAttrs[i].pinned, mAttrs[i].mmap, mAttrs[i].comm, mAttrs[i].freq, mAttrs[i].task, mAttrs[i].sample_id_all); + mFds[offset] = sys_perf_event_open(&mAttrs[i], -1, cpu, mAttrs[i].pinned ? -1 : mFds[mLeaders[getEffectiveType(mAttrs[i].type, mFlags[i])] * gSessionData->mCores + cpu], mAttrs[i].pinned ? 0 : PERF_FLAG_FD_OUTPUT); + if (mFds[offset] < 0) { + logg->logMessage("failed %s", strerror(errno)); if (errno == ENODEV) { + // The core is offline return PG_CPU_OFFLINE; } +#ifndef USE_STRICTER_CHECK continue; +#else + if (errno == ENOENT) { + // This event doesn't apply to this CPU but should apply to a different one, ex bL + continue; + } + logg->logMessage("perf_event_open failed"); + return PG_FAILURE; +#endif } - if (!mPb->useFd(cpu, mFds[cpu + offset])) { - logg->logMessage("%s(%s:%i): PerfBuffer::useFd failed", __FUNCTION__, __FILE__, __LINE__); + if (!mPb->useFd(cpu, mFds[offset])) { + logg->logMessage("PerfBuffer::useFd failed"); return PG_FAILURE; } - if (!monitor->add(mFds[cpu + offset])) { - logg->logMessage("%s(%s:%i): Monitor::add failed", __FUNCTION__, __FILE__, __LINE__); - return PG_FAILURE; + if (!monitor->add(mFds[offset])) { + logg->logMessage("Monitor::add failed"); + return PG_FAILURE; } } return PG_SUCCESS; } -int PerfGroup::onlineCPU(const uint64_t currTime, const int cpu, const bool start, Buffer *const buffer) { - __u64 ids[ARRAY_LENGTH(mKeys)]; - int coreKeys[ARRAY_LENGTH(mKeys)]; - int idCount = 0; +static bool readAndSend(const uint64_t currTime, Buffer *const buffer, const int fd, const int keyCount, const int *const keys) { + char buf[1024]; + ssize_t bytes = read(fd, buf, sizeof(buf)); + if (bytes < 0) { + logg->logMessage("read failed"); + return false; + } + buffer->marshalKeysOld(currTime, keyCount, keys, bytes, buf); - for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) { - const int fd = mFds[cpu + i * gSessionData->mCores]; - if (fd < 0) { - continue; - } + return true; +} - coreKeys[idCount] = mKeys[i]; - if (!gSessionData->perf.getLegacySupport() && ioctl(fd, PERF_EVENT_IOC_ID, &ids[idCount]) != 0 && - // Workaround for running 32-bit gatord on 64-bit systems, kernel patch in the works - ioctl(fd, (PERF_EVENT_IOC_ID & ~IOCSIZE_MASK) | (8 << _IOC_SIZESHIFT), &ids[idCount]) != 0) { - logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__); - return 0; - } - ++idCount; - } +int PerfGroup::onlineCPU(const uint64_t currTime, const int cpu, const bool enable, Buffer *const buffer) { + bool addedEvents = false; if (!gSessionData->perf.getLegacySupport()) { - buffer->keys(currTime, idCount, ids, coreKeys); + int idCount = 0; + int coreKeys[ARRAY_LENGTH(mKeys)]; + __u64 ids[ARRAY_LENGTH(mKeys)]; + + for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) { + const int fd = mFds[cpu + i * gSessionData->mCores]; + if (fd < 0) { + continue; + } + + coreKeys[idCount] = mKeys[i]; + if (ioctl(fd, PERF_EVENT_IOC_ID, &ids[idCount]) != 0 && + // Workaround for running 32-bit gatord on 64-bit systems, kernel patch in the works + ioctl(fd, (PERF_EVENT_IOC_ID & ~IOCSIZE_MASK) | (8 << _IOC_SIZESHIFT), &ids[idCount]) != 0) { + logg->logMessage("ioctl failed"); + return 0; + } + ++idCount; + addedEvents = true; + } + + buffer->marshalKeys(currTime, idCount, ids, coreKeys); } else { - char buf[1024]; - ssize_t bytes = read(mFds[cpu], buf, sizeof(buf)); - if (bytes < 0) { - logg->logMessage("read failed"); - return 0; + int idCounts[ARRAY_LENGTH(mLeaders)] = { 0 }; + int coreKeys[ARRAY_LENGTH(mLeaders)][ARRAY_LENGTH(mKeys)]; + for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) { + const int fd = mFds[cpu + i * gSessionData->mCores]; + if (fd < 0) { + continue; + } + + const int effectiveType = getEffectiveType(mAttrs[i].type, mFlags[i]); + if (mAttrs[i].pinned && mLeaders[effectiveType] != i) { + if (!readAndSend(currTime, buffer, fd, 1, mKeys + i)) { + return 0; + } + } else { + coreKeys[effectiveType][idCounts[effectiveType]] = mKeys[i]; + ++idCounts[effectiveType]; + addedEvents = true; + } + } + + for (int i = 0; i < ARRAY_LENGTH(mLeaders); ++i) { + if (idCounts[i] > 0 && !readAndSend(currTime, buffer, mFds[mLeaders[i] * gSessionData->mCores + cpu], idCounts[i], coreKeys[i])) { + return 0; + } } - buffer->keysOld(currTime, idCount, coreKeys, bytes, buf); } - if (start) { + if (enable) { for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) { int offset = i * gSessionData->mCores + cpu; if (mFds[offset] >= 0 && ioctl(mFds[offset], PERF_EVENT_IOC_ENABLE, 0) < 0) { - logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("ioctl failed"); return 0; } } } - if (idCount == 0) { - logg->logMessage("%s(%s:%i): no events came online", __FUNCTION__, __FILE__, __LINE__); + if (!addedEvents) { + logg->logMessage("no events came online"); } - return idCount; + return 1; } bool PerfGroup::offlineCPU(const int cpu) { - logg->logMessage("%s(%s:%i): Offlining cpu %i", __FUNCTION__, __FILE__, __LINE__, cpu); + logg->logMessage("Offlining cpu %i", cpu); - for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) { + for (int i = ARRAY_LENGTH(mKeys) - 1; i >= 0; --i) { int offset = i * gSessionData->mCores + cpu; if (mFds[offset] >= 0 && ioctl(mFds[offset], PERF_EVENT_IOC_DISABLE, 0) < 0) { - logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("ioctl failed"); return false; } } @@ -204,7 +318,7 @@ bool PerfGroup::offlineCPU(const int cpu) { // Mark the buffer so that it will be released next time it's read mPb->discard(cpu); - for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) { + for (int i = ARRAY_LENGTH(mKeys) - 1; i >= 0; --i) { if (mKeys[i] < 0) { continue; } @@ -222,7 +336,7 @@ bool PerfGroup::offlineCPU(const int cpu) { bool PerfGroup::start() { for (int pos = 0; pos < ARRAY_LENGTH(mFds); ++pos) { if (mFds[pos] >= 0 && ioctl(mFds[pos], PERF_EVENT_IOC_ENABLE, 0) < 0) { - logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("ioctl failed"); goto fail; } } diff --git a/tools/gator/daemon/PerfGroup.h b/tools/gator/daemon/PerfGroup.h index f7b3d725bac7..f30d3a6a9c68 100644 --- a/tools/gator/daemon/PerfGroup.h +++ b/tools/gator/daemon/PerfGroup.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -27,6 +27,8 @@ enum PerfGroupFlags { PERF_GROUP_TASK = 1 << 3, PERF_GROUP_SAMPLE_ID_ALL = 1 << 4, PERF_GROUP_PER_CPU = 1 << 5, + PERF_GROUP_LEADER = 1 << 6, + PERF_GROUP_CPU = 1 << 7, }; enum { @@ -40,22 +42,29 @@ public: PerfGroup(PerfBuffer *const pb); ~PerfGroup(); + bool createCpuGroup(const uint64_t currTime, Buffer *const buffer); bool add(const uint64_t currTime, Buffer *const buffer, const int key, const __u32 type, const __u64 config, const __u64 sample, const __u64 sampleType, const int flags); // Safe to call concurrently int prepareCPU(const int cpu, Monitor *const monitor); // Not safe to call concurrently. Returns the number of events enabled - int onlineCPU(const uint64_t currTime, const int cpu, const bool start, Buffer *const buffer); + int onlineCPU(const uint64_t currTime, const int cpu, const bool enable, Buffer *const buffer); bool offlineCPU(int cpu); bool start(); void stop(); private: - // +1 for the group leader - struct perf_event_attr mAttrs[MAX_PERFORMANCE_COUNTERS + 1]; - bool mPerCpu[MAX_PERFORMANCE_COUNTERS + 1]; - int mKeys[MAX_PERFORMANCE_COUNTERS + 1]; - int mFds[NR_CPUS * (MAX_PERFORMANCE_COUNTERS + 1)]; + int getEffectiveType(const int type, const int flags); + int doAdd(const uint64_t currTime, Buffer *const buffer, const int key, const __u32 type, const __u64 config, const __u64 sample, const __u64 sampleType, const int flags); + + // 2* to be conservative for sched_switch, cpu_idle, hrtimer and non-CPU groups + struct perf_event_attr mAttrs[2*MAX_PERFORMANCE_COUNTERS]; PerfBuffer *const mPb; + int mFlags[2*MAX_PERFORMANCE_COUNTERS]; + int mKeys[2*MAX_PERFORMANCE_COUNTERS]; + int mFds[NR_CPUS * (2*MAX_PERFORMANCE_COUNTERS)]; + // Offset in mAttrs, mFlags and mKeys of the group leaders for each perf type + int mLeaders[16]; + int mSchedSwitchId; // Intentionally undefined PerfGroup(const PerfGroup &); diff --git a/tools/gator/daemon/PerfSource.cpp b/tools/gator/daemon/PerfSource.cpp index 193b7789a290..2c45de8e06e9 100644 --- a/tools/gator/daemon/PerfSource.cpp +++ b/tools/gator/daemon/PerfSource.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -31,16 +31,18 @@ extern Child *child; +static const int cpuIdleKey = getEventKey(); + static bool sendTracepointFormat(const uint64_t currTime, Buffer *const buffer, const char *const name, DynBuf *const printb, DynBuf *const b) { if (!printb->printf(EVENTS_PATH "/%s/format", name)) { - logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("DynBuf::printf failed"); return false; } if (!b->read(printb->getBuf())) { - logg->logMessage("%s(%s:%i): DynBuf::read failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("DynBuf::read failed"); return false; } - buffer->format(currTime, b->getLength(), b->getBuf()); + buffer->marshalFormat(currTime, b->getLength(), b->getBuf()); return true; } @@ -58,18 +60,18 @@ static void *syncFunc(void *arg) { sigset_t set; if (sigfillset(&set) != 0) { - logg->logError(__FILE__, __LINE__, "sigfillset failed"); + logg->logError("sigfillset failed"); handleException(); } if ((err = pthread_sigmask(SIG_SETMASK, &set, NULL)) != 0) { - logg->logError(__FILE__, __LINE__, "pthread_sigmask failed"); + logg->logError("pthread_sigmask failed"); handleException(); } } for (;;) { if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) != 0) { - logg->logError(__FILE__, __LINE__, "clock_gettime failed"); + logg->logError("clock_gettime failed"); handleException(); } const int64_t currTime = ts.tv_sec * NS_PER_S + ts.tv_nsec; @@ -95,7 +97,7 @@ static void *syncFunc(void *arg) static long getMaxCoreNum() { DIR *dir = opendir("/sys/devices/system/cpu"); if (dir == NULL) { - logg->logError(__FILE__, __LINE__, "Unable to determine the number of cores on the target, opendir failed"); + logg->logError("Unable to determine the number of cores on the target, opendir failed"); handleException(); } @@ -114,22 +116,22 @@ static long getMaxCoreNum() { closedir(dir); if (maxCoreNum < 1) { - logg->logError(__FILE__, __LINE__, "Unable to determine the number of cores on the target, no cpu# directories found"); + logg->logError("Unable to determine the number of cores on the target, no cpu# directories found"); handleException(); } if (maxCoreNum >= NR_CPUS) { - logg->logError(__FILE__, __LINE__, "Too many cores on the target, please increase NR_CPUS in Config.h"); + logg->logError("Too many cores on the target, please increase NR_CPUS in Config.h"); handleException(); } return maxCoreNum; } -PerfSource::PerfSource(sem_t *senderSem, sem_t *startProfile) : mSummary(0, FRAME_SUMMARY, 1024, senderSem), mBuffer(0, FRAME_PERF_ATTRS, 1024*1024, senderSem), mCountersBuf(), mCountersGroup(&mCountersBuf), mIdleGroup(&mCountersBuf), mMonitor(), mUEvent(), mSenderSem(senderSem), mStartProfile(startProfile), mInterruptFd(-1), mIsDone(false) { +PerfSource::PerfSource(sem_t *senderSem, sem_t *startProfile) : mSummary(0, FRAME_SUMMARY, 1024, senderSem), mBuffer(NULL), mCountersBuf(), mCountersGroup(&mCountersBuf), mMonitor(), mUEvent(), mSenderSem(senderSem), mStartProfile(startProfile), mInterruptFd(-1), mIsDone(false) { long l = sysconf(_SC_PAGE_SIZE); if (l < 0) { - logg->logError(__FILE__, __LINE__, "Unable to obtain the page size"); + logg->logError("Unable to obtain the page size"); handleException(); } gSessionData->mPageSize = static_cast(l); @@ -137,15 +139,18 @@ PerfSource::PerfSource(sem_t *senderSem, sem_t *startProfile) : mSummary(0, FRAM } PerfSource::~PerfSource() { + delete mBuffer; } bool PerfSource::prepare() { DynBuf printb; DynBuf b1; - long long schedSwitchId; long long cpuIdleId; - const uint64_t currTime = getTime(); + // MonotonicStarted has not yet been assigned! + const uint64_t currTime = 0;//getTime() - gSessionData->mMonotonicStarted; + + mBuffer = new Buffer(0, FRAME_PERF_ATTRS, gSessionData->mTotalBufferSize*1024*1024, mSenderSem); // Reread cpuinfo since cores may have changed since startup gSessionData->readCpuInfo(); @@ -155,72 +160,59 @@ bool PerfSource::prepare() { || !mUEvent.init() || !mMonitor.add(mUEvent.getFd()) - || (schedSwitchId = PerfDriver::getTracepointId(SCHED_SWITCH, &printb)) < 0 - || !sendTracepointFormat(currTime, &mBuffer, SCHED_SWITCH, &printb, &b1) + || !sendTracepointFormat(currTime, mBuffer, SCHED_SWITCH, &printb, &b1) || (cpuIdleId = PerfDriver::getTracepointId(CPU_IDLE, &printb)) < 0 - || !sendTracepointFormat(currTime, &mBuffer, CPU_IDLE, &printb, &b1) + || !sendTracepointFormat(currTime, mBuffer, CPU_IDLE, &printb, &b1) - // Only want RAW but not IP on sched_switch and don't want TID on SAMPLE_ID - || !mCountersGroup.add(currTime, &mBuffer, 100/**/, PERF_TYPE_TRACEPOINT, schedSwitchId, 1, PERF_SAMPLE_RAW, PERF_GROUP_MMAP | PERF_GROUP_COMM | PERF_GROUP_TASK | PERF_GROUP_SAMPLE_ID_ALL | PERF_GROUP_PER_CPU) - || !mIdleGroup.add(currTime, &mBuffer, 101/**/, PERF_TYPE_TRACEPOINT, cpuIdleId, 1, PERF_SAMPLE_RAW, PERF_GROUP_PER_CPU) + || !sendTracepointFormat(currTime, mBuffer, CPU_FREQUENCY, &printb, &b1) - // Only want TID and IP but not RAW on timer - || (gSessionData->mSampleRate > 0 && !gSessionData->mIsEBS && !mCountersGroup.add(currTime, &mBuffer, 102/**/, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK, 1000000000UL / gSessionData->mSampleRate, PERF_SAMPLE_TID | PERF_SAMPLE_IP, PERF_GROUP_PER_CPU)) + || !mCountersGroup.createCpuGroup(currTime, mBuffer) + || !mCountersGroup.add(currTime, mBuffer, cpuIdleKey, PERF_TYPE_TRACEPOINT, cpuIdleId, 1, PERF_SAMPLE_RAW, PERF_GROUP_LEADER | PERF_GROUP_PER_CPU) - || !gSessionData->perf.enable(currTime, &mCountersGroup, &mBuffer) + || !gSessionData->perf.enable(currTime, &mCountersGroup, mBuffer) || 0) { - logg->logMessage("%s(%s:%i): perf setup failed, are you running Linux 3.4 or later?", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("perf setup failed, are you running Linux 3.4 or later?"); return false; } for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) { const int result = mCountersGroup.prepareCPU(cpu, &mMonitor); if ((result != PG_SUCCESS) && (result != PG_CPU_OFFLINE)) { - logg->logError(__FILE__, __LINE__, "PerfGroup::prepareCPU on mCountersGroup failed"); - handleException(); - } - } - for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) { - const int result = mIdleGroup.prepareCPU(cpu, &mMonitor); - if ((result != PG_SUCCESS) && (result != PG_CPU_OFFLINE)) { - logg->logError(__FILE__, __LINE__, "PerfGroup::prepareCPU on mIdleGroup failed"); + logg->logError("PerfGroup::prepareCPU on mCountersGroup failed"); handleException(); } } int numEvents = 0; for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) { - numEvents += mCountersGroup.onlineCPU(currTime, cpu, false, &mBuffer); - } - for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) { - numEvents += mIdleGroup.onlineCPU(currTime, cpu, false, &mBuffer); + numEvents += mCountersGroup.onlineCPU(currTime, cpu, false, mBuffer); } if (numEvents <= 0) { - logg->logMessage("%s(%s:%i): PerfGroup::onlineCPU failed on all cores", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("PerfGroup::onlineCPU failed on all cores"); return false; } // Send the summary right before the start so that the monotonic delta is close to the start time if (!gSessionData->perf.summary(&mSummary)) { - logg->logError(__FILE__, __LINE__, "PerfDriver::summary failed", __FUNCTION__, __FILE__, __LINE__); - handleException(); + logg->logError("PerfDriver::summary failed"); + handleException(); } // Start the timer thread to used to sync perf and monotonic raw times pthread_t syncThread; if (pthread_create(&syncThread, NULL, syncFunc, NULL)) { - logg->logError(__FILE__, __LINE__, "pthread_create failed", __FUNCTION__, __FILE__, __LINE__); - handleException(); + logg->logError("pthread_create failed"); + handleException(); } struct sched_param param; param.sched_priority = sched_get_priority_max(SCHED_FIFO); if (pthread_setschedparam(syncThread, SCHED_FIFO | SCHED_RESET_ON_FORK, ¶m) != 0) { - logg->logError(__FILE__, __LINE__, "pthread_setschedparam failed"); - handleException(); + logg->logError("pthread_setschedparam failed"); + handleException(); } - mBuffer.commit(currTime); + mBuffer->commit(currTime); return true; } @@ -240,18 +232,17 @@ void *procFunc(void *arg) { // Gator runs at a high priority, reset the priority to the default if (setpriority(PRIO_PROCESS, syscall(__NR_gettid), 0) == -1) { - logg->logError(__FILE__, __LINE__, "setpriority failed"); + logg->logError("setpriority failed"); handleException(); } if (!readProcMaps(args->mCurrTime, args->mBuffer, &printb, &b)) { - logg->logError(__FILE__, __LINE__, "readProcMaps failed"); + logg->logError("readProcMaps failed"); handleException(); } - args->mBuffer->commit(args->mCurrTime); if (!readKallsyms(args->mCurrTime, args->mBuffer, &args->mIsDone)) { - logg->logError(__FILE__, __LINE__, "readKallsyms failed"); + logg->logError("readKallsyms failed"); handleException(); } args->mBuffer->commit(args->mCurrTime); @@ -266,67 +257,72 @@ void PerfSource::run() { pthread_t procThread; ProcThreadArgs procThreadArgs; + if (pipe_cloexec(pipefd) != 0) { + logg->logError("pipe failed"); + handleException(); + } + mInterruptFd = pipefd[1]; + + if (!mMonitor.add(pipefd[0])) { + logg->logError("Monitor::add failed"); + handleException(); + } + { DynBuf printb; DynBuf b1; DynBuf b2; - const uint64_t currTime = getTime(); + const uint64_t currTime = getTime() - gSessionData->mMonotonicStarted; // Start events before reading proc to avoid race conditions - if (!mCountersGroup.start() || !mIdleGroup.start()) { - logg->logError(__FILE__, __LINE__, "PerfGroup::start failed", __FUNCTION__, __FILE__, __LINE__); + if (!mCountersGroup.start()) { + logg->logError("PerfGroup::start failed"); handleException(); } - if (!readProcComms(currTime, &mBuffer, &printb, &b1, &b2)) { - logg->logError(__FILE__, __LINE__, "readProcComms failed"); + mBuffer->perfCounterHeader(currTime); + for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) { + gSessionData->perf.read(mBuffer, cpu); + } + mBuffer->perfCounterFooter(currTime); + + if (!readProcComms(currTime, mBuffer, &printb, &b1, &b2)) { + logg->logError("readProcComms failed"); handleException(); } - mBuffer.commit(currTime); + mBuffer->commit(currTime); // Postpone reading kallsyms as on android adb gets too backed up and data is lost - procThreadArgs.mBuffer = &mBuffer; + procThreadArgs.mBuffer = mBuffer; procThreadArgs.mCurrTime = currTime; procThreadArgs.mIsDone = false; if (pthread_create(&procThread, NULL, procFunc, &procThreadArgs)) { - logg->logError(__FILE__, __LINE__, "pthread_create failed", __FUNCTION__, __FILE__, __LINE__); + logg->logError("pthread_create failed"); handleException(); } } - if (pipe_cloexec(pipefd) != 0) { - logg->logError(__FILE__, __LINE__, "pipe failed"); - handleException(); - } - mInterruptFd = pipefd[1]; - - if (!mMonitor.add(pipefd[0])) { - logg->logError(__FILE__, __LINE__, "Monitor::add failed"); - handleException(); - } - - int timeout = -1; - if (gSessionData->mLiveRate > 0) { - timeout = gSessionData->mLiveRate/NS_PER_MS; - } - sem_post(mStartProfile); + const uint64_t NO_RATE = ~0ULL; + const uint64_t rate = gSessionData->mLiveRate > 0 && gSessionData->mSampleRate > 0 ? gSessionData->mLiveRate : NO_RATE; + uint64_t nextTime = 0; + int timeout = rate != NO_RATE ? 0 : -1; while (gSessionData->mSessionIsActive) { // +1 for uevents, +1 for pipe struct epoll_event events[NR_CPUS + 2]; int ready = mMonitor.wait(events, ARRAY_LENGTH(events), timeout); if (ready < 0) { - logg->logError(__FILE__, __LINE__, "Monitor::wait failed"); + logg->logError("Monitor::wait failed"); handleException(); } - const uint64_t currTime = getTime(); + const uint64_t currTime = getTime() - gSessionData->mMonotonicStarted; for (int i = 0; i < ready; ++i) { if (events[i].data.fd == mUEvent.getFd()) { if (!handleUEvent(currTime)) { - logg->logError(__FILE__, __LINE__, "PerfSource::handleUEvent failed"); + logg->logError("PerfSource::handleUEvent failed"); handleException(); } break; @@ -337,18 +333,24 @@ void PerfSource::run() { sem_post(mSenderSem); // In one shot mode, stop collection once all the buffers are filled - // Assume timeout == 0 in this case - if (gSessionData->mOneShot && gSessionData->mSessionIsActive) { - logg->logMessage("%s(%s:%i): One shot", __FUNCTION__, __FILE__, __LINE__); + if (gSessionData->mOneShot && gSessionData->mSessionIsActive && ((mSummary.bytesAvailable() <= 0) || (mBuffer->bytesAvailable() <= 0) || mCountersBuf.isFull())) { + logg->logMessage("One shot (perf)"); child->endSession(); } + + if (rate != NO_RATE) { + while (currTime > nextTime) { + nextTime += rate; + } + // + NS_PER_MS - 1 to ensure always rounding up + timeout = max(0, (int)((nextTime + NS_PER_MS - 1 - getTime() + gSessionData->mMonotonicStarted)/NS_PER_MS)); + } } procThreadArgs.mIsDone = true; pthread_join(procThread, NULL); - mIdleGroup.stop(); mCountersGroup.stop(); - mBuffer.setDone(); + mBuffer->setDone(); mIsDone = true; // send a notification that data is ready @@ -362,57 +364,53 @@ void PerfSource::run() { bool PerfSource::handleUEvent(const uint64_t currTime) { UEventResult result; if (!mUEvent.read(&result)) { - logg->logMessage("%s(%s:%i): UEvent::Read failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("UEvent::Read failed"); return false; } if (strcmp(result.mSubsystem, "cpu") == 0) { if (strncmp(result.mDevPath, CPU_DEVPATH, sizeof(CPU_DEVPATH) - 1) != 0) { - logg->logMessage("%s(%s:%i): Unexpected cpu DEVPATH format", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("Unexpected cpu DEVPATH format"); return false; } char *endptr; errno = 0; int cpu = strtol(result.mDevPath + sizeof(CPU_DEVPATH) - 1, &endptr, 10); if (errno != 0 || *endptr != '\0') { - logg->logMessage("%s(%s:%i): strtol failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("strtol failed"); return false; } if (cpu >= gSessionData->mCores) { - logg->logError(__FILE__, __LINE__, "Only %i cores are expected but core %i reports %s", gSessionData->mCores, cpu, result.mAction); + logg->logError("Only %i cores are expected but core %i reports %s", gSessionData->mCores, cpu, result.mAction); handleException(); } if (strcmp(result.mAction, "online") == 0) { - mBuffer.onlineCPU(currTime, currTime - gSessionData->mMonotonicStarted, cpu); + mBuffer->onlineCPU(currTime, cpu); // Only call onlineCPU if prepareCPU succeeded - bool result = false; + bool ret = false; int err = mCountersGroup.prepareCPU(cpu, &mMonitor); if (err == PG_CPU_OFFLINE) { - result = true; + ret = true; } else if (err == PG_SUCCESS) { - if (mCountersGroup.onlineCPU(currTime, cpu, true, &mBuffer)) { - err = mIdleGroup.prepareCPU(cpu, &mMonitor); - if (err == PG_CPU_OFFLINE) { - result = true; - } else if (err == PG_SUCCESS) { - if (mIdleGroup.onlineCPU(currTime, cpu, true, &mBuffer)) { - result = true; - } - } + if (mCountersGroup.onlineCPU(currTime, cpu, true, mBuffer) > 0) { + mBuffer->perfCounterHeader(currTime); + gSessionData->perf.read(mBuffer, cpu); + mBuffer->perfCounterFooter(currTime); + ret = true; } } - mBuffer.commit(currTime); + mBuffer->commit(currTime); gSessionData->readCpuInfo(); gSessionData->perf.coreName(currTime, &mSummary, cpu); mSummary.commit(currTime); - return result; + return ret; } else if (strcmp(result.mAction, "offline") == 0) { - const bool result = mCountersGroup.offlineCPU(cpu) && mIdleGroup.offlineCPU(cpu); - mBuffer.offlineCPU(currTime, currTime - gSessionData->mMonotonicStarted, cpu); - return result; + const bool ret = mCountersGroup.offlineCPU(cpu); + mBuffer->offlineCPU(currTime, cpu); + return ret; } } @@ -424,14 +422,14 @@ void PerfSource::interrupt() { int8_t c = 0; // Write to the pipe to wake the monitor which will cause mSessionIsActive to be reread if (::write(mInterruptFd, &c, sizeof(c)) != sizeof(c)) { - logg->logError(__FILE__, __LINE__, "write failed"); + logg->logError("write failed"); handleException(); } } } bool PerfSource::isDone () { - return mBuffer.isDone() && mIsDone && mCountersBuf.isEmpty(); + return mBuffer->isDone() && mIsDone && mCountersBuf.isEmpty(); } void PerfSource::write (Sender *sender) { @@ -439,11 +437,11 @@ void PerfSource::write (Sender *sender) { mSummary.write(sender); gSessionData->mSentSummary = true; } - if (!mBuffer.isDone()) { - mBuffer.write(sender); + if (!mBuffer->isDone()) { + mBuffer->write(sender); } if (!mCountersBuf.send(sender)) { - logg->logError(__FILE__, __LINE__, "PerfBuffer::send failed"); + logg->logError("PerfBuffer::send failed"); handleException(); } } diff --git a/tools/gator/daemon/PerfSource.h b/tools/gator/daemon/PerfSource.h index ce1eafe8e953..feec1c269922 100644 --- a/tools/gator/daemon/PerfSource.h +++ b/tools/gator/daemon/PerfSource.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -36,10 +36,9 @@ private: bool handleUEvent(const uint64_t currTime); Buffer mSummary; - Buffer mBuffer; + Buffer *mBuffer; PerfBuffer mCountersBuf; PerfGroup mCountersGroup; - PerfGroup mIdleGroup; Monitor mMonitor; UEvent mUEvent; sem_t *const mSenderSem; diff --git a/tools/gator/daemon/Proc.cpp b/tools/gator/daemon/Proc.cpp index e6b26b1199fa..4ba59b632836 100644 --- a/tools/gator/daemon/Proc.cpp +++ b/tools/gator/daemon/Proc.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -31,20 +31,20 @@ struct ProcStat { static bool readProcStat(ProcStat *const ps, const char *const pathname, DynBuf *const b) { if (!b->read(pathname)) { - logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the thread exited", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("DynBuf::read failed, likely because the thread exited"); // This is not a fatal error - the thread just doesn't exist any more return true; } char *comm = strchr(b->getBuf(), '('); if (comm == NULL) { - logg->logMessage("%s(%s:%i): parsing stat failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("parsing stat failed"); return false; } ++comm; char *const str = strrchr(comm, ')'); if (str == NULL) { - logg->logMessage("%s(%s:%i): parsing stat failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("parsing stat failed"); return false; } *str = '\0'; @@ -53,7 +53,7 @@ static bool readProcStat(ProcStat *const ps, const char *const pathname, DynBuf const int count = sscanf(str + 2, " %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %ld", &ps->numThreads); if (count != 1) { - logg->logMessage("%s(%s:%i): sscanf failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("sscanf failed"); return false; } @@ -65,7 +65,7 @@ static const char APP_PROCESS[] = "app_process"; static const char *readProcExe(DynBuf *const printb, const int pid, const int tid, DynBuf *const b) { if (tid == -1 ? !printb->printf("/proc/%i/exe", pid) : !printb->printf("/proc/%i/task/%i/exe", pid, tid)) { - logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("DynBuf::printf failed"); return NULL; } @@ -82,7 +82,7 @@ static const char *readProcExe(DynBuf *const printb, const int pid, const int ti // readlink /proc/[pid]/exe returns ENOENT for kernel threads image = "\0"; } else { - logg->logMessage("%s(%s:%i): DynBuf::readlink failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("DynBuf::readlink failed"); return NULL; } @@ -94,12 +94,12 @@ static const char *readProcExe(DynBuf *const printb, const int pid, const int ti if (tid == -1 ? !printb->printf("/proc/%i/cmdline", pid) : !printb->printf("/proc/%i/task/%i/cmdline", pid, tid)) { - logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("DynBuf::printf failed"); return NULL; } if (!b->read(printb->getBuf())) { - logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the thread exited", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("DynBuf::read failed, likely because the thread exited"); return NULL; } @@ -110,12 +110,12 @@ static bool readProcTask(const uint64_t currTime, Buffer *const buffer, const in bool result = false; if (!b1->printf("/proc/%i/task", pid)) { - logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("DynBuf::printf failed"); return result; } DIR *task = opendir(b1->getBuf()); if (task == NULL) { - logg->logMessage("%s(%s:%i): opendir failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("opendir failed"); // This is not a fatal error - the thread just doesn't exist any more return true; } @@ -130,22 +130,22 @@ static bool readProcTask(const uint64_t currTime, Buffer *const buffer, const in } if (!printb->printf("/proc/%i/task/%i/stat", pid, tid)) { - logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("DynBuf::printf failed"); goto fail; } ProcStat ps; if (!readProcStat(&ps, printb->getBuf(), b1)) { - logg->logMessage("%s(%s:%i): readProcStat failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("readProcStat failed"); goto fail; } const char *const image = readProcExe(printb, pid, tid, b2); if (image == NULL) { - logg->logMessage("%s(%s:%i): readImage failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("readImage failed"); goto fail; } - buffer->comm(currTime, pid, tid, image, ps.comm); + buffer->marshalComm(currTime, pid, tid, image, ps.comm); } result = true; @@ -161,7 +161,7 @@ bool readProcComms(const uint64_t currTime, Buffer *const buffer, DynBuf *const DIR *proc = opendir("/proc"); if (proc == NULL) { - logg->logMessage("%s(%s:%i): opendir failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("opendir failed"); return result; } @@ -175,26 +175,26 @@ bool readProcComms(const uint64_t currTime, Buffer *const buffer, DynBuf *const } if (!printb->printf("/proc/%i/stat", pid)) { - logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("DynBuf::printf failed"); goto fail; } ProcStat ps; if (!readProcStat(&ps, printb->getBuf(), b1)) { - logg->logMessage("%s(%s:%i): readProcStat failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("readProcStat failed"); goto fail; } if (ps.numThreads <= 1) { const char *const image = readProcExe(printb, pid, -1, b1); if (image == NULL) { - logg->logMessage("%s(%s:%i): readImage failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("readImage failed"); goto fail; } - buffer->comm(currTime, pid, pid, image, ps.comm); + buffer->marshalComm(currTime, pid, pid, image, ps.comm); } else { if (!readProcTask(currTime, buffer, pid, printb, b1, b2)) { - logg->logMessage("%s(%s:%i): readProcTask failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("readProcTask failed"); goto fail; } } @@ -213,7 +213,7 @@ bool readProcMaps(const uint64_t currTime, Buffer *const buffer, DynBuf *const p DIR *proc = opendir("/proc"); if (proc == NULL) { - logg->logMessage("%s(%s:%i): opendir failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("opendir failed"); return result; } @@ -227,16 +227,16 @@ bool readProcMaps(const uint64_t currTime, Buffer *const buffer, DynBuf *const p } if (!printb->printf("/proc/%i/maps", pid)) { - logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("DynBuf::printf failed"); goto fail; } if (!b->read(printb->getBuf())) { - logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the process exited", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("DynBuf::read failed, likely because the process exited"); // This is not a fatal error - the process just doesn't exist any more continue; } - buffer->maps(currTime, pid, pid, b->getBuf()); + buffer->marshalMaps(currTime, pid, pid, b->getBuf()); } result = true; @@ -251,7 +251,7 @@ bool readKallsyms(const uint64_t currTime, Buffer *const buffer, const bool *con int fd = ::open("/proc/kallsyms", O_RDONLY | O_CLOEXEC); if (fd < 0) { - logg->logMessage("%s(%s:%i): open failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("open failed"); return true; }; @@ -260,7 +260,7 @@ bool readKallsyms(const uint64_t currTime, Buffer *const buffer, const bool *con while (gSessionData->mSessionIsActive && !ACCESS_ONCE(*isDone)) { // Assert there is still space in the buffer if (sizeof(buf) - pos - 1 == 0) { - logg->logError(__FILE__, __LINE__, "no space left in buffer"); + logg->logError("no space left in buffer"); handleException(); } @@ -268,13 +268,13 @@ bool readKallsyms(const uint64_t currTime, Buffer *const buffer, const bool *con // -1 to reserve space for \0 const ssize_t bytes = ::read(fd, buf + pos, sizeof(buf) - pos - 1); if (bytes < 0) { - logg->logError(__FILE__, __LINE__, "read failed", __FUNCTION__, __FILE__, __LINE__); + logg->logError("read failed"); handleException(); } if (bytes == 0) { // Assert the buffer is empty if (pos != 0) { - logg->logError(__FILE__, __LINE__, "buffer not empty on eof"); + logg->logError("buffer not empty on eof"); handleException(); } break; @@ -288,13 +288,13 @@ bool readKallsyms(const uint64_t currTime, Buffer *const buffer, const bool *con if (buf[newline] == '\n') { const char was = buf[newline + 1]; buf[newline + 1] = '\0'; - buffer->kallsyms(currTime, buf); + buffer->marshalKallsyms(currTime, buf); // Sleep 3 ms to avoid sending out too much data too quickly usleep(3000); buf[0] = was; // Assert the memory regions do not overlap if (pos - newline >= newline + 1) { - logg->logError(__FILE__, __LINE__, "memcpy src and dst overlap"); + logg->logError("memcpy src and dst overlap"); handleException(); } if (pos - newline - 2 > 0) { diff --git a/tools/gator/daemon/Proc.h b/tools/gator/daemon/Proc.h index 2a1a7cbc1e99..fcc48c546d05 100644 --- a/tools/gator/daemon/Proc.h +++ b/tools/gator/daemon/Proc.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/Sender.cpp b/tools/gator/daemon/Sender.cpp index 8a54a6678974..d7ad757165a2 100644 --- a/tools/gator/daemon/Sender.cpp +++ b/tools/gator/daemon/Sender.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -30,7 +30,7 @@ Sender::Sender(OlySocket* socket) { // Streamline will send data prior to the magic sequence for legacy support, which should be ignored for v4+ while (strcmp("STREAMLINE", streamline) != 0) { if (mDataSocket->receiveString(streamline, sizeof(streamline)) == -1) { - logg->logError(__FILE__, __LINE__, "Socket disconnected"); + logg->logError("Socket disconnected"); handleException(); } } @@ -67,7 +67,7 @@ void Sender::createDataFile(char* apcDir) { sprintf(mDataFileName, "%s/0000000000", apcDir); mDataFile = fopen_cloexec(mDataFileName, "wb"); if (!mDataFile) { - logg->logError(__FILE__, __LINE__, "Failed to open binary file: %s", mDataFileName); + logg->logError("Failed to open binary file: %s", mDataFileName); handleException(); } } @@ -120,7 +120,7 @@ void Sender::writeData(const char* data, int length, int type) { logg->logMessage("Writing data with length %d", length); // Send data to the data file if (fwrite(data, 1, length, mDataFile) != (unsigned int)length) { - logg->logError(__FILE__, __LINE__, "Failed writing binary file %s", mDataFileName); + logg->logError("Failed writing binary file %s", mDataFileName); handleException(); } } diff --git a/tools/gator/daemon/Sender.h b/tools/gator/daemon/Sender.h index 5aa911713820..8f542026e90d 100644 --- a/tools/gator/daemon/Sender.h +++ b/tools/gator/daemon/Sender.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/SessionData.cpp b/tools/gator/daemon/SessionData.cpp index 0e65d7842647..2b661bdf294c 100644 --- a/tools/gator/daemon/SessionData.cpp +++ b/tools/gator/daemon/SessionData.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -13,7 +13,6 @@ #include #include -#include "CPUFreqDriver.h" #include "DiskIODriver.h" #include "FSDriver.h" #include "HwmonDriver.h" @@ -31,8 +30,7 @@ SessionData::SessionData() { usDrivers[1] = new FSDriver(); usDrivers[2] = new MemInfoDriver(); usDrivers[3] = new NetDriver(); - usDrivers[4] = new CPUFreqDriver(); - usDrivers[5] = new DiskIODriver(); + usDrivers[4] = new DiskIODriver(); initialize(); } @@ -50,7 +48,7 @@ void SessionData::initialize() { // Share mCpuIds across all instances of gatord mCpuIds = (int *)mmap(NULL, cpuIdSize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); if (mCpuIds == MAP_FAILED) { - logg->logError(__FILE__, __LINE__, "Unable to mmap shared memory for cpuids"); + logg->logError("Unable to mmap shared memory for cpuids"); handleException(); } memset(mCpuIds, -1, cpuIdSize); @@ -61,6 +59,7 @@ void SessionData::initialize() { mConfigurationXMLPath = NULL; mSessionXMLPath = NULL; mEventsXMLPath = NULL; + mEventsXMLAppend = NULL; mTargetPath = NULL; mAPCDir = NULL; mCaptureWorkingDir = NULL; @@ -75,6 +74,7 @@ void SessionData::initialize() { // sysconf(_SC_NPROCESSORS_CONF) is unreliable on 2.6 Android, get the value from the kernel module mCores = 1; mPageSize = 0; + mAnnotateStart = -1; } void SessionData::parseSessionXML(char* xmlString) { @@ -91,7 +91,7 @@ void SessionData::parseSessionXML(char* xmlString) { } else if (strcmp(session.parameters.sample_rate, "none") == 0) { mSampleRate = 0; } else { - logg->logError(__FILE__, __LINE__, "Invalid sample rate (%s) in session xml.", session.parameters.sample_rate); + logg->logError("Invalid sample rate (%s) in session xml.", session.parameters.sample_rate); handleException(); } mBacktraceDepth = session.parameters.call_stack_unwinding == true ? 128 : 0; @@ -108,7 +108,7 @@ void SessionData::parseSessionXML(char* xmlString) { } else if (strcmp(session.parameters.buffer_mode, "large") == 0) { mTotalBufferSize = 16; } else { - logg->logError(__FILE__, __LINE__, "Invalid value for buffer mode in session xml."); + logg->logError("Invalid value for buffer mode in session xml."); handleException(); } @@ -120,7 +120,7 @@ void SessionData::parseSessionXML(char* xmlString) { } if (!mAllowCommands && (mCaptureCommand != NULL)) { - logg->logError(__FILE__, __LINE__, "Running a command during a capture is not currently allowed. Please restart gatord with the -a flag."); + logg->logError("Running a command during a capture is not currently allowed. Please restart gatord with the -a flag."); handleException(); } } @@ -139,6 +139,20 @@ void SessionData::readModel() { fclose(fh); } +static void setImplementer(int &cpuId, const int implementer) { + if (cpuId == -1) { + cpuId = 0; + } + cpuId |= implementer << 12; +} + +static void setPart(int &cpuId, const int part) { + if (cpuId == -1) { + cpuId = 0; + } + cpuId |= part; +} + void SessionData::readCpuInfo() { char temp[256]; // arbitrarily large amount mMaxCpuId = -1; @@ -150,7 +164,7 @@ void SessionData::readCpuInfo() { return; } - bool foundCoreName = false; + bool foundCoreName = (strcmp(mCoreName, CORE_NAME_UNKNOWN) != 0); int processor = -1; while (fgets(temp, sizeof(temp), f)) { const size_t len = strlen(temp); @@ -166,10 +180,11 @@ void SessionData::readCpuInfo() { temp[len - 1] = '\0'; } - const bool foundHardware = strstr(temp, "Hardware") != 0; + const bool foundHardware = !foundCoreName && strstr(temp, "Hardware") != 0; + const bool foundCPUImplementer = strstr(temp, "CPU implementer") != 0; const bool foundCPUPart = strstr(temp, "CPU part") != 0; const bool foundProcessor = strstr(temp, "processor") != 0; - if (foundHardware || foundCPUPart || foundProcessor) { + if (foundHardware || foundCPUImplementer || foundCPUPart || foundProcessor) { char* position = strchr(temp, ':'); if (position == NULL || (unsigned int)(position - temp) + 2 >= strlen(temp)) { logg->logMessage("Unknown format of /proc/cpuinfo\n" @@ -178,22 +193,31 @@ void SessionData::readCpuInfo() { } position += 2; - if (foundHardware && (strcmp(mCoreName, CORE_NAME_UNKNOWN) == 0)) { + if (foundHardware) { strncpy(mCoreName, position, sizeof(mCoreName)); mCoreName[sizeof(mCoreName) - 1] = 0; // strncpy does not guarantee a null-terminated string foundCoreName = true; } + if (foundCPUImplementer) { + const int implementer = strtol(position, NULL, 0); + if (processor >= NR_CPUS) { + logg->logMessage("Too many processors, please increase NR_CPUS"); + } else if (processor >= 0) { + setImplementer(mCpuIds[processor], implementer); + } else { + setImplementer(mMaxCpuId, implementer); + } + } + if (foundCPUPart) { const int cpuId = strtol(position, NULL, 0); - // If this does not have the full topology in /proc/cpuinfo, mCpuIds[0] may not have the 1 CPU part emitted - this guarantees it's in mMaxCpuId - if (cpuId > mMaxCpuId) { - mMaxCpuId = cpuId; - } if (processor >= NR_CPUS) { logg->logMessage("Too many processors, please increase NR_CPUS"); } else if (processor >= 0) { - mCpuIds[processor] = cpuId; + setPart(mCpuIds[processor], cpuId); + } else { + setPart(mMaxCpuId, cpuId); } } @@ -203,6 +227,13 @@ void SessionData::readCpuInfo() { } } + // If this does not have the full topology in /proc/cpuinfo, mCpuIds[0] may not have the 1 CPU part emitted - this guarantees it's in mMaxCpuId + for (int i = 0; i < NR_CPUS; ++i) { + if (mCpuIds[i] > mMaxCpuId) { + mMaxCpuId = mCpuIds[i]; + } + } + if (!foundCoreName) { logg->logMessage("Could not determine core name from /proc/cpuinfo\n" "The core name in the captured xml file will be 'unknown'."); @@ -213,7 +244,7 @@ void SessionData::readCpuInfo() { uint64_t getTime() { struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) != 0) { - logg->logError(__FILE__, __LINE__, "Failed to get uptime"); + logg->logError("Failed to get uptime"); handleException(); } return (NS_PER_S*ts.tv_sec + ts.tv_nsec); diff --git a/tools/gator/daemon/SessionData.h b/tools/gator/daemon/SessionData.h index ed282af4a869..d0c8900317a5 100644 --- a/tools/gator/daemon/SessionData.h +++ b/tools/gator/daemon/SessionData.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -11,7 +11,6 @@ #include -#include "AnnotateListener.h" #include "Config.h" #include "Counter.h" #include "FtraceDriver.h" @@ -19,7 +18,7 @@ #include "MaliVideoDriver.h" #include "PerfDriver.h" -#define PROTOCOL_VERSION 20 +#define PROTOCOL_VERSION 21 // Differentiates development versions (timestamp) from release versions #define PROTOCOL_DEV 1000 @@ -43,18 +42,18 @@ public: void readModel(); void readCpuInfo(); - PolledDriver *usDrivers[6]; + PolledDriver *usDrivers[5]; KMod kmod; PerfDriver perf; MaliVideoDriver maliVideo; FtraceDriver ftraceDriver; - AnnotateListener annotateListener; char mCoreName[MAX_STRING_LEN]; struct ImageLinkList *mImages; char *mConfigurationXMLPath; char *mSessionXMLPath; char *mEventsXMLPath; + char *mEventsXMLAppend; char *mTargetPath; char *mAPCDir; char *mCaptureWorkingDir; @@ -81,6 +80,7 @@ public: int mPageSize; int *mCpuIds; int mMaxCpuId; + int mAnnotateStart; // PMU Counters int mCounterOverflow; @@ -93,6 +93,7 @@ private: }; extern SessionData* gSessionData; +extern const char *const gSrcMd5; uint64_t getTime(); int getEventKey(); diff --git a/tools/gator/daemon/SessionXML.cpp b/tools/gator/daemon/SessionXML.cpp index dea4c8f299ec..c638dea45912 100644 --- a/tools/gator/daemon/SessionXML.cpp +++ b/tools/gator/daemon/SessionXML.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -36,7 +36,7 @@ SessionXML::SessionXML(const char *str) { parameters.call_stack_unwinding = false; parameters.live_rate = 0; mSessionXML = str; - logg->logMessage(mSessionXML); + logg->logMessage("%s", mSessionXML); } SessionXML::~SessionXML() { @@ -55,7 +55,7 @@ void SessionXML::parse() { return; } - logg->logError(__FILE__, __LINE__, "No session tag found in the session.xml file"); + logg->logError("No session tag found in the session.xml file"); handleException(); } @@ -63,7 +63,7 @@ void SessionXML::sessionTag(mxml_node_t *tree, mxml_node_t *node) { int version = 0; if (mxmlElementGetAttr(node, ATTR_VERSION)) version = strtol(mxmlElementGetAttr(node, ATTR_VERSION), NULL, 10); if (version != 1) { - logg->logError(__FILE__, __LINE__, "Invalid session.xml version: %d", version); + logg->logError("Invalid session.xml version: %d", version); handleException(); } diff --git a/tools/gator/daemon/SessionXML.h b/tools/gator/daemon/SessionXML.h index 53965749c74b..2ba276a38021 100644 --- a/tools/gator/daemon/SessionXML.h +++ b/tools/gator/daemon/SessionXML.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/Setup.cpp b/tools/gator/daemon/Setup.cpp index d4ce0328c633..7dd83ceafcce 100644 --- a/tools/gator/daemon/Setup.cpp +++ b/tools/gator/daemon/Setup.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2014. All rights reserved. + * Copyright (C) ARM Limited 2014-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -15,7 +15,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -24,12 +26,17 @@ #include "Config.h" #include "DynBuf.h" #include "Logging.h" +#include "SessionData.h" + +#define GATOR_MSG "gator: " +#define GATOR_ERROR "gator: error: " +#define GATOR_CONFIRM "gator: confirm: " bool getLinuxVersion(int version[3]) { // Check the kernel version struct utsname utsname; if (uname(&utsname) != 0) { - logg->logMessage("%s(%s:%i): uname failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("uname failed"); return false; } @@ -57,7 +64,7 @@ static int pgrep_gator(DynBuf *const printb) { DIR *proc = opendir("/proc"); if (proc == NULL) { - logg->logError(__FILE__, __LINE__, "gator: error: opendir failed"); + logg->logError(GATOR_ERROR "opendir failed"); handleException(); } @@ -73,7 +80,7 @@ static int pgrep_gator(DynBuf *const printb) { } if (!printb->printf("/proc/%i/stat", pid)) { - logg->logError(__FILE__, __LINE__, "gator: error: DynBuf::printf failed"); + logg->logError(GATOR_ERROR "DynBuf::printf failed"); handleException(); } @@ -84,21 +91,35 @@ static int pgrep_gator(DynBuf *const printb) { char *comm = strchr(b.getBuf(), '('); if (comm == NULL) { - logg->logError(__FILE__, __LINE__, "gator: error: parsing stat begin failed"); + logg->logError(GATOR_ERROR "parsing stat comm begin failed"); handleException(); } ++comm; char *const str = strrchr(comm, ')'); if (str == NULL) { - logg->logError(__FILE__, __LINE__, "gator: error: parsing stat end failed"); + logg->logError(GATOR_ERROR "parsing stat comm end failed"); handleException(); } *str = '\0'; - if (strncmp(comm, "gator", 5) == 0) { - // Assume there is only one gator process - return pid; + if (strncmp(comm, "gator", 5) != 0) { + continue; + } + + char state; + const int count = sscanf(str + 2, " %c ", &state); + if (count != 1) { + logg->logError(GATOR_ERROR "parsing stat state failed"); + handleException(); + } + + if (state == 'Z') { + // This gator is a zombie, ignore + continue; } + + // Assume there is only one gator process + return pid; } closedir(proc); @@ -106,73 +127,106 @@ static int pgrep_gator(DynBuf *const printb) { return -1; } -int update(const char *const gatorPath) { - printf("gator: starting\n"); +static bool confirm(const char *const message) { + char buf[1<<10]; + + printf(GATOR_CONFIRM "%s\n", message); + while (fgets(buf, sizeof(buf), stdin) != NULL) { + if (strcmp(buf, "y\n") == 0) { + return true; + } + if (strcmp(buf, "n\n") == 0) { + return false; + } + // Ignore unrecognized input + } + + return false; +} + +void update(const char *const gatorPath) { + printf(GATOR_MSG "starting\n"); int version[3]; if (!getLinuxVersion(version)) { - logg->logError(__FILE__, __LINE__, "gator: error: getLinuxVersion failed"); + logg->logError(GATOR_ERROR "getLinuxVersion failed"); handleException(); } if (KERNEL_VERSION(version[0], version[1], version[2]) < KERNEL_VERSION(2, 6, 32)) { - logg->logError(__FILE__, __LINE__, "gator: error: Streamline can't automatically setup gator as this kernel version is not supported. Please upgrade the kernel on your device."); + logg->logError(GATOR_ERROR "Streamline can't automatically setup gator as this kernel version is not supported. Please upgrade the kernel on your device."); handleException(); } if (KERNEL_VERSION(version[0], version[1], version[2]) < KERNEL_VERSION(3, 4, 0)) { - logg->logError(__FILE__, __LINE__, "gator: error: Streamline can't automatically setup gator as gator.ko is required for this version of Linux. Please build gator.ko and gatord and install them on your device."); - handleException(); - } - - if (access("/sys/module/gator", F_OK) == 0) { - logg->logError(__FILE__, __LINE__, "gator: error: Streamline has detected that the gator kernel module is loaded on your device. Please build an updated version of gator.ko and gatord and install them on your device."); + logg->logError(GATOR_ERROR "Streamline can't automatically setup gator as gator.ko is required for this version of Linux. Please build gator.ko and gatord and install them on your device."); handleException(); } if (geteuid() != 0) { - printf("gator: trying sudo\n"); + printf(GATOR_MSG "trying sudo\n"); execlp("sudo", "sudo", gatorPath, "-u", NULL); // Streamline will provide the password if needed - printf("gator: trying su\n"); + printf(GATOR_MSG "trying su\n"); char buf[1<<10]; - snprintf(buf, sizeof(buf), "%s -u", gatorPath); - execlp("su", "su", "-", "-c", buf, NULL); + /* + * Different versions of su handle additional -c command line options differently and expect the + * arguments in different ways. Try both ways wrapped in a shell. + * + * Then invoke another shell after su as it avoids odd failures on some Android systems + */ + snprintf(buf, sizeof(buf), "su -c \"sh -c '%s -u'\" || su -c sh -c '%s -u'", gatorPath, gatorPath); + execlp("sh", "sh", "-c", buf, NULL); // Streamline will provide the password if needed - logg->logError(__FILE__, __LINE__, "gator: error: Streamline was unable to sudo to root on your device. Please double check passwords, ensure sudo or su work with this user or try a different username."); + logg->logError(GATOR_ERROR "Streamline was unable to sudo to root on your device. Please double check passwords, ensure sudo or su work with this user or try a different username."); handleException(); } - printf("gator: now root\n"); + printf(GATOR_MSG "now root\n"); + + if (access("/sys/module/gator", F_OK) == 0) { + if (!confirm("Streamline has detected that the gator kernel module is loaded on your device. Click yes to switch to user space gator, click no to abort the install.")) { + printf("gator: cancel\n"); + exit(-1); + } + } // setenforce 0 not needed for userspace gator // Kill existing gator - DynBuf gatorStatPath; - int gator_main = pgrep_gator(&gatorStatPath); + DynBuf printb; + int gator_main = pgrep_gator(&printb); if (gator_main > 0) { if (kill(gator_main, SIGTERM) != 0) { - logg->logError(__FILE__, __LINE__, "gator: error: kill SIGTERM failed"); + logg->logError(GATOR_ERROR "kill SIGTERM failed"); + handleException(); + } + if (!printb.printf("/proc/%i/exe", gator_main)) { + logg->logError(GATOR_ERROR "DynBuf::printf failed"); handleException(); } for (int i = 0; ; ++i) { - if (access(gatorStatPath.getBuf(), F_OK) != 0) { + // /proc//exe exists but will not be accessible for zombies + if (access(printb.getBuf(), F_OK) != 0) { break; } if (i == 5) { if (kill(gator_main, SIGKILL) != 0) { - logg->logError(__FILE__, __LINE__, "gator: error: kill SIGKILL failed"); + logg->logError(GATOR_ERROR "kill SIGKILL failed"); handleException(); } } else if (i >= 10) { - logg->logError(__FILE__, __LINE__, "gator: error: unable to kill running gator"); + logg->logError(GATOR_ERROR "unable to kill running gator"); handleException(); } sleep(1); } } - printf("gator: no gatord running\n"); + printf(GATOR_MSG "no gatord running\n"); + + umount("/dev/gator"); + syscall(__NR_delete_module, "gator", O_NONBLOCK); rename("gatord", "gatord.old"); rename("gator.ko", "gator.ko.old"); @@ -183,50 +237,88 @@ int update(const char *const gatorPath) { if (dot != NULL) { *dot = '\0'; if (rename(gatorPath, newGatorPath) != 0) { - logg->logError(__FILE__, __LINE__, "gator: error: rename failed"); + logg->logError(GATOR_ERROR "rename failed"); handleException(); } } - // Fork and start gatord (redirect stdout and stderr) + char buf[128]; + int pipefd[2]; + if (pipe_cloexec(pipefd) != 0) { + logg->logError(GATOR_ERROR "pipe failed"); + handleException(); + } + + // Fork and start gatord (redirect stdin, stdout and stderr so shell can close) int child = fork(); if (child < 0) { - logg->logError(__FILE__, __LINE__, "gator: error: fork failed"); + logg->logError(GATOR_ERROR "fork failed"); handleException(); } else if (child == 0) { - int inFd = open("/dev/null", O_RDONLY | O_CLOEXEC); + int inFd; + int outFd; + int errFd; + int result = -1; + + buf[0] = '\0'; + close(pipefd[0]); + + inFd = open("/dev/null", O_RDONLY | O_CLOEXEC); if (inFd < 0) { - logg->logError(__FILE__, __LINE__, "gator: error: open of /dev/null failed"); - handleException(); + snprintf(buf, sizeof(buf), GATOR_ERROR "open of /dev/null failed"); + goto fail_exit; } - int outFd = open("gatord.out", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0600); + outFd = open("gatord.out", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644); if (outFd < 0) { - logg->logError(__FILE__, __LINE__, "gator: error: open of gatord.out failed"); - handleException(); + snprintf(buf, sizeof(buf), GATOR_ERROR "open of gatord.out failed"); + goto fail_exit; } - int errFd = open("gatord.err", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0600); + errFd = open("gatord.err", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644); if (errFd < 0) { - logg->logError(__FILE__, __LINE__, "gator: error: open of gatord.err failed"); - handleException(); + snprintf(buf, sizeof(buf), GATOR_ERROR "open of gatord.err failed"); + goto fail_exit; } if (dup2(inFd, STDIN_FILENO) < 0) { - logg->logError(__FILE__, __LINE__, "gator: error: dup2 for stdin failed"); - handleException(); + snprintf(buf, sizeof(buf), GATOR_ERROR "dup2 for stdin failed"); + goto fail_exit; } + fflush(stdout); if (dup2(outFd, STDOUT_FILENO) < 0) { - logg->logError(__FILE__, __LINE__, "gator: error: dup2 for stdout failed"); - handleException(); + snprintf(buf, sizeof(buf), GATOR_ERROR "dup2 for stdout failed"); + goto fail_exit; } + fflush(stderr); if (dup2(errFd, STDERR_FILENO) < 0) { - logg->logError(__FILE__, __LINE__, "gator: error: dup2 for stderr failed"); - handleException(); + snprintf(buf, sizeof(buf), GATOR_ERROR "dup2 for stderr failed"); + goto fail_exit; } - execlp(newGatorPath, newGatorPath, "-a", NULL); - logg->logError(__FILE__, __LINE__, "gator: error: execlp failed"); - handleException(); + + snprintf(buf, sizeof(buf), GATOR_MSG "done"); + result = 0; + + fail_exit: + if (buf[0] != '\0') { + const ssize_t bytes = write(pipefd[1], buf, sizeof(buf)); + // Can't do anything if this fails + (void)bytes; + } + close(pipefd[1]); + + if (result == 0) { + // Continue to execute gator normally + return; + } + exit(-1); } - printf("gator: done\n"); + close(pipefd[1]); + const ssize_t bytes = read(pipefd[0], buf, sizeof(buf)); + if (bytes > 0) { + logg->logError("%s", buf); + handleException(); + } + close(pipefd[0]); - return 0; + // Exit so parent shell can move on + exit(0); } diff --git a/tools/gator/daemon/Setup.h b/tools/gator/daemon/Setup.h index 280d61139784..427e71788c36 100644 --- a/tools/gator/daemon/Setup.h +++ b/tools/gator/daemon/Setup.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2014. All rights reserved. + * Copyright (C) ARM Limited 2014-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -13,6 +13,6 @@ #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) bool getLinuxVersion(int version[3]); -int update(const char *const gatorPath); +void update(const char *const gatorPath); #endif // SETUP_H diff --git a/tools/gator/daemon/Source.cpp b/tools/gator/daemon/Source.cpp index 60cf704e599b..64d6206895b0 100644 --- a/tools/gator/daemon/Source.cpp +++ b/tools/gator/daemon/Source.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -18,7 +18,7 @@ Source::~Source() { void Source::start() { if (pthread_create(&mThreadID, NULL, runStatic, this)) { - logg->logError(__FILE__, __LINE__, "Failed to create source thread"); + logg->logError("Failed to create source thread"); handleException(); } } diff --git a/tools/gator/daemon/Source.h b/tools/gator/daemon/Source.h index 56ac3d6e94f3..b9369be5198b 100644 --- a/tools/gator/daemon/Source.h +++ b/tools/gator/daemon/Source.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/StreamlineSetup.cpp b/tools/gator/daemon/StreamlineSetup.cpp index 2b61eaeb290d..e37f2712cd04 100644 --- a/tools/gator/daemon/StreamlineSetup.cpp +++ b/tools/gator/daemon/StreamlineSetup.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2011-2014. All rights reserved. + * Copyright (C) ARM Limited 2011-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -68,7 +68,7 @@ StreamlineSetup::StreamlineSetup(OlySocket* s) { sendData(NULL, 0, RESPONSE_ACK); break; default: - logg->logError(__FILE__, __LINE__, "Target error: Unknown command type, %d", type); + logg->logError("Target error: Unknown command type, %d", type); handleException(); } @@ -76,7 +76,7 @@ StreamlineSetup::StreamlineSetup(OlySocket* s) { } if (gSessionData->mCounterOverflow > 0) { - logg->logError(__FILE__, __LINE__, "Only %i performance counters are permitted, %i are selected", MAX_PERFORMANCE_COUNTERS, gSessionData->mCounterOverflow); + logg->logError("Only %i performance counters are permitted, %i are selected", MAX_PERFORMANCE_COUNTERS, gSessionData->mCounterOverflow); handleException(); } } @@ -96,7 +96,7 @@ char* StreamlineSetup::readCommand(int* command) { gSessionData->mWaitingOnCommand = false; if (response < 0) { - logg->logError(__FILE__, __LINE__, "Target error: Unexpected socket disconnect"); + logg->logError("Target error: Unexpected socket disconnect"); handleException(); } @@ -105,21 +105,21 @@ char* StreamlineSetup::readCommand(int* command) { // add artificial limit if ((length < 0) || length > 1024 * 1024) { - logg->logError(__FILE__, __LINE__, "Target error: Invalid length received, %d", length); + logg->logError("Target error: Invalid length received, %d", length); handleException(); } // allocate memory to contain the xml file, size of zero returns a zero size object data = (char*)calloc(length + 1, 1); if (data == NULL) { - logg->logError(__FILE__, __LINE__, "Unable to allocate memory for xml"); + logg->logError("Unable to allocate memory for xml"); handleException(); } // receive data response = mSocket->receiveNBytes(data, length); if (response < 0) { - logg->logError(__FILE__, __LINE__, "Target error: Unexpected socket disconnect"); + logg->logError("Target error: Unexpected socket disconnect"); handleException(); } @@ -222,7 +222,7 @@ void StreamlineSetup::sendDefaults() { // Artificial size restriction if (size > 1024*1024) { - logg->logError(__FILE__, __LINE__, "Corrupt default configuration file"); + logg->logError("Corrupt default configuration file"); handleException(); } @@ -241,7 +241,7 @@ void StreamlineSetup::sendCounters() { } if (count == 0) { - logg->logError(__FILE__, __LINE__, "No counters found, this could be because /dev/gator/events can not be read or because perf is not working correctly"); + logg->logError("No counters found, this could be because /dev/gator/events can not be read or because perf is not working correctly"); handleException(); } @@ -258,7 +258,7 @@ void StreamlineSetup::writeConfiguration(char* xml) { ConfigurationXML::getPath(path); if (util->writeToDisk(path, xml) < 0) { - logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify write permissions to this path.", path); + logg->logError("Error writing %s\nPlease verify write permissions to this path.", path); handleException(); } @@ -266,7 +266,7 @@ void StreamlineSetup::writeConfiguration(char* xml) { { ConfigurationXML configuration; } if (gSessionData->mCounterOverflow > 0) { - logg->logError(__FILE__, __LINE__, "Only %i performance counters are permitted, %i are selected", MAX_PERFORMANCE_COUNTERS, gSessionData->mCounterOverflow); + logg->logError("Only %i performance counters are permitted, %i are selected", MAX_PERFORMANCE_COUNTERS, gSessionData->mCounterOverflow); handleException(); } } diff --git a/tools/gator/daemon/StreamlineSetup.h b/tools/gator/daemon/StreamlineSetup.h index 623e14f2b64a..d8b162606436 100644 --- a/tools/gator/daemon/StreamlineSetup.h +++ b/tools/gator/daemon/StreamlineSetup.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/UEvent.cpp b/tools/gator/daemon/UEvent.cpp index f94a995393e8..6a69f5ab137e 100644 --- a/tools/gator/daemon/UEvent.cpp +++ b/tools/gator/daemon/UEvent.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -34,7 +34,7 @@ UEvent::~UEvent() { bool UEvent::init() { mFd = socket_cloexec(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT); if (mFd < 0) { - logg->logMessage("%s(%s:%i): socket failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("socket failed"); return false; } @@ -44,7 +44,7 @@ bool UEvent::init() { sockaddr.nl_groups = 1; // bitmask: (1 << 0) == kernel events, (1 << 1) == udev events sockaddr.nl_pid = 0; if (bind(mFd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) != 0) { - logg->logMessage("%s(%s:%i): bind failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("bind failed"); return false; } @@ -54,7 +54,7 @@ bool UEvent::init() { bool UEvent::read(UEventResult *const result) { ssize_t bytes = recv(mFd, result->mBuf, sizeof(result->mBuf), 0); if (bytes <= 0) { - logg->logMessage("%s(%s:%i): recv failed", __FUNCTION__, __FILE__, __LINE__); + logg->logMessage("recv failed"); return false; } @@ -64,6 +64,7 @@ bool UEvent::read(UEventResult *const result) { for (int pos = 0; pos < bytes; pos += strlen(result->mBuf + pos) + 1) { char *const str = result->mBuf + pos; + logg->logMessage("uevent + %i: %s", pos, str); if (strncmp(str, ACTION, sizeof(ACTION) - 1) == 0) { result->mAction = str + sizeof(ACTION) - 1; } else if (strncmp(str, DEVPATH, sizeof(DEVPATH) - 1) == 0) { diff --git a/tools/gator/daemon/UEvent.h b/tools/gator/daemon/UEvent.h index 2f7ef2c93f5d..4c00f6cff112 100644 --- a/tools/gator/daemon/UEvent.h +++ b/tools/gator/daemon/UEvent.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/UserSpaceSource.cpp b/tools/gator/daemon/UserSpaceSource.cpp index 4a9b22f4b555..f58f828e6e2e 100644 --- a/tools/gator/daemon/UserSpaceSource.cpp +++ b/tools/gator/daemon/UserSpaceSource.cpp @@ -1,13 +1,16 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#define __STDC_FORMAT_MACROS + #include "UserSpaceSource.h" +#include #include #include @@ -35,45 +38,45 @@ void UserSpaceSource::run() { gSessionData->usDrivers[i]->start(); } - int64_t monotonic_started = 0; - while (monotonic_started <= 0) { + int64_t monotonicStarted = 0; + while (monotonicStarted <= 0 && gSessionData->mSessionIsActive) { usleep(10); if (gSessionData->perf.isSetup()) { - monotonic_started = gSessionData->mMonotonicStarted; + monotonicStarted = gSessionData->mMonotonicStarted; } else { - if (DriverSource::readInt64Driver("/dev/gator/started", &monotonic_started) == -1) { - logg->logError(__FILE__, __LINE__, "Error reading gator driver start time"); + if (DriverSource::readInt64Driver("/dev/gator/started", &monotonicStarted) == -1) { + logg->logError("Error reading gator driver start time"); handleException(); } - gSessionData->mMonotonicStarted = monotonic_started; + gSessionData->mMonotonicStarted = monotonicStarted; } } - uint64_t next_time = 0; + uint64_t nextTime = 0; while (gSessionData->mSessionIsActive) { - const uint64_t curr_time = getTime() - monotonic_started; + const uint64_t currTime = getTime() - monotonicStarted; // Sample ten times a second ignoring gSessionData->mSampleRate - next_time += NS_PER_S/10;//gSessionData->mSampleRate; - if (next_time < curr_time) { - logg->logMessage("Too slow, curr_time: %lli next_time: %lli", curr_time, next_time); - next_time = curr_time; + nextTime += NS_PER_S/10;//gSessionData->mSampleRate; + if (nextTime < currTime) { + logg->logMessage("Too slow, currTime: %" PRIi64 " nextTime: %" PRIi64, currTime, nextTime); + nextTime = currTime; } - if (mBuffer.eventHeader(curr_time)) { + if (mBuffer.eventHeader(currTime)) { for (int i = 0; i < ARRAY_LENGTH(gSessionData->usDrivers); ++i) { gSessionData->usDrivers[i]->read(&mBuffer); } // Only check after writing all counters so that time and corresponding counters appear in the same frame - mBuffer.check(curr_time); + mBuffer.check(currTime); } - if (mBuffer.bytesAvailable() <= 0) { + if (gSessionData->mOneShot && gSessionData->mSessionIsActive && (mBuffer.bytesAvailable() <= 0)) { logg->logMessage("One shot (counters)"); child->endSession(); } - usleep((next_time - curr_time)/NS_PER_US); + usleep((nextTime - currTime)/NS_PER_US); } mBuffer.setDone(); diff --git a/tools/gator/daemon/UserSpaceSource.h b/tools/gator/daemon/UserSpaceSource.h index 9b3666016dc5..0038dcb4c3d5 100644 --- a/tools/gator/daemon/UserSpaceSource.h +++ b/tools/gator/daemon/UserSpaceSource.h @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/c++.cpp b/tools/gator/daemon/c++.cpp index 6041e5e96469..caf6f1efdcde 100644 --- a/tools/gator/daemon/c++.cpp +++ b/tools/gator/daemon/c++.cpp @@ -1,7 +1,7 @@ /** * Minimal set of C++ functions so that libstdc++ is not required * - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/common.mk b/tools/gator/daemon/common.mk index 769a92e51a35..0d5a0a835d2c 100644 --- a/tools/gator/daemon/common.mk +++ b/tools/gator/daemon/common.mk @@ -6,7 +6,7 @@ # -std=c++0x is the planned new c++ standard # -std=c++98 is the 1998 c++ standard CPPFLAGS += -O3 -Wall -fno-exceptions -pthread -MMD -DETCDIR=\"/etc\" -Ilibsensors -CXXFLAGS += -fno-rtti -Wextra # -Weffc++ +CXXFLAGS += -fno-rtti -Wextra -Wshadow # -Weffc++ ifeq ($(WERROR),1) CPPFLAGS += -Werror endif @@ -41,7 +41,10 @@ libsensors/conf-parse.c: ; %.o: %.cpp $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $< -$(TARGET): $(CXX_SRC:%.cpp=%.o) $(C_SRC:%.c=%.o) +SrcMd5.cpp: $(wildcard *.cpp *.h mxml/*.c mxml/*.h libsensors/*.c libsensors/*.h) + echo 'extern const char *const gSrcMd5 = "'`ls $^ | grep -Ev '^(.*_xml\.h|$@)$$' | LC_ALL=C sort | xargs cat | md5sum | cut -b 1-32`'";' > $@ + +$(TARGET): $(CXX_SRC:%.cpp=%.o) $(C_SRC:%.c=%.o) SrcMd5.o $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ # Intentionally ignore CC as a native binary is required @@ -49,4 +52,4 @@ escape: escape.c gcc $^ -o $@ clean: - rm -f *.d *.o mxml/*.d mxml/*.o libsensors/*.d libsensors/*.o $(TARGET) escape events.xml events_xml.h defaults_xml.h + rm -f *.d *.o mxml/*.d mxml/*.o libsensors/*.d libsensors/*.o $(TARGET) escape events.xml events_xml.h defaults_xml.h SrcMd5.cpp diff --git a/tools/gator/daemon/defaults.xml b/tools/gator/daemon/defaults.xml index 086eca1e804e..31b127cdcfc6 100644 --- a/tools/gator/daemon/defaults.xml +++ b/tools/gator/daemon/defaults.xml @@ -44,6 +44,11 @@ + + + + + @@ -64,21 +69,5 @@ - - - - - - - - - - - - - - - - diff --git a/tools/gator/daemon/escape.c b/tools/gator/daemon/escape.c index 2b0863aaf425..99f434848cb3 100644 --- a/tools/gator/daemon/escape.c +++ b/tools/gator/daemon/escape.c @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/tools/gator/daemon/events-ARM11.xml b/tools/gator/daemon/events-ARM11.xml index 57e323546314..e481267b21ae 100644 --- a/tools/gator/daemon/events-ARM11.xml +++ b/tools/gator/daemon/events-ARM11.xml @@ -16,7 +16,7 @@ - + diff --git a/tools/gator/daemon/events-CCI-400.xml b/tools/gator/daemon/events-CCI-400.xml index 20002efd1543..40d91e582c19 100644 --- a/tools/gator/daemon/events-CCI-400.xml +++ b/tools/gator/daemon/events-CCI-400.xml @@ -1,5 +1,5 @@ - + - + \ No newline at end of file diff --git a/tools/gator/daemon/events-Mali-T62x_hw.xml b/tools/gator/daemon/events-Mali-T62x_hw.xml index 6ecc53c2ada1..4bc93068f75b 100644 --- a/tools/gator/daemon/events-Mali-T62x_hw.xml +++ b/tools/gator/daemon/events-Mali-T62x_hw.xml @@ -7,12 +7,13 @@ - - - - - - + + + + + + + @@ -78,32 +79,38 @@ - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - + + + - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tools/gator/daemon/events-Mali-T72x_hw.xml b/tools/gator/daemon/events-Mali-T72x_hw.xml index 5587534770c8..fd9cb0f16c6e 100644 --- a/tools/gator/daemon/events-Mali-T72x_hw.xml +++ b/tools/gator/daemon/events-Mali-T72x_hw.xml @@ -7,12 +7,13 @@ - - - - - - + + + + + + + @@ -67,29 +68,34 @@ - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + + diff --git a/tools/gator/daemon/events-Mali-T76x_hw.xml b/tools/gator/daemon/events-Mali-T76x_hw.xml index be74c5a42624..94d059fc09dd 100644 --- a/tools/gator/daemon/events-Mali-T76x_hw.xml +++ b/tools/gator/daemon/events-Mali-T76x_hw.xml @@ -7,12 +7,13 @@ - - - - - - + + + + + + + @@ -78,31 +79,39 @@ - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tools/gator/daemon/events-Mali-T82x_hw.xml b/tools/gator/daemon/events-Mali-T82x_hw.xml new file mode 100644 index 000000000000..5caa464a3078 --- /dev/null +++ b/tools/gator/daemon/events-Mali-T82x_hw.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/gator/daemon/events-Mali-T83x_hw.xml b/tools/gator/daemon/events-Mali-T83x_hw.xml new file mode 100644 index 000000000000..39f7acf31798 --- /dev/null +++ b/tools/gator/daemon/events-Mali-T83x_hw.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/gator/daemon/events-Mali-T86x_hw.xml b/tools/gator/daemon/events-Mali-T86x_hw.xml new file mode 100644 index 000000000000..6653543d5caa --- /dev/null +++ b/tools/gator/daemon/events-Mali-T86x_hw.xml @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/gator/daemon/events-Mali-T88x_hw.xml b/tools/gator/daemon/events-Mali-T88x_hw.xml new file mode 100644 index 000000000000..19385d19c9de --- /dev/null +++ b/tools/gator/daemon/events-Mali-T88x_hw.xml @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/gator/daemon/events-Other.xml b/tools/gator/daemon/events-Other.xml new file mode 100644 index 000000000000..8aec282b7e11 --- /dev/null +++ b/tools/gator/daemon/events-Other.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/gator/daemon/events-ftrace.xml b/tools/gator/daemon/events-ftrace.xml index 33ab7aab2196..ae5529f2678d 100644 --- a/tools/gator/daemon/events-ftrace.xml +++ b/tools/gator/daemon/events-ftrace.xml @@ -1,7 +1,22 @@ - - + + + + + + + + + + + + diff --git a/tools/gator/daemon/main.cpp b/tools/gator/daemon/main.cpp index fbce1e15d0d0..c68a892e74fc 100644 --- a/tools/gator/daemon/main.cpp +++ b/tools/gator/daemon/main.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2010-2014. All rights reserved. + * Copyright (C) ARM Limited 2010-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -19,6 +19,7 @@ #include #include +#include "AnnotateListener.h" #include "CCNDriver.h" #include "Child.h" #include "EventsXML.h" @@ -133,7 +134,7 @@ public: memset(&mDstAns, 0, sizeof(mDstAns)); memcpy(mDstAns.rviHeader, "STR_ANS ", sizeof(mDstAns.rviHeader)); if (gethostname(mDstAns.dhcpName, sizeof(mDstAns.dhcpName) - 1) != 0) { - logg->logError(__FILE__, __LINE__, "gethostname failed"); + logg->logError("gethostname failed"); handleException(); } // Subvert the defaultGateway field for the port number @@ -156,7 +157,7 @@ public: addrlen = sizeof(sockaddr); read = recvfrom(mReq, &buf, sizeof(buf), 0, (struct sockaddr *)&sockaddr, &addrlen); if (read < 0) { - logg->logError(__FILE__, __LINE__, "recvfrom failed"); + logg->logError("recvfrom failed"); handleException(); } else if ((read == 12) && (memcmp(buf, DST_REQ, sizeof(DST_REQ)) == 0)) { // Don't care if sendto fails - gatord shouldn't exit because of it and Streamline will retry @@ -180,23 +181,29 @@ private: family = AF_INET; s = socket_cloexec(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (s == -1) { - logg->logError(__FILE__, __LINE__, "socket failed"); + logg->logError("socket failed"); handleException(); } } on = 1; if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) != 0) { - logg->logError(__FILE__, __LINE__, "setsockopt failed"); + logg->logError("setsockopt REUSEADDR failed"); handleException(); } + // Listen on both IPv4 and IPv6 + on = 0; + if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&on, sizeof(on)) != 0) { + logg->logMessage("setsockopt IPV6_V6ONLY failed"); + } + memset((void*)&sockaddr, 0, sizeof(sockaddr)); sockaddr.sin6_family = family; sockaddr.sin6_port = htons(port); sockaddr.sin6_addr = in6addr_any; if (bind(s, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) < 0) { - logg->logError(__FILE__, __LINE__, "socket failed"); + logg->logError("socket failed"); handleException(); } @@ -252,7 +259,7 @@ static bool setupFilesystem(char* module) { // if still mounted if (access("/dev/gator/buffer", F_OK) == 0) { - logg->logError(__FILE__, __LINE__, "Unable to remove the running gator.ko. Manually remove the module or use the running module by not specifying one on the commandline"); + logg->logError("Unable to remove the running gator.ko. Manually remove the module or use the running module by not specifying one on the commandline"); handleException(); } } @@ -284,7 +291,7 @@ static bool setupFilesystem(char* module) { return false; } else { // gator location specified on the command line but it was not found - logg->logError(__FILE__, __LINE__, "gator module not found at %s", location); + logg->logError("gator module not found at %s", location); handleException(); } } @@ -296,13 +303,13 @@ static bool setupFilesystem(char* module) { snprintf(command, sizeof(command), "insmod %s >/dev/null 2>&1", location); if (system(command) != 0) { logg->logMessage("Unable to load gator.ko driver with command: %s", command); - logg->logError(__FILE__, __LINE__, "Unable to load (insmod) gator.ko driver:\n >>> gator.ko must be built against the current kernel version & configuration\n >>> See dmesg for more details"); + logg->logError("Unable to load (insmod) gator.ko driver:\n >>> gator.ko must be built against the current kernel version & configuration\n >>> See dmesg for more details"); handleException(); } } if (mountGatorFS() == -1) { - logg->logError(__FILE__, __LINE__, "Unable to mount the gator filesystem needed for profiling."); + logg->logError("Unable to mount the gator filesystem needed for profiling."); handleException(); } } @@ -326,7 +333,7 @@ static int shutdownFilesystem() { return 0; // success } -static const char OPTSTRING[] = "hvudap:s:c:e:m:o:"; +static const char OPTSTRING[] = "hvVudap:s:c:e:E:m:o:"; static bool hasDebugFlag(int argc, char** argv) { int c; @@ -368,11 +375,18 @@ static struct cmdline_t parseCommandLine(int argc, char** argv) { case 'e': gSessionData->mEventsXMLPath = optarg; break; + case 'E': + gSessionData->mEventsXMLAppend = optarg; + break; case 'm': cmdline.module = optarg; break; case 'p': cmdline.port = strtol(optarg, NULL, 10); + if ((cmdline.port == 8082) || (cmdline.port == 8083)) { + logg->logError("Gator can't use port %i, as it already uses ports 8082 and 8083 for annotations. Please select a different port.", cmdline.port); + handleException(); + } break; case 's': gSessionData->mSessionXMLPath = optarg; @@ -388,10 +402,11 @@ static struct cmdline_t parseCommandLine(int argc, char** argv) { break; case 'h': case '?': - logg->logError(__FILE__, __LINE__, + logg->logError( "%s. All parameters are optional:\n" - "-c config_xml path and filename of the configuration.xml to use\n" - "-e events_xml path and filename of the events.xml to use\n" + "-c config_xml path and filename of the configuration XML to use\n" + "-e events_xml path and filename of the events XML to use\n" + "-E events_xml path and filename of events XML to append\n" "-h this help page\n" "-m module path and filename of gator.ko\n" "-p port_number port upon which the server listens; default is 8080\n" @@ -399,12 +414,16 @@ static struct cmdline_t parseCommandLine(int argc, char** argv) { "-o apc_dir path and name of the output for a local capture\n" "-v version information\n" "-d enable debug messages\n" - "-a allow the user user to provide a command to run at the start of a capture" + "-a allow the user to issue a command from Streamline" , version_string); handleException(); break; case 'v': - logg->logError(__FILE__, __LINE__, version_string); + logg->logError("%s", version_string); + handleException(); + break; + case 'V': + logg->logError("%s\nSRC_MD5: %s", version_string, gSrcMd5); handleException(); break; } @@ -412,35 +431,38 @@ static struct cmdline_t parseCommandLine(int argc, char** argv) { // Error checking if (cmdline.port != DEFAULT_PORT && gSessionData->mSessionXMLPath != NULL) { - logg->logError(__FILE__, __LINE__, "Only a port or a session xml can be specified, not both"); + logg->logError("Only a port or a session xml can be specified, not both"); handleException(); } if (gSessionData->mTargetPath != NULL && gSessionData->mSessionXMLPath == NULL) { - logg->logError(__FILE__, __LINE__, "Missing -s command line option required for a local capture."); + logg->logError("Missing -s command line option required for a local capture."); handleException(); } if (optind < argc) { - logg->logError(__FILE__, __LINE__, "Unknown argument: %s. Use '-h' for help.", argv[optind]); + logg->logError("Unknown argument: %s. Use '-h' for help.", argv[optind]); handleException(); } return cmdline; } +static AnnotateListener annotateListener; + static void handleClient() { OlySocket client(sock->acceptConnection()); int pid = fork(); if (pid < 0) { // Error - logg->logError(__FILE__, __LINE__, "Fork process failed. Please power cycle the target device if this error persists."); + logg->logError("Fork process failed. Please power cycle the target device if this error persists."); } else if (pid == 0) { // Child sock->closeServerSocket(); udpListener.close(); monitor.close(); + annotateListener.close(); child = new Child(&client, numSessions + 1); child->run(); delete child; @@ -500,21 +522,23 @@ int main(int argc, char** argv) { struct cmdline_t cmdline = parseCommandLine(argc, argv); if (cmdline.update) { - return update(argv[0]); + update(argv[0]); + cmdline.update = false; + gSessionData->mAllowCommands = true; } // Verify root permissions uid_t euid = geteuid(); if (euid) { - logg->logError(__FILE__, __LINE__, "gatord must be launched with root privileges"); + logg->logError("gatord must be launched with root privileges"); handleException(); } // Call before setting up the SIGCHLD handler, as system() spawns child processes if (!setupFilesystem(cmdline.module)) { - logg->logMessage("Unable to setup gatorfs, trying perf"); + logg->logMessage("Unable to set up gatorfs, trying perf"); if (!gSessionData->perf.setup()) { - logg->logError(__FILE__, __LINE__, + logg->logError( "Unable to locate gator.ko driver:\n" " >>> gator.ko should be co-located with gatord in the same directory\n" " >>> OR insmod gator.ko prior to launching gatord\n" @@ -547,15 +571,23 @@ int main(int argc, char** argv) { child->run(); delete child; } else { - gSessionData->annotateListener.setup(); + annotateListener.setup(); + int pipefd[2]; + if (pipe_cloexec(pipefd) != 0) { + logg->logError("Unable to set up annotate pipe"); + handleException(); + } + gSessionData->mAnnotateStart = pipefd[1]; sock = new OlyServerSocket(cmdline.port); udpListener.setup(cmdline.port); if (!monitor.init() || !monitor.add(sock->getFd()) || !monitor.add(udpListener.getReq()) || - !monitor.add(gSessionData->annotateListener.getFd()) || + !monitor.add(annotateListener.getSockFd()) || + !monitor.add(annotateListener.getUdsFd()) || + !monitor.add(pipefd[0]) || false) { - logg->logError(__FILE__, __LINE__, "Monitor setup failed"); + logg->logError("Monitor setup failed"); handleException(); } // Forever loop, can be exited via a signal or exception @@ -564,7 +596,7 @@ int main(int argc, char** argv) { logg->logMessage("Waiting on connection..."); int ready = monitor.wait(events, ARRAY_LENGTH(events), -1); if (ready < 0) { - logg->logError(__FILE__, __LINE__, "Monitor::wait failed"); + logg->logError("Monitor::wait failed"); handleException(); } for (int i = 0; i < ready; ++i) { @@ -572,8 +604,16 @@ int main(int argc, char** argv) { handleClient(); } else if (events[i].data.fd == udpListener.getReq()) { udpListener.handle(); - } else if (events[i].data.fd == gSessionData->annotateListener.getFd()) { - gSessionData->annotateListener.handle(); + } else if (events[i].data.fd == annotateListener.getSockFd()) { + annotateListener.handleSock(); + } else if (events[i].data.fd == annotateListener.getUdsFd()) { + annotateListener.handleUds(); + } else if (events[i].data.fd == pipefd[0]) { + uint64_t val; + if (read(pipefd[0], &val, sizeof(val)) != sizeof(val)) { + logg->logMessage("Reading annotate pipe failed"); + } + annotateListener.signal(); } } } -- cgit v1.2.3 From 0c2fc7bf0a5466f059675633b6b179a118757a13 Mon Sep 17 00:00:00 2001 From: Jon Medhurst Date: Thu, 10 May 2012 17:35:03 +0100 Subject: gator: Add config for building the module in-tree Signed-off-by: Jon Medhurst --- drivers/Kconfig | 2 ++ drivers/Makefile | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/Kconfig b/drivers/Kconfig index 9953a42809ec..d27feb5460f3 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -166,4 +166,6 @@ source "drivers/ipack/Kconfig" source "drivers/reset/Kconfig" +source "drivers/gator/Kconfig" + endmenu diff --git a/drivers/Makefile b/drivers/Makefile index 130abc1dfd65..092a62e79688 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -152,3 +152,5 @@ obj-$(CONFIG_IIO) += iio/ obj-$(CONFIG_VME_BUS) += vme/ obj-$(CONFIG_IPACK_BUS) += ipack/ obj-$(CONFIG_NTB) += ntb/ + +obj-$(CONFIG_GATOR) += gator/ -- cgit v1.2.3 From 66de4b5dc66d8a3f0990ad99ab868db4ad267240 Mon Sep 17 00:00:00 2001 From: Jon Medhurst Date: Mon, 11 May 2015 14:34:54 +0100 Subject: gator: Enable multiple source copies to exist in Android build environments An Android build environment may contain multiple copies of the gator source code, e.g. if it's been copied into a kernel tree as well as having a standalone copy, or if there are two kernel trees with copies. As Android builds tend to include all Android.mk it finds, this can lead to build errors because there is more that one makefile trying to build the daemon. To allow this situation to be catered for we update Android.mk so that if the variable GATOR_DAEMON_PATH is defined, and the makefile doesn't live under that path, then the makefile contents are ignored. An Android build environment can then set GATOR_DAEMON_PATH to specify the copy it wants to use. Signed-off-by: Jon Medhurst --- tools/gator/daemon/Android.mk | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/gator/daemon/Android.mk b/tools/gator/daemon/Android.mk index 68f4a8397379..c5c8bdc1ff29 100644 --- a/tools/gator/daemon/Android.mk +++ b/tools/gator/daemon/Android.mk @@ -1,4 +1,8 @@ LOCAL_PATH := $(call my-dir) + +# Don't use this file if GATOR_DAEMON_PATH is set and we're not under that path +ifneq ($(and $(GATOR_DAEMON_PATH),$(filter $(patsubst %/,%,$(GATOR_DAEMON_PATH))/%,$(LOCAL_PATH)/)),) + include $(CLEAR_VARS) XML_H := $(shell cd $(LOCAL_PATH) && make events_xml.h defaults_xml.h SrcMd5.cpp) @@ -74,3 +78,5 @@ LOCAL_MODULE := gatord LOCAL_MODULE_TAGS := optional include $(BUILD_EXECUTABLE) + +endif -- cgit v1.2.3