Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

auto import from //depot/cupcake/@135843

  • Loading branch information...
commit 10e23eebca4175a8dfe3a788b2bebacb1fcfce54 1 parent dfb3f05
The Android Open Source Project authored
Showing with 15,275 additions and 0 deletions.
  1. +3 −0  Android.mk
  2. 0  MODULE_LICENSE_GPL
  3. +340 −0 NOTICE
  4. +101 −0 config.h
  5. +33 −0 daemon/Android.mk
  6. +373 −0 daemon/init.c
  7. +228 −0 daemon/opd_anon.c
  8. +54 −0 daemon/opd_anon.h
  9. +209 −0 daemon/opd_cookie.c
  10. +39 −0 daemon/opd_cookie.h
  11. +165 −0 daemon/opd_events.c
  12. +47 −0 daemon/opd_events.h
  13. +45 −0 daemon/opd_interface.h
  14. +229 −0 daemon/opd_kernel.c
  15. +43 −0 daemon/opd_kernel.h
  16. +205 −0 daemon/opd_mangling.c
  17. +33 −0 daemon/opd_mangling.h
  18. +496 −0 daemon/opd_perfmon.c
  19. +106 −0 daemon/opd_perfmon.h
  20. +96 −0 daemon/opd_pipe.c
  21. +45 −0 daemon/opd_pipe.h
  22. +35 −0 daemon/opd_printf.h
  23. +619 −0 daemon/opd_sfile.c
  24. +113 −0 daemon/opd_sfile.h
  25. +176 −0 daemon/opd_spu.c
  26. +85 −0 daemon/opd_stats.c
  27. +31 −0 daemon/opd_stats.h
  28. +349 −0 daemon/opd_trans.c
  29. +85 −0 daemon/opd_trans.h
  30. +522 −0 daemon/oprofiled.c
  31. +69 −0 daemon/oprofiled.h
  32. +14 −0 libabi/Android.mk
  33. +75 −0 libabi/abi.cpp
  34. +42 −0 libabi/abi.h
  35. +94 −0 libabi/op_abi.c
  36. +43 −0 libabi/op_abi.h
  37. +225 −0 libabi/opimport.cpp
  38. +17 −0 libdb/Android.mk
  39. +132 −0 libdb/db_debug.c
  40. +102 −0 libdb/db_insert.c
  41. +311 −0 libdb/db_manage.c
  42. +88 −0 libdb/db_stat.c
  43. +18 −0 libdb/db_travel.c
  44. +223 −0 libdb/odb.h
  45. +19 −0 libop/Android.mk
  46. +213 −0 libop/op_alloc_counter.c
  47. +43 −0 libop/op_alloc_counter.h
  48. +77 −0 libop/op_config.c
  49. +58 −0 libop/op_config.h
  50. +79 −0 libop/op_config_24.h
  51. +158 −0 libop/op_cpu_type.c
  52. +139 −0 libop/op_cpu_type.h
  53. +862 −0 libop/op_events.c
  54. +125 −0 libop/op_events.h
  55. +32 −0 libop/op_get_interface.c
  56. +30 −0 libop/op_hw_config.h
  57. +87 −0 libop/op_interface.h
  58. +104 −0 libop/op_mangle.c
  59. +66 −0 libop/op_mangle.h
  60. +120 −0 libop/op_parse_event.c
  61. +42 −0 libop/op_parse_event.h
  62. +42 −0 libop/op_sample_file.h
  63. +15 −0 libpopt/Android.mk
  64. +329 −0 libpopt/config.h
  65. +52 −0 libpopt/findme.c
  66. +20 −0 libpopt/findme.h
  67. +1,262 −0 libpopt/popt.c
  68. +564 −0 libpopt/popt.h
  69. +182 −0 libpopt/poptconfig.c
  70. +819 −0 libpopt/popthelp.c
  71. +116 −0 libpopt/poptint.h
  72. +227 −0 libpopt/poptparse.c
  73. +81 −0 libpopt/system.h
  74. +21 −0 libutil/Android.mk
  75. +22 −0 libutil/fscanf.c
  76. +64 −0 libutil/op_cpufreq.c
  77. +30 −0 libutil/op_cpufreq.h
  78. +42 −0 libutil/op_deviceio.c
  79. +57 −0 libutil/op_deviceio.h
  80. +185 −0 libutil/op_file.c
  81. +109 −0 libutil/op_file.h
  82. +228 −0 libutil/op_fileio.c
  83. +140 −0 libutil/op_fileio.h
  84. +24 −0 libutil/op_get_time.c
  85. +33 −0 libutil/op_get_time.h
  86. +46 −0 libutil/op_growable_buffer.c
  87. +45 −0 libutil/op_growable_buffer.h
  88. +38 −0 libutil/op_libiberty.c
  89. +81 −0 libutil/op_libiberty.h
  90. +177 −0 libutil/op_list.h
  91. +69 −0 libutil/op_lockfile.c
  92. +34 −0 libutil/op_lockfile.h
  93. +43 −0 libutil/op_popt.c
  94. +42 −0 libutil/op_popt.h
  95. +62 −0 libutil/op_string.c
  96. +81 −0 libutil/op_string.h
  97. +37 −0 libutil/op_types.h
  98. +24 −0 libutil/op_version.c
  99. +26 −0 libutil/op_version.h
  100. +18 −0 opcontrol/Android.mk
  101. +542 −0 opcontrol/opcontrol.cpp
  102. +70 −0 opimport_pull
  103. +564 −0 popt.h
