├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── Makefile.am ├── Makefile.in ├── README.md ├── SECURITY.md ├── aclocal.m4 ├── autogen.sh ├── autom4te.cache ├── output.0 ├── output.1 ├── requests ├── traces.0 └── traces.1 ├── compile ├── config.guess ├── config.sub ├── configure ├── configure.ac ├── doc ├── Makefile.am ├── Makefile.in └── README.txt ├── flexmalloc-config.h.in ├── install-sh ├── ltmain.sh ├── missing ├── scripts ├── Makefile.am ├── Makefile.in ├── count.sh └── flexmalloc.sh ├── src ├── Makefile.am ├── Makefile.in ├── allocator-memkind-hbwmalloc.cxx ├── allocator-memkind-hbwmalloc.hxx ├── allocator-memkind-pmem.cxx ├── allocator-memkind-pmem.hxx ├── allocator-posix.cxx ├── allocator-posix.hxx ├── allocator-statistics.cxx ├── allocator-statistics.hxx ├── allocator.cxx ├── allocator.hxx ├── allocators.cxx ├── allocators.hxx ├── bfd-manager.cxx ├── bfd-manager.hxx ├── cache-callstack.cxx ├── cache-callstack.hxx ├── code-locations.cxx ├── code-locations.hxx ├── common.cxx ├── common.hxx ├── counter.cxx ├── flex-malloc.cxx ├── flex-malloc.hxx ├── malloc-interposer.cxx ├── utils.cxx └── utils.hxx └── tests ├── Makefile.am ├── Makefile.in ├── base-memory-configuration ├── libtester.c ├── libtester.h ├── malloc+free-libtester-locations ├── malloc+free-libtester.c ├── malloc+free-locations ├── malloc+free.c ├── malloc+realloc.c ├── multiple-tests.c ├── posix_memalign+realloc.c └── realloc.c /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, caste, color, religion, or sexual 10 | identity and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the overall 26 | community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or advances of 31 | any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email address, 35 | without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | CommunityCodeOfConduct AT intel DOT com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series of 86 | actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or permanent 93 | ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within the 113 | community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.1, available at 119 | [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. 120 | 121 | Community Impact Guidelines were inspired by 122 | [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. 123 | 124 | For answers to common questions about this code of conduct, see the FAQ at 125 | [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at 126 | [https://www.contributor-covenant.org/translations][translations]. 127 | 128 | [homepage]: https://www.contributor-covenant.org 129 | [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html 130 | [Mozilla CoC]: https://github.com/mozilla/diversity 131 | [FAQ]: https://www.contributor-covenant.org/faq 132 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | ### License 4 | 5 | Double-Batched FFT Library is licensed under the terms in [LICENSE](LICENSE.md). By contributing to the project, you agree to the license and copyright terms therein and release your contribution under these terms. 6 | 7 | ### Sign your work 8 | 9 | Please use the sign-off line at the end of the patch. Your signature certifies that you wrote the patch or otherwise have the right to pass it on as an open-source patch. The rules are pretty simple: if you can certify 10 | the below (from [developercertificate.org](http://developercertificate.org/)): 11 | 12 | ``` 13 | Developer Certificate of Origin 14 | Version 1.1 15 | 16 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 17 | 660 York Street, Suite 102, 18 | San Francisco, CA 94110 USA 19 | 20 | Everyone is permitted to copy and distribute verbatim copies of this 21 | license document, but changing it is not allowed. 22 | 23 | Developer's Certificate of Origin 1.1 24 | 25 | By making a contribution to this project, I certify that: 26 | 27 | (a) The contribution was created in whole or in part by me and I 28 | have the right to submit it under the open source license 29 | indicated in the file; or 30 | 31 | (b) The contribution is based upon previous work that, to the best 32 | of my knowledge, is covered under an appropriate open source 33 | license and I have the right under that license to submit that 34 | work with modifications, whether created in whole or in part 35 | by me, under the same open source license (unless I am 36 | permitted to submit under a different license), as indicated 37 | in the file; or 38 | 39 | (c) The contribution was provided directly to me by some other 40 | person who certified (a), (b) or (c) and I have not modified 41 | it. 42 | 43 | (d) I understand and agree that this project and the contribution 44 | are public and that a record of the contribution (including all 45 | personal information I submit with it, including my sign-off) is 46 | maintained indefinitely and may be redistributed consistent with 47 | this project or the open source license(s) involved. 48 | ``` 49 | 50 | Then you just add a line to every git commit message: 51 | 52 | Signed-off-by: Joe Smith 53 | 54 | Use your real name (sorry, no pseudonyms or anonymous contributions.) 55 | 56 | If you set your `user.name` and `user.email` git configs, you can sign your 57 | commit automatically with `git commit -s`. 58 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2022, Intel Sandbox 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS = foreign 2 | SUBDIRS = src tests doc scripts 3 | 4 | EXTRA_DIST = autogen.sh configure.ac 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Flexible Memory Allocation Tool 4 | Flexible Memory Allocation Tool for multi-tiered memory systems 5 | 6 | ## Table of contents 7 | 8 | + [What is the Flexible Memory Allocation Tool?](#what-is-the-flexible-memory-allocation-tool) 9 | + [Requirements](#requirements) 10 | + [Status](#status) 11 | + [Building the tool](#building-the-tool) 12 | + [Using the tool](#using-the-tool) 13 | + [Environment variables](#environment-variables) 14 | + [Copyrights](#copyrights) 15 | 16 | ## What is the Flexible Memory Allocation Tool? 17 | The Flexible Memory Allocation Tool is an interposition library that allocates dynamic-memory objects into designated memory systems on a multi-tiered memory system based on a user-given configuration without having to alter the application binary. 18 | This tool takes two inputs: 19 | 1. Definition of the memory tiers and their respective allocators (e.g. various flavors of memkind) 20 | 2. Code-locations of dynamic allocations that are forwarded to specific allocators 21 | 22 | ## Requirements 23 | 24 | * Linux OS 25 | * C++ compiler (g++ 4.8 will do) 26 | * Optionally: 27 | * [binutils](https://www.gnu.org/software/binutils) - to enable human-readable call-stack matching 28 | * [Memkind](https://github.com/memkind/memkind) - to enable promoting memory allocations to Memkind handled memory (e.g. Intel Optane Persistent Memory or HBM) 29 | * [PMDK](https://github.com/pmem/pmdk) - takes advantage of fast pmem_copy routines 30 | * [PAPI](http://icl.utk.edu/papi/software) - collect some performance metrics 31 | 32 | ## Status 33 | 34 | ## Building the tool 35 | 36 | Create a build directory 37 | ``` 38 | mkdir build 39 | ``` 40 | Go inside that build directory 41 | ``` 42 | cd build 43 | ``` 44 | 45 | Issue the configure 46 | ``` 47 | ../configure --prefix=INSTALL_DIR --with-memkind=MEMKIND_DIR --with-pmdk=PMDK_DIR 48 | ``` 49 | and adapt the respective DIRectories to fit your installation. Ensure that you have permissions to install in `INSTALL_DIR`. 50 | 51 | Compile and install 52 | ``` 53 | make && make install 54 | ``` 55 | 56 | ## Using the tool 57 | 58 | To use the tool, you need to prepare two configuration files. 59 | 1. Memory definitions: This file refers to a list of the available memory tiers/subsystems in the machine. For instance, a base configuration for a DRAM-only system (handled by regular posix calls) and with a limit of 4 GB per process would look like: 60 | ``` 61 | $ cat base-memory-configuration 62 | # Memory configuration for allocator posix 63 | Size 4096 MBytes 64 | ``` 65 | The following configuration file is for a heterogeneous memory system composed by Intel Optane Persistent Memory (handled by memkind) and DRAM (limited to 1GB per process). In this scenario, the `memkind/pmem` allocator specifies one mount point per socket. 66 | ``` 67 | # Memory configuration for allocator posix 68 | Size 1024 Mbytes 69 | # Memory configuration for allocator memkind/pmem 70 | @ /mnt/pmem0 @ /mnt/pmem1 71 | ``` 72 | 73 | 2. Memory locations: This file refers to a list of pairs composed by call-stacks and the memory tier where the data object shall be allocated. The call-stacks are defined by a sequence of code locations identified by pairs of `file:line` number. For instance, the following allocations file would forward allocations found in lines 252, 253, and 254 in stream-manymallocs.c and invoked from line 342 on libc-start to the posix memory allocator. 74 | ``` 75 | $ cat stream-manymallocs-locations 76 | # Memory configuration with size 0 bytes on allocator posix 77 | # This is an example. The format is, one line per call-stack, on each line the complete call-stack 78 | # e.g. file1.c:line1 > file2.c:line2 > file3.c:line3 ... > fileN.c:lineN 79 | stream-manymallocs.c:252 > libc-start.c:342 @ posix 80 | stream-manymallocs.c:253 > libc-start.c:342 @ posix 81 | stream-manymallocs.c:254 > libc-start.c:342 @ posix 82 | ``` 83 | 84 | Once you have the configuration files, issue: 85 | ``` 86 | $INSTALL_DIR/bin/flexmalloc.sh memory-definitions.cfg memory-locations.cfg 87 | ``` 88 | where `binary and params` refers to the binary to be executed and the parameters being passed to that execution. 89 | 90 | ## Environment variables 91 | 92 | ## Copyrights 93 | 94 | © 2024 Harald Servat, Intel Corporation 95 | 96 | Intel is a trademark of Intel Corporation or its subsidiaries. 97 | 98 | \* Other names and brands may be claimed as the property of others. 99 | 100 | We welcome anyone interested in using, developing or contributing in Flexible Memory Tool! 101 | 102 | Go to [top](#top) 103 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | autoreconf -fvi 4 | -------------------------------------------------------------------------------- /autom4te.cache/requests: -------------------------------------------------------------------------------- 1 | # This file was generated. 2 | # It contains the lists of macros which have been traced. 3 | # It can be safely removed. 4 | 5 | @request = ( 6 | bless( [ 7 | '0', 8 | 1, 9 | [ 10 | '/usr/share/autoconf' 11 | ], 12 | [ 13 | '/usr/share/autoconf/autoconf/autoconf.m4f', 14 | '-', 15 | '/usr/share/aclocal-1.16/internal/ac-config-macro-dirs.m4', 16 | '/usr/share/aclocal/libtool.m4', 17 | '/usr/share/aclocal/ltargz.m4', 18 | '/usr/share/aclocal/ltdl.m4', 19 | '/usr/share/aclocal/ltoptions.m4', 20 | '/usr/share/aclocal/ltsugar.m4', 21 | '/usr/share/aclocal/ltversion.m4', 22 | '/usr/share/aclocal/lt~obsolete.m4', 23 | '/usr/share/aclocal-1.16/amversion.m4', 24 | '/usr/share/aclocal-1.16/as.m4', 25 | '/usr/share/aclocal-1.16/auxdir.m4', 26 | '/usr/share/aclocal-1.16/cond.m4', 27 | '/usr/share/aclocal-1.16/depend.m4', 28 | '/usr/share/aclocal-1.16/depout.m4', 29 | '/usr/share/aclocal-1.16/init.m4', 30 | '/usr/share/aclocal-1.16/install-sh.m4', 31 | '/usr/share/aclocal-1.16/lead-dot.m4', 32 | '/usr/share/aclocal-1.16/make.m4', 33 | '/usr/share/aclocal-1.16/missing.m4', 34 | '/usr/share/aclocal-1.16/options.m4', 35 | '/usr/share/aclocal-1.16/prog-cc-c-o.m4', 36 | '/usr/share/aclocal-1.16/runlog.m4', 37 | '/usr/share/aclocal-1.16/sanity.m4', 38 | '/usr/share/aclocal-1.16/silent.m4', 39 | '/usr/share/aclocal-1.16/strip.m4', 40 | '/usr/share/aclocal-1.16/substnot.m4', 41 | '/usr/share/aclocal-1.16/tar.m4', 42 | 'configure.ac' 43 | ], 44 | { 45 | 'LT_FUNC_ARGZ' => 1, 46 | 'AC_LTDL_SYMBOL_USCORE' => 1, 47 | 'AC_CHECK_LIBM' => 1, 48 | 'AC_ENABLE_FAST_INSTALL' => 1, 49 | 'AC_LIBTOOL_SYS_HARD_LINK_LOCKS' => 1, 50 | '_AM_SET_OPTION' => 1, 51 | '_AM_OUTPUT_DEPENDENCY_COMMANDS' => 1, 52 | 'm4_include' => 1, 53 | '_LT_PROG_CXX' => 1, 54 | '_AM_MANGLE_OPTION' => 1, 55 | '_AM_PROG_TAR' => 1, 56 | '_LT_LINKER_OPTION' => 1, 57 | 'AC_LTDL_SHLIBPATH' => 1, 58 | 'AM_ENABLE_STATIC' => 1, 59 | 'AC_DISABLE_STATIC' => 1, 60 | 'LT_AC_PROG_EGREP' => 1, 61 | '_LT_AC_SHELL_INIT' => 1, 62 | '_LT_COMPILER_BOILERPLATE' => 1, 63 | 'AC_PROG_LD' => 1, 64 | 'AC_LIBTOOL_SYS_DYNAMIC_LINKER' => 1, 65 | 'AM_INIT_AUTOMAKE' => 1, 66 | 'AC_DEFUN_ONCE' => 1, 67 | 'AM_SUBST_NOTMAKE' => 1, 68 | 'AM_SILENT_RULES' => 1, 69 | 'LT_LANG' => 1, 70 | 'AM_MAKE_INCLUDE' => 1, 71 | 'AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH' => 1, 72 | '_LT_AC_LANG_GCJ' => 1, 73 | 'AC_LIBTOOL_LANG_RC_CONFIG' => 1, 74 | '_AM_IF_OPTION' => 1, 75 | '_LT_PROG_FC' => 1, 76 | '_LT_REQUIRED_DARWIN_CHECKS' => 1, 77 | 'LT_FUNC_DLSYM_USCORE' => 1, 78 | 'LT_INIT' => 1, 79 | 'LTDL_CONVENIENCE' => 1, 80 | 'LT_AC_PROG_SED' => 1, 81 | '_LT_AC_LANG_CXX' => 1, 82 | 'AC_LIBTOOL_F77' => 1, 83 | 'm4_pattern_forbid' => 1, 84 | '_LT_AC_LOCK' => 1, 85 | '_AC_PROG_LIBTOOL' => 1, 86 | '_LT_LIBOBJ' => 1, 87 | '_LT_AC_LANG_F77_CONFIG' => 1, 88 | 'AC_LIBTOOL_WIN32_DLL' => 1, 89 | 'AC_LIBLTDL_INSTALLABLE' => 1, 90 | 'AC_LTDL_DLSYM_USCORE' => 1, 91 | '_AC_AM_CONFIG_HEADER_HOOK' => 1, 92 | 'AM_PROG_CC_C_O' => 1, 93 | '_LT_PROG_ECHO_BACKSLASH' => 1, 94 | 'AC_LTDL_OBJDIR' => 1, 95 | 'AC_LIBTOOL_PROG_COMPILER_NO_RTTI' => 1, 96 | '_LT_DLL_DEF_P' => 1, 97 | 'AC_LIBTOOL_DLOPEN' => 1, 98 | 'AC_LTDL_SHLIBEXT' => 1, 99 | 'AC_LIBTOOL_LANG_CXX_CONFIG' => 1, 100 | '_LT_AC_SYS_LIBPATH_AIX' => 1, 101 | '_LT_AC_LANG_RC_CONFIG' => 1, 102 | 'LT_CMD_MAX_LEN' => 1, 103 | '_AM_SET_OPTIONS' => 1, 104 | 'AC_ENABLE_STATIC' => 1, 105 | 'AM_DISABLE_STATIC' => 1, 106 | 'AC_PATH_MAGIC' => 1, 107 | 'LT_AC_PROG_GCJ' => 1, 108 | 'AM_PROG_LD' => 1, 109 | '_LT_LINKER_BOILERPLATE' => 1, 110 | 'LTSUGAR_VERSION' => 1, 111 | 'AM_SET_CURRENT_AUTOMAKE_VERSION' => 1, 112 | 'LT_PATH_LD' => 1, 113 | 'LTDL_INSTALLABLE' => 1, 114 | 'LT_LIB_M' => 1, 115 | '_LT_AC_TAGVAR' => 1, 116 | '_AM_PROG_CC_C_O' => 1, 117 | '_LT_AC_TAGCONFIG' => 1, 118 | 'AM_PROG_INSTALL_STRIP' => 1, 119 | '_LT_AC_FILE_LTDLL_C' => 1, 120 | 'LT_PROG_GCJ' => 1, 121 | 'LT_AC_PROG_RC' => 1, 122 | 'LTVERSION_VERSION' => 1, 123 | 'AC_LIBTOOL_PROG_CC_C_O' => 1, 124 | '_LT_AC_PROG_ECHO_BACKSLASH' => 1, 125 | 'AC_LIBTOOL_SETUP' => 1, 126 | 'AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE' => 1, 127 | '_LT_AC_LANG_F77' => 1, 128 | 'LT_SYS_MODULE_PATH' => 1, 129 | 'AM_PROG_AS' => 1, 130 | 'AM_SET_LEADING_DOT' => 1, 131 | 'LT_SYS_DLOPEN_SELF' => 1, 132 | 'AU_DEFUN' => 1, 133 | 'AC_LIBTOOL_CXX' => 1, 134 | 'AC_LTDL_DLLIB' => 1, 135 | '_AM_DEPENDENCIES' => 1, 136 | '_AM_AUTOCONF_VERSION' => 1, 137 | 'AC_LIB_LTDL' => 1, 138 | 'AM_MISSING_HAS_RUN' => 1, 139 | 'AM_CONDITIONAL' => 1, 140 | 'LT_CONFIG_LTDL_DIR' => 1, 141 | 'LT_SYS_DLOPEN_DEPLIBS' => 1, 142 | 'AC_DEPLIBS_CHECK_METHOD' => 1, 143 | 'AC_DISABLE_SHARED' => 1, 144 | 'include' => 1, 145 | '_LT_AC_CHECK_DLFCN' => 1, 146 | '_LT_WITH_SYSROOT' => 1, 147 | '_AM_SUBST_NOTMAKE' => 1, 148 | 'AM_RUN_LOG' => 1, 149 | 'AC_LIBTOOL_CONFIG' => 1, 150 | 'AC_LIBTOOL_OBJDIR' => 1, 151 | 'AC_LIBTOOL_DLOPEN_SELF' => 1, 152 | 'AC_LTDL_ENABLE_INSTALL' => 1, 153 | 'AC_LIBTOOL_SYS_LIB_STRIP' => 1, 154 | 'AC_LTDL_SYS_DLOPEN_DEPLIBS' => 1, 155 | '_LTDL_SETUP' => 1, 156 | 'AM_PROG_INSTALL_SH' => 1, 157 | 'AC_PROG_EGREP' => 1, 158 | 'AC_PATH_TOOL_PREFIX' => 1, 159 | 'AC_LIBTOOL_LANG_C_CONFIG' => 1, 160 | 'AC_LIBTOOL_PICMODE' => 1, 161 | 'LT_SYS_MODULE_EXT' => 1, 162 | '_AM_CONFIG_MACRO_DIRS' => 1, 163 | 'LT_PROG_RC' => 1, 164 | 'AC_LIBTOOL_SYS_MAX_CMD_LEN' => 1, 165 | 'LTOPTIONS_VERSION' => 1, 166 | 'AC_PROG_LIBTOOL' => 1, 167 | 'AM_ENABLE_SHARED' => 1, 168 | '_LT_PROG_F77' => 1, 169 | 'AC_LIBTOOL_PROG_COMPILER_PIC' => 1, 170 | 'AC_PROG_NM' => 1, 171 | 'AC_LIBTOOL_COMPILER_OPTION' => 1, 172 | 'AC_LIBTOOL_PROG_LD_SHLIBS' => 1, 173 | 'AM_DEP_TRACK' => 1, 174 | '_LT_CC_BASENAME' => 1, 175 | 'AM_OUTPUT_DEPENDENCY_COMMANDS' => 1, 176 | '_LT_PATH_TOOL_PREFIX' => 1, 177 | 'AC_LIBTOOL_LINKER_OPTION' => 1, 178 | '_LT_PREPARE_SED_QUOTE_VARS' => 1, 179 | 'LT_SUPPORTED_TAG' => 1, 180 | 'AC_CONFIG_MACRO_DIR' => 1, 181 | '_LT_AC_SYS_COMPILER' => 1, 182 | 'AC_LIBTOOL_RC' => 1, 183 | 'm4_pattern_allow' => 1, 184 | 'LT_SYS_SYMBOL_USCORE' => 1, 185 | 'AC_LTDL_SYSSEARCHPATH' => 1, 186 | 'AC_LIBTOOL_POSTDEP_PREDEP' => 1, 187 | 'AM_AUTOMAKE_VERSION' => 1, 188 | 'AM_SANITY_CHECK' => 1, 189 | 'LT_PATH_NM' => 1, 190 | 'AC_LIBTOOL_LANG_F77_CONFIG' => 1, 191 | 'AC_LIBLTDL_CONVENIENCE' => 1, 192 | 'AM_DISABLE_SHARED' => 1, 193 | 'AC_DISABLE_FAST_INSTALL' => 1, 194 | 'LT_LIB_DLLOAD' => 1, 195 | 'AC_LTDL_PREOPEN' => 1, 196 | 'LT_OUTPUT' => 1, 197 | 'AC_CONFIG_MACRO_DIR_TRACE' => 1, 198 | 'AM_AUX_DIR_EXPAND' => 1, 199 | '_LT_AC_LANG_C_CONFIG' => 1, 200 | 'AC_PROG_LD_GNU' => 1, 201 | 'AC_WITH_LTDL' => 1, 202 | '_LT_AC_PROG_CXXCPP' => 1, 203 | 'LT_WITH_LTDL' => 1, 204 | 'AC_LIBTOOL_LANG_GCJ_CONFIG' => 1, 205 | 'AC_LIBTOOL_GCJ' => 1, 206 | 'AM_SET_DEPDIR' => 1, 207 | '_LT_AC_LANG_GCJ_CONFIG' => 1, 208 | '_LT_PROG_LTMAIN' => 1, 209 | '_LT_COMPILER_OPTION' => 1, 210 | 'AC_DEFUN' => 1, 211 | '_m4_warn' => 1, 212 | 'AC_LIBTOOL_SYS_OLD_ARCHIVE' => 1, 213 | 'AC_LIBTOOL_FC' => 1, 214 | 'LTOBSOLETE_VERSION' => 1, 215 | 'AM_MISSING_PROG' => 1, 216 | 'LT_PROG_GO' => 1, 217 | 'AM_PROG_LIBTOOL' => 1, 218 | 'LT_SYS_DLSEARCH_PATH' => 1, 219 | 'AC_ENABLE_SHARED' => 1, 220 | 'AM_PROG_NM' => 1, 221 | '_LT_AC_LANG_CXX_CONFIG' => 1, 222 | 'AC_PROG_LD_RELOAD_FLAG' => 1, 223 | '_LT_AC_TRY_DLOPEN_SELF' => 1, 224 | 'LTDL_INIT' => 1 225 | } 226 | ], 'Autom4te::Request' ), 227 | bless( [ 228 | '1', 229 | 1, 230 | [ 231 | '/usr/share/autoconf' 232 | ], 233 | [ 234 | '/usr/share/autoconf/autoconf/autoconf.m4f', 235 | 'aclocal.m4', 236 | 'configure.ac' 237 | ], 238 | { 239 | 'm4_pattern_forbid' => 1, 240 | 'AC_FC_PP_DEFINE' => 1, 241 | 'AM_MAINTAINER_MODE' => 1, 242 | 'AC_DEFINE_TRACE_LITERAL' => 1, 243 | 'AC_CONFIG_AUX_DIR' => 1, 244 | 'AC_CANONICAL_TARGET' => 1, 245 | 'm4_sinclude' => 1, 246 | 'AC_CANONICAL_SYSTEM' => 1, 247 | 'LT_INIT' => 1, 248 | 'AM_PROG_FC_C_O' => 1, 249 | 'AM_EXTRA_RECURSIVE_TARGETS' => 1, 250 | 'AC_PROG_LIBTOOL' => 1, 251 | 'AC_INIT' => 1, 252 | '_LT_AC_TAGCONFIG' => 1, 253 | '_m4_warn' => 1, 254 | 'AM_XGETTEXT_OPTION' => 1, 255 | 'AC_CONFIG_FILES' => 1, 256 | 'AC_CANONICAL_HOST' => 1, 257 | 'AM_PROG_AR' => 1, 258 | 'AM_PROG_CXX_C_O' => 1, 259 | 'AC_CONFIG_SUBDIRS' => 1, 260 | 'AC_REQUIRE_AUX_FILE' => 1, 261 | 'AC_CONFIG_LINKS' => 1, 262 | '_AM_COND_ELSE' => 1, 263 | 'AM_SILENT_RULES' => 1, 264 | 'AC_SUBST_TRACE' => 1, 265 | 'AM_PATH_GUILE' => 1, 266 | 'AC_FC_PP_SRCEXT' => 1, 267 | 'AM_POT_TOOLS' => 1, 268 | 'AM_PROG_MOC' => 1, 269 | 'AC_FC_FREEFORM' => 1, 270 | 'AM_INIT_AUTOMAKE' => 1, 271 | 'AC_CONFIG_HEADERS' => 1, 272 | 'AM_PROG_F77_C_O' => 1, 273 | '_AM_COND_IF' => 1, 274 | 'AC_CANONICAL_BUILD' => 1, 275 | '_AM_SUBST_NOTMAKE' => 1, 276 | 'AM_ENABLE_MULTILIB' => 1, 277 | 'AM_PROG_MKDIR_P' => 1, 278 | 'include' => 1, 279 | 'AM_MAKEFILE_INCLUDE' => 1, 280 | 'AH_OUTPUT' => 1, 281 | 'LT_CONFIG_LTDL_DIR' => 1, 282 | 'AM_CONDITIONAL' => 1, 283 | 'AC_SUBST' => 1, 284 | 'AM_GNU_GETTEXT_INTL_SUBDIR' => 1, 285 | 'm4_include' => 1, 286 | 'AM_GNU_GETTEXT' => 1, 287 | 'AM_PROG_CC_C_O' => 1, 288 | 'AM_AUTOMAKE_VERSION' => 1, 289 | 'sinclude' => 1, 290 | 'AC_LIBSOURCE' => 1, 291 | 'm4_pattern_allow' => 1, 292 | 'AC_FC_SRCEXT' => 1, 293 | 'LT_SUPPORTED_TAG' => 1, 294 | '_AM_MAKEFILE_INCLUDE' => 1, 295 | 'AC_CONFIG_LIBOBJ_DIR' => 1, 296 | '_AM_COND_ENDIF' => 1, 297 | 'AM_NLS' => 1 298 | } 299 | ], 'Autom4te::Request' ) 300 | ); 301 | 302 | -------------------------------------------------------------------------------- /compile: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Wrapper for compilers which do not understand '-c -o'. 3 | 4 | scriptversion=2018-03-07.03; # UTC 5 | 6 | # Copyright (C) 1999-2018 Free Software Foundation, Inc. 7 | # Written by Tom Tromey . 8 | # 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2, or (at your option) 12 | # any later version. 13 | # 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | # As a special exception to the GNU General Public License, if you 23 | # distribute this file as part of a program that contains a 24 | # configuration script generated by Autoconf, you may include it under 25 | # the same distribution terms that you use for the rest of that program. 26 | 27 | # This file is maintained in Automake, please report 28 | # bugs to or send patches to 29 | # . 30 | 31 | nl=' 32 | ' 33 | 34 | # We need space, tab and new line, in precisely that order. Quoting is 35 | # there to prevent tools from complaining about whitespace usage. 36 | IFS=" "" $nl" 37 | 38 | file_conv= 39 | 40 | # func_file_conv build_file lazy 41 | # Convert a $build file to $host form and store it in $file 42 | # Currently only supports Windows hosts. If the determined conversion 43 | # type is listed in (the comma separated) LAZY, no conversion will 44 | # take place. 45 | func_file_conv () 46 | { 47 | file=$1 48 | case $file in 49 | / | /[!/]*) # absolute file, and not a UNC file 50 | if test -z "$file_conv"; then 51 | # lazily determine how to convert abs files 52 | case `uname -s` in 53 | MINGW*) 54 | file_conv=mingw 55 | ;; 56 | CYGWIN*) 57 | file_conv=cygwin 58 | ;; 59 | *) 60 | file_conv=wine 61 | ;; 62 | esac 63 | fi 64 | case $file_conv/,$2, in 65 | *,$file_conv,*) 66 | ;; 67 | mingw/*) 68 | file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` 69 | ;; 70 | cygwin/*) 71 | file=`cygpath -m "$file" || echo "$file"` 72 | ;; 73 | wine/*) 74 | file=`winepath -w "$file" || echo "$file"` 75 | ;; 76 | esac 77 | ;; 78 | esac 79 | } 80 | 81 | # func_cl_dashL linkdir 82 | # Make cl look for libraries in LINKDIR 83 | func_cl_dashL () 84 | { 85 | func_file_conv "$1" 86 | if test -z "$lib_path"; then 87 | lib_path=$file 88 | else 89 | lib_path="$lib_path;$file" 90 | fi 91 | linker_opts="$linker_opts -LIBPATH:$file" 92 | } 93 | 94 | # func_cl_dashl library 95 | # Do a library search-path lookup for cl 96 | func_cl_dashl () 97 | { 98 | lib=$1 99 | found=no 100 | save_IFS=$IFS 101 | IFS=';' 102 | for dir in $lib_path $LIB 103 | do 104 | IFS=$save_IFS 105 | if $shared && test -f "$dir/$lib.dll.lib"; then 106 | found=yes 107 | lib=$dir/$lib.dll.lib 108 | break 109 | fi 110 | if test -f "$dir/$lib.lib"; then 111 | found=yes 112 | lib=$dir/$lib.lib 113 | break 114 | fi 115 | if test -f "$dir/lib$lib.a"; then 116 | found=yes 117 | lib=$dir/lib$lib.a 118 | break 119 | fi 120 | done 121 | IFS=$save_IFS 122 | 123 | if test "$found" != yes; then 124 | lib=$lib.lib 125 | fi 126 | } 127 | 128 | # func_cl_wrapper cl arg... 129 | # Adjust compile command to suit cl 130 | func_cl_wrapper () 131 | { 132 | # Assume a capable shell 133 | lib_path= 134 | shared=: 135 | linker_opts= 136 | for arg 137 | do 138 | if test -n "$eat"; then 139 | eat= 140 | else 141 | case $1 in 142 | -o) 143 | # configure might choose to run compile as 'compile cc -o foo foo.c'. 144 | eat=1 145 | case $2 in 146 | *.o | *.[oO][bB][jJ]) 147 | func_file_conv "$2" 148 | set x "$@" -Fo"$file" 149 | shift 150 | ;; 151 | *) 152 | func_file_conv "$2" 153 | set x "$@" -Fe"$file" 154 | shift 155 | ;; 156 | esac 157 | ;; 158 | -I) 159 | eat=1 160 | func_file_conv "$2" mingw 161 | set x "$@" -I"$file" 162 | shift 163 | ;; 164 | -I*) 165 | func_file_conv "${1#-I}" mingw 166 | set x "$@" -I"$file" 167 | shift 168 | ;; 169 | -l) 170 | eat=1 171 | func_cl_dashl "$2" 172 | set x "$@" "$lib" 173 | shift 174 | ;; 175 | -l*) 176 | func_cl_dashl "${1#-l}" 177 | set x "$@" "$lib" 178 | shift 179 | ;; 180 | -L) 181 | eat=1 182 | func_cl_dashL "$2" 183 | ;; 184 | -L*) 185 | func_cl_dashL "${1#-L}" 186 | ;; 187 | -static) 188 | shared=false 189 | ;; 190 | -Wl,*) 191 | arg=${1#-Wl,} 192 | save_ifs="$IFS"; IFS=',' 193 | for flag in $arg; do 194 | IFS="$save_ifs" 195 | linker_opts="$linker_opts $flag" 196 | done 197 | IFS="$save_ifs" 198 | ;; 199 | -Xlinker) 200 | eat=1 201 | linker_opts="$linker_opts $2" 202 | ;; 203 | -*) 204 | set x "$@" "$1" 205 | shift 206 | ;; 207 | *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) 208 | func_file_conv "$1" 209 | set x "$@" -Tp"$file" 210 | shift 211 | ;; 212 | *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) 213 | func_file_conv "$1" mingw 214 | set x "$@" "$file" 215 | shift 216 | ;; 217 | *) 218 | set x "$@" "$1" 219 | shift 220 | ;; 221 | esac 222 | fi 223 | shift 224 | done 225 | if test -n "$linker_opts"; then 226 | linker_opts="-link$linker_opts" 227 | fi 228 | exec "$@" $linker_opts 229 | exit 1 230 | } 231 | 232 | eat= 233 | 234 | case $1 in 235 | '') 236 | echo "$0: No command. Try '$0 --help' for more information." 1>&2 237 | exit 1; 238 | ;; 239 | -h | --h*) 240 | cat <<\EOF 241 | Usage: compile [--help] [--version] PROGRAM [ARGS] 242 | 243 | Wrapper for compilers which do not understand '-c -o'. 244 | Remove '-o dest.o' from ARGS, run PROGRAM with the remaining 245 | arguments, and rename the output as expected. 246 | 247 | If you are trying to build a whole package this is not the 248 | right script to run: please start by reading the file 'INSTALL'. 249 | 250 | Report bugs to . 251 | EOF 252 | exit $? 253 | ;; 254 | -v | --v*) 255 | echo "compile $scriptversion" 256 | exit $? 257 | ;; 258 | cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ 259 | icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) 260 | func_cl_wrapper "$@" # Doesn't return... 261 | ;; 262 | esac 263 | 264 | ofile= 265 | cfile= 266 | 267 | for arg 268 | do 269 | if test -n "$eat"; then 270 | eat= 271 | else 272 | case $1 in 273 | -o) 274 | # configure might choose to run compile as 'compile cc -o foo foo.c'. 275 | # So we strip '-o arg' only if arg is an object. 276 | eat=1 277 | case $2 in 278 | *.o | *.obj) 279 | ofile=$2 280 | ;; 281 | *) 282 | set x "$@" -o "$2" 283 | shift 284 | ;; 285 | esac 286 | ;; 287 | *.c) 288 | cfile=$1 289 | set x "$@" "$1" 290 | shift 291 | ;; 292 | *) 293 | set x "$@" "$1" 294 | shift 295 | ;; 296 | esac 297 | fi 298 | shift 299 | done 300 | 301 | if test -z "$ofile" || test -z "$cfile"; then 302 | # If no '-o' option was seen then we might have been invoked from a 303 | # pattern rule where we don't need one. That is ok -- this is a 304 | # normal compilation that the losing compiler can handle. If no 305 | # '.c' file was seen then we are probably linking. That is also 306 | # ok. 307 | exec "$@" 308 | fi 309 | 310 | # Name of file we expect compiler to create. 311 | cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` 312 | 313 | # Create the lock directory. 314 | # Note: use '[/\\:.-]' here to ensure that we don't use the same name 315 | # that we are using for the .o file. Also, base the name on the expected 316 | # object file name, since that is what matters with a parallel build. 317 | lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d 318 | while true; do 319 | if mkdir "$lockdir" >/dev/null 2>&1; then 320 | break 321 | fi 322 | sleep 1 323 | done 324 | # FIXME: race condition here if user kills between mkdir and trap. 325 | trap "rmdir '$lockdir'; exit 1" 1 2 15 326 | 327 | # Run the compile. 328 | "$@" 329 | ret=$? 330 | 331 | if test -f "$cofile"; then 332 | test "$cofile" = "$ofile" || mv "$cofile" "$ofile" 333 | elif test -f "${cofile}bj"; then 334 | test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" 335 | fi 336 | 337 | rmdir "$lockdir" 338 | exit $ret 339 | 340 | # Local Variables: 341 | # mode: shell-script 342 | # sh-indentation: 2 343 | # eval: (add-hook 'before-save-hook 'time-stamp) 344 | # time-stamp-start: "scriptversion=" 345 | # time-stamp-format: "%:y-%02m-%02d.%02H" 346 | # time-stamp-time-zone: "UTC0" 347 | # time-stamp-end: "; # UTC" 348 | # End: 349 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT(flexmalloc, 0.2.2, harald.servat@intel.com) 2 | AM_INIT_AUTOMAKE([tar-ustar no-dependencies]) 3 | AM_SILENT_RULES([yes]) 4 | 5 | AC_CONFIG_HEADERS([flexmalloc-config.h]) 6 | 7 | LT_INIT([dlopen,shared,pic,disable-static]) 8 | 9 | AC_PROG_CC 10 | AC_PROG_CXX 11 | AM_PROG_AS 12 | 13 | which dpkg-architecture &> /dev/null 14 | if test "$?" -eq "0"; then 15 | if test "${Selected_Binary_Type}" = "default" ; then 16 | AC_MSG_CHECKING([the multiarch triplet through dpkg-architecture]) 17 | multiarch_triplet=$(dpkg-architecture -qDEB_HOST_MULTIARCH) 18 | AC_MSG_RESULT([$multiarch_triplet]) 19 | fi 20 | else 21 | AC_MSG_NOTICE([cannot locate multiarch triplet]) 22 | fi 23 | 24 | 25 | AC_ARG_WITH([binutils], 26 | [AS_HELP_STRING([--with-binutils=DIR], 27 | [Support for binutils installed in DIR - search by default in /usr])], 28 | [], 29 | [with_binutils="/usr"]) 30 | if test "${with_binutils}" = "no"; then 31 | AC_MSG_FAILURE([--with-binutils= is needed!]) 32 | else 33 | if test -r "${with_binutils}/include/bfd.h"; then 34 | if test -r "${with_binutils}/lib/libbfd.so" -o "${with_binutils}/lib/${multiarch_triplet}/libbfd.so"; then 35 | if test -r "${with_binutils}/lib/libiberty." -o "${with_binutils}/lib/${multiarch_triplet}/libiberty.a"; then 36 | BINUTILS_HOME=${with_binutils} 37 | AC_SUBST(BINUTILS_HOME) 38 | else 39 | AC_MSG_FAILURE([Cannot find libiberty.a within given binutils DIR]) 40 | fi 41 | else 42 | AC_MSG_FAILURE([Cannot find libbfd.so within given binutils DIR]) 43 | fi 44 | else 45 | AC_MSG_FAILURE([Cannot find bfd.h within given binutils DIR]) 46 | fi 47 | fi 48 | 49 | AC_ARG_WITH([memkind], 50 | [AS_HELP_STRING([--with-memkind=DIR], 51 | [Support for memkind installed in DIR])], 52 | [], 53 | [with_memkind="no"]) 54 | if test "${with_memkind}" != "no"; then 55 | if test -x "${with_memkind}/bin/memkind-hbw-nodes" ; then 56 | if test -r "${with_memkind}/lib/libmemkind.so" -o -r "${with_memkind}/lib/${multiarch_triplet}/libmemkind.so" ; then 57 | if test -r "${with_memkind}/include/memkind.h" -a -r "${with_memkind}/include/hbwmalloc.h"; then 58 | MEMKIND_SUPPORT="yes" 59 | AC_DEFINE([MEMKIND_SUPPORTED], [1], [Defined if Memkind is available]) 60 | MEMKIND_HOME=${with_memkind} 61 | AC_SUBST(MEMKIND_HOME) 62 | else 63 | AC_MSG_FAILURE([Cannot find memkind.h - hbwmalloc.h within given memkind DIR]) 64 | fi 65 | else 66 | AC_MSG_FAILURE([Cannot find libmemkind.so within given memkind DIR]) 67 | fi 68 | else 69 | AC_MSG_FAILURE([Cannot find memkind-hbw-nodes within given memkind DIR]) 70 | fi 71 | fi 72 | AM_CONDITIONAL(HAVE_MEMKIND, test "${MEMKIND_SUPPORT}" = "yes") 73 | 74 | if test x"{MEMKIND_SUPPORT}" = x"yes" ; then 75 | AC_MSG_CHECKING(for NUMA libraries) 76 | if test -r /usr/lib/x86_64-linux-gnu/libnuma.so -o -r /usr/lib/libnuma.so -o -r /usr/lib64/libnuma.so ; then 77 | AC_MSG_RESULT([found]) 78 | else 79 | AC_MSG_FAILURE([Cannot find libnuma.so]) 80 | fi 81 | AC_MSG_CHECKING(for NUMA header files) 82 | if test -r /usr/include/numa.h ; then 83 | AC_MSG_RESULT([found]) 84 | else 85 | AC_MSG_FAILURE([Cannot find /usr/include/numa.h]) 86 | fi 87 | fi 88 | 89 | AC_ARG_WITH([pmdk], 90 | [AS_HELP_STRING([--with-pmdk=DIR], 91 | [Support for PMDK installed in DIR])], 92 | [], 93 | [with_pmdk="no"]) 94 | if test "${with_pmdk}" != "no"; then 95 | if test -r "${with_pmdk}/lib/libpmem.so" -o -r "${with_pmdk}/lib64/libpmem.so" -o -r "${with_pmdk}/lib/${multiarch_triplet}/libpmem.so" ; then 96 | if test -r "${with_pmdk}/include/libpmem.h" ; then 97 | PMDK_SUPPORT="yes" 98 | AC_DEFINE([PMDK_SUPPORTED], [1], [Defined if PMDK is available]) 99 | PMDK_HOME=${with_pmdk} 100 | AC_SUBST(PMDK_HOME) 101 | else 102 | AC_MSG_FAILURE([Cannot find libpmem.h within given PMDK DIR]) 103 | fi 104 | else 105 | AC_MSG_FAILURE([Cannot find libpmem.so within given PMDK DIR]) 106 | fi 107 | fi 108 | AM_CONDITIONAL(HAVE_PMDK, test "${PMDK_SUPPORT}" = "yes") 109 | 110 | AC_ARG_WITH([papi], 111 | [AS_HELP_STRING([--with-papi=DIR], 112 | [Support for PAPI installed in DIR])], 113 | [], 114 | [with_papi="no"]) 115 | if test "${with_papi}" != "no"; then 116 | if test -r "${with_papi}/include/papi.h" ; then 117 | if test -r "${with_papi}/lib/libpapi.so" -o -r "${with_papi}/lib/${multiarch_triplet}/libpapi.so" ; then 118 | PAPI_SUPPORT="yes" 119 | AC_DEFINE([PAPI_SUPPORTED], [1], [Defined if PAPI is available]) 120 | PAPI_HOME=${with_papi} 121 | AC_SUBST(PAPI_HOME) 122 | else 123 | AC_MSG_FAILURE([Cannot find libpapi.so within given PAPI DIR]) 124 | fi 125 | else 126 | AC_MSG_FAILURE([Cannot find PAPI header fileswithin given PAPI DIR]) 127 | fi 128 | fi 129 | AM_CONDITIONAL(HAVE_PAPI, test "${PAPI_SUPPORT}" = "yes") 130 | 131 | CFLAGS_saved=$CFLAGS 132 | LIBS_saved=$LIBS 133 | CFLAGS="-I${MEMKIND_HOME}/include" 134 | LIBS="-L${MEMKIND_HOME}/lib -lmemkind" 135 | AC_MSG_CHECKING([for hbw_malloc_usable_size]) 136 | AC_TRY_LINK([ 137 | #include 138 | ],[ 139 | size_t s = hbw_malloc_usable_size ((void*) 0); 140 | ],[ 141 | AC_MSG_RESULT([yes]) 142 | AC_DEFINE([HAVE_HBW_MALLOC_USABLE_SIZE], [1], [Defined if hbw_malloc_usable_size is available]) 143 | ],[ 144 | AC_MSG_RESULT([no]) 145 | ]) 146 | AC_MSG_CHECKING([for memkind_malloc_usable_size]) 147 | AC_TRY_LINK([ 148 | #include 149 | ],[ 150 | size_t s = memkind_malloc_usable_size (0, (void*) 0); 151 | ],[ 152 | AC_MSG_RESULT([yes]) 153 | AC_DEFINE([HAVE_MEMKIND_MALLOC_USABLE_SIZE], [1], [Defined if memkind_malloc_usable_size is available]) 154 | ],[ 155 | AC_MSG_RESULT([no]) 156 | ]) 157 | CFLAGS=$CFLAGS_saved 158 | LIBS=$LIBS_saved 159 | 160 | AC_CHECK_HEADERS([ \ 161 | assert.h \ 162 | bfd.h \ 163 | ctype.h \ 164 | dlfcn.h \ 165 | dirent.h \ 166 | execinfo.h \ 167 | errno.h \ 168 | fcntl.h \ 169 | float.h \ 170 | libgen.h \ 171 | limits.h \ 172 | math.h \ 173 | pthread.h \ 174 | sched.h \ 175 | stdint.h \ 176 | stdio.h \ 177 | stdlib.h \ 178 | string.h \ 179 | strings.h \ 180 | time.h \ 181 | unistd.h \ 182 | linux/limits.h \ 183 | sys/mman.h \ 184 | sys/stat.h \ 185 | sys/time.h \ 186 | sys/resource.h \ 187 | sys/param.h 188 | ]) 189 | 190 | AC_OUTPUT([Makefile src/Makefile tests/Makefile doc/Makefile scripts/Makefile]) 191 | 192 | if test "${PMDK_SUPPORT}" != "yes" -a "${MEMKIND_SUPPORT}" = "yes" ; then 193 | AC_MSG_WARN([You configured FlexMalloc with Memkind support but without PMDK.]) 194 | elif test "${PMDK_SUPPORT}" = "yes" -a "${MEMKIND_SUPPORT}" != "yes" ; then 195 | AC_MSG_WARN([You configured FlexMalloc with PMDK support but without Memkind.]) 196 | fi 197 | 198 | -------------------------------------------------------------------------------- /doc/Makefile.am: -------------------------------------------------------------------------------- 1 | EXTRA_DIST = README.txt 2 | -------------------------------------------------------------------------------- /doc/Makefile.in: -------------------------------------------------------------------------------- 1 | # Makefile.in generated by automake 1.16.1 from Makefile.am. 2 | # @configure_input@ 3 | 4 | # Copyright (C) 1994-2018 Free Software Foundation, Inc. 5 | 6 | # This Makefile.in is free software; the Free Software Foundation 7 | # gives unlimited permission to copy and/or distribute it, 8 | # with or without modifications, as long as this notice is preserved. 9 | 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY, to the extent permitted by law; without 12 | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | # PARTICULAR PURPOSE. 14 | 15 | @SET_MAKE@ 16 | VPATH = @srcdir@ 17 | am__is_gnu_make = { \ 18 | if test -z '$(MAKELEVEL)'; then \ 19 | false; \ 20 | elif test -n '$(MAKE_HOST)'; then \ 21 | true; \ 22 | elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ 23 | true; \ 24 | else \ 25 | false; \ 26 | fi; \ 27 | } 28 | am__make_running_with_option = \ 29 | case $${target_option-} in \ 30 | ?) ;; \ 31 | *) echo "am__make_running_with_option: internal error: invalid" \ 32 | "target option '$${target_option-}' specified" >&2; \ 33 | exit 1;; \ 34 | esac; \ 35 | has_opt=no; \ 36 | sane_makeflags=$$MAKEFLAGS; \ 37 | if $(am__is_gnu_make); then \ 38 | sane_makeflags=$$MFLAGS; \ 39 | else \ 40 | case $$MAKEFLAGS in \ 41 | *\\[\ \ ]*) \ 42 | bs=\\; \ 43 | sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ 44 | | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ 45 | esac; \ 46 | fi; \ 47 | skip_next=no; \ 48 | strip_trailopt () \ 49 | { \ 50 | flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ 51 | }; \ 52 | for flg in $$sane_makeflags; do \ 53 | test $$skip_next = yes && { skip_next=no; continue; }; \ 54 | case $$flg in \ 55 | *=*|--*) continue;; \ 56 | -*I) strip_trailopt 'I'; skip_next=yes;; \ 57 | -*I?*) strip_trailopt 'I';; \ 58 | -*O) strip_trailopt 'O'; skip_next=yes;; \ 59 | -*O?*) strip_trailopt 'O';; \ 60 | -*l) strip_trailopt 'l'; skip_next=yes;; \ 61 | -*l?*) strip_trailopt 'l';; \ 62 | -[dEDm]) skip_next=yes;; \ 63 | -[JT]) skip_next=yes;; \ 64 | esac; \ 65 | case $$flg in \ 66 | *$$target_option*) has_opt=yes; break;; \ 67 | esac; \ 68 | done; \ 69 | test $$has_opt = yes 70 | am__make_dryrun = (target_option=n; $(am__make_running_with_option)) 71 | am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 72 | pkgdatadir = $(datadir)/@PACKAGE@ 73 | pkgincludedir = $(includedir)/@PACKAGE@ 74 | pkglibdir = $(libdir)/@PACKAGE@ 75 | pkglibexecdir = $(libexecdir)/@PACKAGE@ 76 | am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd 77 | install_sh_DATA = $(install_sh) -c -m 644 78 | install_sh_PROGRAM = $(install_sh) -c 79 | install_sh_SCRIPT = $(install_sh) -c 80 | INSTALL_HEADER = $(INSTALL_DATA) 81 | transform = $(program_transform_name) 82 | NORMAL_INSTALL = : 83 | PRE_INSTALL = : 84 | POST_INSTALL = : 85 | NORMAL_UNINSTALL = : 86 | PRE_UNINSTALL = : 87 | POST_UNINSTALL = : 88 | build_triplet = @build@ 89 | host_triplet = @host@ 90 | subdir = doc 91 | ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 92 | am__aclocal_m4_deps = $(top_srcdir)/configure.ac 93 | am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ 94 | $(ACLOCAL_M4) 95 | DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) 96 | mkinstalldirs = $(install_sh) -d 97 | CONFIG_HEADER = $(top_builddir)/flexmalloc-config.h 98 | CONFIG_CLEAN_FILES = 99 | CONFIG_CLEAN_VPATH_FILES = 100 | AM_V_P = $(am__v_P_@AM_V@) 101 | am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) 102 | am__v_P_0 = false 103 | am__v_P_1 = : 104 | AM_V_GEN = $(am__v_GEN_@AM_V@) 105 | am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) 106 | am__v_GEN_0 = @echo " GEN " $@; 107 | am__v_GEN_1 = 108 | AM_V_at = $(am__v_at_@AM_V@) 109 | am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) 110 | am__v_at_0 = @ 111 | am__v_at_1 = 112 | depcomp = 113 | am__maybe_remake_depfiles = 114 | SOURCES = 115 | DIST_SOURCES = 116 | am__can_run_installinfo = \ 117 | case $$AM_UPDATE_INFO_DIR in \ 118 | n|no|NO) false;; \ 119 | *) (install-info --version) >/dev/null 2>&1;; \ 120 | esac 121 | am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) 122 | am__DIST_COMMON = $(srcdir)/Makefile.in 123 | DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) 124 | ACLOCAL = @ACLOCAL@ 125 | AMTAR = @AMTAR@ 126 | AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ 127 | AR = @AR@ 128 | AUTOCONF = @AUTOCONF@ 129 | AUTOHEADER = @AUTOHEADER@ 130 | AUTOMAKE = @AUTOMAKE@ 131 | AWK = @AWK@ 132 | BINUTILS_HOME = @BINUTILS_HOME@ 133 | CC = @CC@ 134 | CCAS = @CCAS@ 135 | CCASFLAGS = @CCASFLAGS@ 136 | CFLAGS = @CFLAGS@ 137 | CPP = @CPP@ 138 | CPPFLAGS = @CPPFLAGS@ 139 | CXX = @CXX@ 140 | CXXCPP = @CXXCPP@ 141 | CXXFLAGS = @CXXFLAGS@ 142 | CYGPATH_W = @CYGPATH_W@ 143 | DEFS = @DEFS@ 144 | DLLTOOL = @DLLTOOL@ 145 | DSYMUTIL = @DSYMUTIL@ 146 | DUMPBIN = @DUMPBIN@ 147 | ECHO_C = @ECHO_C@ 148 | ECHO_N = @ECHO_N@ 149 | ECHO_T = @ECHO_T@ 150 | EGREP = @EGREP@ 151 | EXEEXT = @EXEEXT@ 152 | FGREP = @FGREP@ 153 | GREP = @GREP@ 154 | INSTALL = @INSTALL@ 155 | INSTALL_DATA = @INSTALL_DATA@ 156 | INSTALL_PROGRAM = @INSTALL_PROGRAM@ 157 | INSTALL_SCRIPT = @INSTALL_SCRIPT@ 158 | INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ 159 | LD = @LD@ 160 | LDFLAGS = @LDFLAGS@ 161 | LIBOBJS = @LIBOBJS@ 162 | LIBS = @LIBS@ 163 | LIBTOOL = @LIBTOOL@ 164 | LIPO = @LIPO@ 165 | LN_S = @LN_S@ 166 | LTLIBOBJS = @LTLIBOBJS@ 167 | LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ 168 | MAKEINFO = @MAKEINFO@ 169 | MANIFEST_TOOL = @MANIFEST_TOOL@ 170 | MEMKIND_HOME = @MEMKIND_HOME@ 171 | MKDIR_P = @MKDIR_P@ 172 | NM = @NM@ 173 | NMEDIT = @NMEDIT@ 174 | OBJDUMP = @OBJDUMP@ 175 | OBJEXT = @OBJEXT@ 176 | OTOOL = @OTOOL@ 177 | OTOOL64 = @OTOOL64@ 178 | PACKAGE = @PACKAGE@ 179 | PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ 180 | PACKAGE_NAME = @PACKAGE_NAME@ 181 | PACKAGE_STRING = @PACKAGE_STRING@ 182 | PACKAGE_TARNAME = @PACKAGE_TARNAME@ 183 | PACKAGE_URL = @PACKAGE_URL@ 184 | PACKAGE_VERSION = @PACKAGE_VERSION@ 185 | PAPI_HOME = @PAPI_HOME@ 186 | PATH_SEPARATOR = @PATH_SEPARATOR@ 187 | PMDK_HOME = @PMDK_HOME@ 188 | RANLIB = @RANLIB@ 189 | SED = @SED@ 190 | SET_MAKE = @SET_MAKE@ 191 | SHELL = @SHELL@ 192 | STRIP = @STRIP@ 193 | VERSION = @VERSION@ 194 | abs_builddir = @abs_builddir@ 195 | abs_srcdir = @abs_srcdir@ 196 | abs_top_builddir = @abs_top_builddir@ 197 | abs_top_srcdir = @abs_top_srcdir@ 198 | ac_ct_AR = @ac_ct_AR@ 199 | ac_ct_CC = @ac_ct_CC@ 200 | ac_ct_CXX = @ac_ct_CXX@ 201 | ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ 202 | am__leading_dot = @am__leading_dot@ 203 | am__tar = @am__tar@ 204 | am__untar = @am__untar@ 205 | bindir = @bindir@ 206 | build = @build@ 207 | build_alias = @build_alias@ 208 | build_cpu = @build_cpu@ 209 | build_os = @build_os@ 210 | build_vendor = @build_vendor@ 211 | builddir = @builddir@ 212 | datadir = @datadir@ 213 | datarootdir = @datarootdir@ 214 | docdir = @docdir@ 215 | dvidir = @dvidir@ 216 | exec_prefix = @exec_prefix@ 217 | host = @host@ 218 | host_alias = @host_alias@ 219 | host_cpu = @host_cpu@ 220 | host_os = @host_os@ 221 | host_vendor = @host_vendor@ 222 | htmldir = @htmldir@ 223 | includedir = @includedir@ 224 | infodir = @infodir@ 225 | install_sh = @install_sh@ 226 | libdir = @libdir@ 227 | libexecdir = @libexecdir@ 228 | localedir = @localedir@ 229 | localstatedir = @localstatedir@ 230 | mandir = @mandir@ 231 | mkdir_p = @mkdir_p@ 232 | oldincludedir = @oldincludedir@ 233 | pdfdir = @pdfdir@ 234 | prefix = @prefix@ 235 | program_transform_name = @program_transform_name@ 236 | psdir = @psdir@ 237 | runstatedir = @runstatedir@ 238 | sbindir = @sbindir@ 239 | sharedstatedir = @sharedstatedir@ 240 | srcdir = @srcdir@ 241 | sysconfdir = @sysconfdir@ 242 | target_alias = @target_alias@ 243 | top_build_prefix = @top_build_prefix@ 244 | top_builddir = @top_builddir@ 245 | top_srcdir = @top_srcdir@ 246 | EXTRA_DIST = README.txt 247 | all: all-am 248 | 249 | .SUFFIXES: 250 | $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) 251 | @for dep in $?; do \ 252 | case '$(am__configure_deps)' in \ 253 | *$$dep*) \ 254 | ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ 255 | && { if test -f $@; then exit 0; else break; fi; }; \ 256 | exit 1;; \ 257 | esac; \ 258 | done; \ 259 | echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps doc/Makefile'; \ 260 | $(am__cd) $(top_srcdir) && \ 261 | $(AUTOMAKE) --gnu --ignore-deps doc/Makefile 262 | Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status 263 | @case '$?' in \ 264 | *config.status*) \ 265 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ 266 | *) \ 267 | echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ 268 | cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ 269 | esac; 270 | 271 | $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) 272 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 273 | 274 | $(top_srcdir)/configure: $(am__configure_deps) 275 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 276 | $(ACLOCAL_M4): $(am__aclocal_m4_deps) 277 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 278 | $(am__aclocal_m4_deps): 279 | 280 | mostlyclean-libtool: 281 | -rm -f *.lo 282 | 283 | clean-libtool: 284 | -rm -rf .libs _libs 285 | tags TAGS: 286 | 287 | ctags CTAGS: 288 | 289 | cscope cscopelist: 290 | 291 | 292 | distdir: $(BUILT_SOURCES) 293 | $(MAKE) $(AM_MAKEFLAGS) distdir-am 294 | 295 | distdir-am: $(DISTFILES) 296 | @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 297 | topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 298 | list='$(DISTFILES)'; \ 299 | dist_files=`for file in $$list; do echo $$file; done | \ 300 | sed -e "s|^$$srcdirstrip/||;t" \ 301 | -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ 302 | case $$dist_files in \ 303 | */*) $(MKDIR_P) `echo "$$dist_files" | \ 304 | sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ 305 | sort -u` ;; \ 306 | esac; \ 307 | for file in $$dist_files; do \ 308 | if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ 309 | if test -d $$d/$$file; then \ 310 | dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ 311 | if test -d "$(distdir)/$$file"; then \ 312 | find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ 313 | fi; \ 314 | if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ 315 | cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ 316 | find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ 317 | fi; \ 318 | cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ 319 | else \ 320 | test -f "$(distdir)/$$file" \ 321 | || cp -p $$d/$$file "$(distdir)/$$file" \ 322 | || exit 1; \ 323 | fi; \ 324 | done 325 | check-am: all-am 326 | check: check-am 327 | all-am: Makefile 328 | installdirs: 329 | install: install-am 330 | install-exec: install-exec-am 331 | install-data: install-data-am 332 | uninstall: uninstall-am 333 | 334 | install-am: all-am 335 | @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am 336 | 337 | installcheck: installcheck-am 338 | install-strip: 339 | if test -z '$(STRIP)'; then \ 340 | $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ 341 | install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ 342 | install; \ 343 | else \ 344 | $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ 345 | install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ 346 | "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ 347 | fi 348 | mostlyclean-generic: 349 | 350 | clean-generic: 351 | 352 | distclean-generic: 353 | -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) 354 | -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) 355 | 356 | maintainer-clean-generic: 357 | @echo "This command is intended for maintainers to use" 358 | @echo "it deletes files that may require special tools to rebuild." 359 | clean: clean-am 360 | 361 | clean-am: clean-generic clean-libtool mostlyclean-am 362 | 363 | distclean: distclean-am 364 | -rm -f Makefile 365 | distclean-am: clean-am distclean-generic 366 | 367 | dvi: dvi-am 368 | 369 | dvi-am: 370 | 371 | html: html-am 372 | 373 | html-am: 374 | 375 | info: info-am 376 | 377 | info-am: 378 | 379 | install-data-am: 380 | 381 | install-dvi: install-dvi-am 382 | 383 | install-dvi-am: 384 | 385 | install-exec-am: 386 | 387 | install-html: install-html-am 388 | 389 | install-html-am: 390 | 391 | install-info: install-info-am 392 | 393 | install-info-am: 394 | 395 | install-man: 396 | 397 | install-pdf: install-pdf-am 398 | 399 | install-pdf-am: 400 | 401 | install-ps: install-ps-am 402 | 403 | install-ps-am: 404 | 405 | installcheck-am: 406 | 407 | maintainer-clean: maintainer-clean-am 408 | -rm -f Makefile 409 | maintainer-clean-am: distclean-am maintainer-clean-generic 410 | 411 | mostlyclean: mostlyclean-am 412 | 413 | mostlyclean-am: mostlyclean-generic mostlyclean-libtool 414 | 415 | pdf: pdf-am 416 | 417 | pdf-am: 418 | 419 | ps: ps-am 420 | 421 | ps-am: 422 | 423 | uninstall-am: 424 | 425 | .MAKE: install-am install-strip 426 | 427 | .PHONY: all all-am check check-am clean clean-generic clean-libtool \ 428 | cscopelist-am ctags-am distclean distclean-generic \ 429 | distclean-libtool distdir dvi dvi-am html html-am info info-am \ 430 | install install-am install-data install-data-am install-dvi \ 431 | install-dvi-am install-exec install-exec-am install-html \ 432 | install-html-am install-info install-info-am install-man \ 433 | install-pdf install-pdf-am install-ps install-ps-am \ 434 | install-strip installcheck installcheck-am installdirs \ 435 | maintainer-clean maintainer-clean-generic mostlyclean \ 436 | mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ 437 | tags-am uninstall uninstall-am 438 | 439 | .PRECIOUS: Makefile 440 | 441 | 442 | # Tell versions [3.59,3.63) of GNU make to not export all variables. 443 | # Otherwise a system limit (for SysV at least) may be exceeded. 444 | .NOEXPORT: 445 | -------------------------------------------------------------------------------- /doc/README.txt: -------------------------------------------------------------------------------- 1 | * How to use auto-hbwmalloc package 2 | 3 | Simply preload the libauto_hbwmalloc.so using 4 | LD_PRELOAD=/lib/libauto_hbwmalloc.so 5 | and then run the binary. If you run an MPI application, you'd probably want 6 | not to intercept the mpi launcher. You can achieve that by setting the 7 | LD_PRELOAD in a intercept.sh file (for instance) and run the application like 8 | mpirun -np ./intercept.sh 9 | 10 | 11 | * Supported environment variables 12 | 13 | AUTO_HBWMALLOC_VERBOSE=n 14 | where n can be an integral from 0 to 4 that specifies the level of verbosity 15 | of the package. 16 | 17 | AUTO_HBWMALLOC_LOCATIONS=f 18 | where f is a file containing a list of call-stacks to be intercepted and 19 | allocated through the specified allocator in AUTO_HBWMALLOC_ALLOCATOR 20 | 21 | AUTO_HBWMALLOC_MAX_SIZE=s 22 | use allocator if the malloc/realloc size is smaller or equal than s bytes 23 | This option supersedes size ranges provided in the locations file 24 | 25 | AUTO_HBWMALLOC_MIN_SIZE=s 26 | use allocator if the malloc/realloc size is larger or equal than s bytes 27 | This option supersedes size ranges provided in the locations file 28 | 29 | AUTO_HBWMALLOC_COMPARE_WHOLE_PATH=b 30 | where b is either {0/no} or {1/yes} and instructs the package to check for 31 | the whole path in the call-stacks 32 | -------------------------------------------------------------------------------- /flexmalloc-config.h.in: -------------------------------------------------------------------------------- 1 | /* flexmalloc-config.h.in. Generated from configure.ac by autoheader. */ 2 | 3 | /* Define to 1 if you have the header file. */ 4 | #undef HAVE_ASSERT_H 5 | 6 | /* Define to 1 if you have the header file. */ 7 | #undef HAVE_BFD_H 8 | 9 | /* Define to 1 if you have the header file. */ 10 | #undef HAVE_CTYPE_H 11 | 12 | /* Define to 1 if you have the header file. */ 13 | #undef HAVE_DIRENT_H 14 | 15 | /* Define to 1 if you have the header file. */ 16 | #undef HAVE_DLFCN_H 17 | 18 | /* Define to 1 if you have the header file. */ 19 | #undef HAVE_ERRNO_H 20 | 21 | /* Define to 1 if you have the header file. */ 22 | #undef HAVE_EXECINFO_H 23 | 24 | /* Define to 1 if you have the header file. */ 25 | #undef HAVE_FCNTL_H 26 | 27 | /* Define to 1 if you have the header file. */ 28 | #undef HAVE_FLOAT_H 29 | 30 | /* Defined if hbw_malloc_usable_size is available */ 31 | #undef HAVE_HBW_MALLOC_USABLE_SIZE 32 | 33 | /* Define to 1 if you have the header file. */ 34 | #undef HAVE_INTTYPES_H 35 | 36 | /* Define to 1 if you have the header file. */ 37 | #undef HAVE_LIBGEN_H 38 | 39 | /* Define to 1 if you have the header file. */ 40 | #undef HAVE_LIMITS_H 41 | 42 | /* Define to 1 if you have the header file. */ 43 | #undef HAVE_LINUX_LIMITS_H 44 | 45 | /* Define to 1 if you have the header file. */ 46 | #undef HAVE_MATH_H 47 | 48 | /* Defined if memkind_malloc_usable_size is available */ 49 | #undef HAVE_MEMKIND_MALLOC_USABLE_SIZE 50 | 51 | /* Define to 1 if you have the header file. */ 52 | #undef HAVE_MEMORY_H 53 | 54 | /* Define to 1 if you have the header file. */ 55 | #undef HAVE_PTHREAD_H 56 | 57 | /* Define to 1 if you have the header file. */ 58 | #undef HAVE_SCHED_H 59 | 60 | /* Define to 1 if you have the header file. */ 61 | #undef HAVE_STDINT_H 62 | 63 | /* Define to 1 if you have the header file. */ 64 | #undef HAVE_STDIO_H 65 | 66 | /* Define to 1 if you have the header file. */ 67 | #undef HAVE_STDLIB_H 68 | 69 | /* Define to 1 if you have the header file. */ 70 | #undef HAVE_STRINGS_H 71 | 72 | /* Define to 1 if you have the header file. */ 73 | #undef HAVE_STRING_H 74 | 75 | /* Define to 1 if you have the header file. */ 76 | #undef HAVE_SYS_MMAN_H 77 | 78 | /* Define to 1 if you have the header file. */ 79 | #undef HAVE_SYS_PARAM_H 80 | 81 | /* Define to 1 if you have the header file. */ 82 | #undef HAVE_SYS_RESOURCE_H 83 | 84 | /* Define to 1 if you have the header file. */ 85 | #undef HAVE_SYS_STAT_H 86 | 87 | /* Define to 1 if you have the header file. */ 88 | #undef HAVE_SYS_TIME_H 89 | 90 | /* Define to 1 if you have the header file. */ 91 | #undef HAVE_SYS_TYPES_H 92 | 93 | /* Define to 1 if you have the header file. */ 94 | #undef HAVE_TIME_H 95 | 96 | /* Define to 1 if you have the header file. */ 97 | #undef HAVE_UNISTD_H 98 | 99 | /* Define to the sub-directory where libtool stores uninstalled libraries. */ 100 | #undef LT_OBJDIR 101 | 102 | /* Defined if Memkind is available */ 103 | #undef MEMKIND_SUPPORTED 104 | 105 | /* Name of package */ 106 | #undef PACKAGE 107 | 108 | /* Define to the address where bug reports for this package should be sent. */ 109 | #undef PACKAGE_BUGREPORT 110 | 111 | /* Define to the full name of this package. */ 112 | #undef PACKAGE_NAME 113 | 114 | /* Define to the full name and version of this package. */ 115 | #undef PACKAGE_STRING 116 | 117 | /* Define to the one symbol short name of this package. */ 118 | #undef PACKAGE_TARNAME 119 | 120 | /* Define to the home page for this package. */ 121 | #undef PACKAGE_URL 122 | 123 | /* Define to the version of this package. */ 124 | #undef PACKAGE_VERSION 125 | 126 | /* Defined if PAPI is available */ 127 | #undef PAPI_SUPPORTED 128 | 129 | /* Defined if PMDK is available */ 130 | #undef PMDK_SUPPORTED 131 | 132 | /* Define to 1 if you have the ANSI C header files. */ 133 | #undef STDC_HEADERS 134 | 135 | /* Version number of package */ 136 | #undef VERSION 137 | -------------------------------------------------------------------------------- /install-sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # install - install a program, script, or datafile 3 | 4 | scriptversion=2018-03-11.20; # UTC 5 | 6 | # This originates from X11R5 (mit/util/scripts/install.sh), which was 7 | # later released in X11R6 (xc/config/util/install.sh) with the 8 | # following copyright and license. 9 | # 10 | # Copyright (C) 1994 X Consortium 11 | # 12 | # Permission is hereby granted, free of charge, to any person obtaining a copy 13 | # of this software and associated documentation files (the "Software"), to 14 | # deal in the Software without restriction, including without limitation the 15 | # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16 | # sell copies of the Software, and to permit persons to whom the Software is 17 | # furnished to do so, subject to the following conditions: 18 | # 19 | # The above copyright notice and this permission notice shall be included in 20 | # all copies or substantial portions of the Software. 21 | # 22 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26 | # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27 | # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | # 29 | # Except as contained in this notice, the name of the X Consortium shall not 30 | # be used in advertising or otherwise to promote the sale, use or other deal- 31 | # ings in this Software without prior written authorization from the X Consor- 32 | # tium. 33 | # 34 | # 35 | # FSF changes to this file are in the public domain. 36 | # 37 | # Calling this script install-sh is preferred over install.sh, to prevent 38 | # 'make' implicit rules from creating a file called install from it 39 | # when there is no Makefile. 40 | # 41 | # This script is compatible with the BSD install script, but was written 42 | # from scratch. 43 | 44 | tab=' ' 45 | nl=' 46 | ' 47 | IFS=" $tab$nl" 48 | 49 | # Set DOITPROG to "echo" to test this script. 50 | 51 | doit=${DOITPROG-} 52 | doit_exec=${doit:-exec} 53 | 54 | # Put in absolute file names if you don't have them in your path; 55 | # or use environment vars. 56 | 57 | chgrpprog=${CHGRPPROG-chgrp} 58 | chmodprog=${CHMODPROG-chmod} 59 | chownprog=${CHOWNPROG-chown} 60 | cmpprog=${CMPPROG-cmp} 61 | cpprog=${CPPROG-cp} 62 | mkdirprog=${MKDIRPROG-mkdir} 63 | mvprog=${MVPROG-mv} 64 | rmprog=${RMPROG-rm} 65 | stripprog=${STRIPPROG-strip} 66 | 67 | posix_mkdir= 68 | 69 | # Desired mode of installed file. 70 | mode=0755 71 | 72 | chgrpcmd= 73 | chmodcmd=$chmodprog 74 | chowncmd= 75 | mvcmd=$mvprog 76 | rmcmd="$rmprog -f" 77 | stripcmd= 78 | 79 | src= 80 | dst= 81 | dir_arg= 82 | dst_arg= 83 | 84 | copy_on_change=false 85 | is_target_a_directory=possibly 86 | 87 | usage="\ 88 | Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 89 | or: $0 [OPTION]... SRCFILES... DIRECTORY 90 | or: $0 [OPTION]... -t DIRECTORY SRCFILES... 91 | or: $0 [OPTION]... -d DIRECTORIES... 92 | 93 | In the 1st form, copy SRCFILE to DSTFILE. 94 | In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 95 | In the 4th, create DIRECTORIES. 96 | 97 | Options: 98 | --help display this help and exit. 99 | --version display version info and exit. 100 | 101 | -c (ignored) 102 | -C install only if different (preserve the last data modification time) 103 | -d create directories instead of installing files. 104 | -g GROUP $chgrpprog installed files to GROUP. 105 | -m MODE $chmodprog installed files to MODE. 106 | -o USER $chownprog installed files to USER. 107 | -s $stripprog installed files. 108 | -t DIRECTORY install into DIRECTORY. 109 | -T report an error if DSTFILE is a directory. 110 | 111 | Environment variables override the default commands: 112 | CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG 113 | RMPROG STRIPPROG 114 | " 115 | 116 | while test $# -ne 0; do 117 | case $1 in 118 | -c) ;; 119 | 120 | -C) copy_on_change=true;; 121 | 122 | -d) dir_arg=true;; 123 | 124 | -g) chgrpcmd="$chgrpprog $2" 125 | shift;; 126 | 127 | --help) echo "$usage"; exit $?;; 128 | 129 | -m) mode=$2 130 | case $mode in 131 | *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) 132 | echo "$0: invalid mode: $mode" >&2 133 | exit 1;; 134 | esac 135 | shift;; 136 | 137 | -o) chowncmd="$chownprog $2" 138 | shift;; 139 | 140 | -s) stripcmd=$stripprog;; 141 | 142 | -t) 143 | is_target_a_directory=always 144 | dst_arg=$2 145 | # Protect names problematic for 'test' and other utilities. 146 | case $dst_arg in 147 | -* | [=\(\)!]) dst_arg=./$dst_arg;; 148 | esac 149 | shift;; 150 | 151 | -T) is_target_a_directory=never;; 152 | 153 | --version) echo "$0 $scriptversion"; exit $?;; 154 | 155 | --) shift 156 | break;; 157 | 158 | -*) echo "$0: invalid option: $1" >&2 159 | exit 1;; 160 | 161 | *) break;; 162 | esac 163 | shift 164 | done 165 | 166 | # We allow the use of options -d and -T together, by making -d 167 | # take the precedence; this is for compatibility with GNU install. 168 | 169 | if test -n "$dir_arg"; then 170 | if test -n "$dst_arg"; then 171 | echo "$0: target directory not allowed when installing a directory." >&2 172 | exit 1 173 | fi 174 | fi 175 | 176 | if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then 177 | # When -d is used, all remaining arguments are directories to create. 178 | # When -t is used, the destination is already specified. 179 | # Otherwise, the last argument is the destination. Remove it from $@. 180 | for arg 181 | do 182 | if test -n "$dst_arg"; then 183 | # $@ is not empty: it contains at least $arg. 184 | set fnord "$@" "$dst_arg" 185 | shift # fnord 186 | fi 187 | shift # arg 188 | dst_arg=$arg 189 | # Protect names problematic for 'test' and other utilities. 190 | case $dst_arg in 191 | -* | [=\(\)!]) dst_arg=./$dst_arg;; 192 | esac 193 | done 194 | fi 195 | 196 | if test $# -eq 0; then 197 | if test -z "$dir_arg"; then 198 | echo "$0: no input file specified." >&2 199 | exit 1 200 | fi 201 | # It's OK to call 'install-sh -d' without argument. 202 | # This can happen when creating conditional directories. 203 | exit 0 204 | fi 205 | 206 | if test -z "$dir_arg"; then 207 | if test $# -gt 1 || test "$is_target_a_directory" = always; then 208 | if test ! -d "$dst_arg"; then 209 | echo "$0: $dst_arg: Is not a directory." >&2 210 | exit 1 211 | fi 212 | fi 213 | fi 214 | 215 | if test -z "$dir_arg"; then 216 | do_exit='(exit $ret); exit $ret' 217 | trap "ret=129; $do_exit" 1 218 | trap "ret=130; $do_exit" 2 219 | trap "ret=141; $do_exit" 13 220 | trap "ret=143; $do_exit" 15 221 | 222 | # Set umask so as not to create temps with too-generous modes. 223 | # However, 'strip' requires both read and write access to temps. 224 | case $mode in 225 | # Optimize common cases. 226 | *644) cp_umask=133;; 227 | *755) cp_umask=22;; 228 | 229 | *[0-7]) 230 | if test -z "$stripcmd"; then 231 | u_plus_rw= 232 | else 233 | u_plus_rw='% 200' 234 | fi 235 | cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; 236 | *) 237 | if test -z "$stripcmd"; then 238 | u_plus_rw= 239 | else 240 | u_plus_rw=,u+rw 241 | fi 242 | cp_umask=$mode$u_plus_rw;; 243 | esac 244 | fi 245 | 246 | for src 247 | do 248 | # Protect names problematic for 'test' and other utilities. 249 | case $src in 250 | -* | [=\(\)!]) src=./$src;; 251 | esac 252 | 253 | if test -n "$dir_arg"; then 254 | dst=$src 255 | dstdir=$dst 256 | test -d "$dstdir" 257 | dstdir_status=$? 258 | else 259 | 260 | # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 261 | # might cause directories to be created, which would be especially bad 262 | # if $src (and thus $dsttmp) contains '*'. 263 | if test ! -f "$src" && test ! -d "$src"; then 264 | echo "$0: $src does not exist." >&2 265 | exit 1 266 | fi 267 | 268 | if test -z "$dst_arg"; then 269 | echo "$0: no destination specified." >&2 270 | exit 1 271 | fi 272 | dst=$dst_arg 273 | 274 | # If destination is a directory, append the input filename. 275 | if test -d "$dst"; then 276 | if test "$is_target_a_directory" = never; then 277 | echo "$0: $dst_arg: Is a directory" >&2 278 | exit 1 279 | fi 280 | dstdir=$dst 281 | dstbase=`basename "$src"` 282 | case $dst in 283 | */) dst=$dst$dstbase;; 284 | *) dst=$dst/$dstbase;; 285 | esac 286 | dstdir_status=0 287 | else 288 | dstdir=`dirname "$dst"` 289 | test -d "$dstdir" 290 | dstdir_status=$? 291 | fi 292 | fi 293 | 294 | case $dstdir in 295 | */) dstdirslash=$dstdir;; 296 | *) dstdirslash=$dstdir/;; 297 | esac 298 | 299 | obsolete_mkdir_used=false 300 | 301 | if test $dstdir_status != 0; then 302 | case $posix_mkdir in 303 | '') 304 | # Create intermediate dirs using mode 755 as modified by the umask. 305 | # This is like FreeBSD 'install' as of 1997-10-28. 306 | umask=`umask` 307 | case $stripcmd.$umask in 308 | # Optimize common cases. 309 | *[2367][2367]) mkdir_umask=$umask;; 310 | .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; 311 | 312 | *[0-7]) 313 | mkdir_umask=`expr $umask + 22 \ 314 | - $umask % 100 % 40 + $umask % 20 \ 315 | - $umask % 10 % 4 + $umask % 2 316 | `;; 317 | *) mkdir_umask=$umask,go-w;; 318 | esac 319 | 320 | # With -d, create the new directory with the user-specified mode. 321 | # Otherwise, rely on $mkdir_umask. 322 | if test -n "$dir_arg"; then 323 | mkdir_mode=-m$mode 324 | else 325 | mkdir_mode= 326 | fi 327 | 328 | posix_mkdir=false 329 | case $umask in 330 | *[123567][0-7][0-7]) 331 | # POSIX mkdir -p sets u+wx bits regardless of umask, which 332 | # is incompatible with FreeBSD 'install' when (umask & 300) != 0. 333 | ;; 334 | *) 335 | # Note that $RANDOM variable is not portable (e.g. dash); Use it 336 | # here however when possible just to lower collision chance. 337 | tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ 338 | 339 | trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 340 | 341 | # Because "mkdir -p" follows existing symlinks and we likely work 342 | # directly in world-writeable /tmp, make sure that the '$tmpdir' 343 | # directory is successfully created first before we actually test 344 | # 'mkdir -p' feature. 345 | if (umask $mkdir_umask && 346 | $mkdirprog $mkdir_mode "$tmpdir" && 347 | exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 348 | then 349 | if test -z "$dir_arg" || { 350 | # Check for POSIX incompatibilities with -m. 351 | # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or 352 | # other-writable bit of parent directory when it shouldn't. 353 | # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. 354 | test_tmpdir="$tmpdir/a" 355 | ls_ld_tmpdir=`ls -ld "$test_tmpdir"` 356 | case $ls_ld_tmpdir in 357 | d????-?r-*) different_mode=700;; 358 | d????-?--*) different_mode=755;; 359 | *) false;; 360 | esac && 361 | $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { 362 | ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` 363 | test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" 364 | } 365 | } 366 | then posix_mkdir=: 367 | fi 368 | rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 369 | else 370 | # Remove any dirs left behind by ancient mkdir implementations. 371 | rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null 372 | fi 373 | trap '' 0;; 374 | esac;; 375 | esac 376 | 377 | if 378 | $posix_mkdir && ( 379 | umask $mkdir_umask && 380 | $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" 381 | ) 382 | then : 383 | else 384 | 385 | # The umask is ridiculous, or mkdir does not conform to POSIX, 386 | # or it failed possibly due to a race condition. Create the 387 | # directory the slow way, step by step, checking for races as we go. 388 | 389 | case $dstdir in 390 | /*) prefix='/';; 391 | [-=\(\)!]*) prefix='./';; 392 | *) prefix='';; 393 | esac 394 | 395 | oIFS=$IFS 396 | IFS=/ 397 | set -f 398 | set fnord $dstdir 399 | shift 400 | set +f 401 | IFS=$oIFS 402 | 403 | prefixes= 404 | 405 | for d 406 | do 407 | test X"$d" = X && continue 408 | 409 | prefix=$prefix$d 410 | if test -d "$prefix"; then 411 | prefixes= 412 | else 413 | if $posix_mkdir; then 414 | (umask=$mkdir_umask && 415 | $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break 416 | # Don't fail if two instances are running concurrently. 417 | test -d "$prefix" || exit 1 418 | else 419 | case $prefix in 420 | *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; 421 | *) qprefix=$prefix;; 422 | esac 423 | prefixes="$prefixes '$qprefix'" 424 | fi 425 | fi 426 | prefix=$prefix/ 427 | done 428 | 429 | if test -n "$prefixes"; then 430 | # Don't fail if two instances are running concurrently. 431 | (umask $mkdir_umask && 432 | eval "\$doit_exec \$mkdirprog $prefixes") || 433 | test -d "$dstdir" || exit 1 434 | obsolete_mkdir_used=true 435 | fi 436 | fi 437 | fi 438 | 439 | if test -n "$dir_arg"; then 440 | { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && 441 | { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && 442 | { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || 443 | test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 444 | else 445 | 446 | # Make a couple of temp file names in the proper directory. 447 | dsttmp=${dstdirslash}_inst.$$_ 448 | rmtmp=${dstdirslash}_rm.$$_ 449 | 450 | # Trap to clean up those temp files at exit. 451 | trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 452 | 453 | # Copy the file name to the temp name. 454 | (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && 455 | 456 | # and set any options; do chmod last to preserve setuid bits. 457 | # 458 | # If any of these fail, we abort the whole thing. If we want to 459 | # ignore errors from any of these, just make sure not to ignore 460 | # errors from the above "$doit $cpprog $src $dsttmp" command. 461 | # 462 | { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && 463 | { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && 464 | { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && 465 | { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && 466 | 467 | # If -C, don't bother to copy if it wouldn't change the file. 468 | if $copy_on_change && 469 | old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && 470 | new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && 471 | set -f && 472 | set X $old && old=:$2:$4:$5:$6 && 473 | set X $new && new=:$2:$4:$5:$6 && 474 | set +f && 475 | test "$old" = "$new" && 476 | $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 477 | then 478 | rm -f "$dsttmp" 479 | else 480 | # Rename the file to the real destination. 481 | $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || 482 | 483 | # The rename failed, perhaps because mv can't rename something else 484 | # to itself, or perhaps because mv is so ancient that it does not 485 | # support -f. 486 | { 487 | # Now remove or move aside any old file at destination location. 488 | # We try this two ways since rm can't unlink itself on some 489 | # systems and the destination file might be busy for other 490 | # reasons. In this case, the final cleanup might fail but the new 491 | # file should still install successfully. 492 | { 493 | test ! -f "$dst" || 494 | $doit $rmcmd -f "$dst" 2>/dev/null || 495 | { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && 496 | { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } 497 | } || 498 | { echo "$0: cannot unlink or rename $dst" >&2 499 | (exit 1); exit 1 500 | } 501 | } && 502 | 503 | # Now rename the file to the real destination. 504 | $doit $mvcmd "$dsttmp" "$dst" 505 | } 506 | fi || exit 1 507 | 508 | trap '' 0 509 | fi 510 | done 511 | 512 | # Local variables: 513 | # eval: (add-hook 'before-save-hook 'time-stamp) 514 | # time-stamp-start: "scriptversion=" 515 | # time-stamp-format: "%:y-%02m-%02d.%02H" 516 | # time-stamp-time-zone: "UTC0" 517 | # time-stamp-end: "; # UTC" 518 | # End: 519 | -------------------------------------------------------------------------------- /missing: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Common wrapper for a few potentially missing GNU programs. 3 | 4 | scriptversion=2018-03-07.03; # UTC 5 | 6 | # Copyright (C) 1996-2018 Free Software Foundation, Inc. 7 | # Originally written by Fran,cois Pinard , 1996. 8 | 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2, or (at your option) 12 | # any later version. 13 | 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | # As a special exception to the GNU General Public License, if you 23 | # distribute this file as part of a program that contains a 24 | # configuration script generated by Autoconf, you may include it under 25 | # the same distribution terms that you use for the rest of that program. 26 | 27 | if test $# -eq 0; then 28 | echo 1>&2 "Try '$0 --help' for more information" 29 | exit 1 30 | fi 31 | 32 | case $1 in 33 | 34 | --is-lightweight) 35 | # Used by our autoconf macros to check whether the available missing 36 | # script is modern enough. 37 | exit 0 38 | ;; 39 | 40 | --run) 41 | # Back-compat with the calling convention used by older automake. 42 | shift 43 | ;; 44 | 45 | -h|--h|--he|--hel|--help) 46 | echo "\ 47 | $0 [OPTION]... PROGRAM [ARGUMENT]... 48 | 49 | Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due 50 | to PROGRAM being missing or too old. 51 | 52 | Options: 53 | -h, --help display this help and exit 54 | -v, --version output version information and exit 55 | 56 | Supported PROGRAM values: 57 | aclocal autoconf autoheader autom4te automake makeinfo 58 | bison yacc flex lex help2man 59 | 60 | Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 61 | 'g' are ignored when checking the name. 62 | 63 | Send bug reports to ." 64 | exit $? 65 | ;; 66 | 67 | -v|--v|--ve|--ver|--vers|--versi|--versio|--version) 68 | echo "missing $scriptversion (GNU Automake)" 69 | exit $? 70 | ;; 71 | 72 | -*) 73 | echo 1>&2 "$0: unknown '$1' option" 74 | echo 1>&2 "Try '$0 --help' for more information" 75 | exit 1 76 | ;; 77 | 78 | esac 79 | 80 | # Run the given program, remember its exit status. 81 | "$@"; st=$? 82 | 83 | # If it succeeded, we are done. 84 | test $st -eq 0 && exit 0 85 | 86 | # Also exit now if we it failed (or wasn't found), and '--version' was 87 | # passed; such an option is passed most likely to detect whether the 88 | # program is present and works. 89 | case $2 in --version|--help) exit $st;; esac 90 | 91 | # Exit code 63 means version mismatch. This often happens when the user 92 | # tries to use an ancient version of a tool on a file that requires a 93 | # minimum version. 94 | if test $st -eq 63; then 95 | msg="probably too old" 96 | elif test $st -eq 127; then 97 | # Program was missing. 98 | msg="missing on your system" 99 | else 100 | # Program was found and executed, but failed. Give up. 101 | exit $st 102 | fi 103 | 104 | perl_URL=https://www.perl.org/ 105 | flex_URL=https://github.com/westes/flex 106 | gnu_software_URL=https://www.gnu.org/software 107 | 108 | program_details () 109 | { 110 | case $1 in 111 | aclocal|automake) 112 | echo "The '$1' program is part of the GNU Automake package:" 113 | echo "<$gnu_software_URL/automake>" 114 | echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" 115 | echo "<$gnu_software_URL/autoconf>" 116 | echo "<$gnu_software_URL/m4/>" 117 | echo "<$perl_URL>" 118 | ;; 119 | autoconf|autom4te|autoheader) 120 | echo "The '$1' program is part of the GNU Autoconf package:" 121 | echo "<$gnu_software_URL/autoconf/>" 122 | echo "It also requires GNU m4 and Perl in order to run:" 123 | echo "<$gnu_software_URL/m4/>" 124 | echo "<$perl_URL>" 125 | ;; 126 | esac 127 | } 128 | 129 | give_advice () 130 | { 131 | # Normalize program name to check for. 132 | normalized_program=`echo "$1" | sed ' 133 | s/^gnu-//; t 134 | s/^gnu//; t 135 | s/^g//; t'` 136 | 137 | printf '%s\n' "'$1' is $msg." 138 | 139 | configure_deps="'configure.ac' or m4 files included by 'configure.ac'" 140 | case $normalized_program in 141 | autoconf*) 142 | echo "You should only need it if you modified 'configure.ac'," 143 | echo "or m4 files included by it." 144 | program_details 'autoconf' 145 | ;; 146 | autoheader*) 147 | echo "You should only need it if you modified 'acconfig.h' or" 148 | echo "$configure_deps." 149 | program_details 'autoheader' 150 | ;; 151 | automake*) 152 | echo "You should only need it if you modified 'Makefile.am' or" 153 | echo "$configure_deps." 154 | program_details 'automake' 155 | ;; 156 | aclocal*) 157 | echo "You should only need it if you modified 'acinclude.m4' or" 158 | echo "$configure_deps." 159 | program_details 'aclocal' 160 | ;; 161 | autom4te*) 162 | echo "You might have modified some maintainer files that require" 163 | echo "the 'autom4te' program to be rebuilt." 164 | program_details 'autom4te' 165 | ;; 166 | bison*|yacc*) 167 | echo "You should only need it if you modified a '.y' file." 168 | echo "You may want to install the GNU Bison package:" 169 | echo "<$gnu_software_URL/bison/>" 170 | ;; 171 | lex*|flex*) 172 | echo "You should only need it if you modified a '.l' file." 173 | echo "You may want to install the Fast Lexical Analyzer package:" 174 | echo "<$flex_URL>" 175 | ;; 176 | help2man*) 177 | echo "You should only need it if you modified a dependency" \ 178 | "of a man page." 179 | echo "You may want to install the GNU Help2man package:" 180 | echo "<$gnu_software_URL/help2man/>" 181 | ;; 182 | makeinfo*) 183 | echo "You should only need it if you modified a '.texi' file, or" 184 | echo "any other file indirectly affecting the aspect of the manual." 185 | echo "You might want to install the Texinfo package:" 186 | echo "<$gnu_software_URL/texinfo/>" 187 | echo "The spurious makeinfo call might also be the consequence of" 188 | echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" 189 | echo "want to install GNU make:" 190 | echo "<$gnu_software_URL/make/>" 191 | ;; 192 | *) 193 | echo "You might have modified some files without having the proper" 194 | echo "tools for further handling them. Check the 'README' file, it" 195 | echo "often tells you about the needed prerequisites for installing" 196 | echo "this package. You may also peek at any GNU archive site, in" 197 | echo "case some other package contains this missing '$1' program." 198 | ;; 199 | esac 200 | } 201 | 202 | give_advice "$1" | sed -e '1s/^/WARNING: /' \ 203 | -e '2,$s/^/ /' >&2 204 | 205 | # Propagate the correct exit status (expected to be 127 for a program 206 | # not found, 63 for a program that failed due to version mismatch). 207 | exit $st 208 | 209 | # Local variables: 210 | # eval: (add-hook 'before-save-hook 'time-stamp) 211 | # time-stamp-start: "scriptversion=" 212 | # time-stamp-format: "%:y-%02m-%02d.%02H" 213 | # time-stamp-time-zone: "UTC0" 214 | # time-stamp-end: "; # UTC" 215 | # End: 216 | -------------------------------------------------------------------------------- /scripts/Makefile.am: -------------------------------------------------------------------------------- 1 | EXTRA_DIST = flexmalloc.sh count.sh 2 | 3 | install-data-hook: 4 | mkdir -p $(bindir) 5 | cp $(srcdir)/flexmalloc.sh $(srcdir)/count.sh $(bindir) 6 | sed "s|@__sub_FLEXMALLOC_HOME__@|$(prefix)|g" -i $(bindir)/flexmalloc.sh 7 | sed "s|@__sub_FLEXMALLOC_HOME__@|$(prefix)|g" -i $(bindir)/count.sh 8 | chmod +x $(bindir)/flexmalloc.sh $(bindir)/count.sh 9 | -------------------------------------------------------------------------------- /scripts/Makefile.in: -------------------------------------------------------------------------------- 1 | # Makefile.in generated by automake 1.16.1 from Makefile.am. 2 | # @configure_input@ 3 | 4 | # Copyright (C) 1994-2018 Free Software Foundation, Inc. 5 | 6 | # This Makefile.in is free software; the Free Software Foundation 7 | # gives unlimited permission to copy and/or distribute it, 8 | # with or without modifications, as long as this notice is preserved. 9 | 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY, to the extent permitted by law; without 12 | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | # PARTICULAR PURPOSE. 14 | 15 | @SET_MAKE@ 16 | VPATH = @srcdir@ 17 | am__is_gnu_make = { \ 18 | if test -z '$(MAKELEVEL)'; then \ 19 | false; \ 20 | elif test -n '$(MAKE_HOST)'; then \ 21 | true; \ 22 | elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ 23 | true; \ 24 | else \ 25 | false; \ 26 | fi; \ 27 | } 28 | am__make_running_with_option = \ 29 | case $${target_option-} in \ 30 | ?) ;; \ 31 | *) echo "am__make_running_with_option: internal error: invalid" \ 32 | "target option '$${target_option-}' specified" >&2; \ 33 | exit 1;; \ 34 | esac; \ 35 | has_opt=no; \ 36 | sane_makeflags=$$MAKEFLAGS; \ 37 | if $(am__is_gnu_make); then \ 38 | sane_makeflags=$$MFLAGS; \ 39 | else \ 40 | case $$MAKEFLAGS in \ 41 | *\\[\ \ ]*) \ 42 | bs=\\; \ 43 | sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ 44 | | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ 45 | esac; \ 46 | fi; \ 47 | skip_next=no; \ 48 | strip_trailopt () \ 49 | { \ 50 | flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ 51 | }; \ 52 | for flg in $$sane_makeflags; do \ 53 | test $$skip_next = yes && { skip_next=no; continue; }; \ 54 | case $$flg in \ 55 | *=*|--*) continue;; \ 56 | -*I) strip_trailopt 'I'; skip_next=yes;; \ 57 | -*I?*) strip_trailopt 'I';; \ 58 | -*O) strip_trailopt 'O'; skip_next=yes;; \ 59 | -*O?*) strip_trailopt 'O';; \ 60 | -*l) strip_trailopt 'l'; skip_next=yes;; \ 61 | -*l?*) strip_trailopt 'l';; \ 62 | -[dEDm]) skip_next=yes;; \ 63 | -[JT]) skip_next=yes;; \ 64 | esac; \ 65 | case $$flg in \ 66 | *$$target_option*) has_opt=yes; break;; \ 67 | esac; \ 68 | done; \ 69 | test $$has_opt = yes 70 | am__make_dryrun = (target_option=n; $(am__make_running_with_option)) 71 | am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 72 | pkgdatadir = $(datadir)/@PACKAGE@ 73 | pkgincludedir = $(includedir)/@PACKAGE@ 74 | pkglibdir = $(libdir)/@PACKAGE@ 75 | pkglibexecdir = $(libexecdir)/@PACKAGE@ 76 | am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd 77 | install_sh_DATA = $(install_sh) -c -m 644 78 | install_sh_PROGRAM = $(install_sh) -c 79 | install_sh_SCRIPT = $(install_sh) -c 80 | INSTALL_HEADER = $(INSTALL_DATA) 81 | transform = $(program_transform_name) 82 | NORMAL_INSTALL = : 83 | PRE_INSTALL = : 84 | POST_INSTALL = : 85 | NORMAL_UNINSTALL = : 86 | PRE_UNINSTALL = : 87 | POST_UNINSTALL = : 88 | build_triplet = @build@ 89 | host_triplet = @host@ 90 | subdir = scripts 91 | ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 92 | am__aclocal_m4_deps = $(top_srcdir)/configure.ac 93 | am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ 94 | $(ACLOCAL_M4) 95 | DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) 96 | mkinstalldirs = $(install_sh) -d 97 | CONFIG_HEADER = $(top_builddir)/flexmalloc-config.h 98 | CONFIG_CLEAN_FILES = 99 | CONFIG_CLEAN_VPATH_FILES = 100 | AM_V_P = $(am__v_P_@AM_V@) 101 | am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) 102 | am__v_P_0 = false 103 | am__v_P_1 = : 104 | AM_V_GEN = $(am__v_GEN_@AM_V@) 105 | am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) 106 | am__v_GEN_0 = @echo " GEN " $@; 107 | am__v_GEN_1 = 108 | AM_V_at = $(am__v_at_@AM_V@) 109 | am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) 110 | am__v_at_0 = @ 111 | am__v_at_1 = 112 | depcomp = 113 | am__maybe_remake_depfiles = 114 | SOURCES = 115 | DIST_SOURCES = 116 | am__can_run_installinfo = \ 117 | case $$AM_UPDATE_INFO_DIR in \ 118 | n|no|NO) false;; \ 119 | *) (install-info --version) >/dev/null 2>&1;; \ 120 | esac 121 | am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) 122 | am__DIST_COMMON = $(srcdir)/Makefile.in 123 | DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) 124 | ACLOCAL = @ACLOCAL@ 125 | AMTAR = @AMTAR@ 126 | AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ 127 | AR = @AR@ 128 | AUTOCONF = @AUTOCONF@ 129 | AUTOHEADER = @AUTOHEADER@ 130 | AUTOMAKE = @AUTOMAKE@ 131 | AWK = @AWK@ 132 | BINUTILS_HOME = @BINUTILS_HOME@ 133 | CC = @CC@ 134 | CCAS = @CCAS@ 135 | CCASFLAGS = @CCASFLAGS@ 136 | CFLAGS = @CFLAGS@ 137 | CPP = @CPP@ 138 | CPPFLAGS = @CPPFLAGS@ 139 | CXX = @CXX@ 140 | CXXCPP = @CXXCPP@ 141 | CXXFLAGS = @CXXFLAGS@ 142 | CYGPATH_W = @CYGPATH_W@ 143 | DEFS = @DEFS@ 144 | DLLTOOL = @DLLTOOL@ 145 | DSYMUTIL = @DSYMUTIL@ 146 | DUMPBIN = @DUMPBIN@ 147 | ECHO_C = @ECHO_C@ 148 | ECHO_N = @ECHO_N@ 149 | ECHO_T = @ECHO_T@ 150 | EGREP = @EGREP@ 151 | EXEEXT = @EXEEXT@ 152 | FGREP = @FGREP@ 153 | GREP = @GREP@ 154 | INSTALL = @INSTALL@ 155 | INSTALL_DATA = @INSTALL_DATA@ 156 | INSTALL_PROGRAM = @INSTALL_PROGRAM@ 157 | INSTALL_SCRIPT = @INSTALL_SCRIPT@ 158 | INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ 159 | LD = @LD@ 160 | LDFLAGS = @LDFLAGS@ 161 | LIBOBJS = @LIBOBJS@ 162 | LIBS = @LIBS@ 163 | LIBTOOL = @LIBTOOL@ 164 | LIPO = @LIPO@ 165 | LN_S = @LN_S@ 166 | LTLIBOBJS = @LTLIBOBJS@ 167 | LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ 168 | MAKEINFO = @MAKEINFO@ 169 | MANIFEST_TOOL = @MANIFEST_TOOL@ 170 | MEMKIND_HOME = @MEMKIND_HOME@ 171 | MKDIR_P = @MKDIR_P@ 172 | NM = @NM@ 173 | NMEDIT = @NMEDIT@ 174 | OBJDUMP = @OBJDUMP@ 175 | OBJEXT = @OBJEXT@ 176 | OTOOL = @OTOOL@ 177 | OTOOL64 = @OTOOL64@ 178 | PACKAGE = @PACKAGE@ 179 | PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ 180 | PACKAGE_NAME = @PACKAGE_NAME@ 181 | PACKAGE_STRING = @PACKAGE_STRING@ 182 | PACKAGE_TARNAME = @PACKAGE_TARNAME@ 183 | PACKAGE_URL = @PACKAGE_URL@ 184 | PACKAGE_VERSION = @PACKAGE_VERSION@ 185 | PAPI_HOME = @PAPI_HOME@ 186 | PATH_SEPARATOR = @PATH_SEPARATOR@ 187 | PMDK_HOME = @PMDK_HOME@ 188 | RANLIB = @RANLIB@ 189 | SED = @SED@ 190 | SET_MAKE = @SET_MAKE@ 191 | SHELL = @SHELL@ 192 | STRIP = @STRIP@ 193 | VERSION = @VERSION@ 194 | abs_builddir = @abs_builddir@ 195 | abs_srcdir = @abs_srcdir@ 196 | abs_top_builddir = @abs_top_builddir@ 197 | abs_top_srcdir = @abs_top_srcdir@ 198 | ac_ct_AR = @ac_ct_AR@ 199 | ac_ct_CC = @ac_ct_CC@ 200 | ac_ct_CXX = @ac_ct_CXX@ 201 | ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ 202 | am__leading_dot = @am__leading_dot@ 203 | am__tar = @am__tar@ 204 | am__untar = @am__untar@ 205 | bindir = @bindir@ 206 | build = @build@ 207 | build_alias = @build_alias@ 208 | build_cpu = @build_cpu@ 209 | build_os = @build_os@ 210 | build_vendor = @build_vendor@ 211 | builddir = @builddir@ 212 | datadir = @datadir@ 213 | datarootdir = @datarootdir@ 214 | docdir = @docdir@ 215 | dvidir = @dvidir@ 216 | exec_prefix = @exec_prefix@ 217 | host = @host@ 218 | host_alias = @host_alias@ 219 | host_cpu = @host_cpu@ 220 | host_os = @host_os@ 221 | host_vendor = @host_vendor@ 222 | htmldir = @htmldir@ 223 | includedir = @includedir@ 224 | infodir = @infodir@ 225 | install_sh = @install_sh@ 226 | libdir = @libdir@ 227 | libexecdir = @libexecdir@ 228 | localedir = @localedir@ 229 | localstatedir = @localstatedir@ 230 | mandir = @mandir@ 231 | mkdir_p = @mkdir_p@ 232 | oldincludedir = @oldincludedir@ 233 | pdfdir = @pdfdir@ 234 | prefix = @prefix@ 235 | program_transform_name = @program_transform_name@ 236 | psdir = @psdir@ 237 | runstatedir = @runstatedir@ 238 | sbindir = @sbindir@ 239 | sharedstatedir = @sharedstatedir@ 240 | srcdir = @srcdir@ 241 | sysconfdir = @sysconfdir@ 242 | target_alias = @target_alias@ 243 | top_build_prefix = @top_build_prefix@ 244 | top_builddir = @top_builddir@ 245 | top_srcdir = @top_srcdir@ 246 | EXTRA_DIST = flexmalloc.sh count.sh 247 | all: all-am 248 | 249 | .SUFFIXES: 250 | $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) 251 | @for dep in $?; do \ 252 | case '$(am__configure_deps)' in \ 253 | *$$dep*) \ 254 | ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ 255 | && { if test -f $@; then exit 0; else break; fi; }; \ 256 | exit 1;; \ 257 | esac; \ 258 | done; \ 259 | echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps scripts/Makefile'; \ 260 | $(am__cd) $(top_srcdir) && \ 261 | $(AUTOMAKE) --gnu --ignore-deps scripts/Makefile 262 | Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status 263 | @case '$?' in \ 264 | *config.status*) \ 265 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ 266 | *) \ 267 | echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ 268 | cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ 269 | esac; 270 | 271 | $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) 272 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 273 | 274 | $(top_srcdir)/configure: $(am__configure_deps) 275 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 276 | $(ACLOCAL_M4): $(am__aclocal_m4_deps) 277 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 278 | $(am__aclocal_m4_deps): 279 | 280 | mostlyclean-libtool: 281 | -rm -f *.lo 282 | 283 | clean-libtool: 284 | -rm -rf .libs _libs 285 | tags TAGS: 286 | 287 | ctags CTAGS: 288 | 289 | cscope cscopelist: 290 | 291 | 292 | distdir: $(BUILT_SOURCES) 293 | $(MAKE) $(AM_MAKEFLAGS) distdir-am 294 | 295 | distdir-am: $(DISTFILES) 296 | @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 297 | topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 298 | list='$(DISTFILES)'; \ 299 | dist_files=`for file in $$list; do echo $$file; done | \ 300 | sed -e "s|^$$srcdirstrip/||;t" \ 301 | -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ 302 | case $$dist_files in \ 303 | */*) $(MKDIR_P) `echo "$$dist_files" | \ 304 | sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ 305 | sort -u` ;; \ 306 | esac; \ 307 | for file in $$dist_files; do \ 308 | if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ 309 | if test -d $$d/$$file; then \ 310 | dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ 311 | if test -d "$(distdir)/$$file"; then \ 312 | find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ 313 | fi; \ 314 | if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ 315 | cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ 316 | find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ 317 | fi; \ 318 | cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ 319 | else \ 320 | test -f "$(distdir)/$$file" \ 321 | || cp -p $$d/$$file "$(distdir)/$$file" \ 322 | || exit 1; \ 323 | fi; \ 324 | done 325 | check-am: all-am 326 | check: check-am 327 | all-am: Makefile 328 | installdirs: 329 | install: install-am 330 | install-exec: install-exec-am 331 | install-data: install-data-am 332 | uninstall: uninstall-am 333 | 334 | install-am: all-am 335 | @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am 336 | 337 | installcheck: installcheck-am 338 | install-strip: 339 | if test -z '$(STRIP)'; then \ 340 | $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ 341 | install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ 342 | install; \ 343 | else \ 344 | $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ 345 | install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ 346 | "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ 347 | fi 348 | mostlyclean-generic: 349 | 350 | clean-generic: 351 | 352 | distclean-generic: 353 | -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) 354 | -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) 355 | 356 | maintainer-clean-generic: 357 | @echo "This command is intended for maintainers to use" 358 | @echo "it deletes files that may require special tools to rebuild." 359 | clean: clean-am 360 | 361 | clean-am: clean-generic clean-libtool mostlyclean-am 362 | 363 | distclean: distclean-am 364 | -rm -f Makefile 365 | distclean-am: clean-am distclean-generic 366 | 367 | dvi: dvi-am 368 | 369 | dvi-am: 370 | 371 | html: html-am 372 | 373 | html-am: 374 | 375 | info: info-am 376 | 377 | info-am: 378 | 379 | install-data-am: 380 | @$(NORMAL_INSTALL) 381 | $(MAKE) $(AM_MAKEFLAGS) install-data-hook 382 | install-dvi: install-dvi-am 383 | 384 | install-dvi-am: 385 | 386 | install-exec-am: 387 | 388 | install-html: install-html-am 389 | 390 | install-html-am: 391 | 392 | install-info: install-info-am 393 | 394 | install-info-am: 395 | 396 | install-man: 397 | 398 | install-pdf: install-pdf-am 399 | 400 | install-pdf-am: 401 | 402 | install-ps: install-ps-am 403 | 404 | install-ps-am: 405 | 406 | installcheck-am: 407 | 408 | maintainer-clean: maintainer-clean-am 409 | -rm -f Makefile 410 | maintainer-clean-am: distclean-am maintainer-clean-generic 411 | 412 | mostlyclean: mostlyclean-am 413 | 414 | mostlyclean-am: mostlyclean-generic mostlyclean-libtool 415 | 416 | pdf: pdf-am 417 | 418 | pdf-am: 419 | 420 | ps: ps-am 421 | 422 | ps-am: 423 | 424 | uninstall-am: 425 | 426 | .MAKE: install-am install-data-am install-strip 427 | 428 | .PHONY: all all-am check check-am clean clean-generic clean-libtool \ 429 | cscopelist-am ctags-am distclean distclean-generic \ 430 | distclean-libtool distdir dvi dvi-am html html-am info info-am \ 431 | install install-am install-data install-data-am \ 432 | install-data-hook install-dvi install-dvi-am install-exec \ 433 | install-exec-am install-html install-html-am install-info \ 434 | install-info-am install-man install-pdf install-pdf-am \ 435 | install-ps install-ps-am install-strip installcheck \ 436 | installcheck-am installdirs maintainer-clean \ 437 | maintainer-clean-generic mostlyclean mostlyclean-generic \ 438 | mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ 439 | uninstall-am 440 | 441 | .PRECIOUS: Makefile 442 | 443 | 444 | install-data-hook: 445 | mkdir -p $(bindir) 446 | cp $(srcdir)/flexmalloc.sh $(srcdir)/count.sh $(bindir) 447 | sed "s|@__sub_FLEXMALLOC_HOME__@|$(prefix)|g" -i $(bindir)/flexmalloc.sh 448 | sed "s|@__sub_FLEXMALLOC_HOME__@|$(prefix)|g" -i $(bindir)/count.sh 449 | chmod +x $(bindir)/flexmalloc.sh $(bindir)/count.sh 450 | 451 | # Tell versions [3.59,3.63) of GNU make to not export all variables. 452 | # Otherwise a system limit (for SysV at least) may be exceeded. 453 | .NOEXPORT: 454 | -------------------------------------------------------------------------------- /scripts/count.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | FLEXMALLOC_HOME=@__sub_FLEXMALLOC_HOME__@ 4 | 5 | library=libcounter 6 | 7 | # # If MPI rank is 0 or non MPI-execution, set minimum verbosity 8 | if [[ "${PMI_RANK}" == "0" || "${PMI_RANK}" == "" ]] ; then 9 | LD_PRELOAD=${FLEXMALLOC_HOME}/lib/${library}.so ${@} 10 | else 11 | LD_PRELOAD=${FLEXMALLOC_HOME}/lib/${library}.so ${@} > /dev/null 2> /dev/null 12 | fi 13 | 14 | -------------------------------------------------------------------------------- /scripts/flexmalloc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | FLEXMALLOC_HOME=@__sub_FLEXMALLOC_HOME__@ 4 | 5 | library=libflexmalloc 6 | if [[ ${FLEXMALLOC_DEBUG} == "1" ]] || [[ ${FLEXMALLOC_DEBUG} == "enabled" ]] || [[ ${FLEXMALLOC_DEBUG} == "yes" ]] ; then 7 | library=${library}_dbg 8 | fi 9 | 10 | if [[ $# -lt 3 ]] ; then 11 | echo Error! Check for parameters! 12 | echo 1st parameter: memory definitions 13 | echo 2nd parameter: data-object allocation locations 14 | echo 3rd and successive parameters: application process 15 | exit 16 | fi 17 | 18 | if [[ ! -f ${1} ]] ; then 19 | echo Warning! Cannot locate given definitions file ${1} 20 | fi 21 | 22 | if [[ ! -f ${2} ]] ; then 23 | echo Warning! Cannot locate given locations file ${2} 24 | fi 25 | 26 | export FLEXMALLOC_DEFINITIONS=${1} 27 | export FLEXMALLOC_LOCATIONS=${2} 28 | 29 | set_LD_PRELOAD="LD_PRELOAD=${FLEXMALLOC_HOME}/lib/${library}.so" 30 | runner="env ${set_LD_PRELOAD}" 31 | 32 | mpi_rank="${PMIX_RANK}" 33 | if [[ -z "${mpi_rank}" ]]; then 34 | mpi_rank="${PMI_RANK}" 35 | fi 36 | 37 | if test -z "${TMPDIR}" 38 | then 39 | TMPDIR=/tmp 40 | fi 41 | 42 | # # If MPI rank is 0 or non MPI-execution, set minimum verbosity 43 | if [[ "${mpi_rank}" == "0" || "${mpi_rank}" == "" ]] ; then 44 | # Set verbose level 1 if no verbosity requested in rank 0 45 | if [[ "${FLEXMALLOC_VERBOSE}" == "" ]] ; then 46 | export FLEXMALLOC_VERBOSE=1 47 | fi 48 | # Ease the starting of a program using flexmalloc through GDB debugger 49 | if test -n "${FLEXMALLOC_GDB}" 50 | then 51 | tmp_gdb=`mktemp "${TMPDIR}"/flexmalloc_gdb_cmd_file.XXXXXX` 52 | cat >$tmp_gdb < /dev/null 2> /dev/null 69 | fi 70 | 71 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | lib_LTLIBRARIES = libflexmalloc.la libflexmalloc_dbg.la libcounter.la 2 | 3 | libflexmalloc_la_SOURCES = \ 4 | common.cxx common.hxx \ 5 | utils.cxx utils.hxx \ 6 | bfd-manager.cxx bfd-manager.hxx \ 7 | code-locations.cxx code-locations.hxx \ 8 | allocators.cxx allocators.hxx \ 9 | allocator.cxx allocator.hxx \ 10 | allocator-posix.cxx allocator-posix.hxx \ 11 | allocator-statistics.cxx allocator-statistics.hxx \ 12 | cache-callstack.cxx cache-callstack.hxx \ 13 | flex-malloc.cxx flex-malloc.hxx \ 14 | malloc-interposer.cxx 15 | libflexmalloc_dbg_la_SOURCES = $(libflexmalloc_la_SOURCES) 16 | 17 | libflexmalloc_la_CXXFLAGS = -O3 -DNDEBUG -Wall -Wextra -std=c++11 -I.. -I$(BINUTILS_HOME)/include -pthread 18 | libflexmalloc_la_LDFLAGS = -DNDEBUG -ldl -L$(BINUTILS_HOME)/lib -lbfd -liberty -lpthread 19 | libflexmalloc_dbg_la_CXXFLAGS = -O3 -Wall -Wextra -DDEBUG -std=c++11 -I.. -I$(BINUTILS_HOME)/include -pthread 20 | libflexmalloc_dbg_la_LDFLAGS = -ldl -L$(BINUTILS_HOME)/lib -lbfd -liberty -lpthread 21 | 22 | if HAVE_MEMKIND 23 | libflexmalloc_la_SOURCES += \ 24 | allocator-memkind-hbwmalloc.cxx allocator-memkind-hbwmalloc.hxx \ 25 | allocator-memkind-pmem.cxx allocator-memkind-pmem.hxx 26 | libflexmalloc_la_CXXFLAGS += -I$(MEMKIND_HOME)/include 27 | libflexmalloc_la_LDFLAGS += -L$(MEMKIND_HOME)/lib -lmemkind -R $(MEMKIND_HOME)/lib -lnuma 28 | libflexmalloc_dbg_la_CXXFLAGS += -I$(MEMKIND_HOME)/include 29 | libflexmalloc_dbg_la_LDFLAGS += -L$(MEMKIND_HOME)/lib -lmemkind -R $(MEMKIND_HOME)/lib -lnuma 30 | endif 31 | 32 | if HAVE_PAPI 33 | libflexmalloc_la_CXXFLAGS += -DHWC -I$(PAPI_HOME)/include 34 | libflexmalloc_la_LDFLAGS += -L$(PAPI_HOME)/lib -lpapi -R $(PAPI_HOME)/lib 35 | libflexmalloc_dbg_la_CXXFLAGS += -DHWC -I$(PAPI_HOME)/include 36 | libflexmalloc_dbg_la_LDFLAGS += -L$(PAPI_HOME)/lib -lpapi -R $(PAPI_HOME)/lib 37 | endif 38 | 39 | if HAVE_PMDK 40 | libflexmalloc_la_CXXFLAGS += -I$(PMDK_HOME)/include 41 | libflexmalloc_la_LDFLAGS += -L$(PMDK_HOME)/lib -lpmem -R $(PMDK_HOME)/lib 42 | libflexmalloc_dbg_la_CXXFLAGS += -I$(PMDK_HOME)/include 43 | libflexmalloc_dbg_la_LDFLAGS += -L$(PMDK_HOME)/lib -lpmem -R $(PMDK_HOME)/lib 44 | endif 45 | 46 | libcounter_la_SOURCES = counter.cxx 47 | libcounter_la_CXXFLAGS = -O3 -DNDEBUG -Wall -Wextra -std=c++11 48 | libcounter_la_LDFLAGS = -DNDEBUG -ldl 49 | -------------------------------------------------------------------------------- /src/allocator-memkind-hbwmalloc.cxx: -------------------------------------------------------------------------------- 1 | // Author: Harald Servat 2 | // Date: Feb 10, 2017 3 | // License: To determine 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "common.hxx" 13 | #include "allocator-memkind-hbwmalloc.hxx" 14 | 15 | #define ALLOCATOR_NAME "memkind/hbwmalloc" 16 | 17 | AllocatorMemkindHBWMalloc::AllocatorMemkindHBWMalloc (allocation_functions_t &af) 18 | : Allocator (af) 19 | { 20 | hbw_set_policy (HBW_POLICY_PREFERRED); 21 | } 22 | 23 | AllocatorMemkindHBWMalloc::~AllocatorMemkindHBWMalloc () 24 | { 25 | } 26 | 27 | void * AllocatorMemkindHBWMalloc::malloc (size_t size) 28 | { 29 | // Forward memory request to real malloc and reserve some space for the header 30 | void * baseptr = hbw_malloc (Allocator::getTotalSize (size)); 31 | void * res = nullptr; 32 | 33 | // If malloc succeded, then forge a header and the pointer points to the 34 | // data space after the header 35 | if (baseptr) 36 | { 37 | res = Allocator::generateAllocatorHeader (baseptr, this, size); 38 | 39 | // Verbosity and emit statistics 40 | VERBOSE_MSG(3, ALLOCATOR_NAME": Allocated %lu bytes in %p (hdr & base at %p) w/ allocator %s (%p)\n", size, res, Allocator::getAllocatorHeader (res), name(), this); 41 | _stats.record_malloc (size); 42 | } 43 | 44 | return res; 45 | } 46 | 47 | void * AllocatorMemkindHBWMalloc::calloc (size_t nmemb, size_t size) 48 | { 49 | // Forward memory request to real malloc and request additional space to store 50 | // the allocator and the basepointer 51 | void * baseptr = hbw_malloc (Allocator::getTotalSize (nmemb * size)); 52 | void * res = nullptr; 53 | 54 | // If malloc succeded, then forge a header and the pointer points to the 55 | // data space after the header 56 | if (baseptr) 57 | { 58 | res = Allocator::generateAllocatorHeader (baseptr, this, nmemb * size); 59 | 60 | // Verbosity and emit statistics 61 | VERBOSE_MSG(3, ALLOCATOR_NAME": Allocated %lu bytes in %p (hdr & base %p) w/ allocator %s (%p)\n", size, res, Allocator::getAllocatorHeader (res), name(), this); 62 | _stats.record_calloc (nmemb * size); 63 | } 64 | 65 | return res; 66 | } 67 | 68 | int AllocatorMemkindHBWMalloc::posix_memalign (void **ptr, size_t align, size_t size) 69 | { 70 | assert (ptr != nullptr); 71 | 72 | // Forward memory request to real malloc and request additional space to 73 | // store the allocator and the basepointer 74 | void * baseptr = hbw_malloc (Allocator::getTotalSize (size + align)); 75 | void * res = nullptr; 76 | 77 | // If malloc succeded, then forge a header and the pointer points to the 78 | // data space after the header 79 | if (baseptr) 80 | { 81 | res = Allocator::generateAllocatorHeaderOnAligned (baseptr, align, this, size); 82 | 83 | // Verbosity and emit statistics 84 | VERBOSE_MSG(3, ALLOCATOR_NAME": Allocated %lu bytes in %p (hdr %p, base %p) w/ allocator %s (%p)\n", size, res, Allocator::getAllocatorHeader (res), baseptr, name(), this); 85 | _stats.record_aligned_malloc (size + align); 86 | 87 | *ptr = res; 88 | return 0; 89 | } 90 | else 91 | return ENOMEM; 92 | } 93 | 94 | void AllocatorMemkindHBWMalloc::free (void *ptr) 95 | { 96 | Allocator::Header_t *hdr = Allocator::getAllocatorHeader (ptr); 97 | 98 | // When freeing the memory, need to free the base pointe 99 | VERBOSE_MSG(3, ALLOCATOR_NAME": Freeing up pointer %p (hdr %p) w/ size - %lu (base pointer located in %p)\n", ptr, hdr, hdr->size, hdr->base_ptr); 100 | 101 | _stats.record_free (hdr->size); 102 | hbw_free (hdr->base_ptr); 103 | } 104 | 105 | void * AllocatorMemkindHBWMalloc::realloc (void *ptr, size_t size) 106 | { 107 | // If previous pointer is not null, behave normally. otherwise, behave like a malloc but 108 | // without calling information 109 | if (ptr) 110 | { 111 | // Search for previous allocation size through the header 112 | Allocator::Header_t *prev_hdr = Allocator::getAllocatorHeader (ptr); 113 | size_t prev_size = prev_hdr->size; 114 | void * prev_baseptr = prev_hdr->base_ptr; 115 | uintptr_t extra_size = Allocator::getExtraSize (prev_hdr); 116 | 117 | if (prev_size < size) 118 | { 119 | // Reallocate, from base pointer to fit the new size plus a new header 120 | void *new_baseptr = hbw_realloc (prev_baseptr, Allocator::getTotalSize (size + extra_size)); 121 | void *res = nullptr; 122 | 123 | // If realloc was successful, it also copied the data from previous allocation. 124 | // We need to update the header. 125 | if (new_baseptr) 126 | { 127 | // res points to the space where the user can store their data 128 | res = Allocator::generateAllocatorHeader (new_baseptr, extra_size, this, size); 129 | DBG("Reallocated (%ld->%ld [extra bytes = %lu]) from %p (base at %p, header at %p) into %p (base at %p, header at %p) w/ allocator %s (%p)\n", prev_size, size, extra_size, ptr, prev_baseptr, prev_hdr, res, new_baseptr, Allocator::getAllocatorHeader (res), name(), this); 130 | } 131 | 132 | _stats.record_realloc (size, prev_size); 133 | 134 | return res; 135 | } 136 | else 137 | { 138 | DBG("Reallocated (%ld->%ld) from %p but not touching as new size is smaller w/ allocator %s (%p)\n", prev_size, size, ptr, name(), this); 139 | return ptr; 140 | } 141 | } 142 | else 143 | { 144 | VERBOSE_MSG(3, ALLOCATOR_NAME": realloc (NULL, ...) forwarded to malloc\n"); 145 | _stats.record_realloc_forward_malloc(); 146 | 147 | return this->malloc (size); 148 | } 149 | } 150 | 151 | size_t AllocatorMemkindHBWMalloc::malloc_usable_size (void *ptr) 152 | { 153 | Allocator::Header_t *hdr = Allocator::getAllocatorHeader (ptr); 154 | 155 | // When checking for the usable size, return the size we requested originally, no matter 156 | // what the underlying library did. This may alter execution behaviors, though. 157 | VERBOSE_MSG(3, ALLOCATOR_NAME": Checking usable size on pointer %p w/ size - %lu (but base pointer located in %p)\n", 158 | ptr, hdr->size, hdr->base_ptr); 159 | 160 | return hdr->size; 161 | } 162 | 163 | void AllocatorMemkindHBWMalloc::configure (const char *config) 164 | { 165 | const char * MEMORYCONFIG_SIZE = "Size "; 166 | const char * MEMORYCONFIG_MBYTES_SUFFIX = " MBytes"; 167 | 168 | if (strncmp (config, MEMORYCONFIG_SIZE, strlen(MEMORYCONFIG_SIZE)) == 0) 169 | { 170 | // Get given size after the Size marker 171 | char *pEnd = nullptr; 172 | long long s_size = strtoll (&config[strlen(MEMORYCONFIG_SIZE)], &pEnd, 10); 173 | // Was text converted into s? If so, now look for suffix 174 | if (pEnd != &config[strlen(MEMORYCONFIG_SIZE)]) 175 | { 176 | if (strncmp (pEnd, MEMORYCONFIG_MBYTES_SUFFIX, strlen(MEMORYCONFIG_MBYTES_SUFFIX)) == 0) 177 | { 178 | size_t s; 179 | if (s_size < 0) 180 | { 181 | VERBOSE_MSG(1, ALLOCATOR_NAME": Invalid given size.\n"); 182 | exit (1); 183 | } 184 | else 185 | s = s_size; 186 | VERBOSE_MSG(1, ALLOCATOR_NAME": Setting up size %lu MBytes.\n", s); 187 | size (s << 20); 188 | } 189 | else 190 | { 191 | VERBOSE_MSG(0, ALLOCATOR_NAME": Invalid size suffix.\n"); 192 | exit (1); 193 | } 194 | } 195 | else 196 | { 197 | VERBOSE_MSG(0, ALLOCATOR_NAME": Could not parse given size.\n"); 198 | exit (1); 199 | } 200 | } 201 | else 202 | { 203 | VERBOSE_MSG(0, ALLOCATOR_NAME": Wrong configuration for the allocator. Available options include:\n" 204 | " Size MBytes\n"); 205 | exit (1); 206 | } 207 | 208 | _is_ready = true; 209 | } 210 | 211 | const char * AllocatorMemkindHBWMalloc::name (void) const 212 | { 213 | return ALLOCATOR_NAME; 214 | } 215 | 216 | const char * AllocatorMemkindHBWMalloc::description (void) const 217 | { 218 | return "Allocator based on hbwmalloc on top of memkind"; 219 | } 220 | 221 | void AllocatorMemkindHBWMalloc::show_statistics (void) const 222 | { 223 | _stats.show_statistics (ALLOCATOR_NAME, true); 224 | } 225 | 226 | bool AllocatorMemkindHBWMalloc::fits (size_t s) const 227 | { 228 | return _stats.water_mark() + s <= this->size(); 229 | } 230 | -------------------------------------------------------------------------------- /src/allocator-memkind-hbwmalloc.hxx: -------------------------------------------------------------------------------- 1 | // Author: Harald Servat 2 | // Date: Feb 10, 2017 3 | // License: To determine 4 | 5 | #pragma once 6 | 7 | #include "allocator.hxx" 8 | 9 | class AllocatorMemkindHBWMalloc final : public Allocator 10 | { 11 | private: 12 | AllocatorStatistics _stats; 13 | 14 | public: 15 | AllocatorMemkindHBWMalloc (allocation_functions_t &); 16 | ~AllocatorMemkindHBWMalloc(); 17 | 18 | void* malloc (size_t); 19 | void* calloc (size_t, size_t); 20 | int posix_memalign (void **, size_t, size_t); 21 | void free (void *); 22 | void* realloc (void *, size_t); 23 | size_t malloc_usable_size (void*); 24 | 25 | void configure (const char *); 26 | const char * name (void) const; 27 | const char * description (void) const; 28 | void show_statistics (void) const; 29 | 30 | void *memcpy (void *dest, const void *src, size_t n) 31 | { return ::memcpy (dest, src, n); } 32 | 33 | bool fits (size_t s) const; 34 | size_t hwm (void) const 35 | { return _stats.water_mark(); } 36 | void record_unfitted_malloc (size_t s) 37 | { _stats.record_unfitted_malloc (s); } ; 38 | void record_unfitted_calloc (size_t s) 39 | { _stats.record_unfitted_calloc (s); } ; 40 | void record_unfitted_aligned_malloc (size_t s) 41 | { _stats.record_unfitted_aligned_malloc (s); } ; 42 | void record_unfitted_realloc (size_t s) 43 | { _stats.record_unfitted_realloc (s); } ; 44 | 45 | void record_source_realloc (size_t s) 46 | { _stats.record_source_realloc (s); }; 47 | void record_target_realloc (size_t s) 48 | { _stats.record_target_realloc (s); }; 49 | void record_self_realloc (size_t s) 50 | { _stats.record_self_realloc (s); }; 51 | 52 | void record_realloc_forward_malloc (void) 53 | { _stats.record_realloc_forward_malloc (); } 54 | }; 55 | -------------------------------------------------------------------------------- /src/allocator-memkind-pmem.cxx: -------------------------------------------------------------------------------- 1 | // Author: Harald Servat 2 | // Date: Feb 10, 2017 3 | // Author: Clement Foyer 4 | // Date: Aug 24, 2023 5 | // License: To determine 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "flex-malloc.hxx" 18 | 19 | #include "common.hxx" 20 | #include "allocator-memkind-pmem.hxx" 21 | 22 | #define ALLOCATOR_NAME "memkind/pmem" 23 | 24 | AllocatorMemkindPMEM::AllocatorMemkindPMEM (allocation_functions_t &af) 25 | : Allocator (af) 26 | { 27 | if (numa_available() == -1) 28 | { 29 | VERBOSE_MSG(0, "Error! NUMA is not supported in this machine!\n"); 30 | exit (-1); 31 | } 32 | _num_NUMA_nodes = numa_num_configured_nodes(); 33 | int _num_CPUs = numa_num_configured_cpus(); 34 | 35 | _cpu_2_NUMA = (short*) _af.malloc (sizeof(short)*_num_CPUs); 36 | assert (_cpu_2_NUMA != nullptr); 37 | for (int c = 0; c < _num_CPUs; ++c) 38 | _cpu_2_NUMA[c] = numa_node_of_cpu(c); 39 | 40 | _kind = (memkind_t*) _af.malloc (sizeof(memkind_t)*_num_NUMA_nodes); 41 | assert (_kind != nullptr); 42 | 43 | _stats = (AllocatorStatistics*) _af.malloc (_num_NUMA_nodes * sizeof(AllocatorStatistics)); 44 | assert (_stats != nullptr); 45 | new (_stats) AllocatorStatistics[_num_NUMA_nodes]; 46 | } 47 | 48 | AllocatorMemkindPMEM::~AllocatorMemkindPMEM () 49 | { 50 | _af.free (_stats); 51 | _af.free (_kind); 52 | _af.free (_cpu_2_NUMA); 53 | } 54 | 55 | void * AllocatorMemkindPMEM::malloc (size_t size) 56 | { 57 | int cpu = sched_getcpu(); 58 | long n = _cpu_2_NUMA[cpu]; 59 | assert (0 <= n && n < _num_NUMA_nodes); 60 | 61 | DBG("Running on CPU %d - NUMA node %ld\n", cpu, n); 62 | 63 | // Forward memory request to real malloc and reserve some space for the header 64 | void * baseptr = memkind_malloc (_kind[n], Allocator::getTotalSize (size)); 65 | void * res = nullptr; 66 | 67 | // If malloc succeded, then forge a header and the pointer points to the 68 | // data space after the header 69 | if (baseptr) 70 | { 71 | res = Allocator::generateAllocatorHeader (baseptr, this, size); 72 | Allocator::pmemNode (res, n); 73 | 74 | // Verbosity and emit statistics 75 | VERBOSE_MSG(3, ALLOCATOR_NAME": Allocated %lu bytes in %p (hdr & base at %p) w/ allocator %s (%p)\n", size, res, Allocator::getAllocatorHeader (res), name(), this); 76 | _stats[n].record_malloc (size); 77 | } 78 | 79 | return res; 80 | } 81 | 82 | void * AllocatorMemkindPMEM::calloc (size_t nmemb, size_t size) 83 | { 84 | int cpu = sched_getcpu(); 85 | long n = _cpu_2_NUMA[cpu]; 86 | assert (0 <= n && n < _num_NUMA_nodes); 87 | 88 | DBG("Running on CPU %d - NUMA node %ld\n", cpu, n); 89 | 90 | // Forward memory request to real malloc and request additional space to store 91 | // the allocator and the basepointer 92 | void * baseptr = memkind_malloc (_kind[n], Allocator::getTotalSize (nmemb * size)); 93 | void * res = nullptr; 94 | 95 | // If malloc succeded, then forge a header and the pointer points to the 96 | // data space after the header 97 | if (baseptr) 98 | { 99 | res = Allocator::generateAllocatorHeader (baseptr, this, nmemb * size); 100 | Allocator::pmemNode (res, n); 101 | 102 | // Verbosity and emit statistics 103 | VERBOSE_MSG(3, ALLOCATOR_NAME": Allocated %lu bytes in %p (hdr & base %p) w/ allocator %s (%p)\n", size, res, Allocator::getAllocatorHeader (res), name(), this); 104 | _stats[n].record_calloc (nmemb * size); 105 | } 106 | 107 | return res; 108 | } 109 | 110 | int AllocatorMemkindPMEM::posix_memalign (void **ptr, size_t align, size_t size) 111 | { 112 | assert (ptr != nullptr); 113 | 114 | int cpu = sched_getcpu(); 115 | long n = _cpu_2_NUMA[cpu]; 116 | assert (0 <= n && n < _num_NUMA_nodes); 117 | 118 | DBG("Running on CPU %d - NUMA node %ld\n", cpu, n); 119 | 120 | // Forward memory request to real malloc and request additional space to 121 | // store the allocator and the basepointer 122 | void * baseptr = memkind_malloc (_kind[n], Allocator::getTotalSize (size + align)); 123 | void * res = nullptr; 124 | 125 | // If malloc succeded, then forge a header and the pointer points to the 126 | // data space after the header 127 | if (baseptr) 128 | { 129 | res = Allocator::generateAllocatorHeaderOnAligned (baseptr, align, this, size); 130 | Allocator::pmemNode (res, n); 131 | 132 | // Verbosity and emit statistics 133 | VERBOSE_MSG(3, ALLOCATOR_NAME": Allocated %lu bytes in %p (hdr %p, base %p) w/ allocator %s (%p)\n", size, res, Allocator::getAllocatorHeader (res), baseptr, name(), this); 134 | _stats[n].record_aligned_malloc (size + align); 135 | 136 | *ptr = res; 137 | return 0; 138 | } 139 | else 140 | return ENOMEM; 141 | } 142 | 143 | void AllocatorMemkindPMEM::free (void *ptr) 144 | { 145 | Allocator::Header_t *hdr = Allocator::getAllocatorHeader (ptr); 146 | 147 | // When freeing the memory, need to free the base pointe 148 | VERBOSE_MSG(3, ALLOCATOR_NAME": Freeing up pointer %p (hdr %p) w/ size - %lu (base pointer located in %p)\n", ptr, hdr, hdr->size, hdr->base_ptr); 149 | 150 | // Recover memkind kind from AUX field and pass base pointer 151 | bool gotnode; 152 | int n = Allocator::pmemNode (ptr, gotnode); 153 | assert (gotnode); 154 | assert (0 <= n && n < _num_NUMA_nodes); 155 | 156 | _stats[n].record_free (hdr->size); 157 | memkind_free (_kind[n], hdr->base_ptr); 158 | } 159 | 160 | void * AllocatorMemkindPMEM::realloc (void *ptr, size_t size) 161 | { 162 | // If previous pointer is not null, behave normally. otherwise, behave like a malloc but 163 | // without calling information 164 | if (ptr) 165 | { 166 | // Search for previous allocation size through the header 167 | Allocator::Header_t *prev_hdr = Allocator::getAllocatorHeader (ptr); 168 | size_t prev_size = prev_hdr->size; 169 | void * prev_baseptr = prev_hdr->base_ptr; 170 | // Recover memkind kind from AUX field and pass base pointer 171 | bool gotnode; 172 | int n = Allocator::pmemNode (ptr, gotnode); 173 | assert (gotnode); 174 | assert (0 <= n && n < _num_NUMA_nodes); 175 | uintptr_t extra_size = Allocator::getExtraSize (prev_hdr); 176 | 177 | if (prev_size < size) 178 | { 179 | // Reallocate, from base pointer to fit the new size plus a new header 180 | void *new_baseptr = memkind_realloc (_kind[n], prev_baseptr, Allocator::getTotalSize (size + extra_size)); 181 | void *res = nullptr; 182 | 183 | // If realloc was successful, it also copied the data from previous allocation. 184 | // We need to update the header. 185 | if (new_baseptr) 186 | { 187 | res = Allocator::generateAllocatorHeader (new_baseptr, extra_size, this, size); 188 | Allocator::pmemNode (res, n); 189 | 190 | DBG("Reallocated (%ld->%ld [extra bytes = %lu]) from %p (base at %p, header at %p) into %p (base at %p, header at %p) w/ allocator %s (%p) on node %d\n", prev_size, size, extra_size, ptr, prev_baseptr, prev_hdr, res, new_baseptr, Allocator::getAllocatorHeader (res), name(), this, n); 191 | } 192 | 193 | _stats[n].record_realloc (size, prev_size); 194 | 195 | return res; 196 | } 197 | else 198 | { 199 | DBG("Reallocated (%ld->%ld) from %p but not touching as new size is smaller w/ allocator %s (%p)\n", prev_size, size, ptr, name(), this); 200 | return ptr; 201 | } 202 | } 203 | else 204 | { 205 | VERBOSE_MSG(3, ALLOCATOR_NAME": realloc (NULL, ...) forwarded to malloc\n"); 206 | int cpu = sched_getcpu(); 207 | long n = _cpu_2_NUMA[cpu]; 208 | _stats[n].record_realloc_forward_malloc(); 209 | 210 | return this->malloc (size); 211 | } 212 | } 213 | 214 | size_t AllocatorMemkindPMEM::malloc_usable_size (void * ptr) 215 | { 216 | Allocator::Header_t *hdr = Allocator::getAllocatorHeader (ptr); 217 | 218 | // When checking for the usable size, return the size we requested originally, no matter 219 | // what the underlying library did. This may alter execution behaviors, though. 220 | VERBOSE_MSG(3, ALLOCATOR_NAME": Checking usable size on pointer %p w/ size - %lu (but base pointer located in %p)\n", 221 | ptr, hdr->size, hdr->base_ptr); 222 | 223 | return hdr->size; 224 | } 225 | 226 | void AllocatorMemkindPMEM::configure (const char *config) 227 | { 228 | int nnodes = 0; 229 | 230 | #warning This casting is necessary for gcc 7.3.1/fedora 27 231 | for (char *tmp = strchr ((char*)config, '@'); 232 | tmp != nullptr && nnodes < _num_NUMA_nodes; 233 | tmp = strchr (tmp, '@')) 234 | { 235 | bool has_path = false; 236 | char path[PATH_MAX] = {0}; 237 | { 238 | // Copy into path the given path for PMEM -- skip every empty char after @ 239 | tmp++; 240 | constexpr char blankchars[] = " \n\r\t\f\v"; 241 | size_t count = strspn(tmp, blankchars); // skip blank chars 242 | const char* in = &tmp[count]; 243 | count = strcspn(in, blankchars); // count valid characters 244 | if (count == 0 || *in == '\0') 245 | { 246 | VERBOSE_MSG(0, "Error! pmem configuration line poorly formatted: nothing found after '@'.\n"); 247 | exit (-1); 248 | } 249 | const size_t path_len = std::min(count, sizeof(path)-1); 250 | memcpy(path, in, path_len); 251 | path[path_len] = '\0'; 252 | 253 | // If we have read something, then we have a path (not necessarily absolute) 254 | // Also check for untruncated path 255 | has_path = (count > 0 && path_len == count); 256 | } 257 | 258 | if (has_path) 259 | { 260 | DBG("Checking for directory %s for PMEM allocator.\n", path); 261 | struct stat statbuf; 262 | if (stat(path, &statbuf) == 0) 263 | { 264 | if (! S_ISDIR(statbuf.st_mode) ) 265 | { 266 | VERBOSE_MSG(0, "Error! Given path (%s) is not a directory.\n", path); 267 | exit (-1); 268 | } 269 | } 270 | else 271 | { 272 | VERBOSE_MSG(0, "Error! Cannot stat path (%s). Does it exist?\n", path); 273 | exit (-1); 274 | } 275 | DIR *dir = opendir (path); 276 | if (dir != nullptr) 277 | { 278 | closedir (dir); 279 | } 280 | else if (ENOENT == errno) 281 | { 282 | VERBOSE_MSG(0, "Error! Given path (%s) for PMEM allocator is not found.\n", path); 283 | exit (-1); 284 | } 285 | else 286 | { 287 | VERBOSE_MSG(0, "Error! An unknown error when opening given path (%s) for PMEM allocator.\n", path); 288 | exit (-1); 289 | } 290 | 291 | if (nnodes >= _num_NUMA_nodes) 292 | { 293 | VERBOSE_MSG(0, "Error! Number of given PMEM nodes is larger than the number of NUMA nodes (%d).\n", _num_NUMA_nodes); 294 | exit (-1); 295 | } 296 | 297 | int err = memkind_create_pmem (path, 0, &_kind[nnodes]); 298 | if (err) 299 | { 300 | VERBOSE_MSG(0, "Error! An error ocurred during memkind_create_pmem invocation for path %s.\n", path); 301 | char msg[1024]; 302 | memkind_error_message(err, msg, sizeof(msg)); 303 | VERBOSE_MSG_NOPREFIX(0, "%s", msg); 304 | exit (-1); 305 | } 306 | else 307 | VERBOSE_MSG(0, "* Successfully created PMEM on top of %s for NUMA node %d.\n", path, nnodes); 308 | 309 | nnodes++; 310 | } 311 | } 312 | 313 | if (nnodes != _num_NUMA_nodes) 314 | { 315 | VERBOSE_MSG(0, "Error! Incorrect number of PMEM nodes for PMEM allocator (%d). Should be equal to number of NUMA nodes (%d).\n", nnodes, _num_NUMA_nodes); 316 | exit (-1); 317 | } 318 | 319 | _is_ready = true; 320 | } 321 | 322 | const char * AllocatorMemkindPMEM::name (void) const 323 | { 324 | return ALLOCATOR_NAME; 325 | } 326 | 327 | const char * AllocatorMemkindPMEM::description (void) const 328 | { 329 | return "Allocator based on pmem on top of memkind"; 330 | } 331 | 332 | void AllocatorMemkindPMEM::show_statistics (void) const 333 | { 334 | char node[32]; 335 | 336 | for (long n = 0; n < _num_NUMA_nodes; ++n) 337 | { 338 | memset (node, 0, sizeof(node)); 339 | snprintf (node, sizeof(node), "node%ld", n); 340 | _stats[n].show_statistics (ALLOCATOR_NAME, true, node); 341 | } 342 | } 343 | 344 | bool AllocatorMemkindPMEM::fits (size_t) const 345 | { 346 | return true; 347 | } 348 | 349 | size_t AllocatorMemkindPMEM::hwm (void) const 350 | { 351 | int cpu = sched_getcpu(); 352 | long n = _cpu_2_NUMA[cpu]; 353 | return _stats[n].water_mark (); 354 | } 355 | 356 | void AllocatorMemkindPMEM::record_unfitted_malloc (size_t s) 357 | { 358 | int cpu = sched_getcpu(); 359 | long n = _cpu_2_NUMA[cpu]; 360 | _stats[n].record_unfitted_malloc (s); 361 | } 362 | 363 | void AllocatorMemkindPMEM::record_unfitted_calloc (size_t s) 364 | { 365 | int cpu = sched_getcpu(); 366 | long n = _cpu_2_NUMA[cpu]; 367 | _stats[n].record_unfitted_calloc (s); 368 | } 369 | 370 | void AllocatorMemkindPMEM::record_unfitted_aligned_malloc (size_t s) 371 | { 372 | int cpu = sched_getcpu(); 373 | long n = _cpu_2_NUMA[cpu]; 374 | _stats[n].record_unfitted_aligned_malloc (s); 375 | } 376 | 377 | void AllocatorMemkindPMEM::record_unfitted_realloc (size_t s) 378 | { 379 | int cpu = sched_getcpu(); 380 | long n = _cpu_2_NUMA[cpu]; 381 | _stats[n].record_unfitted_realloc (s); 382 | } 383 | 384 | void AllocatorMemkindPMEM::record_source_realloc (size_t s) 385 | { 386 | int cpu = sched_getcpu(); 387 | long n = _cpu_2_NUMA[cpu]; 388 | _stats[n].record_source_realloc (s); 389 | } 390 | 391 | void AllocatorMemkindPMEM::record_target_realloc (size_t s) 392 | { 393 | int cpu = sched_getcpu(); 394 | long n = _cpu_2_NUMA[cpu]; 395 | _stats[n].record_target_realloc (s); 396 | } 397 | 398 | void AllocatorMemkindPMEM::record_self_realloc (size_t s) 399 | { 400 | int cpu = sched_getcpu(); 401 | long n = _cpu_2_NUMA[cpu]; 402 | _stats[n].record_self_realloc (s); 403 | } 404 | 405 | void AllocatorMemkindPMEM::record_realloc_forward_malloc (void) 406 | { 407 | int cpu = sched_getcpu(); 408 | long n = _cpu_2_NUMA[cpu]; 409 | _stats[n].record_realloc_forward_malloc (); 410 | } 411 | 412 | -------------------------------------------------------------------------------- /src/allocator-memkind-pmem.hxx: -------------------------------------------------------------------------------- 1 | // Author: Harald Servat 2 | // Date: Feb 10, 2017 3 | // License: To determine 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | #if defined(PMDK_SUPPORTED) 10 | # include 11 | #else 12 | # include 13 | #endif 14 | 15 | #include "allocator.hxx" 16 | 17 | class AllocatorMemkindPMEM final : public Allocator 18 | { 19 | private: 20 | memkind_t *_kind; 21 | AllocatorStatistics *_stats; 22 | short *_cpu_2_NUMA; 23 | int _num_NUMA_nodes; 24 | 25 | public: 26 | AllocatorMemkindPMEM (allocation_functions_t &af); 27 | ~AllocatorMemkindPMEM(); 28 | 29 | void* malloc (size_t); 30 | void* calloc (size_t,size_t); 31 | int posix_memalign (void **, size_t, size_t); 32 | void free (void *); 33 | void* realloc (void *, size_t); 34 | size_t malloc_usable_size (void*); 35 | 36 | void configure (const char *); 37 | const char * name (void) const; 38 | const char * description (void) const; 39 | void show_statistics (void) const; 40 | 41 | void *memcpy (void *dest, const void *src, size_t n) 42 | { 43 | #if defined(PMDK_SUPPORTED) 44 | return ::pmem_memcpy (dest, src, n, 0); 45 | #else 46 | return ::memcpy (dest, src, n); 47 | #endif 48 | } 49 | 50 | bool fits (size_t s) const; 51 | size_t hwm (void) const; 52 | void record_unfitted_malloc (size_t s); 53 | void record_unfitted_calloc (size_t s); 54 | void record_unfitted_aligned_malloc (size_t s); 55 | void record_unfitted_realloc (size_t s); 56 | 57 | void record_source_realloc (size_t s); 58 | void record_target_realloc (size_t s); 59 | void record_self_realloc (size_t s); 60 | 61 | void record_realloc_forward_malloc (void); 62 | }; 63 | -------------------------------------------------------------------------------- /src/allocator-posix.cxx: -------------------------------------------------------------------------------- 1 | // Author: Harald Servat 2 | // Date: Feb 10, 2017 3 | // License: To determine 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "common.hxx" 11 | #include "allocator-posix.hxx" 12 | 13 | #define ALLOCATOR_NAME "posix" 14 | 15 | AllocatorPOSIX::AllocatorPOSIX (allocation_functions_t &af) 16 | : Allocator (af) 17 | { 18 | } 19 | 20 | AllocatorPOSIX::~AllocatorPOSIX () 21 | { 22 | } 23 | 24 | void * AllocatorPOSIX::malloc (size_t size) 25 | { 26 | // Forward memory request to real malloc and reserve some space for the header 27 | void * baseptr = _af.malloc (Allocator::getTotalSize (size)); 28 | void * res = nullptr; 29 | 30 | // If malloc succeded, then forge a header and the pointer points to the 31 | // data space after the header 32 | if (baseptr) 33 | { 34 | res = Allocator::generateAllocatorHeader (baseptr, this, size); 35 | 36 | // Verbosity and emit statistics 37 | VERBOSE_MSG(3, ALLOCATOR_NAME": Allocated %lu bytes in %p (hdr & base at %p) w/ allocator %s (%p)\n", size, res, Allocator::getAllocatorHeader (res), name(), this); 38 | _stats.record_malloc (size); 39 | } 40 | 41 | return res; 42 | } 43 | 44 | void * AllocatorPOSIX::calloc (size_t nmemb, size_t size) 45 | { 46 | // Forward memory request to real malloc and request additional space to store 47 | // the allocator and the basepointer 48 | void * baseptr = _af.malloc (Allocator::getTotalSize (nmemb * size)); 49 | void * res = nullptr; 50 | 51 | // If malloc succeded, then forge a header and the pointer points to the 52 | // data space after the header 53 | if (baseptr) 54 | { 55 | res = Allocator::generateAllocatorHeader (baseptr, this, nmemb *size); 56 | 57 | // Verbosity and emit statistics 58 | VERBOSE_MSG(3, ALLOCATOR_NAME": Allocated %lu bytes in %p (hdr & base %p) w/ allocator %s (%p)\n", size, res, Allocator::getAllocatorHeader (res), name(), this); 59 | _stats.record_calloc (nmemb * size); 60 | } 61 | 62 | return res; 63 | } 64 | 65 | int AllocatorPOSIX::posix_memalign (void **ptr, size_t align, size_t size) 66 | { 67 | assert (ptr != nullptr); 68 | 69 | // Forward memory request to real malloc and request additional space to 70 | // store the allocator and the basepointer 71 | void * baseptr = _af.malloc (Allocator::getTotalSize (size + align)); 72 | void * res = nullptr; 73 | // If malloc succeded, then forge a header and the pointer points to the 74 | // data space after the header 75 | if (baseptr) 76 | { 77 | res = Allocator::generateAllocatorHeaderOnAligned (baseptr, align, this, size); 78 | 79 | // Verbosity and emit statistics 80 | VERBOSE_MSG(3, ALLOCATOR_NAME": Allocated %lu bytes in %p (hdr %p, base %p) w/ allocator %s (%p)\n", size, res, Allocator::getAllocatorHeader (res), baseptr, name(), this); 81 | _stats.record_aligned_malloc (size + align); 82 | 83 | *ptr = res; 84 | return 0; 85 | } 86 | else 87 | return ENOMEM; 88 | } 89 | 90 | void AllocatorPOSIX::free (void *ptr) 91 | { 92 | Allocator::Header_t *hdr = Allocator::getAllocatorHeader (ptr); 93 | 94 | // When freeing the memory, need to free the base pointe 95 | VERBOSE_MSG(3, ALLOCATOR_NAME": Freeing up pointer %p (hdr %p) w/ size - %lu (base pointer located in %p)\n", ptr, hdr, hdr->size, hdr->base_ptr); 96 | 97 | _stats.record_free (hdr->size); 98 | _af.free (hdr->base_ptr); 99 | } 100 | 101 | void * AllocatorPOSIX::realloc (void *ptr, size_t size) 102 | { 103 | // If previous pointer is not null, behave normally. otherwise, behave like a malloc but 104 | // without calling information 105 | if (ptr) 106 | { 107 | // Search for previous allocation size through the header 108 | Allocator::Header_t *prev_hdr = Allocator::getAllocatorHeader (ptr); 109 | size_t prev_size = prev_hdr->size; 110 | void * prev_baseptr = prev_hdr->base_ptr; 111 | uintptr_t extra_size = Allocator::getExtraSize (prev_hdr); 112 | 113 | if (prev_size < size) 114 | { 115 | // Reallocate, from base pointer to fit the new size plus a new header 116 | void *new_baseptr = _af.realloc (prev_baseptr, Allocator::getTotalSize (size + extra_size)); 117 | void *res = nullptr; 118 | 119 | // If realloc was successful, it also copied the data from previous allocation. 120 | // We need to update the header. 121 | if (new_baseptr) 122 | { 123 | res = Allocator::generateAllocatorHeader (new_baseptr, extra_size, this, size); 124 | DBG("Reallocated (%ld->%ld [extra bytes = %lu]) from %p (base at %p, header at %p) into %p (base at %p, header at %p) w/ allocator %s (%p)\n", prev_size, size, extra_size, ptr, prev_baseptr, prev_hdr, res, new_baseptr, Allocator::getAllocatorHeader (res), name(), this); 125 | } 126 | 127 | _stats.record_realloc (size, prev_size); 128 | 129 | return res; 130 | } 131 | else 132 | { 133 | DBG("Reallocated (%ld->%ld) from %p but not touching as new size is smaller w/ allocator %s (%p)\n", prev_size, size, ptr, name(), this); 134 | return ptr; 135 | } 136 | } 137 | else 138 | { 139 | VERBOSE_MSG(3, ALLOCATOR_NAME": realloc (NULL, ...) forwarded to malloc\n"); 140 | _stats.record_realloc_forward_malloc(); 141 | 142 | return this->malloc (size); 143 | } 144 | } 145 | 146 | size_t AllocatorPOSIX::malloc_usable_size (void* ptr) 147 | { 148 | Allocator::Header_t *hdr = Allocator::getAllocatorHeader (ptr); 149 | 150 | // When checking for the usable size, return the size we requested originally, no matter 151 | // what the underlying library did. This may alter execution behaviors, though. 152 | VERBOSE_MSG(3, ALLOCATOR_NAME": Checking usable size on pointer %p w/ size - %lu (but base pointer located in %p)\n", 153 | ptr, hdr->size, hdr->base_ptr); 154 | 155 | return hdr->size; 156 | } 157 | 158 | void AllocatorPOSIX::configure (const char *config) 159 | { 160 | const char * MEMORYCONFIG_SIZE = "Size "; 161 | const char * MEMORYCONFIG_MBYTES_SUFFIX = " MBytes"; 162 | 163 | if (strncmp (config, MEMORYCONFIG_SIZE, strlen(MEMORYCONFIG_SIZE)) == 0) 164 | { 165 | // Get given size after the Size marker 166 | char *pEnd = nullptr; 167 | long long s_size = strtoll (&config[strlen(MEMORYCONFIG_SIZE)], &pEnd, 10); 168 | // Was text converted into s? If so, now look for suffix 169 | if (pEnd != &config[strlen(MEMORYCONFIG_SIZE)]) 170 | { 171 | if (strncmp (pEnd, MEMORYCONFIG_MBYTES_SUFFIX, strlen(MEMORYCONFIG_MBYTES_SUFFIX)) == 0) 172 | { 173 | size_t s; 174 | if (s_size < 0) 175 | { 176 | VERBOSE_MSG(1, ALLOCATOR_NAME": Invalid given size.\n"); 177 | exit (1); 178 | } 179 | else 180 | s = s_size; 181 | VERBOSE_MSG(1, ALLOCATOR_NAME": Setting up size %lu MBytes.\n", s); 182 | size (s << 20); 183 | } 184 | else 185 | { 186 | VERBOSE_MSG(0, ALLOCATOR_NAME": Invalid size suffix.\n"); 187 | exit (1); 188 | } 189 | } 190 | else 191 | { 192 | VERBOSE_MSG(0, ALLOCATOR_NAME": Could not parse given size.\n"); 193 | exit (1); 194 | } 195 | } 196 | else 197 | { 198 | VERBOSE_MSG(0, ALLOCATOR_NAME": Wrong configuration for the allocator. Available options include:\n" 199 | " Size MBytes\n"); 200 | exit (1); 201 | } 202 | 203 | _is_ready = true; 204 | } 205 | 206 | const char * AllocatorPOSIX::name (void) const 207 | { 208 | return ALLOCATOR_NAME; 209 | } 210 | 211 | const char * AllocatorPOSIX::description (void) const 212 | { 213 | return "Fallback allocator based on regular POSIX calls from system's libc"; 214 | } 215 | 216 | void AllocatorPOSIX::show_statistics (void) const 217 | { 218 | _stats.show_statistics (ALLOCATOR_NAME, true); 219 | } 220 | 221 | bool AllocatorPOSIX::fits (size_t s) const 222 | { 223 | return _stats.water_mark() + s <= this->size(); 224 | } 225 | -------------------------------------------------------------------------------- /src/allocator-posix.hxx: -------------------------------------------------------------------------------- 1 | // Author: Harald Servat 2 | // Date: Feb 10, 2017 3 | // License: To determine 4 | 5 | #pragma once 6 | 7 | #include "allocator.hxx" 8 | #include 9 | 10 | class AllocatorPOSIX final : public Allocator 11 | { 12 | private: 13 | AllocatorStatistics _stats; 14 | 15 | public: 16 | AllocatorPOSIX(allocation_functions_t &); 17 | ~AllocatorPOSIX(); 18 | 19 | void* malloc (size_t); 20 | void* calloc (size_t, size_t); 21 | int posix_memalign (void **, size_t, size_t); 22 | void free (void *); 23 | void* realloc (void *, size_t); 24 | size_t malloc_usable_size (void*); 25 | 26 | void configure (const char *); 27 | const char * name (void) const; 28 | const char * description (void) const; 29 | void show_statistics (void) const; 30 | 31 | void *memcpy (void *dest, const void *src, size_t n) 32 | { return ::memcpy (dest, src, n); } 33 | 34 | bool fits (size_t s) const; 35 | size_t hwm (void) const 36 | { return _stats.water_mark(); } 37 | void record_unfitted_malloc (size_t s) 38 | { _stats.record_unfitted_malloc (s); } ; 39 | void record_unfitted_calloc (size_t s) 40 | { _stats.record_unfitted_calloc (s); } ; 41 | void record_unfitted_aligned_malloc (size_t s) 42 | { _stats.record_unfitted_aligned_malloc (s); } ; 43 | void record_unfitted_realloc (size_t s) 44 | { _stats.record_unfitted_realloc (s); } ; 45 | 46 | void record_source_realloc (size_t s) 47 | { _stats.record_source_realloc (s); }; 48 | void record_target_realloc (size_t s) 49 | { _stats.record_target_realloc (s); }; 50 | void record_self_realloc (size_t s) 51 | { _stats.record_self_realloc (s); }; 52 | 53 | void record_realloc_forward_malloc (void) 54 | { _stats.record_realloc_forward_malloc (); } 55 | }; 56 | -------------------------------------------------------------------------------- /src/allocator-statistics.cxx: -------------------------------------------------------------------------------- 1 | // Author: Harald Servat 2 | // Date: Feb 10, 2017 3 | // License: To determine 4 | 5 | #include 6 | #include 7 | #include "allocator-statistics.hxx" 8 | #include "common.hxx" 9 | 10 | AllocatorStatistics::AllocatorStatistics () : 11 | high_water_mark (0), 12 | current_water_mark (0), 13 | malloc_total_allocated_size (0), 14 | malloc_min_allocated_size (LONG_MAX), 15 | malloc_max_allocated_size (0), 16 | calloc_total_allocated_size (0), 17 | calloc_min_allocated_size (LONG_MAX), 18 | calloc_max_allocated_size (0), 19 | aligned_malloc_total_allocated_size (0), 20 | aligned_malloc_min_allocated_size (LONG_MAX), 21 | aligned_malloc_max_allocated_size (0), 22 | realloc_total_allocated_size (0), 23 | realloc_min_allocated_size (LONG_MAX), 24 | realloc_max_allocated_size (0), 25 | n_malloc_calls (0), 26 | n_calloc_calls (0), 27 | n_aligned_malloc_calls (0), 28 | n_realloc_calls (0), 29 | n_free_calls (0), 30 | n_unfitted_malloc_calls (0), unfitted_malloc_calls_size(0), 31 | n_unfitted_calloc_calls (0), unfitted_calloc_calls_size (0), 32 | n_unfitted_aligned_malloc_calls (0), unfitted_aligned_malloc_calls_size (0), 33 | n_unfitted_realloc_calls (0), unfitted_realloc_calls_size (0), 34 | n_source_realloc (0), source_realloc_size (0), 35 | n_target_realloc (0), target_realloc_size (0), 36 | n_self_realloc (0), self_realloc_size (0), 37 | n_realloc_fwd_malloc (0) 38 | { 39 | } 40 | 41 | AllocatorStatistics::~AllocatorStatistics () 42 | { 43 | } 44 | 45 | void AllocatorStatistics::record_malloc (size_t s) 46 | { 47 | n_malloc_calls++; 48 | malloc_total_allocated_size += s; 49 | malloc_min_allocated_size = 50 | s > malloc_min_allocated_size ? malloc_min_allocated_size : s; 51 | malloc_max_allocated_size = 52 | s < malloc_max_allocated_size ? malloc_max_allocated_size : s; 53 | 54 | current_water_mark += s; 55 | if (current_water_mark > high_water_mark) 56 | high_water_mark = current_water_mark; 57 | } 58 | 59 | void AllocatorStatistics::record_calloc (size_t s) 60 | { 61 | n_calloc_calls++; 62 | calloc_total_allocated_size += s; 63 | calloc_min_allocated_size = 64 | s > calloc_min_allocated_size ? calloc_min_allocated_size : s; 65 | calloc_max_allocated_size = 66 | s < calloc_max_allocated_size ? calloc_max_allocated_size : s; 67 | 68 | current_water_mark += s; 69 | if (current_water_mark > high_water_mark) 70 | high_water_mark = current_water_mark; 71 | } 72 | 73 | void AllocatorStatistics::record_aligned_malloc (size_t s) 74 | { 75 | n_aligned_malloc_calls++; 76 | aligned_malloc_total_allocated_size += s; 77 | aligned_malloc_min_allocated_size = 78 | s > aligned_malloc_min_allocated_size ? aligned_malloc_min_allocated_size : s; 79 | aligned_malloc_max_allocated_size = 80 | s < aligned_malloc_max_allocated_size ? aligned_malloc_max_allocated_size : s; 81 | 82 | current_water_mark += s; 83 | if (current_water_mark > high_water_mark) 84 | high_water_mark = current_water_mark; 85 | } 86 | 87 | void AllocatorStatistics::record_realloc (size_t size, size_t prev_size) 88 | { 89 | n_realloc_calls++; 90 | realloc_total_allocated_size += size; 91 | realloc_min_allocated_size = 92 | size > realloc_min_allocated_size ? realloc_min_allocated_size : size; 93 | realloc_max_allocated_size = 94 | size < realloc_max_allocated_size ? realloc_max_allocated_size : size; 95 | 96 | if (current_water_mark > prev_size) 97 | current_water_mark -= prev_size; 98 | else 99 | current_water_mark = 0; // This should not happen 100 | 101 | current_water_mark += size; 102 | if (current_water_mark > high_water_mark) 103 | high_water_mark = current_water_mark; 104 | } 105 | 106 | void AllocatorStatistics::record_free (size_t s) 107 | { 108 | n_free_calls++; 109 | 110 | if (current_water_mark > s) 111 | current_water_mark -= s; 112 | else 113 | current_water_mark = 0; // This should not happen 114 | } 115 | 116 | void AllocatorStatistics::record_source_realloc (size_t s) 117 | { 118 | n_source_realloc++; 119 | source_realloc_size += s; 120 | } 121 | 122 | void AllocatorStatistics::record_target_realloc (size_t s) 123 | { 124 | n_target_realloc++; 125 | target_realloc_size += s; 126 | } 127 | 128 | void AllocatorStatistics::record_self_realloc (size_t s) 129 | { 130 | n_self_realloc++; 131 | self_realloc_size += s; 132 | } 133 | 134 | void AllocatorStatistics::record_unfitted_malloc (size_t s) 135 | { 136 | n_unfitted_malloc_calls++; 137 | unfitted_malloc_calls_size += s; 138 | } 139 | 140 | void AllocatorStatistics::record_unfitted_calloc (size_t s) 141 | { 142 | n_unfitted_calloc_calls++; 143 | unfitted_calloc_calls_size += s; 144 | } 145 | 146 | void AllocatorStatistics::record_unfitted_aligned_malloc (size_t s) 147 | { 148 | n_unfitted_aligned_malloc_calls++; 149 | unfitted_aligned_malloc_calls_size += s; 150 | } 151 | 152 | void AllocatorStatistics::record_unfitted_realloc (size_t s) 153 | { 154 | n_unfitted_realloc_calls++; 155 | unfitted_realloc_calls_size += s; 156 | } 157 | 158 | void AllocatorStatistics::record_realloc_forward_malloc (void) 159 | { 160 | n_realloc_fwd_malloc++; 161 | } 162 | 163 | void AllocatorStatistics::show_statistics (const char * allocator_name, 164 | bool show_high_water_mark, const char *extra_name) const 165 | { 166 | size_t s; 167 | if (extra_name) 168 | s = strlen(allocator_name) + strlen(extra_name) + 2 + 1; 169 | else 170 | s = strlen(allocator_name) + 1; 171 | char full_name[s]; 172 | memset (full_name, 0, sizeof(char)*s); 173 | if (extra_name) 174 | snprintf (full_name, s, "%s(%s)", allocator_name, extra_name); 175 | else 176 | snprintf (full_name, s, "%s", allocator_name); 177 | 178 | VERBOSE_MSG(1, "%s|Number of malloc calls: %u\n", full_name, n_malloc_calls); 179 | if (n_malloc_calls > 0) 180 | { 181 | VERBOSE_MSG(1, "%s|Malloc total allocated size = %lu bytes\n", 182 | full_name, malloc_total_allocated_size); 183 | VERBOSE_MSG(1, "%s|Malloc min allocated size = %lu bytes\n", 184 | full_name, malloc_min_allocated_size); 185 | VERBOSE_MSG(1 ,"%s|Malloc max allocated size = %lu bytes\n", 186 | full_name, malloc_max_allocated_size); 187 | VERBOSE_MSG(1, "%s|%u not fitted malloc calls = %lu bytes.\n", 188 | full_name, n_unfitted_malloc_calls, unfitted_malloc_calls_size); 189 | } 190 | if (n_realloc_fwd_malloc > 0) 191 | { 192 | VERBOSE_MSG(1, "%s|%u realloc calls were forwarded to malloc because of NULL pointer.\n", 193 | full_name, n_realloc_fwd_malloc); 194 | } 195 | 196 | VERBOSE_MSG(1, "%s|Number of calloc calls: %u\n", full_name, n_calloc_calls); 197 | if (n_calloc_calls > 0) 198 | { 199 | VERBOSE_MSG(1, "%s|Calloc total allocated size = %lu bytes\n", 200 | full_name, calloc_total_allocated_size); 201 | VERBOSE_MSG(1, "%s|Calloc min allocated size = %lu bytes\n", 202 | full_name, calloc_min_allocated_size); 203 | VERBOSE_MSG(1 ,"%s|Calloc max allocated size = %lu bytes\n", 204 | full_name, calloc_max_allocated_size); 205 | VERBOSE_MSG(1, "%s|%u not fitted calloc calls = %lu bytes.\n", 206 | full_name, n_unfitted_calloc_calls, unfitted_calloc_calls_size); 207 | } 208 | 209 | VERBOSE_MSG(1, "%s|Number of aligned malloc calls: %u\n", full_name, n_aligned_malloc_calls); 210 | if (n_aligned_malloc_calls > 0) 211 | { 212 | VERBOSE_MSG(1, "%s|Aligned malloc total allocated size = %lu bytes\n", 213 | full_name, aligned_malloc_total_allocated_size); 214 | VERBOSE_MSG(1, "%s|Aligned malloc min allocated size = %lu bytes\n", 215 | full_name, aligned_malloc_min_allocated_size); 216 | VERBOSE_MSG(1 ,"%s|Aligned malloc max allocated size = %lu bytes\n", 217 | full_name, aligned_malloc_max_allocated_size); 218 | VERBOSE_MSG(1, "%s|%u not fitted aligned malloc calls = %lu bytes.\n", 219 | full_name, n_unfitted_aligned_malloc_calls, unfitted_aligned_malloc_calls_size); 220 | } 221 | 222 | VERBOSE_MSG(1, "%s|Number of realloc calls: %u\n", full_name, n_realloc_calls); 223 | if (n_realloc_calls > 0) 224 | { 225 | if (n_self_realloc > 0) 226 | { 227 | VERBOSE_MSG(1, "%s| - %u realloc on same allocator for a total of %lu copied bytes.\n", 228 | full_name, n_self_realloc, self_realloc_size); 229 | } 230 | if (n_source_realloc > 0) 231 | { 232 | VERBOSE_MSG(1, "%s| - %u realloc as source allocator for a total of %lu copied bytes.\n", 233 | full_name, n_source_realloc, source_realloc_size); 234 | } 235 | if (n_target_realloc > 0) 236 | { 237 | VERBOSE_MSG(1, "%s| - %u realloc as target allocator for a total of %lu copied bytes.\n", 238 | full_name, n_target_realloc, target_realloc_size); 239 | } 240 | VERBOSE_MSG(1, "%s|Realloc total allocated size = %lu bytes\n", 241 | full_name, realloc_total_allocated_size); 242 | VERBOSE_MSG(1, "%s|Realloc min allocated size = %lu bytes\n", 243 | full_name, realloc_min_allocated_size); 244 | VERBOSE_MSG(1, "%s|Realloc max allocated size = %lu bytes\n", 245 | full_name, realloc_max_allocated_size); 246 | VERBOSE_MSG(1, "%s|%u not fitted realloc calls = %lu bytes.\n", 247 | full_name, n_unfitted_realloc_calls, unfitted_realloc_calls_size); 248 | } 249 | 250 | VERBOSE_MSG(1, "%s|Number of free calls: %u\n", full_name, n_free_calls); 251 | 252 | if (show_high_water_mark) 253 | { 254 | VERBOSE_MSG(1 ,"%s|High-water mark = %lu bytes\n", full_name, high_water_mark); 255 | } 256 | } 257 | 258 | -------------------------------------------------------------------------------- /src/allocator-statistics.hxx: -------------------------------------------------------------------------------- 1 | // Author: Harald Servat 2 | // Date: Feb 10, 2017 3 | // License: To determine 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | class AllocatorStatistics 10 | { 11 | private: 12 | size_t high_water_mark; 13 | size_t current_water_mark; 14 | size_t malloc_total_allocated_size; 15 | size_t malloc_min_allocated_size; 16 | size_t malloc_max_allocated_size; 17 | size_t calloc_total_allocated_size; 18 | size_t calloc_min_allocated_size; 19 | size_t calloc_max_allocated_size; 20 | size_t aligned_malloc_total_allocated_size; 21 | size_t aligned_malloc_min_allocated_size; 22 | size_t aligned_malloc_max_allocated_size; 23 | size_t realloc_total_allocated_size; 24 | size_t realloc_min_allocated_size; 25 | size_t realloc_max_allocated_size; 26 | unsigned n_malloc_calls; 27 | unsigned n_calloc_calls; 28 | unsigned n_aligned_malloc_calls; 29 | unsigned n_realloc_calls; 30 | unsigned n_free_calls; 31 | unsigned n_unfitted_malloc_calls; 32 | size_t unfitted_malloc_calls_size; 33 | unsigned n_unfitted_calloc_calls; 34 | size_t unfitted_calloc_calls_size; 35 | unsigned n_unfitted_aligned_malloc_calls; 36 | size_t unfitted_aligned_malloc_calls_size; 37 | unsigned n_unfitted_realloc_calls; 38 | size_t unfitted_realloc_calls_size; 39 | unsigned n_source_realloc; 40 | size_t source_realloc_size; 41 | unsigned n_target_realloc; 42 | size_t target_realloc_size; 43 | unsigned n_self_realloc; 44 | size_t self_realloc_size; 45 | unsigned n_realloc_fwd_malloc; // number of realloc(null, X) forwarded to malloc (X) 46 | 47 | public: 48 | AllocatorStatistics (); 49 | ~AllocatorStatistics (); 50 | 51 | void record_malloc (size_t); 52 | void record_calloc (size_t); 53 | void record_aligned_malloc (size_t); 54 | void record_realloc (size_t size, size_t prev_size); 55 | void record_free (size_t); 56 | 57 | void record_source_realloc (size_t s); 58 | void record_target_realloc (size_t s); 59 | void record_self_realloc (size_t s); 60 | 61 | void record_unfitted_malloc (size_t); 62 | void record_unfitted_calloc (size_t); 63 | void record_unfitted_aligned_malloc (size_t); 64 | void record_unfitted_realloc (size_t); 65 | 66 | void record_realloc_forward_malloc (void); 67 | 68 | void show_statistics (const char * allocator_name, 69 | bool show_high_water_mark, const char *extra_name = nullptr) const; 70 | 71 | size_t water_mark (void) const { return current_water_mark; }; 72 | }; 73 | 74 | -------------------------------------------------------------------------------- /src/allocator.cxx: -------------------------------------------------------------------------------- 1 | // Author: Harald Servat 2 | // Date: Feb 10, 2017 3 | // License: To determine 4 | 5 | #include "allocator.hxx" 6 | 7 | // Macro to align an address to the nearest power of two 8 | #ifndef align_to 9 | # define align_to(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) 10 | #endif 11 | 12 | size_t Allocator::getTotalSize (size_t size) 13 | { 14 | return size + ALLOCATOR_HEADER_SZ; 15 | } 16 | 17 | Allocator::Header_t * Allocator::getAllocatorHeader (void * ptr) 18 | { 19 | return (Header_t*) ((uintptr_t) ptr - ALLOCATOR_HEADER_SZ); 20 | } 21 | 22 | void * Allocator::generateAllocatorHeader (void *ptr, Allocator *a, size_t s) 23 | { 24 | // Calculate new storage address 25 | void *res = (void*) (((uintptr_t) ptr) + ALLOCATOR_HEADER_SZ); 26 | 27 | // Record the header contents 28 | Header_t *hdr = getAllocatorHeader (res); 29 | hdr->allocator = a; 30 | hdr->base_ptr = ptr; 31 | hdr->size = s; 32 | hdr->aux.u64[0] = 0; // Reset AUX field 33 | 34 | return res; 35 | } 36 | 37 | void * Allocator::generateAllocatorHeader (void *ptr, size_t extrabytes, Allocator *a, size_t s) 38 | { 39 | // Calculate new storage address 40 | void *res = (void*) (((uintptr_t) ptr) + ALLOCATOR_HEADER_SZ + extrabytes); 41 | 42 | // Record the header contents 43 | Header_t *hdr = getAllocatorHeader (res); 44 | hdr->allocator = a; 45 | hdr->base_ptr = ptr; 46 | hdr->size = s; 47 | hdr->aux.u64[0] = 0; // Reset AUX field 48 | 49 | return res; 50 | } 51 | 52 | void * Allocator::generateAllocatorHeaderOnAligned (void *ptr, size_t align, Allocator *a, size_t s) 53 | { 54 | // Calculate new storage address 55 | void * res = (void*) align_to (((uintptr_t) ptr + ALLOCATOR_HEADER_SZ), align); 56 | 57 | // Well-aligned given the requested alignment 58 | assert ( ( (uintptr_t) res & (align - 1) ) == 0); 59 | // Ensure enough space for a header between newptr and baseptr 60 | assert ( ( (uintptr_t) res - (uintptr_t) ptr ) >= ALLOCATOR_HEADER_SZ ); 61 | 62 | // Record the header contents 63 | Header_t *hdr = getAllocatorHeader (res); 64 | hdr->allocator = a; 65 | hdr->base_ptr = ptr; 66 | hdr->size = s; 67 | hdr->aux.u64[0] = 0; // Reset AUX field 68 | 69 | return res; 70 | } 71 | 72 | Allocator::Allocator (allocation_functions_t &af) 73 | : _af(af), _has_size (false), _size(0), _used(false) 74 | { 75 | _fallback = nullptr; 76 | } 77 | 78 | Allocator::~Allocator () 79 | { 80 | } 81 | 82 | void Allocator::codeLocation (void *ptr, uint32_t CL) 83 | { 84 | if (nullptr != ptr) 85 | { 86 | Header_t *hdr = getAllocatorHeader (ptr); 87 | hdr->aux.u32[ALLOCATOR_HEADER_AUX_CALLSTACKID] = CL + 1; 88 | } 89 | } 90 | 91 | uint32_t Allocator::codeLocation (void *ptr, bool& valid) 92 | { 93 | uint32_t res = 0; 94 | if (nullptr != ptr) 95 | { 96 | Header_t *hdr = getAllocatorHeader (ptr); 97 | valid = hdr->aux.u32[ALLOCATOR_HEADER_AUX_CALLSTACKID] > 0; 98 | if (valid) 99 | res = hdr->aux.u32[ALLOCATOR_HEADER_AUX_CALLSTACKID] - 1; 100 | } 101 | else 102 | valid = false; 103 | return res; 104 | } 105 | 106 | void Allocator::pmemNode (void *ptr, uint32_t node) 107 | { 108 | if (nullptr != ptr) 109 | { 110 | Header_t *hdr = getAllocatorHeader (ptr); 111 | hdr->aux.u32[ALLOCATOR_HEADER_AUX_PMEM_NODE] = 1+node; 112 | } 113 | } 114 | 115 | uint32_t Allocator::pmemNode (void *ptr, bool& valid) 116 | { 117 | uint32_t res = 0; 118 | if (nullptr != ptr) 119 | { 120 | Header_t *hdr = getAllocatorHeader (ptr); 121 | valid = hdr->aux.u32[ALLOCATOR_HEADER_AUX_PMEM_NODE] > 0; 122 | if (valid) 123 | res = hdr->aux.u32[ALLOCATOR_HEADER_AUX_PMEM_NODE] - 1; 124 | } 125 | else 126 | valid = false; 127 | return res; 128 | } 129 | 130 | 131 | // This is a bit obscure. This extra size comes from aligned mallocs. 132 | // The alignment bytes need to be reallocated as well to avoid passing to the user 133 | // some FlexMalloc internal bytes (the header, more precisely) and other bytes. 134 | uintptr_t Allocator::getExtraSize (Header_t *hdr) 135 | { 136 | assert (hdr != nullptr); 137 | return (uintptr_t) hdr - ((uintptr_t) hdr->base_ptr); 138 | } 139 | 140 | -------------------------------------------------------------------------------- /src/allocator.hxx: -------------------------------------------------------------------------------- 1 | // Author: Harald Servat 2 | // Date: Feb 10, 2017 3 | // License: To determine 4 | // 5 | #pragma once 6 | 7 | #include 8 | #include "common.hxx" 9 | #include "allocator-statistics.hxx" 10 | 11 | class Allocator 12 | { 13 | public: 14 | // Internal header structure to hold information around the allocator used and other data. 15 | // Contains: 16 | // - (pos-1) Allocator pointer that should handle 17 | // - (pos-2) Original allocated pointer -- for free, realloc. Needed as there may be a gap 18 | // when issuing aligned allocations 19 | // - (pos-3) Requested size 20 | // - (pos-4) Auxiliary field 21 | typedef struct Header_st { 22 | Allocator *allocator; 23 | void *base_ptr; 24 | size_t size; 25 | union 26 | { 27 | uint64_t u64[1]; 28 | uint32_t u32[2]; 29 | } aux; 30 | } Header_t; 31 | 32 | enum ALLOCATOR_HEADER_AUX_IDX { ALLOCATOR_HEADER_AUX_PMEM_NODE = 0, ALLOCATOR_HEADER_AUX_CALLSTACKID }; 33 | 34 | private: 35 | static const size_t ALLOCATOR_HEADER_SZ = sizeof(Header_t); 36 | 37 | protected: 38 | const allocation_functions_t _af; 39 | bool _has_size; 40 | size_t _size; 41 | bool _used; 42 | Allocator * _fallback; 43 | bool _is_ready; 44 | 45 | public: 46 | Allocator (allocation_functions_t &); 47 | virtual ~Allocator (); 48 | 49 | static Header_t * getAllocatorHeader (void * ptr); 50 | static void * generateAllocatorHeader (void *ptr, Allocator *a, size_t s); 51 | static void * generateAllocatorHeader (void *ptr, size_t extrabytes, Allocator *a, size_t s); 52 | static void * generateAllocatorHeaderOnAligned (void *ptr, size_t align, Allocator *a, size_t s); 53 | static size_t getTotalSize (size_t size); 54 | static uintptr_t getExtraSize (Header_t *hdr); 55 | 56 | static void codeLocation (void *ptr, uint32_t codelocation); 57 | static uint32_t codeLocation (void *ptr, bool& valid); 58 | static void pmemNode (void *ptr, uint32_t node); 59 | static uint32_t pmemNode (void *ptr, bool& valid); 60 | 61 | virtual const char * name (void) const = 0; 62 | virtual const char * description (void) const = 0; 63 | 64 | virtual void* malloc (size_t) = 0; 65 | virtual void* calloc (size_t, size_t) = 0; 66 | virtual int posix_memalign (void **, size_t, size_t) = 0; 67 | virtual void free (void *) = 0; 68 | virtual void* realloc (void *, size_t) = 0; 69 | virtual size_t malloc_usable_size (void*) = 0; 70 | 71 | virtual void *memcpy (void *dest, const void *src, size_t n) = 0; 72 | 73 | virtual void configure (const char *) = 0; 74 | virtual bool is_ready (void) const { return _is_ready; }; 75 | 76 | void size (size_t s) { _size = s; _has_size = s > 0; }; 77 | size_t size (void) const { return _size; }; 78 | bool has_size (void) const { return _has_size; }; 79 | virtual void show_statistics (void) const = 0; 80 | 81 | bool used (void) const { return _used; }; 82 | void used (bool b) { _used = b; }; 83 | 84 | virtual bool fits (size_t s) const = 0; 85 | virtual size_t hwm (void) const = 0; 86 | virtual void record_unfitted_malloc (size_t) = 0; 87 | virtual void record_unfitted_calloc (size_t) = 0; 88 | virtual void record_unfitted_aligned_malloc (size_t) = 0; 89 | virtual void record_unfitted_realloc (size_t) = 0; 90 | 91 | virtual void record_source_realloc (size_t) = 0; 92 | virtual void record_target_realloc (size_t) = 0; 93 | virtual void record_self_realloc (size_t) = 0; 94 | 95 | virtual void record_realloc_forward_malloc (void) = 0; 96 | }; 97 | 98 | -------------------------------------------------------------------------------- /src/allocators.cxx: -------------------------------------------------------------------------------- 1 | // Author: Harald Servat 2 | // Date: Feb 10, 2017 3 | // Author: Clement Foyer 4 | // Date: Aug 24, 2023 5 | // License: To determine 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "common.hxx" 18 | 19 | #include "allocators.hxx" 20 | #include "allocator-posix.hxx" 21 | #if defined(MEMKIND_SUPPORTED) 22 | # include "allocator-memkind-hbwmalloc.hxx" 23 | # include "allocator-memkind-pmem.hxx" 24 | #endif 25 | 26 | Allocators::Allocators (allocation_functions_t &af, const char *definitions) 27 | { 28 | unsigned indx = 0; 29 | #if defined(MEMKIND_SUPPORTED) 30 | void *a_memkind_hbwmalloc = (AllocatorMemkindHBWMalloc*) malloc (sizeof(AllocatorMemkindHBWMalloc)); 31 | void *a_memkind_pmem = (AllocatorMemkindPMEM*) malloc (sizeof(AllocatorMemkindPMEM)); 32 | allocators[indx++] = new (a_memkind_hbwmalloc) AllocatorMemkindHBWMalloc(af); 33 | allocators[indx++] = new (a_memkind_pmem) AllocatorMemkindPMEM(af); 34 | #endif 35 | void *a_posix = (AllocatorPOSIX*) malloc (sizeof(AllocatorPOSIX)); 36 | allocators[indx++] = new (a_posix) AllocatorPOSIX(af); 37 | allocators[indx] = nullptr; 38 | 39 | // Objects have been already initialized when constructing (allocating them) -- just use 40 | // this function to list them 41 | unsigned u = 0; 42 | VERBOSE_MSG(1, "Initializing allocators:\n"); 43 | 44 | while (allocators[u] != nullptr) 45 | { 46 | VERBOSE_MSG(1, "* %s\n", allocators[u]->name()); 47 | u++; 48 | } 49 | 50 | struct stat sb; 51 | int fd; 52 | 53 | VERBOSE_MSG(0, "Parsing %s\n", definitions); 54 | 55 | fd = open(definitions, O_RDONLY); 56 | if (fd == -1) 57 | { 58 | VERBOSE_MSG(0, "Warning! Could not open file %s\n", definitions); 59 | perror("open"); 60 | return; 61 | } 62 | if (fstat(fd, &sb) == -1) 63 | { 64 | VERBOSE_MSG(0, "Warning! fstat failed on file %s\n", definitions); 65 | perror("fstat"); 66 | close (fd); 67 | return; 68 | } 69 | if (!S_ISREG(sb.st_mode)) 70 | { 71 | VERBOSE_MSG(0, "Warning! Given file (%s) is not a regular file\n", definitions); 72 | close (fd); 73 | return; 74 | } 75 | if (sb.st_size == 0) 76 | { 77 | VERBOSE_MSG(0, "Warning! Given file (%s) is empty\n", definitions); 78 | close (fd); 79 | return; 80 | } 81 | void *p = mmap (nullptr, sb.st_size, PROT_READ, MAP_SHARED, fd, 0); 82 | if (p == MAP_FAILED) 83 | { 84 | VERBOSE_MSG(0, "Warning! Could not mmap file %s\n", definitions); 85 | perror("mmap"); 86 | close (fd); 87 | return; 88 | } 89 | close(fd); 90 | 91 | // Process memory definitions 92 | char *defs = strchr ((char*)p, '#'); 93 | while (defs != nullptr) 94 | { 95 | char allocatorname[256] = {0}; 96 | const char blankchars[] = "\n\r\t\f\v"; // only allow single space as blank in the allocator's name 97 | const char * MEMORYCONFIG_ALLOCATOR = "# Memory configuration for allocator "; 98 | bool has_memoryconfig_allocator = false; 99 | size_t count = 0; 100 | 101 | // Have we found an entry for a memory allocator configuration? 102 | if (strncmp (defs, MEMORYCONFIG_ALLOCATOR, strlen (MEMORYCONFIG_ALLOCATOR)) == 0) 103 | { 104 | const char *in = &defs[strlen(MEMORYCONFIG_ALLOCATOR)]; 105 | count = std::min (strcspn (in, blankchars), sizeof (allocatorname)-1); 106 | memcpy (allocatorname, in, count); 107 | allocatorname[count] = '\0'; 108 | 109 | // If we have read something, then we have a new allocator 110 | has_memoryconfig_allocator = (count > 0 && count < sizeof (allocatorname)); 111 | } 112 | 113 | if (has_memoryconfig_allocator) 114 | { 115 | char configureline[256] = {0}; 116 | Allocator * allocator = get (allocatorname); 117 | if (allocator != nullptr) 118 | { 119 | // Set in configureline the next line, except the trailing LF 120 | defs += strlen (MEMORYCONFIG_ALLOCATOR) + count + 1; 121 | count = std::min (strcspn (defs, blankchars), sizeof (configureline)-1); 122 | memcpy (configureline, defs, count); 123 | configureline[count] = '\0'; 124 | VERBOSE_MSG(1, "Configuring allocator %s with \"%s\"\n", allocatorname, configureline); 125 | allocator->configure (configureline); 126 | } 127 | else 128 | { 129 | VERBOSE_MSG(0, "Allocator %s is not registered.\n", allocatorname); 130 | exit (0); 131 | } 132 | } 133 | defs = strchr (defs+count+1, '#'); // Search for next # Memory configuration 134 | } 135 | munmap(p, sb.st_size); 136 | } 137 | 138 | Allocators::~Allocators (void) 139 | { 140 | } 141 | 142 | Allocator * Allocators::get (const char *name) 143 | { 144 | unsigned u = 0; 145 | while (allocators[u] != nullptr) 146 | { 147 | if (strcasecmp (name, allocators[u]->name()) == 0) 148 | return allocators[u]; 149 | u++; 150 | } 151 | return nullptr; 152 | } 153 | 154 | Allocator ** Allocators::get (void) 155 | { 156 | return allocators; 157 | } 158 | 159 | void Allocators::show_statistics (void) const 160 | { 161 | unsigned u = 0; 162 | 163 | while (allocators[u] != nullptr) 164 | { 165 | if (allocators[u]->used()) 166 | allocators[u]->show_statistics(); 167 | u++; 168 | } 169 | } 170 | 171 | -------------------------------------------------------------------------------- /src/allocators.hxx: -------------------------------------------------------------------------------- 1 | // Author: Harald Servat 2 | // Date: Feb 10, 2017 3 | // License: To determine 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | #include "allocator-statistics.hxx" 10 | #include "allocator.hxx" 11 | 12 | #if defined(MEMKIND_SUPPORTED) 13 | # define NUM_ALLOCATORS 3 14 | #else 15 | # define NUM_ALLOCATORS 1 16 | #endif 17 | 18 | class Allocators 19 | { 20 | private: 21 | Allocator * allocators[NUM_ALLOCATORS+1]; // +1 for null-terminated 22 | 23 | public: 24 | Allocators (allocation_functions_t &, const char * definitions); 25 | ~Allocators (); 26 | Allocator * get (const char *name); 27 | Allocator ** get (void); 28 | void show_statistics (void) const; 29 | }; 30 | -------------------------------------------------------------------------------- /src/bfd-manager.cxx: -------------------------------------------------------------------------------- 1 | // Author: Harald Servat 2 | // Date: Feb 10, 2017 3 | // License: To determine 4 | 5 | #include 6 | #include 7 | 8 | #include "common.hxx" 9 | #include "bfd-manager.hxx" 10 | 11 | static bool __bfd_manager_initialized = false; 12 | 13 | BFDManager::BFDManager () 14 | { 15 | } 16 | 17 | BFDManager::~BFDManager () 18 | { 19 | } 20 | 21 | bool BFDManager::load_binary (const char *file) 22 | { 23 | if ( !__bfd_manager_initialized ) 24 | { 25 | bfd_init (); 26 | __bfd_manager_initialized = true; 27 | } 28 | 29 | /* Open the binary in read-only mode */ 30 | BFDImage = bfd_openr (file, nullptr); 31 | if (BFDImage == nullptr) 32 | { 33 | VERBOSE_MSG(0, "Error! Could not read symbols from file %s\n", 34 | file); 35 | return false; 36 | } 37 | 38 | /* Check the binary file format */ 39 | if (!bfd_check_format (BFDImage, bfd_object)) 40 | { 41 | VERBOSE_MSG(0, "Error! Binary file format does not match for file %s\n", 42 | file); 43 | return false; 44 | } 45 | 46 | /* Load the symbol table */ 47 | if (bfd_get_file_flags (BFDImage) & HAS_SYMS) 48 | { 49 | size_t size = bfd_get_symtab_upper_bound (BFDImage); 50 | if (size > 0) 51 | { 52 | BFDSymbols = (asymbol**) malloc (size); /* TODO, fix this call */ 53 | if (BFDSymbols == nullptr) 54 | { 55 | VERBOSE_MSG(0, "Error! Could not allocate memory to translate addresses into source code references\n"); 56 | return false; 57 | } 58 | 59 | // Based from binutils/addr2info.c 60 | // If we haven't found symbols even though size > 0, try with dynamic symbols 61 | if (bfd_canonicalize_symtab (BFDImage, BFDSymbols) == 0) 62 | { 63 | free (BFDSymbols); 64 | 65 | size = bfd_get_dynamic_symtab_upper_bound (BFDImage); 66 | if (size > 0) 67 | { 68 | BFDSymbols = (asymbol**) malloc (size); /* TODO, fix this call */ 69 | if (BFDSymbols == nullptr) 70 | { 71 | VERBOSE_MSG(0, "Error! Could not allocate memory to translate addresses into source code references\n"); 72 | return false; 73 | } 74 | return bfd_canonicalize_dynamic_symtab (BFDImage, BFDSymbols) > 0; 75 | } 76 | return false; 77 | } 78 | else 79 | return true; 80 | } 81 | else if (size == 0) 82 | { 83 | size = bfd_get_dynamic_symtab_upper_bound (BFDImage); 84 | if (size > 0) 85 | { 86 | BFDSymbols = (asymbol**) malloc (size); /* TODO, fix this call */ 87 | if (BFDSymbols == nullptr) 88 | { 89 | VERBOSE_MSG(0, "Error! Could not allocate memory to translate addresses into source code references\n"); 90 | return false; 91 | } 92 | return bfd_canonicalize_dynamic_symtab (BFDImage, BFDSymbols) > 0; 93 | } 94 | } 95 | } 96 | 97 | return false; 98 | } 99 | 100 | typedef struct symbol_information_st 101 | { 102 | bfd_vma pc; 103 | asymbol **symbols; 104 | char *filename; 105 | const char *function; 106 | unsigned line; 107 | bfd_boolean found; 108 | } symbol_information_t; 109 | 110 | static void find_address_in_section (bfd *abfd, asection *section, void *data) 111 | { 112 | /* TODO fix this */ 113 | #define HAVE_BFD_GET_SECTION_SIZE 1 114 | 115 | #if HAVE_BFD_GET_SECTION_SIZE || HAVE_BFD_GET_SECTION_SIZE_BEFORE_RELOC 116 | bfd_size_type size; 117 | #endif 118 | bfd_vma vma; 119 | 120 | symbol_information_t *sdata = (symbol_information_t*) data; 121 | 122 | if (sdata->found) 123 | return; 124 | 125 | if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0) 126 | return; 127 | 128 | vma = bfd_get_section_vma (abfd, section); 129 | 130 | if (sdata->pc < vma) 131 | return; 132 | 133 | #if HAVE_BFD_GET_SECTION_SIZE 134 | size = bfd_get_section_size (section); 135 | if (sdata->pc >= vma + size) 136 | return; 137 | #elif HAVE_BFD_GET_SECTION_SIZE_BEFORE_RELOC 138 | size = bfd_get_section_size_before_reloc (section); 139 | if (sdata->pc >= vma + size) 140 | return; 141 | #endif 142 | 143 | sdata->found = bfd_find_nearest_line (abfd, section, sdata->symbols, 144 | sdata->pc - vma, (const char **) &sdata->filename, &sdata->function, 145 | &sdata->line); 146 | } 147 | 148 | bool BFDManager::translate_address ( 149 | const void *address, const char **function, char **file, unsigned *line) 150 | { 151 | // #define HAVE_BFD_DEMANGLE 152 | // #warning "Need to work on BFD_demangle - collision w/ realloc ?" 153 | 154 | if (BFDImage && BFDSymbols) 155 | { 156 | symbol_information_t symbol_info; 157 | symbol_info.found = 0; 158 | symbol_info.pc = (bfd_vma) address; 159 | symbol_info.symbols = BFDSymbols; 160 | 161 | /* Iterate through sections of bfd Image */ 162 | bfd_map_over_sections (BFDImage, ::find_address_in_section, &symbol_info); 163 | //bfdmanager_find_address_in_section (BFDImage, &symbol_info); 164 | // 165 | DBG ("symbol_info.found = %d\n", symbol_info.found); 166 | 167 | /* Found the symbol? */ 168 | if (symbol_info.found) 169 | { 170 | *file = (char*) symbol_info.filename; 171 | *line = symbol_info.line; 172 | 173 | #if defined(HAVE_BFD_DEMANGLE) 174 | char *demangled = nullptr; 175 | if (symbol_info.function) 176 | demangled = bfd_demangle (BFDImage, symbol_info.function, 0); 177 | 178 | if (demangled) 179 | *function = demangled; 180 | else 181 | *function = (char*) symbol_info.function; 182 | #else 183 | *function = (char*) symbol_info.function; 184 | #endif 185 | 186 | DBG ("function = %s file = %s line = %d\n", *function, *file, *line); 187 | 188 | /* Sometimes BFD seems to mess a bit, indicates that translation was 189 | successful but data is not available */ 190 | // return *function != nullptr && *file != nullptr && *line > 0; 191 | return *function != nullptr && *file != nullptr; 192 | } 193 | else 194 | { 195 | return false; 196 | } 197 | } 198 | else 199 | { 200 | return false; 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /src/bfd-manager.hxx: -------------------------------------------------------------------------------- 1 | // Author: Harald Servat 2 | // Date: Feb 10, 2017 3 | // License: To determine 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | #define bfd_get_section_size(ptr) ((ptr)->size) 10 | #define bfd_get_section_vma(bfd, ptr) ((void) bfd, (ptr)->vma) 11 | #define bfd_get_section_flags(bfd, ptr) ((void) bfd, (ptr)->flags) 12 | 13 | class BFDManager 14 | { 15 | private: 16 | bfd *BFDImage; 17 | asymbol **BFDSymbols; 18 | 19 | public: 20 | BFDManager(); 21 | ~BFDManager(); 22 | 23 | bool load_binary (const char *file); 24 | bool translate_address (const void *address, const char **function, char **file, unsigned *line); 25 | }; 26 | -------------------------------------------------------------------------------- /src/cache-callstack.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include "common.hxx" 3 | #include "cache-callstack.hxx" 4 | 5 | CacheCallstacks::CacheCallstacks () 6 | : _num_entries (0), _first_entry(0) 7 | { 8 | _stats.n_hits = 9 | _stats.n_miss = 10 | _stats.n_miss_too_long = 0; 11 | } 12 | 13 | CacheCallstacks::~CacheCallstacks () 14 | { 15 | } 16 | 17 | bool CacheCallstacks::match (unsigned nframes, void *frames[], Allocator *&a, unsigned &id) const 18 | { 19 | if (nframes <= CALLSTACKS_PER_ENTRY) 20 | { 21 | for (unsigned e = 0; e < _num_entries; ++e) 22 | if (_entries[e].n_frames == nframes) 23 | { 24 | bool match = true; 25 | for (unsigned f = 0; f < nframes && match; ++f) 26 | match = _entries[e].frames[f] == frames[f]; 27 | if (match) 28 | { 29 | a = _entries[e].allocator; 30 | id = _entries[e].id; 31 | _stats.n_hits++; 32 | return true; 33 | } 34 | } 35 | _stats.n_miss++; 36 | } 37 | else 38 | { 39 | _stats.n_miss_too_long++; 40 | } 41 | 42 | return false; 43 | } 44 | 45 | void CacheCallstacks::add_match (unsigned nframes, void *frames[], Allocator *a, unsigned id) 46 | { 47 | if (nframes <= CALLSTACKS_PER_ENTRY) 48 | { 49 | if (_num_entries < NUM_ENTRIES) 50 | { 51 | // We have space in cache -- no need to evict an entry 52 | _entries[_num_entries].allocator = a; 53 | _entries[_num_entries].n_frames = nframes; 54 | _entries[_num_entries].id = id; 55 | for (unsigned f = 0; f < nframes; ++f) 56 | _entries[_num_entries].frames[f] = frames[f]; 57 | _num_entries++; 58 | } 59 | else 60 | { 61 | // We don't have enough space -- need to evict an entry 62 | // Use circular buffer approach 63 | _entries[_first_entry].allocator = a; 64 | _entries[_first_entry].n_frames = nframes; 65 | _entries[_first_entry].id = id; 66 | for (unsigned f = 0; f < nframes; ++f) 67 | _entries[_first_entry].frames[f] = frames[f]; 68 | _first_entry = (_first_entry+1) & MASK_ENTRIES; // Set next entry 69 | } 70 | } 71 | } 72 | 73 | void CacheCallstacks::show_statistics (void) const 74 | { 75 | VERBOSE_MSG(1, "- Cache size = %u with %u call-stack segments per entry\n", NUM_ENTRIES, CALLSTACKS_PER_ENTRY); 76 | VERBOSE_MSG(1, "- Cache hits = %u, misses = %u, misses for being too long = %u\n", 77 | _stats.n_hits, _stats.n_miss, _stats.n_miss_too_long); 78 | 79 | float cache_hits = _stats.n_hits; 80 | float cache_miss = _stats.n_miss; 81 | float cache_miss_too_long = _stats.n_miss_too_long; 82 | float cache_hit_ratio = 0., n_cache_hit_ratio = 0.; 83 | if (cache_hits + cache_miss > 0.) 84 | cache_hit_ratio = 100. * cache_hits / ( cache_hits + cache_miss ); 85 | if (cache_hits + cache_miss + cache_miss_too_long > 0.) 86 | n_cache_hit_ratio = 100. * cache_hits / ( cache_hits + cache_miss + cache_miss_too_long ); 87 | VERBOSE_MSG(1, "- Cache hit ratio = %.1f %%\n", cache_hit_ratio); 88 | VERBOSE_MSG(1, "- Normalized cache hit ratio = %.1f %%\n", n_cache_hit_ratio); 89 | } 90 | 91 | -------------------------------------------------------------------------------- /src/cache-callstack.hxx: -------------------------------------------------------------------------------- 1 | 2 | #include "allocator.hxx" 3 | 4 | #pragma once 5 | 6 | #define CALLSTACKS_PER_ENTRY 32 // Deepest callpath that we can store 7 | #define NUM_ENTRIES (1 << 6) // 64 entries, needs to be power of 2 8 | #define MASK_ENTRIES (NUM_ENTRIES-1) // to simplify calculations 9 | 10 | class CacheCallstacks 11 | { 12 | private: 13 | typedef struct cache_entry_st 14 | { 15 | void *frames[CALLSTACKS_PER_ENTRY]; 16 | Allocator *allocator; 17 | unsigned n_frames; 18 | unsigned id; 19 | } cache_entry_t; 20 | 21 | cache_entry_t _entries[NUM_ENTRIES]; 22 | unsigned _num_entries; 23 | unsigned _first_entry; 24 | 25 | typedef struct cache_stats_st 26 | { 27 | unsigned n_hits; 28 | unsigned n_miss; 29 | unsigned n_miss_too_long; 30 | } cache_stats_t; 31 | 32 | mutable cache_stats_t _stats; 33 | 34 | public: 35 | CacheCallstacks (); 36 | ~CacheCallstacks (); 37 | 38 | bool match (unsigned nframes, void *frames[], Allocator *&a, unsigned &id) const; 39 | void add_match (unsigned nframes, void *frames[], Allocator *a, unsigned); 40 | void show_statistics (void) const; 41 | }; 42 | -------------------------------------------------------------------------------- /src/code-locations.hxx: -------------------------------------------------------------------------------- 1 | // Authors: Harald Servat 2 | // Date: 02/02/2017 3 | // License: 4 | 5 | #pragma once 6 | 7 | #include "allocators.hxx" 8 | 9 | typedef struct { 10 | bool translated; 11 | char *file; 12 | unsigned line; 13 | } translated_frame_t; 14 | 15 | class CodeLocations 16 | { 17 | private: 18 | 19 | typedef struct 20 | { 21 | char file[PATH_MAX]; 22 | unsigned line; 23 | bool valid; 24 | } source_frame_t; 25 | 26 | typedef struct 27 | { 28 | long frame; 29 | } raw_frame_t; 30 | 31 | typedef struct { 32 | size_t current_used_memory; 33 | size_t HWM; 34 | size_t current_used_memory_fb; 35 | size_t HWM_fb; 36 | unsigned n_living_objects; 37 | unsigned n_max_living_objects; 38 | unsigned n_allocations_in_cache; 39 | unsigned n_allocations_not_in_cache; 40 | unsigned n_allocations_not_fit; 41 | unsigned n_allocations; 42 | } location_stats_t; 43 | 44 | typedef struct st_pending_module 45 | { 46 | char path[PATH_MAX+1]; 47 | unsigned nframes; 48 | struct st_pending_module* next; 49 | } pending_module_t; 50 | 51 | typedef struct st_pending_raw_frame 52 | { 53 | pending_module_t* module; 54 | long offset; 55 | unsigned index; 56 | struct st_pending_raw_frame* next; 57 | } pending_raw_frame_t; 58 | 59 | typedef struct 60 | { 61 | union 62 | { 63 | source_frame_t *source; 64 | raw_frame_t *raw; 65 | } frames; 66 | Allocator * allocator; 67 | location_stats_t stats; 68 | unsigned nframes; 69 | unsigned id; 70 | pending_raw_frame_t* pending_frames; 71 | } location_t; 72 | 73 | #define LINE_SIZE 2048 74 | typedef struct 75 | { 76 | unsigned long start; 77 | unsigned long end; 78 | unsigned long offset; 79 | char module[LINE_SIZE+1]; 80 | bool perm_read; 81 | bool perm_write; 82 | bool perm_exec; 83 | } memory_maps_entry_t; 84 | 85 | typedef struct 86 | { 87 | unsigned num_entries; 88 | unsigned capacity; 89 | memory_maps_entry_t* entries; 90 | } memory_maps_t; 91 | 92 | static bool comparator_by_ID (const location_t &lhs, const location_t &rhs); 93 | static bool comparator_by_NumberOfFrames (const location_t &lhs, const location_t &rhs); 94 | 95 | unsigned * _fast_indexes_frames;// This is an array (up to _max_frames) 96 | // pointing to the first element with N frames 97 | // when locations are sorted by comparator_by_NumberOfFrames 98 | const allocation_functions_t _af; 99 | Allocators * const _allocators; 100 | location_t * _locations; 101 | unsigned _nlocations; 102 | unsigned _min_nframes; 103 | unsigned _max_nframes; 104 | 105 | memory_maps_t _maps_info; 106 | 107 | pending_module_t* _pending_modules; 108 | 109 | unsigned get_min_index_for_number_of_frames (unsigned nframes) const; 110 | unsigned get_max_index_for_number_of_frames (unsigned nframes) const; 111 | 112 | char * find_and_set_allocator (char *location_txt, location_t * location, const char * fallback_allocator_name); 113 | size_t count_frames (char *location_txt, location_t * location, const char * const allocator_marker, char marker); 114 | bool process_source_location (char *location_txt, location_t * location, const char * fallback_allocator_name); 115 | bool process_raw_location (char *location_txt, location_t * location, const char * fallback_allocator_name); 116 | void clean_source_location (location_t * location); 117 | void show_frames (void); 118 | long file_offset_to_address (const char *lib, unsigned long address, bool& found); 119 | void create_fast_indexes_for_frames (void); 120 | bool load_memory_mappings_info (memory_maps_t& maps); 121 | pending_module_t* get_pending_module(const char* path); 122 | pending_module_t* add_or_get_pending_module(const char* path); 123 | void delete_unused_pending_modules(void); 124 | 125 | public: 126 | CodeLocations (allocation_functions_t &, Allocators *); 127 | ~CodeLocations(); 128 | bool readfile (const char *f, const char *fallback_allocator_name); 129 | void show_stats (void); 130 | void show_hmem_visualizer_stats (const char *fallback_allocator_name); 131 | Allocator * match (unsigned nframes, const translated_frame_t *tf, 132 | unsigned &location_id); 133 | Allocator * match (unsigned nframes, void **frames, unsigned & location_id); 134 | Allocators * allocators () const 135 | { return _allocators; }; 136 | void record_location (unsigned location_id, bool fits, bool in_cache); 137 | void record_location (unsigned location_id, bool fits); 138 | void record_location_add_memory (unsigned location_id, size_t sz, bool fallback_allocator); 139 | void record_location_sub_memory (unsigned location_id, size_t sz, bool fallback_allocator); 140 | unsigned num_locations (void) const { return _nlocations; }; 141 | unsigned min_nframes (void) const { return _min_nframes; }; 142 | unsigned max_nframes (void) const { return _max_nframes; }; 143 | unsigned has_locations (void) const { return _nlocations > 0; }; 144 | Allocator * allocator (unsigned cl) const { return cl <= _nlocations ? _locations[cl].allocator : nullptr; }; 145 | void translate_pending_frames(const char* module); 146 | }; 147 | 148 | -------------------------------------------------------------------------------- /src/common.cxx: -------------------------------------------------------------------------------- 1 | // Author: Harald Servat 2 | // Date: Feb 10, 2017 3 | // License: To determine 4 | 5 | #include 6 | #include 7 | #include 8 | #include "common.hxx" 9 | 10 | Options options; 11 | 12 | #define CHECK_ENABLED(x) \ 13 | (strncasecmp (s, "yes", 3) == 0 || \ 14 | strncasecmp (s, "enabled", 7) == 0 || \ 15 | strncasecmp (s, "true", 4) == 0 || \ 16 | strncasecmp (s, "1", 1) == 0) 17 | 18 | #define CHECK_DISABLED(x) \ 19 | (strncasecmp (s, "no", 2) == 0 || \ 20 | strncasecmp (s, "disabled", 8) == 0 || \ 21 | strncasecmp (s, "false", 5) == 0 || \ 22 | strncasecmp (s, "0", 1) == 0) 23 | 24 | #define COMPARE_WHOLE_PATH_DEFAULT false 25 | #define DEBUG_DEFAULT false 26 | #define DEBUG_MESSAGES_ON_STDERR_DEFAULT true 27 | #define CALLSTACK_MINUS1_DEFAULT false 28 | #define CALLSTACK_STOP_AT_MAIN_DEFAULT false 29 | #define CALLSTACK_SHORTEN_FRAMES_DEFAULT true 30 | #define MATCH_ONLY_ON_MAIN_BINARY_DEFAULT false 31 | #define SOURCE_FRAMES_DEFAULT true 32 | #define IGNORE_IF_FALLBACK_ALLOCATOR_DEFAULT true 33 | 34 | #define PROCESS_ENVVAR(envvar,var,defvalue) \ 35 | { \ 36 | char *s = getenv (envvar); \ 37 | if (s != nullptr) \ 38 | { \ 39 | if (CHECK_ENABLED(s)) \ 40 | var = true; \ 41 | else if (CHECK_DISABLED(s)) \ 42 | var = false; \ 43 | else \ 44 | var = defvalue; \ 45 | } \ 46 | else \ 47 | var = defvalue;\ 48 | } 49 | 50 | Options::Options () 51 | : _minSize(0), _max_depth(100) 52 | { 53 | char *verbose = getenv(TOOL_VERBOSE); 54 | if (verbose != nullptr) 55 | { 56 | _VerboseLvl = atoi(verbose); 57 | if (_VerboseLvl < 0) 58 | { 59 | VERBOSE_MSG(0, "Wrong value for environment variable %s. Setting it to 0.\n", 60 | TOOL_VERBOSE); 61 | _VerboseLvl = 0; 62 | } 63 | } 64 | else 65 | _VerboseLvl = 0; 66 | 67 | PROCESS_ENVVAR(TOOL_COMPARE_WHOLE_PATH, _comparewholepath, COMPARE_WHOLE_PATH_DEFAULT); 68 | PROCESS_ENVVAR(TOOL_DEBUG, _debug, DEBUG_DEFAULT); 69 | PROCESS_ENVVAR(TOOL_MESSAGES_ON_STDERR, _messages_on_stderr, DEBUG_MESSAGES_ON_STDERR_DEFAULT); 70 | PROCESS_ENVVAR(TOOL_CALLSTACK_MINUS1, _callstack_minus_1, CALLSTACK_MINUS1_DEFAULT); 71 | PROCESS_ENVVAR(TOOL_CALLSTACK_STOP_AT_MAIN, _stopAtMain, CALLSTACK_STOP_AT_MAIN_DEFAULT); 72 | PROCESS_ENVVAR(TOOL_SHORTEN_FRAMES, _shorten_frames, CALLSTACK_SHORTEN_FRAMES_DEFAULT); 73 | PROCESS_ENVVAR(TOOL_IGNORE_IF_FALLBACK_ALLOCATOR, _ignoreIfFallbackAllocator, IGNORE_IF_FALLBACK_ALLOCATOR_DEFAULT); 74 | if (getenv (TOOL_SOURCE_FRAMES)) 75 | { 76 | PROCESS_ENVVAR(TOOL_SOURCE_FRAMES, _sourceFrames, SOURCE_FRAMES_DEFAULT); 77 | _sourceFramesSet = true; 78 | } 79 | else 80 | { 81 | _sourceFramesSet = false; 82 | _sourceFrames = false; 83 | } 84 | 85 | int msize = 0; 86 | char *msize_threshold = getenv(TOOL_MINSIZE_THRESHOLD); 87 | if (msize_threshold != nullptr) 88 | msize = atoi (msize_threshold); 89 | if (msize < 0) 90 | { 91 | VERBOSE_MSG(0, "Wrong value for environment variable %s. Setting it to 0.\n", 92 | TOOL_MINSIZE_THRESHOLD); 93 | _minSize = 0; 94 | } 95 | else 96 | _minSize = msize; 97 | 98 | struct timespec ts; 99 | clock_gettime (CLOCK_MONOTONIC, &ts); 100 | _initial_time = ((uint64_t) ts.tv_sec * 1000000000ULL + ts.tv_nsec); 101 | } 102 | 103 | Options::~Options () 104 | { 105 | } 106 | 107 | uint64_t Options::getTime (void) const 108 | { 109 | struct timespec ts; 110 | clock_gettime (CLOCK_MONOTONIC, &ts); 111 | uint64_t current_time = ((uint64_t) ts.tv_sec * 1000000000ULL + ts.tv_nsec); 112 | return current_time - _initial_time; 113 | } 114 | 115 | -------------------------------------------------------------------------------- /src/common.hxx: -------------------------------------------------------------------------------- 1 | // Author: Harald Servat 2 | // Date: Feb 10, 2017 3 | // License: To determine 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "flexmalloc-config.h" 14 | 15 | class Options 16 | { 17 | private: 18 | int _VerboseLvl; 19 | bool _comparewholepath; 20 | size_t _minSize; 21 | uint64_t _initial_time; 22 | bool _debug; 23 | bool _messages_on_stderr; 24 | unsigned _max_depth; 25 | bool _callstack_minus_1; 26 | bool _stopAtMain; 27 | bool _shorten_frames; 28 | bool _sourceFrames; 29 | bool _sourceFramesSet; 30 | bool _ignoreIfFallbackAllocator; 31 | 32 | public: 33 | Options (); 34 | ~Options (); 35 | int verboseLvl (void) const 36 | { return _VerboseLvl; }; 37 | bool compareWholePath (void) const 38 | { return _comparewholepath; }; 39 | void minSize (unsigned s) 40 | { _minSize = s; }; 41 | size_t minSize (void) const 42 | { return _minSize; }; 43 | bool debug (void) const 44 | { return _debug; }; 45 | bool messages_on_stderr(void) const 46 | { return _messages_on_stderr; }; 47 | unsigned maxDepth (void) const 48 | { return _max_depth; }; 49 | void callstackMinus1(bool b) 50 | { _callstack_minus_1 = b; } 51 | bool callstackMinus1(void) const 52 | { return _callstack_minus_1; }; 53 | void stopAtMain (bool b) 54 | { _stopAtMain = b; }; 55 | bool stopAtMain (void) const 56 | { return _stopAtMain; }; 57 | void shortenFrames (bool b) 58 | { _shorten_frames = b; }; 59 | bool shortenFrames (void) const 60 | { return _shorten_frames; }; 61 | uint64_t getTime(void) const; 62 | bool sourceFrames (void) const 63 | { return _sourceFrames; }; 64 | void sourceFrames (bool b) 65 | { _sourceFrames = b; }; 66 | bool sourceFrame_set (void) const 67 | { return _sourceFramesSet; }; 68 | bool ignoreIfFallbackAllocator (void) const 69 | { return _ignoreIfFallbackAllocator; }; 70 | }; 71 | 72 | typedef struct allocation_functions_st 73 | { 74 | void* (*malloc)(size_t); 75 | void* (*calloc)(size_t,size_t); 76 | void (*free)(void*); 77 | void* (*realloc)(void*, size_t); 78 | int (*posix_memalign)(void**, size_t, size_t); 79 | size_t (*malloc_usable_size)(void *); 80 | } allocation_functions_t; 81 | 82 | extern Options options; 83 | 84 | #define TOOL_NAME "FLEXMALLOC" 85 | #define TOOL_VERBOSE TOOL_NAME"_VERBOSE" 86 | #define TOOL_LOCATIONS_FILE TOOL_NAME"_LOCATIONS" 87 | #define TOOL_DEFINITIONS_FILE TOOL_NAME"_DEFINITIONS" 88 | #define TOOL_COMPARE_WHOLE_PATH TOOL_NAME"_COMPARE_WHOLE_PATH" 89 | #define TOOL_DEBUG TOOL_NAME"_DEBUG" 90 | #define TOOL_MESSAGES_ON_STDERR TOOL_NAME"_MESSAGES_ON_STDERR" 91 | #define TOOL_FALLBACK_ALLOCATOR TOOL_NAME"_FALLBACK_ALLOCATOR" 92 | #define TOOL_CALLSTACK_MINUS1 TOOL_NAME"_CALLSTACK_MINUS1" 93 | #define TOOL_CALLSTACK_STOP_AT_MAIN TOOL_NAME"_CALLSTACK_STOP_AT_MAIN" 94 | #define TOOL_MINSIZE_THRESHOLD TOOL_NAME"_MINSIZE_THRESHOLD" 95 | #define TOOL_MINSIZE_THRESHOLD_ALLOCATOR TOOL_NAME"_MINSIZE_THRESHOLD_ALLOCATOR" 96 | #define TOOL_SHORTEN_FRAMES TOOL_NAME"_SHORTEN_FRAMES" 97 | #define TOOL_MATCH_ONLY_ON_MAIN_BINARY TOOL_NAME"_MATCH_ONLY_ON_MAIN_BINARY" 98 | #define TOOL_SOURCE_FRAMES TOOL_NAME"_SOURCE_FRAMES" 99 | #define TOOL_IGNORE_IF_FALLBACK_ALLOCATOR TOOL_NAME"_IGNORE_LOCATIONS_ON_FALLBACK_ALLOCATOR" 100 | 101 | #define VERBOSE_MSG(level,...) \ 102 | { if (options.verboseLvl() >= level || options.debug()) { fprintf (options.messages_on_stderr() ? stderr : stdout, TOOL_NAME"|" __VA_ARGS__); } } 103 | #define VERBOSE_MSG_NOPREFIX(level,...) \ 104 | { if (options.verboseLvl() >= level || options.debug()) { fprintf (options.messages_on_stderr() ? stderr : stdout, __VA_ARGS__); } } 105 | 106 | #if defined(DEBUG) 107 | # define DBG(fmt,...) \ 108 | { \ 109 | if (options.debug()) \ 110 | { \ 111 | fprintf (options.messages_on_stderr() ? stderr : stdout, \ 112 | TOOL_NAME"|DBG|%s (%s:%d)|%luus: " fmt, __func__, __FILE__, __LINE__, options.getTime()/1000, __VA_ARGS__); \ 113 | fflush (options.messages_on_stderr() ? stderr : stdout); \ 114 | } \ 115 | } 116 | #else 117 | # define DBG(fmt,...) 118 | #endif 119 | 120 | #define LIKELY(condition) __builtin_expect(static_cast(condition), 1) 121 | #define UNLIKELY(condition) __builtin_expect(static_cast(condition), 0) 122 | 123 | -------------------------------------------------------------------------------- /src/flex-malloc.hxx: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "allocator.hxx" 6 | #include "code-locations.hxx" 7 | #include "bfd-manager.hxx" 8 | #include "cache-callstack.hxx" 9 | 10 | class FlexMalloc 11 | { 12 | private: 13 | const allocation_functions_t _af; 14 | Allocator * _fallback; 15 | const Allocators * _allocators; 16 | 17 | CacheCallstacks _c_cache; 18 | 19 | typedef struct module_st 20 | { 21 | BFDManager *bfd; 22 | char *name; 23 | long startAddress; 24 | long endAddress; 25 | bool symbolsLoaded; 26 | bool do_not_backtrace; 27 | } module_t; 28 | 29 | module_t *_modules; 30 | unsigned _nmodules; 31 | void parse_map_files (void); 32 | CodeLocations * const _cl; 33 | 34 | bool excluded_library (const char *library); 35 | Allocator * allocatorForCallstack_source (unsigned nptrs, void **callstack, size_t sz, bool &fits, uint32_t& codelocation); 36 | Allocator * allocatorForCallstack_raw (unsigned nptrs, void **callstack, size_t sz, bool &fits, uint32_t& codelocation); 37 | Allocator * allocatorForCallstack (unsigned nptrs, void **callstack, size_t sz, bool &fits, uint32_t& codelocation); 38 | 39 | public: 40 | FlexMalloc (allocation_functions_t &, Allocator *, CodeLocations *); 41 | ~FlexMalloc (); 42 | 43 | void * malloc (unsigned nptrs, void **callstack, size_t sz); 44 | void * calloc (unsigned nptrs, void **callstack, size_t nmemb, size_t sz); 45 | int posix_memalign (unsigned nptrs, void **callstack, void ** memptr, size_t alignment, size_t sz); 46 | void * realloc (unsigned nptrs, void **callstack, void *ptr, size_t sz); 47 | void free (void *ptr); 48 | size_t malloc_usable_size (void *ptr) const; 49 | 50 | void show_statistics (void) const; 51 | 52 | ////// Static methods - to be called before FlexMalloc has been fully initiliazed 53 | 54 | static void * uninitialized_malloc (size_t s); 55 | static int uninitialized_posix_memalign (void **ptr, size_t align, size_t s); 56 | static void * uninitialized_realloc (void *ptr, size_t s); 57 | static void uninitialized_free (void *ptr); 58 | static size_t uninitialized_malloc_usable_size (void *ptr); 59 | }; 60 | 61 | -------------------------------------------------------------------------------- /src/utils.cxx: -------------------------------------------------------------------------------- 1 | // Author: Harald Servat 2 | // Date: Feb 10, 2017 3 | // License: To determine 4 | 5 | #include 6 | #include 7 | #include 8 | #include "utils.hxx" 9 | 10 | // Process /proc/self/maps entries like 11 | // 2aff88d78000-2aff88d7a000 rw-p 001c7000 fd:00 33555446 /usr/lib64/libc-2.17.so 12 | // ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] 13 | 14 | bool parse_proc_self_maps_entry (const char *entry, 15 | size_t *start, size_t *end, size_t lenpermissions, char *permissions, 16 | size_t *offset, size_t lenmodule, char *module) 17 | { 18 | const char blankchars[] = "\n\r\t\f\v"; 19 | constexpr size_t LENPERMISSIONS = 5; 20 | bool res = false; 21 | char *beginptr = nullptr, *endptr = nullptr; 22 | char _module[lenmodule]; 23 | size_t _start, _end, _offset; 24 | char _perms[LENPERMISSIONS]; 25 | 26 | if (lenpermissions < LENPERMISSIONS) 27 | return false; 28 | 29 | // Parse first hex number, start address (e.g. 2aff88d78000) 30 | _start = strtoull (entry, &endptr, 16); 31 | if (endptr != entry) 32 | { 33 | if (*endptr == '-') 34 | { 35 | // Skip hyphen 36 | beginptr = endptr+1; 37 | // Parse second hex number, end address (e.g. 2aff88d7a000) 38 | _end = strtoull (beginptr, &endptr, 16); 39 | if (endptr != beginptr) 40 | { 41 | // Now get the permissions (e.g. rw-p) 42 | // if there are at least 4 chars to be processed 43 | if ((*endptr == ' ') && (strlen(endptr) >= 5)) 44 | { 45 | _perms[0] = endptr[1]; 46 | _perms[1] = endptr[2]; 47 | _perms[2] = endptr[3]; 48 | _perms[3] = endptr[4]; 49 | _perms[4] = '\0'; 50 | endptr += 4; 51 | 52 | // Get offset after a white space (e.g. 001c7000) 53 | if (strlen(endptr) > 1) 54 | { 55 | beginptr = endptr+1; 56 | _offset = strtoull (beginptr, &endptr, 16); 57 | 58 | // If we have parsed an offset, now ignore the fd:00 and size, 59 | // and grab the module name. 60 | // Need to skip 2 fields, plus an indefinite number of spaces 61 | if (endptr != beginptr && endptr != nullptr) 62 | { 63 | lenmodule -= endptr-entry; // Update remaining length of the string to parse 64 | enum skipped_fields_e { MAJOR_MINOR, INODE, FILEPATH }; 65 | size_t skip_count = 0; 66 | for (int sf = MAJOR_MINOR; sf < FILEPATH; sf++) 67 | { 68 | // Skip over some blankspace + everything that is not a blankspace (in regex: "\s+\S+") 69 | skip_count += std::min (strspn (endptr+skip_count, " "), lenmodule); 70 | lenmodule -= skip_count; 71 | skip_count += std::min (strcspn (endptr+skip_count, " "), lenmodule); 72 | lenmodule -= skip_count; 73 | } 74 | // Skip over indefinite number of spaces 75 | skip_count += std::min (strspn (endptr+skip_count, " "), lenmodule); 76 | lenmodule -= skip_count; 77 | endptr += skip_count; 78 | // We found the module name 79 | if (*endptr != '\0') 80 | { 81 | size_t count = std::min (strcspn (endptr, blankchars), lenmodule); 82 | strncpy (_module, endptr, count); 83 | _module[count] = '\0'; 84 | // If module is non-empty, then we have all 85 | // the data needed and we can return 86 | res = strlen(_module) > 0; 87 | } 88 | } 89 | } 90 | } 91 | } 92 | } 93 | } 94 | 95 | // If everything worked, let's copy the data back 96 | if (res) 97 | { 98 | *start = _start; 99 | *end = _end; 100 | memcpy (permissions, _perms, LENPERMISSIONS); 101 | *offset = _offset; 102 | memcpy (module, _module, lenmodule); 103 | } 104 | 105 | return res; 106 | } 107 | -------------------------------------------------------------------------------- /src/utils.hxx: -------------------------------------------------------------------------------- 1 | // Author: Harald Servat 2 | // Date: Feb 10, 2017 3 | // License: To determine 4 | 5 | #pragma once 6 | 7 | bool parse_proc_self_maps_entry (const char *entry, 8 | size_t *start, size_t *end, size_t lenpermissions, char *permissions, 9 | size_t *offset, size_t lenmodule, char *module); 10 | -------------------------------------------------------------------------------- /tests/Makefile.am: -------------------------------------------------------------------------------- 1 | EXTRA_DIST = malloc+free-libtester-locations \ 2 | malloc+free-locations \ 3 | base-memory-configuration 4 | 5 | CFLAGS= 6 | 7 | lib_LTLIBRARIES = libtester.la 8 | 9 | bin_PROGRAMS = malloc+free \ 10 | malloc+free-libtester \ 11 | multiple-tests \ 12 | realloc \ 13 | posix_memalign+realloc \ 14 | malloc+realloc 15 | 16 | libtester_la_SOURCES = libtester.c libtester.h 17 | libtester_la_CFLAGS = -g -O0 18 | 19 | malloc_free_SOURCES = malloc+free.c 20 | malloc_free_CFLAGS = -g -O0 21 | 22 | malloc_free_libtester_SOURCES = malloc+free-libtester.c 23 | malloc_free_libtester_CFLAGS = -g -O0 24 | malloc_free_libtester_LDFLAGS = libtester.la 25 | malloc_free_libtester_DEPENDENCIES = libtester.la 26 | 27 | multiple_tests_SOURCES = multiple-tests.c 28 | multiple_tests_CFLAGS = -g -O0 29 | 30 | realloc_SOURCES = realloc.c 31 | realloc_CFLAGS = -g -O0 32 | 33 | posix_memalign_realloc_SOURCES = posix_memalign+realloc.c 34 | posix_memalign_realloc_CFLAGS = -g -O0 35 | 36 | malloc_realloc_SOURCES = malloc+realloc.c 37 | malloc_realloc_CFLAGS = -g -O0 38 | 39 | install-data-hook: 40 | $(mkdir_p) $(datadir) 41 | cp $(srcdir)/*-locations $(srcdir)/base-memory-configuration $(datadir) 42 | 43 | -------------------------------------------------------------------------------- /tests/base-memory-configuration: -------------------------------------------------------------------------------- 1 | # Memory configuration for allocator posix 2 | Size 4096 MBytes 3 | -------------------------------------------------------------------------------- /tests/libtester.c: -------------------------------------------------------------------------------- 1 | #include "libtester.h" 2 | 3 | void * malloc_lib (size_t s) 4 | { 5 | return malloc (s); 6 | } 7 | -------------------------------------------------------------------------------- /tests/libtester.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #pragma once 4 | 5 | void * malloc_lib (size_t); 6 | -------------------------------------------------------------------------------- /tests/malloc+free-libtester-locations: -------------------------------------------------------------------------------- 1 | # Memory configuration with size 0 bytes on allocator posix 2 | # This is an example. The format is, one line per call-stack, on each line the complete call-stack 3 | # e.g. file1.c:line1 > file2.c:line2 > file3.c:line3 ... > fileN.c:lineN 4 | malloc+free-libtester.c:9 > libtester.c:6 > libc-start.c:342 @ posix 5 | -------------------------------------------------------------------------------- /tests/malloc+free-libtester.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "libtester.h" 4 | 5 | int main (int argc, char *argv[]) 6 | { 7 | int *p; 8 | printf ("Hello world\n"); 9 | p = (int*) malloc_lib (16); 10 | free (p); 11 | printf ("Bye world\n"); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /tests/malloc+free-locations: -------------------------------------------------------------------------------- 1 | # Memory configuration with size 0 bytes on allocator posix 2 | # This is an example. The format is, one line per call-stack, on each line the complete call-stack 3 | # e.g. file1.c:line1 > file2.c:line2 > file3.c:line3 ... > fileN.c:lineN 4 | malloc+free.c:8 > libc-start.c:342 @ posix 5 | -------------------------------------------------------------------------------- /tests/malloc+free.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main (int argc, char *argv[]) 5 | { 6 | int *p; 7 | printf ("Hello world\n"); 8 | p = (int*) malloc (16); 9 | free (p); 10 | printf ("Bye world\n"); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /tests/malloc+realloc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define N 1024*1024 7 | 8 | #define TAG1 ((void*) 0xdeadbeef) 9 | #define TAG2 ((void*) 0xbeefdead) 10 | 11 | int main (int argc, char *argv[]) 12 | { 13 | size_t s; 14 | void * ptr; 15 | uintptr_t c = 0; 16 | assert ((ptr = malloc (2 * sizeof(void*))) != NULL); 17 | void **p = (void**) ptr; 18 | p[0] = TAG1; 19 | p[1] = TAG2; 20 | for (s = 2 * sizeof(void*); s < N; s *= 2) 21 | { 22 | ptr = realloc (ptr, s); 23 | if (ptr != NULL) 24 | { 25 | c = ((uintptr_t) ptr) ^ c; 26 | p = (void**) ptr; 27 | if (p[0] != TAG1) 28 | { 29 | fprintf (stderr, "Error! TAG1 not found in p[0] after realloc (, %lu)! -- value found %p\n", s, p[0]); 30 | free (ptr); 31 | return 0; 32 | } 33 | if (p[1] != TAG2) 34 | { 35 | fprintf (stderr, "Error! TAG2 not found in p[1] after realloc (, %lu)! -- value found %p\n", s, p[1]); 36 | free (ptr); 37 | return 0; 38 | } 39 | } 40 | } 41 | printf ("c = %p\n", (void*) c); 42 | free (ptr); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /tests/multiple-tests.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | static int check_zero (int n, int *p) 7 | { 8 | int i; 9 | int sum; 10 | for (sum = 0, i = 0; i < n; ++i) 11 | sum += p[i]; 12 | return sum == 0; 13 | } 14 | 15 | int main (int argc, char *argv[]) 16 | { 17 | printf ("Testing malloc:\n"); 18 | 19 | { 20 | #define MAX_MALLOC 16 21 | int i; 22 | void * ptr[MAX_MALLOC]; 23 | 24 | // Sequence of mallocs and then freeing them 25 | printf ("* malloc test 1\n"); 26 | for (i = 0; i < MAX_MALLOC; ++i) 27 | ptr[i] = malloc (i*2+1); 28 | 29 | for (i = 0; i < MAX_MALLOC; ++i) 30 | assert (ptr[i] != NULL); 31 | 32 | for (i = 0; i < MAX_MALLOC; ++i) 33 | free (ptr[i]); 34 | 35 | // Sequence of mallocs and then freing them in reverse order 36 | printf ("* malloc test 2\n"); 37 | for (i = 0; i < MAX_MALLOC; ++i) 38 | ptr[i] = malloc (i*4+1); 39 | 40 | for (i = 0; i < MAX_MALLOC; ++i) 41 | assert (ptr[i] != NULL); 42 | 43 | for (i = MAX_MALLOC-1; i >= 0; --i) 44 | free (ptr[i]); 45 | 46 | // Sequence of malloc-and-free 47 | printf ("* malloc test 3\n"); 48 | for (i = 0; i < MAX_MALLOC; ++i) 49 | { 50 | void * p = malloc (i+1); 51 | assert (p != NULL); 52 | free (p); 53 | } 54 | #undef MAX_MALLOC 55 | } 56 | 57 | printf ("Testing calloc:\n"); 58 | { 59 | #define MAX_CALLOC 16 60 | int i; 61 | int * ptr[MAX_CALLOC]; 62 | 63 | // Sequence of callocs, check they're 0 and then freeing them 64 | printf ("* calloc test 1\n"); 65 | for (i = 0; i < MAX_CALLOC; ++i) 66 | ptr[i] = (int*) calloc (i+1, sizeof(int)); 67 | 68 | for (i = 0; i < MAX_CALLOC; ++i) 69 | assert (check_zero (i+1, ptr[i])); 70 | 71 | for (i = 0; i < MAX_CALLOC; ++i) 72 | assert (ptr[i] != NULL); 73 | 74 | for (i = 0; i < MAX_CALLOC; ++i) 75 | free (ptr[i]); 76 | 77 | // Sequence of mallocs, check they're 0 and then freeing them in reverse order 78 | printf ("* calloc test 2\n"); 79 | for (i = 0; i < MAX_CALLOC; ++i) 80 | ptr[i] = (int*) calloc (i+2, sizeof(int)); 81 | 82 | for (i = 0; i < MAX_CALLOC; ++i) 83 | assert (check_zero (i+2, ptr[i])); 84 | 85 | for (i = 0; i < MAX_CALLOC; ++i) 86 | assert (ptr[i] != NULL); 87 | 88 | for (i = MAX_CALLOC-1; i >= 0; --i) 89 | free (ptr[i]); 90 | 91 | // Sequence of calloc-and-free 92 | printf ("* calloc test 3\n"); 93 | for (i = 0; i < MAX_CALLOC; ++i) 94 | { 95 | int *p = (int *) calloc (i+1, sizeof(int)); 96 | assert (check_zero (i, p)); 97 | assert (p != NULL); 98 | free (p); 99 | } 100 | #undef MAX_MALLOC 101 | } 102 | 103 | printf ("Testing realloc:\n"); 104 | { 105 | #define MAX_REALLOC 16 106 | int i; 107 | void * ptr[MAX_REALLOC]; 108 | 109 | printf ("* realloc test 1\n"); 110 | for (i = 0; i < MAX_REALLOC; ++i) 111 | ptr[i] = malloc (1+i*2); 112 | 113 | for (i = 0; i < MAX_REALLOC; ++i) 114 | assert (ptr[i] != NULL); 115 | 116 | for (i = 0; i < MAX_REALLOC; ++i) 117 | ptr[i] = realloc (ptr[i], i*4); 118 | 119 | for (i = 0; i < MAX_REALLOC; ++i) 120 | free (ptr[i]); 121 | 122 | printf ("* realloc test 2\n"); 123 | for (i = 0; i < MAX_REALLOC; ++i) 124 | ptr[i] = malloc (3+i*4); 125 | 126 | for (i = 0; i < MAX_REALLOC; ++i) 127 | assert (ptr[i] != NULL); 128 | 129 | for (i = 0; i < MAX_REALLOC; ++i) 130 | ptr[i] = realloc (ptr[i], i*2); 131 | 132 | for (i = MAX_REALLOC-1; i >= 0; i--) 133 | free (ptr[i]); 134 | 135 | printf ("* realloc test 3\n"); 136 | for (i = 0; i < MAX_REALLOC; i++) 137 | { 138 | void * p = realloc (NULL, 2+i*4); 139 | assert (p != NULL); 140 | free (p); 141 | } 142 | #undef MAX_REALLOC 143 | } 144 | 145 | printf ("Testing posix_memalign:\n"); 146 | { 147 | #define MAX_ALLOC 16 148 | int i; 149 | void * ptr[MAX_ALLOC]; 150 | 151 | // Sequence of posix_memalign with different alignments starting at 8 152 | printf ("* posix_memalign test 1\n"); 153 | for (i = 0; i < MAX_ALLOC; ++i) 154 | { 155 | assert (0 == posix_memalign (&ptr[i], 1 << (i+3), i+1)); 156 | } 157 | 158 | for (i = 0; i < MAX_ALLOC; ++i) 159 | { 160 | assert (ptr[i] != NULL); 161 | assert ( (((long) ptr[i]) & (1 << (i+3) - 1)) == 0 ); 162 | } 163 | 164 | for (i = 0; i < MAX_ALLOC; ++i) 165 | free (ptr[i]); 166 | 167 | // Sequence of posix_memalign with different alignments starting at 32, and freeing in reverse order 168 | printf ("* posix_memalign test 2\n"); 169 | for (i = 0; i < MAX_ALLOC; ++i) 170 | { 171 | assert (0 == posix_memalign (&ptr[i], 1 << (i+5), i+1)); 172 | } 173 | 174 | for (i = 0; i < MAX_ALLOC; ++i) 175 | { 176 | assert (ptr[i] != NULL); 177 | assert ( (((long) ptr[i]) & (1 << (i+5) - 1)) == 0 ); 178 | } 179 | 180 | for (i = MAX_ALLOC-1; i >= 0; --i) 181 | free (ptr[i]); 182 | 183 | #undef MAX_ALLOC 184 | } 185 | 186 | 187 | return 0; 188 | } 189 | -------------------------------------------------------------------------------- /tests/posix_memalign+realloc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define N 1024*1024 7 | 8 | #define TAG1 ((void*) 0xdeadbeef) 9 | #define TAG2 ((void*) 0xbeefdead) 10 | 11 | int main (int argc, char *argv[]) 12 | { 13 | size_t s; 14 | void * ptr; 15 | uintptr_t c = 0; 16 | assert (posix_memalign (&ptr, 64, 2 * sizeof(void*)) == 0); 17 | if (ptr == NULL) 18 | return 0; 19 | void **p = (void**) ptr; 20 | p[0] = TAG1; 21 | p[1] = TAG2; 22 | for (s = 2 * sizeof(void*) ; s < N; s *= 2) 23 | { 24 | ptr = realloc (ptr, s); 25 | if (ptr != NULL) 26 | { 27 | c = ((uintptr_t) ptr) ^ c; 28 | p = (void**) ptr; 29 | if (p[0] != TAG1) 30 | { 31 | fprintf (stderr, "Error! TAG1 not found in p[0] after realloc (, %lu)! -- value found %p\n", s, p[0]); 32 | free (ptr); 33 | return 0; 34 | } 35 | if (p[1] != TAG2) 36 | { 37 | fprintf (stderr, "Error! TAG2 not found in p[1] after realloc (, %lu)! -- value found %p\n", s, p[1]); 38 | free (ptr); 39 | return 0; 40 | } 41 | } 42 | } 43 | printf ("c = %p\n", (void*) c); 44 | free (ptr); 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /tests/realloc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define N 1024*1024 6 | 7 | int main (int argc, char *argv[]) 8 | { 9 | size_t s = 1; 10 | void * ptr = NULL; 11 | uintptr_t c = 0; 12 | 13 | for ( ; s < N; ++s) 14 | { 15 | ptr = realloc (ptr, s); 16 | c = ((uintptr_t) ptr) ^ c; 17 | } 18 | printf ("c = %p\n", (void*)c); 19 | free (ptr); 20 | return 0; 21 | } 22 | --------------------------------------------------------------------------------