View
3  Android.mk
@@ -0,0 +1,3 @@
+ifeq ($(TARGET_ARCH),arm)
+include $(call all-subdir-makefiles)
+endif
View
0  MODULE_LICENSE_GPL
No changes.
View
340 NOTICE
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library 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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
+
+ <signature of Ty Coon>, 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 Library General
+Public License instead of this License.
View
101 config.h
@@ -0,0 +1,101 @@
+/* config.h. Generated by configure. */
+/* config.h.in. Generated from configure.in by autoheader. */
+
+/* whether popt prototype takes a const char ** */
+#define CONST_POPT 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `bfd' library (-lbfd). */
+#define HAVE_LIBBFD 1
+
+/* Define to 1 if you have the `iberty' library (-liberty). */
+#define HAVE_LIBIBERTY 1
+
+/* Define to 1 if you have the <libiberty.h> header file. */
+/* #undef HAVE_LIBIBERTY_H */
+
+/* Define to 1 if you have the `popt' library (-lpopt). */
+#define HAVE_LIBPOPT 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `perfmonctl' function. */
+/* #undef HAVE_PERFMONCTL */
+
+/* Define to 1 if you have the `sched_setaffinity' function. */
+/* #undef HAVE_SCHED_SETAFFINITY */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `xcalloc' function. */
+#undef HAVE_XCALLOC
+
+/* Define to 1 if you have the `xmemdup' function. */
+#undef HAVE_XMEMDUP
+
+/* whether malloc attribute is understood */
+#define MALLOC_ATTRIBUTE_OK 1
+
+/* whether to build ABI tools */
+#define OPROF_ABI 1
+
+/* package binary directory */
+#define OP_BINDIR "/usr/local/bin/"
+
+/* package data directory */
+#define OP_DATADIR "/usr/local/share/oprofile/"
+
+/* Name of package */
+#define PACKAGE "oprofile"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME ""
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING ""
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION ""
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Synthesize special symbols when needed */
+/* #undef SYNTHESIZE_SYMBOLS */
+
+/* whether bfd.h defines bool values */
+/* #undef TRUE_FALSE_ALREADY_DEFINED */
+
+/* Version number of package */
+#define VERSION "0.9.1"
+
+/* Define to 1 if the X Window System is missing or not being used. */
+/* #undef X_DISPLAY_MISSING */
View
33 daemon/Android.mk
@@ -0,0 +1,33 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ init.c \
+ opd_anon.c \
+ opd_cookie.c \
+ opd_events.c \
+ opd_kernel.c \
+ opd_mangling.c \
+ opd_perfmon.c \
+ opd_pipe.c \
+ opd_sfile.c \
+ opd_spu.c \
+ opd_stats.c \
+ opd_trans.c \
+ oprofiled.c
+
+LOCAL_STATIC_LIBRARIES := \
+ libpopt libutil libdb libabi libop
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/.. \
+ $(LOCAL_PATH)/../libdb \
+ $(LOCAL_PATH)/../libutil \
+ $(LOCAL_PATH)/../libop \
+ $(LOCAL_PATH)/../libabi
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
+LOCAL_MODULE_TAGS := debug
+LOCAL_MODULE:= oprofiled
+
+include $(BUILD_EXECUTABLE)
View
373 daemon/init.c
@@ -0,0 +1,373 @@
+/**
+ * @file daemon/init.c
+ * Daemon set up and main loop for 2.6
+ *
+ * @remark Copyright 2002 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon
+ * @author Philippe Elie
+ * @Modifications Daniel Hansel
+ * Modified by Aravind Menon for Xen
+ * These modifications are:
+ * Copyright (C) 2005 Hewlett-Packard Co.
+ */
+
+#include "config.h"
+
+#include "oprofiled.h"
+#include "opd_stats.h"
+#include "opd_sfile.h"
+#include "opd_pipe.h"
+#include "opd_kernel.h"
+#include "opd_trans.h"
+#include "opd_anon.h"
+#include "opd_perfmon.h"
+#include "opd_printf.h"
+
+#include "op_version.h"
+#include "op_config.h"
+#include "op_deviceio.h"
+#include "op_get_time.h"
+#include "op_libiberty.h"
+#include "op_fileio.h"
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#if ANDROID
+#include <sys/wait.h>
+#else
+#include <wait.h>
+#endif
+#include <string.h>
+
+size_t kernel_pointer_size;
+
+static fd_t devfd;
+static char * sbuf;
+static size_t s_buf_bytesize;
+extern char * session_dir;
+static char start_time_str[32];
+static int jit_conversion_running;
+
+static void opd_sighup(void);
+static void opd_alarm(void);
+static void opd_sigterm(void);
+static void opd_sigchild(void);
+static void opd_do_jitdumps(void);
+
+/**
+ * opd_open_files - open necessary files
+ *
+ * Open the device files and the log file,
+ * and mmap() the hash map.
+ */
+static void opd_open_files(void)
+{
+ devfd = op_open_device("/dev/oprofile/buffer");
+ if (devfd == -1) {
+ if (errno == EINVAL)
+ fprintf(stderr, "Failed to open device. Possibly you have passed incorrect\n"
+ "parameters. Check /var/log/messages.");
+ else
+ perror("Failed to open profile device");
+ exit(EXIT_FAILURE);
+ }
+
+ /* give output before re-opening stdout as the logfile */
+ printf("Using log file %s\n", op_log_file);
+
+ /* set up logfile */
+ close(0);
+ close(1);
+
+ if (open("/dev/null", O_RDONLY) == -1) {
+ perror("oprofiled: couldn't re-open stdin as /dev/null: ");
+ exit(EXIT_FAILURE);
+ }
+
+ opd_open_logfile();
+ opd_create_pipe();
+
+ printf("oprofiled started %s", op_get_time());
+ printf("kernel pointer size: %lu\n",
+ (unsigned long)kernel_pointer_size);
+ fflush(stdout);
+}
+
+
+/** Done writing out the samples, indicate with complete_dump file */
+static void complete_dump(void)
+{
+ FILE * status_file;
+
+retry:
+ status_file = fopen(op_dump_status, "w");
+
+ if (!status_file && errno == EMFILE) {
+ if (sfile_lru_clear()) {
+ printf("LRU cleared but file open fails for %s.\n",
+ op_dump_status);
+ abort();
+ }
+ goto retry;
+ }
+
+ if (!status_file) {
+ perror("warning: couldn't set complete_dump: ");
+ return;
+ }
+
+ fprintf(status_file, "1\n");
+ fclose(status_file);
+}
+
+
+/**
+ * opd_do_samples - process a sample buffer
+ * @param opd_buf buffer to process
+ *
+ * Process a buffer of samples.
+ *
+ * If the sample could be processed correctly, it is written
+ * to the relevant sample file.
+ */
+static void opd_do_samples(char const * opd_buf, ssize_t count)
+{
+ size_t num = count / kernel_pointer_size;
+
+ opd_stats[OPD_DUMP_COUNT]++;
+
+ verbprintf(vmisc, "Read buffer of %d entries.\n", (unsigned int)num);
+
+ opd_process_samples(opd_buf, num);
+
+ complete_dump();
+}
+
+static void opd_do_jitdumps(void)
+{
+ pid_t childpid;
+ int arg_num;
+ unsigned long long end_time = 0ULL;
+ struct timeval tv;
+ char end_time_str[32];
+ char opjitconv_path[PATH_MAX + 1];
+ char * exec_args[6];
+
+ if (jit_conversion_running)
+ return;
+ jit_conversion_running = 1;
+
+ childpid = fork();
+ switch (childpid) {
+ case -1:
+ perror("Error forking JIT dump process!");
+ break;
+ case 0:
+ gettimeofday(&tv, NULL);
+ end_time = tv.tv_sec;
+ sprintf(end_time_str, "%llu", end_time);
+ sprintf(opjitconv_path, "%s/%s", OP_BINDIR, "opjitconv");
+ arg_num = 0;
+ exec_args[arg_num++] = opjitconv_path;
+ if (vmisc)
+ exec_args[arg_num++] = "-d";
+ exec_args[arg_num++] = session_dir;
+ exec_args[arg_num++] = start_time_str;
+ exec_args[arg_num++] = end_time_str;
+ exec_args[arg_num] = (char *) NULL;
+ execvp("opjitconv", exec_args);
+ fprintf(stderr, "Failed to exec %s: %s\n",
+ exec_args[0], strerror(errno));
+ /* We don't want any cleanup in the child */
+ _exit(EXIT_FAILURE);
+ default:
+ break;
+ }
+
+}
+
+/**
+ * opd_do_read - enter processing loop
+ * @param buf buffer to read into
+ * @param size size of buffer
+ *
+ * Read some of a buffer from the device and process
+ * the contents.
+ */
+static void opd_do_read(char * buf, size_t size)
+{
+ opd_open_pipe();
+
+ while (1) {
+ ssize_t count = -1;
+
+ /* loop to handle EINTR */
+ while (count < 0) {
+ count = op_read_device(devfd, buf, size);
+
+ /* we can lose an alarm or a hup but
+ * we don't care.
+ */
+ if (signal_alarm) {
+ signal_alarm = 0;
+ opd_alarm();
+ }
+
+ if (signal_hup) {
+ signal_hup = 0;
+ opd_sighup();
+ }
+
+ if (signal_term)
+ opd_sigterm();
+
+ if (signal_child)
+ opd_sigchild();
+
+ if (signal_usr1) {
+ signal_usr1 = 0;
+ perfmon_start();
+ }
+
+ if (signal_usr2) {
+ signal_usr2 = 0;
+ perfmon_stop();
+ }
+
+ if (is_jitconv_requested()) {
+ verbprintf(vmisc, "Start opjitconv was triggered\n");
+ opd_do_jitdumps();
+ }
+ }
+
+ opd_do_samples(buf, count);
+ }
+
+ opd_close_pipe();
+}
+
+
+/** opd_alarm - sync files and report stats */
+static void opd_alarm(void)
+{
+ sfile_sync_files();
+ opd_print_stats();
+ alarm(60 * 10);
+}
+
+
+/** re-open files for logrotate/opcontrol --reset */
+static void opd_sighup(void)
+{
+ printf("Received SIGHUP.\n");
+ /* We just close them, and re-open them lazily as usual. */
+ sfile_close_files();
+ close(1);
+ close(2);
+ opd_open_logfile();
+}
+
+
+static void clean_exit(void)
+{
+ perfmon_exit();
+ unlink(op_lock_file);
+}
+
+
+static void opd_sigterm(void)
+{
+ opd_do_jitdumps();
+ opd_print_stats();
+ printf("oprofiled stopped %s", op_get_time());
+ exit(EXIT_FAILURE);
+}
+
+/* SIGCHLD received from JIT dump child process. */
+static void opd_sigchild(void)
+{
+ int child_status;
+ wait(&child_status);
+ jit_conversion_running = 0;
+ if (WIFEXITED(child_status) && (!WEXITSTATUS(child_status))) {
+ verbprintf(vmisc, "JIT dump processing complete.\n");
+ } else {
+ printf("JIT dump processing exited abnormally: %d\n",
+ WEXITSTATUS(child_status));
+ }
+
+}
+
+static void opd_26_init(void)
+{
+ size_t i;
+ size_t opd_buf_size;
+ unsigned long long start_time = 0ULL;
+ struct timeval tv;
+
+ opd_create_vmlinux(vmlinux, kernel_range);
+ opd_create_xen(xenimage, xen_range);
+
+ opd_buf_size = opd_read_fs_int("/dev/oprofile/", "buffer_size", 1);
+ kernel_pointer_size = opd_read_fs_int("/dev/oprofile/", "pointer_size", 1);
+
+ s_buf_bytesize = opd_buf_size * kernel_pointer_size;
+
+ sbuf = xmalloc(s_buf_bytesize);
+
+ opd_reread_module_info();
+
+ for (i = 0; i < OPD_MAX_STATS; i++)
+ opd_stats[i] = 0;
+
+ perfmon_init();
+
+ cookie_init();
+ sfile_init();
+ anon_init();
+
+ /* must be /after/ perfmon_init() at least */
+ if (atexit(clean_exit)) {
+ perfmon_exit();
+ perror("oprofiled: couldn't set exit cleanup: ");
+ exit(EXIT_FAILURE);
+ }
+
+ /* trigger kernel module setup before returning control to opcontrol */
+ opd_open_files();
+ gettimeofday(&tv, NULL);
+ start_time = 0ULL;
+ start_time = tv.tv_sec;
+ sprintf(start_time_str, "%llu", start_time);
+
+}
+
+
+static void opd_26_start(void)
+{
+ /* simple sleep-then-process loop */
+ opd_do_read(sbuf, s_buf_bytesize);
+}
+
+
+static void opd_26_exit(void)
+{
+ opd_print_stats();
+ printf("oprofiled stopped %s", op_get_time());
+
+ free(sbuf);
+ free(vmlinux);
+ /* FIXME: free kernel images, sfiles etc. */
+}
+
+struct oprofiled_ops opd_26_ops = {
+ .init = opd_26_init,
+ .start = opd_26_start,
+ .exit = opd_26_exit,
+};
View
228 daemon/opd_anon.c
@@ -0,0 +1,228 @@
+/**
+ * @file opd_anon.c
+ * Anonymous region handling.
+ *
+ * Our caching of maps has some problems: if we get tgid reuse,
+ * and it's the same application, we might end up with wrong
+ * maps. The same happens in an unmap-remap case. There's not much
+ * we can do about this, we just hope it's not too common...
+ *
+ * What is relatively common is expanding anon maps, which leaves us
+ * with lots of separate sample files.
+ *
+ * @remark Copyright 2005 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon
+ * @Modifications Gisle Dankel
+ */
+
+#include "opd_anon.h"
+#include "opd_trans.h"
+#include "opd_sfile.h"
+#include "opd_printf.h"
+#include "op_libiberty.h"
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define HASH_SIZE 1024
+#define HASH_BITS (HASH_SIZE - 1)
+
+/*
+ * Note that this value is tempered by the fact that when we miss in the
+ * anon cache, we'll tear down all the mappings for that tgid. Thus, LRU
+ * of a mapping can potentially clear out a much larger number of
+ * mappings.
+ */
+#define LRU_SIZE 8192
+#define LRU_AMOUNT (LRU_SIZE/8)
+
+static struct list_head hashes[HASH_SIZE];
+static struct list_head lru;
+static size_t nr_lru;
+
+static void do_lru(struct transient * trans)
+{
+ size_t nr_to_kill = LRU_AMOUNT;
+ struct list_head * pos;
+ struct list_head * pos2;
+ struct anon_mapping * entry;
+
+ list_for_each_safe(pos, pos2, &lru) {
+ entry = list_entry(pos, struct anon_mapping, lru_list);
+ if (trans->anon == entry)
+ clear_trans_current(trans);
+ if (trans->last_anon == entry)
+ clear_trans_last(trans);
+ sfile_clear_anon(entry);
+ list_del(&entry->list);
+ list_del(&entry->lru_list);
+ --nr_lru;
+ free(entry);
+ if (nr_to_kill-- == 0)
+ break;
+ }
+}
+
+
+static unsigned long hash_anon(pid_t tgid, cookie_t app)
+{
+ return ((app >> DCOOKIE_SHIFT) ^ (tgid >> 2)) & (HASH_SIZE - 1);
+}
+
+
+static void clear_anon_maps(struct transient * trans)
+{
+ unsigned long hash = hash_anon(trans->tgid, trans->app_cookie);
+ pid_t tgid = trans->tgid;
+ cookie_t app = trans->app_cookie;
+ struct list_head * pos;
+ struct list_head * pos2;
+ struct anon_mapping * entry;
+
+ clear_trans_current(trans);
+
+ list_for_each_safe(pos, pos2, &hashes[hash]) {
+ entry = list_entry(pos, struct anon_mapping, list);
+ if (entry->tgid == tgid && entry->app_cookie == app) {
+ if (trans->last_anon == entry)
+ clear_trans_last(trans);
+ sfile_clear_anon(entry);
+ list_del(&entry->list);
+ list_del(&entry->lru_list);
+ --nr_lru;
+ free(entry);
+ }
+ }
+
+ if (vmisc) {
+ char const * name = verbose_cookie(app);
+ printf("Cleared anon maps for tgid %u (%s).\n", tgid, name);
+ }
+}
+
+
+static void
+add_anon_mapping(struct transient * trans, vma_t start, vma_t end, char * name)
+{
+ unsigned long hash = hash_anon(trans->tgid, trans->app_cookie);
+ struct anon_mapping * m = xmalloc(sizeof(struct anon_mapping));
+ m->tgid = trans->tgid;
+ m->app_cookie = trans->app_cookie;
+ m->start = start;
+ m->end = end;
+ strncpy(m->name, name, MAX_IMAGE_NAME_SIZE + 1);
+ list_add_tail(&m->list, &hashes[hash]);
+ list_add_tail(&m->lru_list, &lru);
+ if (++nr_lru == LRU_SIZE)
+ do_lru(trans);
+ if (vmisc) {
+ char const * name = verbose_cookie(m->app_cookie);
+ printf("Added anon map 0x%llx-0x%llx for tgid %u (%s).\n",
+ start, end, m->tgid, name);
+ }
+}
+
+
+/* 42000000-4212f000 r-xp 00000000 16:03 424334 /lib/tls/libc-2.3.2.so */
+static void get_anon_maps(struct transient * trans)
+{
+ FILE * fp = NULL;
+ char buf[PATH_MAX];
+ vma_t start, end;
+ int ret;
+
+ snprintf(buf, PATH_MAX, "/proc/%d/maps", trans->tgid);
+ fp = fopen(buf, "r");
+ if (!fp)
+ return;
+
+ while (fgets(buf, PATH_MAX, fp) != NULL) {
+ char tmp[MAX_IMAGE_NAME_SIZE + 1];
+ char name[MAX_IMAGE_NAME_SIZE + 1];
+ /* Some anon maps have labels like
+ * [heap], [stack], [vdso], [vsyscall] ...
+ * Keep track of these labels. If a map has no name, call it "anon".
+ * Ignore all mappings starting with "/" (file or shared memory object)
+ */
+ strcpy(name, "anon");
+ ret = sscanf(buf, "%llx-%llx %20s %20s %20s %20s %20s",
+ &start, &end, tmp, tmp, tmp, tmp, name);
+ if (ret < 6 || name[0] == '/')
+ continue;
+
+ add_anon_mapping(trans, start, end, name);
+ }
+
+ fclose(fp);
+}
+
+
+static int
+anon_match(struct transient const * trans, struct anon_mapping const * anon)
+{
+ if (!anon)
+ return 0;
+ if (trans->tgid != anon->tgid)
+ return 0;
+ if (trans->app_cookie != anon->app_cookie)
+ return 0;
+ if (trans->pc < anon->start)
+ return 0;
+ return (trans->pc < anon->end);
+}
+
+
+struct anon_mapping * find_anon_mapping(struct transient * trans)
+{
+ unsigned long hash = hash_anon(trans->tgid, trans->app_cookie);
+ struct list_head * pos;
+ struct anon_mapping * entry;
+ int tried = 0;
+
+ if (anon_match(trans, trans->anon))
+ return (trans->anon);
+
+retry:
+ list_for_each(pos, &hashes[hash]) {
+ entry = list_entry(pos, struct anon_mapping, list);
+ if (anon_match(trans, entry))
+ goto success;
+ }
+
+ if (!tried) {
+ clear_anon_maps(trans);
+ get_anon_maps(trans);
+ tried = 1;
+ goto retry;
+ }
+
+ return NULL;
+
+success:
+ /*
+ * Typically, there's one big mapping that matches. Let's go
+ * faster.
+ */
+ list_del(&entry->list);
+ list_add(&entry->list, &hashes[hash]);
+
+ verbprintf(vmisc, "Found range 0x%llx-0x%llx for tgid %u, pc %llx.\n",
+ entry->start, entry->end, (unsigned int)entry->tgid,
+ trans->pc);
+ return entry;
+}
+
+
+void anon_init(void)
+{
+ size_t i;
+
+ for (i = 0; i < HASH_SIZE; ++i)
+ list_init(&hashes[i]);
+
+ list_init(&lru);
+}
View
54 daemon/opd_anon.h
@@ -0,0 +1,54 @@
+/**
+ * @file opd_anon.h
+ * Anonymous region handling.
+ *
+ * @remark Copyright 2005 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon
+ */
+
+#ifndef OPD_ANON_H
+#define OPD_ANON_H
+
+#include "op_types.h"
+#include "op_list.h"
+
+#include "opd_cookie.h"
+
+#include <sys/types.h>
+
+struct transient;
+
+/**
+ * Shift useful bits into play for VMA hashing.
+ */
+#define VMA_SHIFT 13
+
+/* Maximum size of the image name considered */
+#define MAX_IMAGE_NAME_SIZE 20
+
+struct anon_mapping {
+ /** start of the mapping */
+ vma_t start;
+ /** end of the mapping */
+ vma_t end;
+ /** tgid of the app */
+ pid_t tgid;
+ /** cookie of the app */
+ cookie_t app_cookie;
+ /** hash list */
+ struct list_head list;
+ /** lru list */
+ struct list_head lru_list;
+ char name[MAX_IMAGE_NAME_SIZE+1];
+};
+
+/**
+ * Try to find an anonymous mapping for the given pc/tgid pair.
+ */
+struct anon_mapping * find_anon_mapping(struct transient *);
+
+void anon_init(void);
+
+#endif /* OPD_ANON_H */
View
209 daemon/opd_cookie.c
@@ -0,0 +1,209 @@
+/**
+ * @file opd_cookie.c
+ * cookie -> name cache
+ *
+ * @remark Copyright 2002, 2005 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon
+ */
+
+#include "opd_cookie.h"
+#include "oprofiled.h"
+#include "op_list.h"
+#include "op_libiberty.h"
+
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#ifndef __NR_lookup_dcookie
+#if defined(__i386__)
+#define __NR_lookup_dcookie 253
+#elif defined(__x86_64__)
+#define __NR_lookup_dcookie 212
+#elif defined(__powerpc__)
+#define __NR_lookup_dcookie 235
+#elif defined(__alpha__)
+#define __NR_lookup_dcookie 406
+#elif defined(__hppa__)
+#define __NR_lookup_dcookie 223
+#elif defined(__ia64__)
+#define __NR_lookup_dcookie 1237
+#elif defined(__sparc__)
+/* untested */
+#define __NR_lookup_dcookie 208
+#elif defined(__s390__) || defined (__s390x__)
+#define __NR_lookup_dcookie 110
+#elif defined(__arm__)
+#define __NR_lookup_dcookie (__NR_SYSCALL_BASE+249)
+#elif defined(__mips__)
+#include <sgidefs.h>
+/* O32 */
+#if _MIPS_SIM == _MIPS_SIM_ABI32
+#define __NR_lookup_dcookie 4247
+/* N64 */
+#elif _MIPS_SIM == _MIPS_SIM_ABI64
+#define __NR_lookup_dcookie 5206
+/* N32 */
+#elif _MIPS_SIM == _MIPS_SIM_NABI32
+#define __NR_lookup_dcookie 6206
+#else
+#error Unknown MIPS ABI: Dunno __NR_lookup_dcookie
+#endif
+#else
+#error Please define __NR_lookup_dcookie for your architecture
+#endif
+#endif /* __NR_lookup_dcookie */
+
+#if (defined(__powerpc__) && !defined(__powerpc64__)) || defined(__hppa__)\
+ || (defined(__s390__) && !defined(__s390x__)) \
+ || (defined(__mips__) && (_MIPS_SIM == _MIPS_SIM_ABI32) \
+ && defined(__MIPSEB__)) \
+ || (defined(__arm__) && defined(__ARM_EABI__) \
+ && defined(__ARMEB__))
+static inline int lookup_dcookie(cookie_t cookie, char * buf, size_t size)
+{
+ return syscall(__NR_lookup_dcookie, (unsigned long)(cookie >> 32),
+ (unsigned long)(cookie & 0xffffffff), buf, size);
+}
+#elif (defined(__mips__) && (_MIPS_SIM == _MIPS_SIM_ABI32)) \
+ || (defined(__arm__) && defined(__ARM_EABI__))
+static inline int lookup_dcookie(cookie_t cookie, char * buf, size_t size)
+{
+ return syscall(__NR_lookup_dcookie,
+ (unsigned long)(cookie & 0xffffffff),
+ (unsigned long)(cookie >> 32), buf, size);
+}
+#else
+static inline int lookup_dcookie(cookie_t cookie, char * buf, size_t size)
+{
+ return syscall(__NR_lookup_dcookie, cookie, buf, size);
+}
+#endif
+
+
+struct cookie_entry {
+ cookie_t value;
+ char * name;
+ int ignored;
+ struct list_head list;
+};
+
+
+#define HASH_SIZE 512
+#define HASH_BITS (HASH_SIZE - 1)
+
+static struct list_head hashes[HASH_SIZE];
+
+static struct cookie_entry * create_cookie(cookie_t cookie)
+{
+ int err;
+ struct cookie_entry * entry = xmalloc(sizeof(struct cookie_entry));
+
+ entry->value = cookie;
+ entry->name = xmalloc(PATH_MAX + 1);
+
+ err = lookup_dcookie(cookie, entry->name, PATH_MAX);
+
+ if (err < 0) {
+ fprintf(stderr, "Lookup of cookie %llx failed, errno=%d\n",
+ cookie, errno);
+ free(entry->name);
+ entry->name = NULL;
+ entry->ignored = 0;
+ } else {
+ entry->ignored = is_image_ignored(entry->name);
+ }
+
+ return entry;
+}
+
+
+/* Cookie monster want cookie! */
+static unsigned long hash_cookie(cookie_t cookie)
+{
+ return (cookie >> DCOOKIE_SHIFT) & (HASH_SIZE - 1);
+}
+
+
+char const * find_cookie(cookie_t cookie)
+{
+ unsigned long hash = hash_cookie(cookie);
+ struct list_head * pos;
+ struct cookie_entry * entry;
+
+ if (cookie == INVALID_COOKIE || cookie == NO_COOKIE)
+ return NULL;
+
+ list_for_each(pos, &hashes[hash]) {
+ entry = list_entry(pos, struct cookie_entry, list);
+ if (entry->value == cookie)
+ goto out;
+ }
+
+ /* not sure this can ever happen due to is_cookie_ignored */
+ entry = create_cookie(cookie);
+ list_add(&entry->list, &hashes[hash]);
+out:
+ return entry->name;
+}
+
+
+int is_cookie_ignored(cookie_t cookie)
+{
+ unsigned long hash = hash_cookie(cookie);
+ struct list_head * pos;
+ struct cookie_entry * entry;
+
+ if (cookie == INVALID_COOKIE || cookie == NO_COOKIE)
+ return 1;
+
+ list_for_each(pos, &hashes[hash]) {
+ entry = list_entry(pos, struct cookie_entry, list);
+ if (entry->value == cookie)
+ goto out;
+ }
+
+ entry = create_cookie(cookie);
+ list_add(&entry->list, &hashes[hash]);
+out:
+ return entry->ignored;
+}
+
+
+char const * verbose_cookie(cookie_t cookie)
+{
+ unsigned long hash = hash_cookie(cookie);
+ struct list_head * pos;
+ struct cookie_entry * entry;
+
+ if (cookie == INVALID_COOKIE)
+ return "invalid";
+
+ if (cookie == NO_COOKIE)
+ return "anonymous";
+
+ list_for_each(pos, &hashes[hash]) {
+ entry = list_entry(pos, struct cookie_entry, list);
+ if (entry->value == cookie) {
+ if (!entry->name)
+ return "failed lookup";
+ return entry->name;
+ }
+ }
+
+ return "not hashed";
+}
+
+
+void cookie_init(void)
+{
+ size_t i;
+
+ for (i = 0; i < HASH_SIZE; ++i)
+ list_init(&hashes[i]);
+}
View
39 daemon/opd_cookie.h
@@ -0,0 +1,39 @@
+/**
+ * @file opd_cookie.h
+ * cookie -> name cache
+ *
+ * @remark Copyright 2002, 2005 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon
+ */
+
+#ifndef OPD_COOKIE_H
+#define OPD_COOKIE_H
+
+typedef unsigned long long cookie_t;
+
+#define INVALID_COOKIE ~0LLU
+#define NO_COOKIE 0LLU
+
+/**
+ * Shift value to remove trailing zero on a dcookie value, 7 is sufficient
+ * for most architecture
+ */
+#define DCOOKIE_SHIFT 7
+
+/**
+ * Return the name of the given dcookie. May return
+ * NULL on failure.
+ */
+char const * find_cookie(cookie_t cookie);
+
+/** return true if this cookie should be ignored */
+int is_cookie_ignored(cookie_t cookie);
+
+/** give a textual description of the cookie */
+char const * verbose_cookie(cookie_t cookie);
+
+void cookie_init(void);
+
+#endif /* OPD_COOKIE_H */
View
165 daemon/opd_events.c
@@ -0,0 +1,165 @@
+/**
+ * @file daemon/opd_events.c
+ * Event details for each counter
+ *
+ * @remark Copyright 2002, 2003 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon
+ * @author Philippe Elie
+ */
+
+#include "config.h"
+
+#include "opd_events.h"
+#include "opd_printf.h"
+#include "oprofiled.h"
+
+#include "op_string.h"
+#include "op_config.h"
+#include "op_cpufreq.h"
+#include "op_cpu_type.h"
+#include "op_libiberty.h"
+#include "op_hw_config.h"
+#include "op_sample_file.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+extern op_cpu cpu_type;
+
+struct opd_event opd_events[OP_MAX_COUNTERS];
+
+static double cpu_speed;
+
+static void malformed_events(void)
+{
+ fprintf(stderr, "oprofiled: malformed events passed "
+ "on the command line\n");
+ exit(EXIT_FAILURE);
+}
+
+
+static char * copy_token(char ** c, char delim)
+{
+ char * tmp = *c;
+ char * tmp2 = *c;
+ char * str;
+
+ if (!**c)
+ return NULL;
+
+ while (*tmp2 && *tmp2 != delim)
+ ++tmp2;
+
+ if (tmp2 == tmp)
+ return NULL;
+
+ str = op_xstrndup(tmp, tmp2 - tmp);
+ *c = tmp2;
+ if (**c)
+ ++*c;
+ return str;
+}
+
+
+static unsigned long copy_ulong(char ** c, char delim)
+{
+ unsigned long val = 0;
+ char * str = copy_token(c, delim);
+ if (!str)
+ malformed_events();
+ val = strtoul(str, NULL, 0);
+ free(str);
+ return val;
+}
+
+
+void opd_parse_events(char const * events)
+{
+ char * ev = xstrdup(events);
+ char * c;
+ size_t cur = 0;
+
+ if (cpu_type == CPU_TIMER_INT) {
+ struct opd_event * event = &opd_events[0];
+ event->name = xstrdup("TIMER");
+ event->value = event->counter
+ = event->count = event->um = 0;
+ event->kernel = 1;
+ event->user = 1;
+ return;
+ }
+
+ if (!ev || !strlen(ev)) {
+ fprintf(stderr, "oprofiled: no events passed.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ verbprintf(vmisc, "Events: %s\n", ev);
+
+ c = ev;
+
+ while (*c && cur < op_nr_counters) {
+ struct opd_event * event = &opd_events[cur];
+
+ if (!(event->name = copy_token(&c, ':')))
+ malformed_events();
+ event->value = copy_ulong(&c, ':');
+ event->counter = copy_ulong(&c, ':');
+ event->count = copy_ulong(&c, ':');
+ event->um = copy_ulong(&c, ':');
+ event->kernel = copy_ulong(&c, ':');
+ event->user = copy_ulong(&c, ',');
+ ++cur;
+ }
+
+ if (*c) {
+ fprintf(stderr, "oprofiled: too many events passed.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ free(ev);
+
+ cpu_speed = op_cpu_frequency();
+}
+
+
+struct opd_event * find_counter_event(unsigned long counter)
+{
+ size_t i;
+
+ for (i = 0; i < op_nr_counters && opd_events[i].name; ++i) {
+ if (counter == opd_events[i].counter)
+ return &opd_events[i];
+ }
+
+ fprintf(stderr, "Unknown event for counter %lu\n", counter);
+ abort();
+ return NULL;
+}
+
+
+void fill_header(struct opd_header * header, unsigned long counter,
+ vma_t anon_start, vma_t cg_to_anon_start,
+ int is_kernel, int cg_to_is_kernel,
+ int spu_samples, uint64_t embed_offset, time_t mtime)
+{
+ struct opd_event * event = find_counter_event(counter);
+
+ memset(header, '\0', sizeof(struct opd_header));
+ header->version = OPD_VERSION;
+ memcpy(header->magic, OPD_MAGIC, sizeof(header->magic));
+ header->cpu_type = cpu_type;
+ header->ctr_event = event->value;
+ header->ctr_count = event->count;
+ header->ctr_um = event->um;
+ header->is_kernel = is_kernel;
+ header->cg_to_is_kernel = cg_to_is_kernel;
+ header->cpu_speed = cpu_speed;
+ header->mtime = mtime;
+ header->anon_start = anon_start;
+ header->spu_profile = spu_samples;
+ header->embedded_offset = embed_offset;
+ header->cg_to_anon_start = cg_to_anon_start;
+}
View
47 daemon/opd_events.h
@@ -0,0 +1,47 @@
+/**
+ * @file daemon/opd_events.h
+ * Event details for each counter
+ *
+ * @remark Copyright 2002, 2003 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon
+ * @author Philippe Elie
+ */
+
+#ifndef OPD_EVENTS_H
+
+#include "op_types.h"
+
+#include <stdint.h>
+#include <time.h>
+
+/** event description for setup (perfmon) and mangling */
+struct opd_event {
+ char * name;
+ unsigned long value;
+ unsigned long counter;
+ unsigned long count;
+ unsigned long um;
+ unsigned long kernel;
+ unsigned long user;
+};
+
+/* needed for opd_perfmon.c */
+extern struct opd_event opd_events[];
+
+/** parse the events into the opd_events array */
+void opd_parse_events(char const * events);
+
+/** Find the event for the given counter */
+struct opd_event * find_counter_event(unsigned long counter);
+
+struct opd_header;
+
+/** fill the sample file header with event info etc. */
+void fill_header(struct opd_header * header, unsigned long counter,
+ vma_t anon_start, vma_t anon_end,
+ int is_kernel, int cg_to_is_kernel,
+ int spu_samples, uint64_t embed_offset, time_t mtime);
+
+#endif /* OPD_EVENTS_H */
View
45 daemon/opd_interface.h
@@ -0,0 +1,45 @@
+/**
+ * @file opd_interface.h
+ *
+ * Module / user space interface for 2.6 kernels and above
+ *
+ * @remark Copyright 2002 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon
+ * @author Philippe Elie
+ * Modified by Aravind Menon for Xen
+ * These modifications are:
+ * Copyright (C) 2005 Hewlett-Packard Co.
+ */
+
+#ifndef OPD_INTERFACE_H
+#define OPD_INTERFACE_H
+
+#define CTX_SWITCH_CODE 1
+#define CPU_SWITCH_CODE 2
+#define COOKIE_SWITCH_CODE 3
+#define KERNEL_ENTER_SWITCH_CODE 4
+#define USER_ENTER_SWITCH_CODE 5
+#define MODULE_LOADED_CODE 6
+#define CTX_TGID_CODE 7
+#define TRACE_BEGIN_CODE 8
+/* Code 9 used to be TRACE_END_CODE which is not used anymore */
+/* Code 9 is now considered an unknown escape code */
+#define XEN_ENTER_SWITCH_CODE 10
+/*
+ * Ugly work-around for the unfortunate collision between Xenoprof's
+ * DOMAIN_SWITCH_CODE (in use on x86) and Cell's SPU_PROFILING_CODE
+ * (in use with Power):
+ */
+#if defined(__powerpc__)
+#define SPU_PROFILING_CODE 11
+#define SPU_CTX_SWITCH_CODE 12
+#define DOMAIN_SWITCH_CODE 13
+#define LAST_CODE 14
+#else
+#define DOMAIN_SWITCH_CODE 11
+#define LAST_CODE 12
+#endif
+
+#endif /* OPD_INTERFACE_H */
View
229 daemon/opd_kernel.c
@@ -0,0 +1,229 @@
+/**
+ * @file daemon/opd_kernel.c
+ * Dealing with the kernel and kernel module samples
+ *
+ * @remark Copyright 2002 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon
+ * @author Philippe Elie
+ * Modified by Aravind Menon for Xen
+ * These modifications are:
+ * Copyright (C) 2005 Hewlett-Packard Co.
+ */
+
+#include "opd_kernel.h"
+#include "opd_sfile.h"
+#include "opd_trans.h"
+#include "opd_printf.h"
+#include "opd_stats.h"
+#include "oprofiled.h"
+
+#include "op_fileio.h"
+#include "op_config.h"
+#include "op_libiberty.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <assert.h>
+
+static LIST_HEAD(modules);
+
+static struct kernel_image vmlinux_image;
+
+static struct kernel_image xen_image;
+
+void opd_create_vmlinux(char const * name, char const * arg)
+{
+ /* vmlinux is *not* on the list of modules */
+ list_init(&vmlinux_image.list);
+
+ /* for no vmlinux */
+ if (no_vmlinux) {
+ vmlinux_image.name = "no-vmlinux";
+ return;
+ }
+
+ vmlinux_image.name = xstrdup(name);
+
+ sscanf(arg, "%llx,%llx", &vmlinux_image.start, &vmlinux_image.end);
+
+ verbprintf(vmisc, "kernel_start = %llx, kernel_end = %llx\n",
+ vmlinux_image.start, vmlinux_image.end);
+
+ if (!vmlinux_image.start && !vmlinux_image.end) {
+ fprintf(stderr, "error: mis-parsed kernel range: %llx-%llx\n",
+ vmlinux_image.start, vmlinux_image.end);
+ exit(EXIT_FAILURE);
+ }
+}
+
+void opd_create_xen(char const * name, char const * arg)
+{
+ /* xen is *not* on the list of modules */
+ list_init(&xen_image.list);
+
+ /* for no xen */
+ if (no_xen) {
+ xen_image.name = "no-xen";
+ return;
+ }
+
+ xen_image.name = xstrdup(name);
+
+ sscanf(arg, "%llx,%llx", &xen_image.start, &xen_image.end);
+
+ verbprintf(vmisc, "xen_start = %llx, xen_end = %llx\n",
+ xen_image.start, xen_image.end);
+
+ if (!xen_image.start && !xen_image.end) {
+ fprintf(stderr, "error: mis-parsed xen range: %llx-%llx\n",
+ xen_image.start, xen_image.end);
+ exit(EXIT_FAILURE);
+ }
+}
+
+
+/**
+ * Allocate and initialise a kernel image description
+ * @param name image name
+ * @param start start address
+ * @param end end address
+ */
+static struct kernel_image *
+opd_create_module(char const * name, vma_t start, vma_t end)
+{
+ struct kernel_image * image = xmalloc(sizeof(struct kernel_image));
+
+ image->name = xstrdup(name);
+ image->start = start;
+ image->end = end;
+ list_add(&image->list, &modules);
+
+ return image;
+}
+
+
+/**
+ * Clear and free all kernel image information and reset
+ * values.
+ */
+static void opd_clear_modules(void)
+{
+ struct list_head * pos;
+ struct list_head * pos2;
+ struct kernel_image * image;
+
+ list_for_each_safe(pos, pos2, &modules) {
+ image = list_entry(pos, struct kernel_image, list);
+ if (image->name)
+ free(image->name);
+ free(image);
+ }
+
+ list_init(&modules);
+
+ /* clear out lingering references */
+ sfile_clear_kernel();
+}
+
+
+/*
+ * each line is in the format:
+ *
+ * module_name 16480 1 dependencies Live 0xe091e000
+ *
+ * without any blank space in each field
+ */
+void opd_reread_module_info(void)
+{
+ FILE * fp;
+ char * line;
+ struct kernel_image * image;
+ int module_size;
+ char ref_count[32+1];
+ int ret;
+ char module_name[256+1];
+ char live_info[32+1];
+ char dependencies[4096+1];
+ unsigned long long start_address;
+
+ if (no_vmlinux)
+ return;
+
+ opd_clear_modules();
+
+ printf("Reading module info.\n");
+
+ fp = op_try_open_file("/proc/modules", "r");
+
+ if (!fp) {
+ printf("oprofiled: /proc/modules not readable, "
+ "can't process module samples.\n");
+ return;
+ }
+
+ while (1) {
+ line = op_get_line(fp);
+
+ if (!line)
+ break;
+
+ if (line[0] == '\0') {
+ free(line);
+ continue;
+ }
+
+ ret = sscanf(line, "%256s %u %32s %4096s %32s %llx",
+ module_name, &module_size, ref_count,
+ dependencies, live_info, &start_address);
+ if (ret != 6) {
+ printf("bad /proc/modules entry: %s\n", line);
+ free(line);
+ continue;
+ }
+
+ image = opd_create_module(module_name, start_address,
+ start_address + module_size);
+
+ verbprintf(vmodule, "module %s start %llx end %llx\n",
+ image->name, image->start, image->end);
+
+ free(line);
+ }
+
+ op_close_file(fp);
+}
+
+
+/**
+ * find a kernel image by PC value
+ * @param trans holds PC value to look up
+ *
+ * find the kernel image which contains this PC.
+ *
+ * Return %NULL if not found.
+ */
+struct kernel_image * find_kernel_image(struct transient const * trans)
+{
+ struct list_head * pos;
+ struct kernel_image * image = &vmlinux_image;
+
+ if (no_vmlinux)
+ return image;
+
+ if (image->start <= trans->pc && image->end > trans->pc)
+ return image;
+
+ list_for_each(pos, &modules) {
+ image = list_entry(pos, struct kernel_image, list);
+ if (image->start <= trans->pc && image->end > trans->pc)
+ return image;
+ }
+
+ if (xen_image.start <= trans->pc && xen_image.end > trans->pc)
+ return &xen_image;
+
+ return NULL;
+}
View
43 daemon/opd_kernel.h
@@ -0,0 +1,43 @@
+/**
+ * @file daemon/opd_kernel.h
+ * Dealing with the kernel and kernel module images
+ *
+ * @remark Copyright 2002 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon
+ * @author Philippe Elie
+ * Modified by Aravind Menon for Xen
+ * These modifications are:
+ * Copyright (C) 2005 Hewlett-Packard Co.
+ */
+
+#ifndef OPD_KERNEL_H
+#define OPD_KERNEL_H
+
+#include "op_types.h"
+#include "op_list.h"
+
+struct transient;
+
+/** create the kernel image */
+void opd_create_vmlinux(char const * name, char const * arg);
+
+void opd_create_xen(char const * name, char const * arg);
+
+/** opd_reread_module_info - parse /proc/modules for kernel modules */
+void opd_reread_module_info(void);
+
+/** Describes a kernel module or vmlinux itself */
+struct kernel_image {
+ char * name;
+ vma_t start;
+ vma_t end;
+ struct list_head list;
+};
+
+/** Find a kernel_image based upon the given parameters in trans. */
+struct kernel_image *
+find_kernel_image(struct transient const * trans);
+
+#endif /* OPD_KERNEL_H */
View
205 daemon/opd_mangling.c
@@ -0,0 +1,205 @@
+/**
+ * @file daemon/opd_mangling.c
+ * Mangling and opening of sample files
+ *
+ * @remark Copyright 2002 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon
+ * @author Philippe Elie
+ */
+
+#include <sys/types.h>
+
+#include "opd_mangling.h"
+#include "opd_kernel.h"
+#include "opd_cookie.h"
+#include "opd_sfile.h"
+#include "opd_anon.h"
+#include "opd_printf.h"
+#include "opd_events.h"
+#include "oprofiled.h"
+
+#include "op_file.h"
+#include "op_sample_file.h"
+#include "op_config.h"
+#include "op_mangle.h"
+#include "op_events.h"
+#include "op_libiberty.h"
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+
+static char const * get_dep_name(struct sfile const * sf)
+{
+ if (sf->anon)
+ return find_cookie(sf->app_cookie);
+
+ /* avoid to call find_cookie(), caller can recover using image_name */
+ if (sf->cookie == sf->app_cookie)
+ return NULL;
+
+ if (!separate_kernel && !(separate_lib && !sf->kernel))
+ return NULL;
+
+ /* this will fail if e.g. kernel thread */
+ if (sf->app_cookie == 0)
+ return NULL;
+
+ return find_cookie(sf->app_cookie);
+}
+
+
+static char * mangle_anon(struct anon_mapping const * anon)
+{
+ char * name = xmalloc(PATH_MAX);
+
+ snprintf(name, 1024, "%u.0x%llx.0x%llx", (unsigned int)anon->tgid,
+ anon->start, anon->end);
+
+ return name;
+}
+
+
+static char *
+mangle_filename(struct sfile * last, struct sfile const * sf, int counter, int cg)
+{
+ char * mangled;
+ struct mangle_values values;
+ struct opd_event * event = find_counter_event(counter);
+
+ values.flags = 0;
+
+ if (sf->kernel) {
+ values.image_name = sf->kernel->name;
+ values.flags |= MANGLE_KERNEL;
+ } else if (sf->anon) {
+ values.flags |= MANGLE_ANON;
+ values.image_name = mangle_anon(sf->anon);
+ values.anon_name = sf->anon->name;
+ } else {
+ values.image_name = find_cookie(sf->cookie);
+ }
+
+ values.dep_name = get_dep_name(sf);
+ if (!values.dep_name)
+ values.dep_name = values.image_name;
+
+ /* FIXME: log */
+ if (!values.image_name || !values.dep_name)
+ return NULL;
+
+ if (separate_thread) {
+ values.flags |= MANGLE_TGID | MANGLE_TID;
+ values.tid = sf->tid;
+ values.tgid = sf->tgid;
+ }
+
+ if (separate_cpu) {
+ values.flags |= MANGLE_CPU;
+ values.cpu = sf->cpu;
+ }
+
+ if (cg) {
+ values.flags |= MANGLE_CALLGRAPH;
+ if (last->kernel) {
+ values.cg_image_name = last->kernel->name;
+ } else if (last->anon) {
+ values.flags |= MANGLE_CG_ANON;
+ values.cg_image_name = mangle_anon(last->anon);
+ values.anon_name = last->anon->name;
+ } else {
+ values.cg_image_name = find_cookie(last->cookie);
+ }
+
+ /* FIXME: log */
+ if (!values.cg_image_name) {
+ if (values.flags & MANGLE_ANON)
+ free((char *)values.image_name);
+ return NULL;
+ }
+ }
+
+ values.event_name = event->name;
+ values.count = event->count;
+ values.unit_mask = event->um;
+
+ mangled = op_mangle_filename(&values);
+
+ if (values.flags & MANGLE_ANON)
+ free((char *)values.image_name);
+ if (values.flags & MANGLE_CG_ANON)
+ free((char *)values.cg_image_name);
+ return mangled;
+}
+
+
+int opd_open_sample_file(odb_t * file, struct sfile * last,
+ struct sfile * sf, int counter, int cg)
+{
+ char * mangled;
+ char const * binary;
+ int spu_profile = 0;
+ vma_t last_start = 0;
+ int err;
+
+ mangled = mangle_filename(last, sf, counter, cg);
+
+ if (!mangled)
+ return EINVAL;
+
+ verbprintf(vsfile, "Opening \"%s\"\n", mangled);
+
+ create_path(mangled);
+
+ /* locking sf will lock associated cg files too */
+ sfile_get(sf);
+ if (sf != last)
+ sfile_get(last);
+
+retry:
+ err = odb_open(file, mangled, ODB_RDWR, sizeof(struct opd_header));
+
+ /* This can naturally happen when racing against opcontrol --reset. */
+ if (err) {
+ if (err == EMFILE) {
+ if (sfile_lru_clear()) {
+ printf("LRU cleared but odb_open() fails for %s.\n", mangled);
+ abort();
+ }
+ goto retry;
+ }
+
+ fprintf(stderr, "oprofiled: open of %s failed: %s\n",
+ mangled, strerror(err));
+ goto out;
+ }
+
+ if (!sf->kernel)
+ binary = find_cookie(sf->cookie);
+ else
+ binary = sf->kernel->name;
+
+ if (last && last->anon)
+ last_start = last->anon->start;
+
+ if (sf->embedded_offset != UNUSED_EMBEDDED_OFFSET)
+ spu_profile = 1;
+
+ fill_header(odb_get_data(file), counter,
+ sf->anon ? sf->anon->start : 0, last_start,
+ !!sf->kernel, last ? !!last->kernel : 0,
+ spu_profile, sf->embedded_offset,
+ binary ? op_get_mtime(binary) : 0);
+
+out:
+ sfile_put(sf);
+ if (sf != last)
+ sfile_put(last);
+ free(mangled);
+ return err;
+}
View
33 daemon/opd_mangling.h
@@ -0,0 +1,33 @@
+/**
+ * @file daemon/opd_mangling.h
+ * Mangling and opening of sample files
+ *
+ * @remark Copyright 2002 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon
+ * @author Philippe Elie
+ */
+
+#ifndef OPD_MANGLING_H
+#define OPD_MANGLING_H
+
+#include "odb.h"
+
+struct sfile;
+
+/*
+ * opd_open_sample_file - open a sample file
+ * @param sf sfile to open sample file for
+ * @param counter counter number
+ * @param cg if this is a callgraph file
+ *
+ * Open image sample file for the sfile, counter
+ * counter and set up memory mappings for it.
+ *
+ * Returns 0 on success.
+ */
+int opd_open_sample_file(odb_t * file, struct sfile * last,
+ struct sfile * sf, int counter, int cg);
+
+#endif /* OPD_MANGLING_H */
View
496 daemon/opd_perfmon.c
@@ -0,0 +1,496 @@
+/**
+ * @file opd_perfmon.c
+ * perfmonctl() handling
+ *
+ * @remark Copyright 2003 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon
+ */
+
+#ifdef __ia64__
+
+/* need this for sched_setaffinity() in <sched.h> */
+#define _GNU_SOURCE
+
+#include "oprofiled.h"
+#include "opd_perfmon.h"
+#include "opd_events.h"
+
+#include "op_cpu_type.h"
+#include "op_libiberty.h"
+#include "op_hw_config.h"
+
+#include <sys/syscall.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#ifdef HAVE_SCHED_SETAFFINITY
+#include <sched.h>
+#endif
+
+extern op_cpu cpu_type;
+
+#ifndef HAVE_SCHED_SETAFFINITY
+
+/* many glibc's are not yet up to date */
+#ifndef __NR_sched_setaffinity
+#define __NR_sched_setaffinity 1231
+#endif
+
+/* Copied from glibc's <sched.h> and <bits/sched.h> and munged */
+#define CPU_SETSIZE 1024
+#define __NCPUBITS (8 * sizeof (unsigned long))
+typedef struct
+{
+ unsigned long __bits[CPU_SETSIZE / __NCPUBITS];
+} cpu_set_t;
+
+#define CPU_SET(cpu, cpusetp) \
+ ((cpusetp)->__bits[(cpu)/__NCPUBITS] |= (1UL << ((cpu) % __NCPUBITS)))
+#define CPU_ZERO(cpusetp) \
+ memset((cpusetp), 0, sizeof(cpu_set_t))
+
+static int
+sched_setaffinity(pid_t pid, size_t len, cpu_set_t const * cpusetp)
+{
+ return syscall(__NR_sched_setaffinity, pid, len, cpusetp);
+}
+#endif
+
+
+#ifndef HAVE_PERFMONCTL
+#ifndef __NR_perfmonctl
+#define __NR_perfmonctl 1175
+#endif
+
+static int perfmonctl(int fd, int cmd, void * arg, int narg)
+{
+ return syscall(__NR_perfmonctl, fd, cmd, arg, narg);
+}
+#endif
+
+
+static unsigned char uuid[16] = {
+ 0x77, 0x7a, 0x6e, 0x61, 0x20, 0x65, 0x73, 0x69,
+ 0x74, 0x6e, 0x72, 0x20, 0x61, 0x65, 0x0a, 0x6c
+};
+
+
+static size_t nr_cpus;
+
+struct child {
+ pid_t pid;
+ int up_pipe[2];
+ int ctx_fd;
+ sig_atomic_t sigusr1;
+ sig_atomic_t sigusr2;
+ sig_atomic_t sigterm;
+};
+
+static struct child * children;
+
+static void perfmon_start_child(int ctx_fd)
+{
+ if (perfmonctl(ctx_fd, PFM_START, 0, 0) == -1) {
+ perror("Couldn't start perfmon: ");
+ exit(EXIT_FAILURE);
+ }
+}
+
+
+static void perfmon_stop_child(int ctx_fd)
+{
+ if (perfmonctl(ctx_fd, PFM_STOP, 0, 0) == -1) {
+ perror("Couldn't stop perfmon: ");
+ exit(EXIT_FAILURE);
+ }
+}
+
+
+static void child_sigusr1(int val __attribute__((unused)))
+{
+ size_t i;
+
+ for (i = 0; i < nr_cpus; ++i) {
+ if (children[i].pid == getpid()) {
+ children[i].sigusr1 = 1;
+ return;
+ }
+ }
+}
+
+
+static void child_sigusr2(int val __attribute__((unused)))
+{
+ size_t i;
+
+ for (i = 0; i < nr_cpus; ++i) {
+ if (children[i].pid == getpid()) {
+ children[i].sigusr2 = 1;
+ return;
+ }
+ }
+}
+
+
+static void child_sigterm(int val __attribute__((unused)))
+{
+ printf("Child received SIGTERM, killing parent.\n");
+ kill(getppid(), SIGTERM);
+}
+
+
+static void set_affinity(size_t cpu)
+{
+ cpu_set_t set;
+
+ CPU_ZERO(&set);
+ CPU_SET(cpu, &set);
+
+ int err = sched_setaffinity(getpid(), sizeof(set), &set);
+
+ if (err == -1) {
+ fprintf(stderr, "Failed to set affinity: %s\n",
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+}
+
+
+static void setup_signals(void)
+{
+ struct sigaction act;
+ sigset_t mask;
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGUSR1);
+ sigaddset(&mask, SIGUSR2);
+ sigprocmask(SIG_BLOCK, &mask, NULL);
+
+ act.sa_handler = child_sigusr1;
+ act.sa_flags = 0;
+ sigemptyset(&act.sa_mask);
+
+ if (sigaction(SIGUSR1, &act, NULL)) {
+ perror("oprofiled: install of SIGUSR1 handler failed: ");
+ exit(EXIT_FAILURE);
+ }
+
+ act.sa_handler = child_sigusr2;
+ act.sa_flags = 0;
+ sigemptyset(&act.sa_mask);
+
+ if (sigaction(SIGUSR2, &act, NULL)) {
+ perror("oprofiled: install of SIGUSR2 handler failed: ");
+ exit(EXIT_FAILURE);
+ }
+
+ act.sa_handler = child_sigterm;
+ act.sa_flags = 0;
+ sigemptyset(&act.sa_mask);
+
+ if (sigaction(SIGTERM, &act, NULL)) {
+ perror("oprofiled: install of SIGTERM handler failed: ");
+ exit(EXIT_FAILURE);
+ }
+}
+
+
+/** create the per-cpu context */
+static void create_context(struct child * self)
+{
+ pfarg_context_t ctx;
+ int err;
+
+ memset(&ctx, 0, sizeof(pfarg_context_t)