├── .github ├── ISSUE_TEMPLATE │ ├── bugreport.md │ └── config.yml └── workflows │ ├── linux.yml │ └── macos.yml ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── doc ├── culog1.png ├── culog2.png ├── culog3.png ├── culog4.png └── culog5.png ├── ext ├── README.md ├── catapult.tar.gz ├── catapult_trace_event_format.pdf └── update.sh ├── make.sh ├── posixwrap ├── apple │ ├── aio.h │ ├── arpa │ │ └── inet.h │ ├── dirent.h │ ├── fcntl.h │ ├── glob.h │ ├── iconv.h │ ├── langinfo.h │ ├── locale.h │ ├── pthread.h │ ├── sched.h │ ├── search.h │ ├── semaphore.h │ ├── signal.h │ ├── spawn.h │ ├── stdio.h │ ├── stdlib.h │ ├── string.h │ ├── strings.h │ ├── sys │ │ ├── mman.h │ │ └── stat.h │ ├── time.h │ ├── unistd.h │ ├── wchar.h │ └── wctype.h ├── common │ ├── assert.h │ ├── complex.h │ ├── cpio.h │ ├── ctype.h │ ├── dlfcn.h │ ├── errno.h │ ├── fenv.h │ ├── float.h │ ├── fmtmsg.h │ ├── fnmatch.h │ ├── grp.h │ ├── inttypes.h │ ├── iso646.h │ ├── libgen.h │ ├── limits.h │ ├── math.h │ ├── monetary.h │ ├── net │ │ └── if.h │ ├── netdb.h │ ├── netinet │ │ ├── in.h │ │ └── tcp.h │ ├── nl_types.h │ ├── poll.h │ ├── pwd.h │ ├── regex.h │ ├── setjmp.h │ ├── stdarg.h │ ├── stdbool.h │ ├── stddef.h │ ├── stdint.h │ ├── sys │ │ ├── ipc.h │ │ ├── msg.h │ │ ├── resource.h │ │ ├── select.h │ │ ├── sem.h │ │ ├── shm.h │ │ ├── socket.h │ │ ├── statvfs.h │ │ ├── time.h │ │ ├── times.h │ │ ├── types.h │ │ ├── uio.h │ │ ├── un.h │ │ ├── utsname.h │ │ └── wait.h │ ├── syslog.h │ ├── tar.h │ ├── termios.h │ ├── ulimit.h │ ├── utime.h │ ├── utmpx.h │ └── wordexp.h └── linux │ ├── aio.h │ ├── arpa │ └── inet.h │ ├── dirent.h │ ├── fcntl.h │ ├── ftw.h │ ├── glob.h │ ├── iconv.h │ ├── langinfo.h │ ├── locale.h │ ├── mqueue.h │ ├── pthread.h │ ├── sched.h │ ├── search.h │ ├── semaphore.h │ ├── signal.h │ ├── spawn.h │ ├── stdio.h │ ├── stdlib.h │ ├── string.h │ ├── strings.h │ ├── sys │ ├── mman.h │ └── stat.h │ ├── time.h │ ├── unistd.h │ ├── wchar.h │ └── wctype.h ├── src ├── cpuusage ├── cpuusage.1 ├── cpuusage.h ├── cugenwrapper ├── cumain.cpp ├── cupmain.cpp └── libcpuusage_CMakeLists.txt └── tests ├── ex.json ├── ex001.c ├── ex002.c ├── ex003.cpp ├── ex004.cpp ├── ex005.sh ├── ex005b.sh ├── test001 ├── test002 ├── test003 ├── test004 └── test005 /.github/ISSUE_TEMPLATE/bugreport.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Report a bug by creating a new issue. 4 | labels: bug 5 | assignees: d99kris 6 | --- 7 | 8 | **Description**: 9 | 10 | **How to reproduce it**: 11 | 12 | **Environment**: 13 | - Version: 14 | - OS / distro: 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Feature request 4 | url: https://github.com/d99kris/cpuusage/discussions/new?category=ideas 5 | about: Suggest a new feature by starting a new discussion. 6 | - name: Question 7 | url: https://github.com/d99kris/cpuusage/discussions/new?category=q-a 8 | about: Ask a question by starting a new discussion. 9 | -------------------------------------------------------------------------------- /.github/workflows/linux.yml: -------------------------------------------------------------------------------- 1 | name: Linux 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - master 8 | - main 9 | - dev/* 10 | 11 | jobs: 12 | linux-build: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v1 17 | - name: Build Linux 18 | run: ./make.sh all 19 | -------------------------------------------------------------------------------- /.github/workflows/macos.yml: -------------------------------------------------------------------------------- 1 | name: macOS 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - master 8 | - main 9 | - dev/* 10 | 11 | jobs: 12 | mac-build: 13 | runs-on: macos-latest 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v1 17 | - name: Build macOS 18 | run: ./make.sh all 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMake 2 | cmake_minimum_required(VERSION 3.14...3.22 FATAL_ERROR) 3 | 4 | # Project 5 | project(cpuusage) 6 | 7 | # Utilities 8 | configure_file(src/cpuusage ${CMAKE_CURRENT_BINARY_DIR}/bin/cpuusage COPYONLY) 9 | install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/bin/cpuusage DESTINATION bin) 10 | configure_file(src/cugenwrapper ${CMAKE_CURRENT_BINARY_DIR}/bin/cugenwrapper COPYONLY) 11 | install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/bin/cugenwrapper DESTINATION bin) 12 | 13 | # Manual 14 | configure_file(src/cpuusage.1 ${CMAKE_CURRENT_BINARY_DIR}/share/man/man1/cpuusage.1 COPYONLY) 15 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/share/man/man1/cpuusage.1 DESTINATION share/man/man1) 16 | 17 | # Catapult 18 | if (NOT IS_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/share/cpuusage/catapult) 19 | execute_process(COMMAND ${CMAKE_COMMAND} -E tar -xzvf ${CMAKE_SOURCE_DIR}/ext/catapult.tar.gz) 20 | endif () 21 | install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/share/cpuusage/catapult DESTINATION share/cpuusage) 22 | 23 | # POSIX Wrappers - Apple 24 | if (APPLE) 25 | file(COPY posixwrap/apple/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/share/cpuusage/posixwrap) 26 | endif () 27 | 28 | # POSIX Wrappers - Linux 29 | if (UNIX AND NOT APPLE) 30 | file(COPY posixwrap/linux/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/share/cpuusage/posixwrap) 31 | endif () 32 | 33 | # POSIX Wrappers - Common 34 | file(COPY posixwrap/common/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/share/cpuusage/posixwrap) 35 | install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/share/cpuusage/posixwrap DESTINATION share/cpuusage) 36 | 37 | # Cpuusage library source 38 | configure_file(src/cumain.cpp ${CMAKE_CURRENT_BINARY_DIR}/share/cpuusage/src/cumain.cpp COPYONLY) 39 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/share/cpuusage/src/cumain.cpp DESTINATION share/cpuusage/src) 40 | 41 | # Cpuusage library CMakeLists 42 | configure_file(src/libcpuusage_CMakeLists.txt ${CMAKE_CURRENT_BINARY_DIR}/share/cpuusage/src/libcpuusage_CMakeLists.txt COPYONLY) 43 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/share/cpuusage/src/libcpuusage_CMakeLists.txt DESTINATION share/cpuusage/src) 44 | 45 | # Cpuusage library header 46 | configure_file(src/cpuusage.h ${CMAKE_CURRENT_BINARY_DIR}/include/cpuusage.h COPYONLY) 47 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/cpuusage.h DESTINATION include) 48 | 49 | include_directories("src") 50 | 51 | # Cpuusage library build 52 | set(CMAKE_BUILD_TYPE Debug) 53 | set(CMAKE_CXX_STANDARD 11) 54 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib) 55 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib) 56 | add_library(${PROJECT_NAME} SHARED src/cumain.cpp src/cpuusage.h) 57 | add_library(${PROJECT_NAME}static STATIC src/cumain.cpp src/cpuusage.h) 58 | set_property(TARGET ${PROJECT_NAME}static PROPERTY POSITION_INDEPENDENT_CODE 1) 59 | target_link_libraries(${PROJECT_NAME} dl) 60 | target_link_libraries(${PROJECT_NAME}static dl) 61 | set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "-g -Wall -Wextra -pedantic") 62 | set_target_properties(${PROJECT_NAME}static PROPERTIES COMPILE_FLAGS "-g -Wall -Wextra -pedantic") 63 | install(TARGETS ${PROJECT_NAME} DESTINATION lib) 64 | 65 | # Cpuusageproc library build 66 | add_library(${PROJECT_NAME}proc SHARED src/cupmain.cpp) 67 | target_link_libraries(${PROJECT_NAME}proc dl) 68 | set_target_properties(${PROJECT_NAME}proc PROPERTIES COMPILE_FLAGS "-g -Wall -Wextra -pedantic") 69 | install(TARGETS ${PROJECT_NAME}proc DESTINATION lib) 70 | 71 | # Example - ex001 - regular program / non-instrumented 72 | add_executable(ex001 tests/ex001.c) 73 | target_link_libraries(ex001 pthread) 74 | 75 | # Example - ex002 - instrumented 76 | add_executable(ex002 tests/ex002.c) 77 | set_target_properties(ex002 PROPERTIES COMPILE_FLAGS "-finstrument-functions") 78 | target_link_options(ex002 PRIVATE "-rdynamic") 79 | target_link_libraries(ex002 pthread cpuusage) 80 | 81 | # Example - ex003 - manually instrumented 82 | add_executable(ex003 tests/ex003.cpp src/cpuusage.h) 83 | target_link_libraries(ex003 pthread cpuusage) 84 | 85 | # Example - ex004 - simple program (sleep) 86 | add_executable(ex004 tests/ex004.cpp) 87 | target_link_libraries(ex004) 88 | 89 | # Example - ex005 - simple scripts 90 | configure_file(tests/ex005.sh ${CMAKE_CURRENT_BINARY_DIR}/ex005.sh COPYONLY) 91 | configure_file(tests/ex005b.sh ${CMAKE_CURRENT_BINARY_DIR}/ex005b.sh COPYONLY) 92 | 93 | # Tests 94 | enable_testing() 95 | 96 | configure_file(tests/test001 ${CMAKE_CURRENT_BINARY_DIR}/test001 COPYONLY) 97 | add_test(test001 "${PROJECT_BINARY_DIR}/test001") 98 | 99 | configure_file(tests/test002 ${CMAKE_CURRENT_BINARY_DIR}/test002 COPYONLY) 100 | add_test(test002 "${PROJECT_BINARY_DIR}/test002") 101 | 102 | configure_file(tests/test003 ${CMAKE_CURRENT_BINARY_DIR}/test003 COPYONLY) 103 | add_test(test003 "${PROJECT_BINARY_DIR}/test003") 104 | 105 | configure_file(tests/test004 ${CMAKE_CURRENT_BINARY_DIR}/test004 COPYONLY) 106 | add_test(test004 "${PROJECT_BINARY_DIR}/test004") 107 | 108 | if(UNIX AND NOT APPLE) 109 | configure_file(tests/test005 ${CMAKE_CURRENT_BINARY_DIR}/test005 COPYONLY) 110 | add_test(test005 "${PROJECT_BINARY_DIR}/test005") 111 | endif() 112 | 113 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2017, Kristofer Berggren 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 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * 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 | * 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Cpuusage 2 | ======== 3 | 4 | | **Linux** | **Mac** | 5 | |-----------|---------| 6 | | [![Linux](https://github.com/d99kris/cpuusage/workflows/Linux/badge.svg)](https://github.com/d99kris/cpuusage/actions?query=workflow%3ALinux) | [![macOS](https://github.com/d99kris/cpuusage/workflows/macOS/badge.svg)](https://github.com/d99kris/cpuusage/actions?query=workflow%3AmacOS) | 7 | 8 | Cpuusage is an instrumentation CPU profiler for Linux and macOS applications. 9 | It provides logging of standard POSIX function calls for any application, and logging of 10 | internal function calls for programs compiled with -finstrument-functions. 11 | The logging output format is a HTML-file generated using 12 | [Chromium Catapult](https://github.com/catapult-project/catapult). 13 | 14 | Example Usage 15 | ============= 16 | Tracing all POSIX function calls from a regular (non-instrumented) application: 17 | 18 | $ cpuusage -v -o cutrace1.html -a ./ex001 19 | cpuusage: https://github.com/d99kris/cpuusage 20 | cpuusage: initializing 21 | cpuusage: starting program ./ex001 22 | cpuusage: processing output trace 23 | cpuusage: completed processing 96 samples 24 | $ xdg-open cutrace1.html 25 | 26 | Resulting visualization: 27 | ![culog1 screenshot](/doc/culog1.png) 28 | 29 | Supported Platforms 30 | =================== 31 | Cpuusage is primarily developed and tested on Linux, but basic functionality 32 | should work in macOS as well. Current version has been tested on: 33 | - macOS Sequoia 15.2 34 | - Ubuntu 24.04 LTS 35 | 36 | Limitation: On macOS this tool relies on code injection using 37 | DYLD_INSERT_LIBRARIES, which generally does not work with third-party 38 | applications in a standard system. Using it on (your own) applications built 39 | from source should work fine though. 40 | 41 | Installation 42 | ============ 43 | Pre-requisites (Ubuntu): 44 | 45 | sudo apt install git cmake build-essential python3-six 46 | 47 | Download the source code: 48 | 49 | git clone https://github.com/d99kris/cpuusage && cd cpuusage 50 | 51 | Generate Makefile and build: 52 | 53 | mkdir -p build && cd build && cmake .. && make -s 54 | 55 | Optionally install in system: 56 | 57 | sudo make install 58 | 59 | Usage 60 | ===== 61 | 62 | General syntax: 63 | 64 | cpuusage -a [OPTIONS] PROG [ARGS..] 65 | cpuusage -c [OPTIONS] PROG [ARGS..] 66 | cpuusage -f [OPTIONS] PROG [ARGS..] 67 | cpuusage -i [OPTIONS] PROG [ARGS..] 68 | cpuusage -p [OPTIONS] PROG [ARGS..] 69 | cpuusage -r JSONFILE [OPTIONS] 70 | cpuusage --help|-h 71 | cpuusage --version|-v 72 | 73 | Options: 74 | 75 | -a trace all standard POSIX function calls 76 | 77 | -c trace internal function calls (requires PROG to be compiled with 78 | -finstrument-functions) 79 | 80 | -d debug mode, running program through debugger 81 | 82 | -e separate processes for child process trace 83 | 84 | -f 85 | trace specified POSIX functions 86 | 87 | -i 88 | trace functions in specified POSIX headers 89 | 90 | -p trace child process durations 91 | 92 | --help, -h 93 | display this help and exit 94 | 95 | --version, -v 96 | output version information and exit 97 | 98 | -j 99 | write iterim JSON trace log to specified path 100 | 101 | -m 102 | only log samples with minimum specified duration (in usec) 103 | currently only supported when tracing main-thread only. 104 | 105 | -n 106 | only log up to specified number of samples 107 | 108 | -o 109 | write HTML report to specified path, rather than default 110 | ./cutrace-PID.html 111 | 112 | -r 113 | read JSON file and convert to HTML report 114 | 115 | -s start tracing with SIGUSR1 and stop with SIGUSR2, instead of 116 | trace from process start 117 | 118 | -u trace only main-thread 119 | 120 | -v verbose mode 121 | 122 | -y auto-open resulting html file 123 | 124 | PROG program to run and profile 125 | 126 | [ARGS] optional arguments to the program 127 | 128 | More Examples 129 | ============= 130 | **Tracing specified POSIX function calls from a regular (non-instrumented) application:** 131 | 132 | $ cpuusage -v -o cutrace2.html -f fopen,fwrite,fread,fclose ./ex001 133 | cpuusage: https://github.com/d99kris/cpuusage 134 | cpuusage: initializing 135 | cpuusage: starting program ./ex001 136 | cpuusage: processing output trace 137 | cpuusage: completed processing 36 samples 138 | $ xdg-open cutrace2.html 139 | 140 | Resulting visualization: 141 | ![culog2 screenshot](/doc/culog2.png) 142 | 143 | **Tracing internal function calls in an instrumented application:** 144 | 145 | $ cpuusage -v -o cutrace3.html -c ./ex002 146 | cpuusage: https://github.com/d99kris/cpuusage 147 | cpuusage: initializing 148 | cpuusage: starting program ./ex002 149 | cpuusage: processing output trace 150 | cpuusage: completed processing 8 samples 151 | $ xdg-open cutrace3.html 152 | 153 | Resulting visualization: 154 | ![culog3 screenshot](/doc/culog3.png) 155 | 156 | **Tracing internal function calls and all external POSIX function calls in an instrumented application:** 157 | 158 | $ cpuusage -v -o cutrace4.html -c -a ./ex002 159 | cpuusage: https://github.com/d99kris/cpuusage 160 | cpuusage: initializing 161 | cpuusage: starting program ./ex002 162 | cpuusage: processing output trace 163 | cpuusage: completed processing 104 samples 164 | $ xdg-open cutrace4.html 165 | 166 | Resulting visualization: 167 | ![culog4 screenshot](/doc/culog4.png) 168 | 169 | **Tracing process durations:** 170 | 171 | $ cpuusage -v -o cutrace5.html -p ./ex005.sh 172 | cpuusage: https://github.com/d99kris/cpuusage 173 | cpuusage: initializing 174 | cpuusage: starting program ./ex005.sh 175 | cpuusage: processing output trace 176 | cpuusage: completed processing 5 samples 177 | 178 | Resulting visualization: 179 | ![culog5 screenshot](/doc/culog5.png) 180 | 181 | Alternatives 182 | ============ 183 | There are many CPU profilers available for Linux and macOS. Most of them are 184 | sample-based, and here is a list of some of them: 185 | - Gperftools 186 | - Gprof 187 | - Instruments - Time Profiler 188 | - Valgrind - Callgrind 189 | 190 | Technical Details 191 | ================= 192 | Refer to [ext/README.md](/ext/README.md) for details on the external components 193 | used by cpuusage. 194 | 195 | License 196 | ======= 197 | Cpuusage is distributed under the BSD 3-Clause license. See LICENSE file. 198 | 199 | Keywords 200 | ======== 201 | linux, macos, cpu usage, instrumented profiler, alternative to callgrind. 202 | -------------------------------------------------------------------------------- /doc/culog1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d99kris/cpuusage/69f846c099de316f10790a5fd0eac61bee39ead8/doc/culog1.png -------------------------------------------------------------------------------- /doc/culog2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d99kris/cpuusage/69f846c099de316f10790a5fd0eac61bee39ead8/doc/culog2.png -------------------------------------------------------------------------------- /doc/culog3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d99kris/cpuusage/69f846c099de316f10790a5fd0eac61bee39ead8/doc/culog3.png -------------------------------------------------------------------------------- /doc/culog4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d99kris/cpuusage/69f846c099de316f10790a5fd0eac61bee39ead8/doc/culog4.png -------------------------------------------------------------------------------- /doc/culog5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d99kris/cpuusage/69f846c099de316f10790a5fd0eac61bee39ead8/doc/culog5.png -------------------------------------------------------------------------------- /ext/README.md: -------------------------------------------------------------------------------- 1 | External Components 2 | =================== 3 | This directory contains external components used by cpuusage. 4 | 5 | Catapult 6 | -------- 7 | Catapult is the most important third-party component of cpuusage. Not the entire 8 | Catapult software is needed by cpuusage, so only a part of the original package 9 | is distributed with cpuusage. It is compressed and located in catapult.tar.gz 10 | 11 | ### Trace File Format 12 | Cpuusage generates JSON files following the 13 | [Trace Event Format](/ext/catapult_trace_event_format.pdf) which subsequently 14 | is converted by Catapult into a HTML report. 15 | 16 | The Trace Event Format PDF was generated from the Google Document 17 | [Trace Event Format](https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit) 18 | linked from [Catapult Tracing](https://chromium.googlesource.com/catapult/+/HEAD/tracing/README.md). 19 | 20 | ### Updating Catapult 21 | In case Catapult needs to be updated (it happened when updating to Python 3.x 22 | support) the recommended method is: 23 | 24 | 1. Run script to update external modules 25 | 26 | ./ext/update.sh 27 | 28 | 2. Perform any necessary updates to the update.sh script to make tests pass. 29 | 30 | 3. Once all tests are passing, ext/catapult.tar.gz will be updated 31 | automatically. 32 | 33 | -------------------------------------------------------------------------------- /ext/catapult.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d99kris/cpuusage/69f846c099de316f10790a5fd0eac61bee39ead8/ext/catapult.tar.gz -------------------------------------------------------------------------------- /ext/catapult_trace_event_format.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d99kris/cpuusage/69f846c099de316f10790a5fd0eac61bee39ead8/ext/catapult_trace_event_format.pdf -------------------------------------------------------------------------------- /ext/update.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright (C) 2022-2025 Kristofer Berggren 4 | # All rights reserved. 5 | # 6 | # cpuusage is distributed under the BSD 3-Clause license, see LICENSE for 7 | # details. 8 | 9 | TMPCATAPULT="/tmp/cpuusage-catapult" 10 | 11 | prereq() 12 | { 13 | if [[ ! -d "${TMPCATAPULT}" ]]; then 14 | git clone https://chromium.googlesource.com/catapult ${TMPCATAPULT} || exit 1 15 | else 16 | echo "using existing clone in ${TMPCATAPULT}" 17 | fi 18 | 19 | if [[ ! -d "build" ]]; then 20 | ./make.sh build || exit 1 21 | else 22 | echo "using existing build in ./build" 23 | fi 24 | } 25 | 26 | update_catapult() 27 | { 28 | pushd ./build/share/cpuusage/catapult/ > /dev/null && \ 29 | rm -rf ./* && \ 30 | cp ${TMPCATAPULT}/LICENSE LICENSE && \ 31 | cp -a ${TMPCATAPULT}/tracing tracing && \ 32 | rm -rf tracing/test_data && \ 33 | mkdir common && \ 34 | cp -a ${TMPCATAPULT}/common/py_vulcanize common/ && \ 35 | mkdir third_party && \ 36 | cp -a ${TMPCATAPULT}/third_party/beautifulsoup4-4.9.3 third_party/ && \ 37 | cp -a ${TMPCATAPULT}/third_party/polymer third_party/ && \ 38 | cp -a ${TMPCATAPULT}/third_party/html5lib-1.1 third_party/ && \ 39 | cp -a ${TMPCATAPULT}/third_party/webencodings-0.5.1 third_party/ && \ 40 | popd > /dev/null && \ 41 | echo "updated catapult module" || exit 1 42 | } 43 | 44 | package_catapult() 45 | { 46 | pushd ./build > /dev/null && \ 47 | rm -f catapult.tar.gz && \ 48 | tar -czvf catapult.tar.gz share/cpuusage/catapult && \ 49 | popd > /dev/null && \ 50 | cp ./build/catapult.tar.gz ./ext/catapult.tar.gz && \ 51 | rm -f ./build/catapult.tar.gz && \ 52 | echo "packaged catapult module" || exit 1 53 | } 54 | 55 | test_catapult() 56 | { 57 | SCRIPT="./build/share/cpuusage/catapult/tracing/bin/trace2html" 58 | TESTJSON="./tests/ex.json" 59 | TMPHTML="./build/sanity_test.html" 60 | python3 ${SCRIPT} ${TESTJSON} --output=${TMPHTML} > /dev/null && \ 61 | rm "${TMPHTML}" && \ 62 | echo "sanity test passed" || exit 1 63 | } 64 | 65 | test_all() 66 | { 67 | ./make.sh tests && \ 68 | echo "all tests passed" || exit 1 69 | } 70 | 71 | cleanup() 72 | { 73 | rm -rf build && \ 74 | rm -rf "${TMPCATAPULT}" && \ 75 | echo "cleanup complete" || exit 1 76 | } 77 | 78 | prereq 79 | update_catapult 80 | test_catapult 81 | test_all 82 | update_catapult 83 | package_catapult 84 | #cleanup 85 | 86 | echo "success" 87 | exit 0 88 | -------------------------------------------------------------------------------- /make.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # make.sh 4 | # 5 | # Copyright (C) 2020-2025 Kristofer Berggren 6 | # All rights reserved. 7 | # 8 | # See LICENSE for redistribution information. 9 | 10 | # exiterr 11 | exiterr() 12 | { 13 | >&2 echo "${1}" 14 | exit 1 15 | } 16 | 17 | # process arguments 18 | DEPS="0" 19 | BUILD="0" 20 | TESTS="0" 21 | DOC="0" 22 | INSTALL="0" 23 | case "${1%/}" in 24 | deps) 25 | DEPS="1" 26 | ;; 27 | 28 | build) 29 | BUILD="1" 30 | ;; 31 | 32 | test*) 33 | BUILD="1" 34 | TESTS="1" 35 | ;; 36 | 37 | doc) 38 | BUILD="1" 39 | DOC="1" 40 | ;; 41 | 42 | install) 43 | BUILD="1" 44 | INSTALL="1" 45 | ;; 46 | 47 | all) 48 | DEPS="1" 49 | BUILD="1" 50 | TESTS="1" 51 | DOC="1" 52 | INSTALL="1" 53 | ;; 54 | 55 | *) 56 | echo "usage: make.sh " 57 | echo " deps - install project dependencies" 58 | echo " build - perform build" 59 | echo " tests - perform build and run tests" 60 | echo " doc - perform build and generate documentation" 61 | echo " install - perform build and install" 62 | echo " all - perform all actions above" 63 | exit 1 64 | ;; 65 | esac 66 | 67 | # deps 68 | if [[ "${DEPS}" == "1" ]]; then 69 | OS="$(uname)" 70 | if [ "${OS}" == "Linux" ]; then 71 | DISTRO="$(lsb_release -i | awk -F':\t' '{print $2}')" 72 | if [[ "${DISTRO}" == "Ubuntu" ]]; then 73 | sudo apt install git cmake build-essential python3-six || exiterr "deps failed (linux), exiting." 74 | else 75 | exiterr "deps failed (unsupported linux distro ${DISTRO}), exiting." 76 | fi 77 | elif [ "${OS}" == "Darwin" ]; then 78 | HOMEBREW_NO_AUTO_UPDATE=1 brew install six || exiterr "deps failed (mac), exiting." 79 | else 80 | exiterr "deps failed (unsupported os ${OS}), exiting." 81 | fi 82 | fi 83 | 84 | # build 85 | if [[ "${BUILD}" == "1" ]]; then 86 | OS="$(uname)" 87 | MAKEARGS="" 88 | if [ "${OS}" == "Linux" ]; then 89 | MAKEARGS="-j$(nproc)" 90 | elif [ "${OS}" == "Darwin" ]; then 91 | MAKEARGS="-j$(sysctl -n hw.ncpu)" 92 | fi 93 | mkdir -p build && cd build && cmake .. && make ${MAKEARGS} && cd .. || exiterr "build failed, exiting." 94 | fi 95 | 96 | # tests 97 | if [[ "${TESTS}" == "1" ]]; then 98 | cd build && ctest --output-on-failure && cd .. || exiterr "tests failed, exiting." 99 | fi 100 | 101 | # doc 102 | if [[ "${DOC}" == "1" ]]; then 103 | if [[ -x "$(command -v help2man)" ]]; then 104 | if [[ "$(uname)" == "Darwin" ]]; then 105 | SED="gsed -i" 106 | else 107 | SED="sed -i" 108 | fi 109 | cd src && help2man -n "instrumentation CPU profiler" -N -o cpuusage.1 ./cpuusage && cd - > /dev/null && ${SED} "s/\.\\\\\" DO NOT MODIFY THIS FILE\! It was generated by help2man.*/\.\\\\\" DO NOT MODIFY THIS FILE\! It was generated by help2man./g" src/cpuusage.1 || exiterr "doc failed, exiting." 110 | fi 111 | fi 112 | 113 | # install 114 | if [[ "${INSTALL}" == "1" ]]; then 115 | OS="$(uname)" 116 | if [ "${OS}" == "Linux" ]; then 117 | cd build && sudo make install && cd .. || exiterr "install failed (linux), exiting." 118 | elif [ "${OS}" == "Darwin" ]; then 119 | GHSUDO="" 120 | if [[ "${GITHUB_ACTIONS}" == "true" ]]; then 121 | GHSUDO="sudo" 122 | fi 123 | cd build && ${GHSUDO} make install && cd .. || exiterr "install failed (mac), exiting." 124 | else 125 | exiterr "install failed (unsupported os ${OS}), exiting." 126 | fi 127 | fi 128 | 129 | # exit 130 | exit 0 131 | -------------------------------------------------------------------------------- /posixwrap/apple/aio.h: -------------------------------------------------------------------------------- 1 | int aio_cancel(int a, struct aiocb *b); 2 | int aio_error(const struct aiocb *a); 3 | int aio_fsync(int a, struct aiocb *b); 4 | int aio_read(struct aiocb *a); 5 | ssize_t aio_return(struct aiocb *b); 6 | int aio_suspend(const struct aiocb *const a[], int b, const struct timespec *c); 7 | int aio_write(struct aiocb *a); 8 | -------------------------------------------------------------------------------- /posixwrap/apple/arpa/inet.h: -------------------------------------------------------------------------------- 1 | in_addr_t inet_addr(const char *a); 2 | char *inet_ntoa(struct in_addr a); 3 | const char *inet_ntop(int a, const void *restrict b, char *restrict c, socklen_t d); 4 | int inet_pton(int a, const char *restrict b, void *restrict c); 5 | -------------------------------------------------------------------------------- /posixwrap/apple/dirent.h: -------------------------------------------------------------------------------- 1 | int alphasort(const struct dirent **a, const struct dirent **b); 2 | int closedir(DIR *a); 3 | int dirfd(DIR *a); 4 | DIR *fdopendir(int a); 5 | DIR *opendir(const char *a); 6 | struct dirent *readdir(DIR *a); 7 | int readdir_r(DIR *restrict a, struct dirent *restrict b, struct dirent **restrict c); 8 | void rewinddir(DIR *a); 9 | //unsupported (incompatible pointer): int scandir(const char *a, struct dirent ***b, int (*c)(const struct dirent *), int (*d)(const struct dirent **, const struct dirent **)); 10 | void seekdir(DIR *a, long b); 11 | long telldir(DIR *a); 12 | -------------------------------------------------------------------------------- /posixwrap/apple/fcntl.h: -------------------------------------------------------------------------------- 1 | int creat(const char *a, mode_t b); 2 | //unsupported (variable args): int fcntl(int, int, ...); 3 | //unsupported (variable args): int open(const char *, int, ...); 4 | //unsupported (variable args): int openat(int, const char *, int, ...); 5 | -------------------------------------------------------------------------------- /posixwrap/apple/glob.h: -------------------------------------------------------------------------------- 1 | //unsupported (incompatible pointer): int glob(const char *restrict a, int b, int(*c)(const char *, int), glob_t *restrict d); 2 | void globfree(glob_t *a); 3 | -------------------------------------------------------------------------------- /posixwrap/apple/iconv.h: -------------------------------------------------------------------------------- 1 | //unsupported (undefined symbol iconv): size_t iconv(iconv_t a, char **restrict b, size_t *restrict c, char **restrict d, size_t *restrict e); 2 | //unsupported (undefined symbol iconv_close): int iconv_close(iconv_t a); 3 | //unsupported (undefined symbol iconv_open): iconv_t iconv_open(const char *a, const char *b); 4 | -------------------------------------------------------------------------------- /posixwrap/apple/langinfo.h: -------------------------------------------------------------------------------- 1 | char *nl_langinfo(nl_item a); 2 | -------------------------------------------------------------------------------- /posixwrap/apple/locale.h: -------------------------------------------------------------------------------- 1 | char *setlocale(int a, const char *b); 2 | -------------------------------------------------------------------------------- /posixwrap/apple/pthread.h: -------------------------------------------------------------------------------- 1 | int pthread_atfork(void (*a)(void), void (*b)(void), void(*c)(void)); 2 | int pthread_attr_destroy(pthread_attr_t *a); 3 | int pthread_attr_getdetachstate(const pthread_attr_t *a, int *b); 4 | int pthread_attr_getguardsize(const pthread_attr_t *restrict a, size_t *restrict b); 5 | int pthread_attr_getinheritsched(const pthread_attr_t *restrict a, int *restrict b); 6 | int pthread_attr_getschedparam(const pthread_attr_t *restrict a, struct sched_param *restrict b); 7 | int pthread_attr_getschedpolicy(const pthread_attr_t *restrict a, int *restrict b); 8 | int pthread_attr_getscope(const pthread_attr_t *restrict a, int *restrict b); 9 | int pthread_attr_getstack(const pthread_attr_t *restrict a, void **restrict b, size_t *restrict c); 10 | int pthread_attr_getstacksize(const pthread_attr_t *restrict a, size_t *restrict b); 11 | int pthread_attr_init(pthread_attr_t *a); 12 | int pthread_attr_setdetachstate(pthread_attr_t *a, int b); 13 | int pthread_attr_setguardsize(pthread_attr_t *a, size_t b); 14 | int pthread_attr_setinheritsched(pthread_attr_t *a, int b); 15 | int pthread_attr_setschedparam(pthread_attr_t *restrict a, const struct sched_param *restrict b); 16 | int pthread_attr_setschedpolicy(pthread_attr_t *a, int b); 17 | int pthread_attr_setscope(pthread_attr_t *a, int b); 18 | int pthread_attr_setstack(pthread_attr_t *a, void *b, size_t c); 19 | int pthread_attr_setstacksize(pthread_attr_t *a, size_t b); 20 | int pthread_cancel(pthread_t a); 21 | int pthread_cond_broadcast(pthread_cond_t *a); 22 | int pthread_cond_destroy(pthread_cond_t *a); 23 | int pthread_cond_init(pthread_cond_t *restrict a, const pthread_condattr_t *restrict b); 24 | int pthread_cond_signal(pthread_cond_t *a); 25 | int pthread_cond_timedwait(pthread_cond_t *restrict a, pthread_mutex_t *restrict b, const struct timespec *restrict c); 26 | int pthread_cond_wait(pthread_cond_t *restrict a, pthread_mutex_t *restrict b); 27 | int pthread_condattr_destroy(pthread_condattr_t *a); 28 | int pthread_condattr_getpshared(const pthread_condattr_t *restrict a, int *restrict b); 29 | int pthread_condattr_init(pthread_condattr_t *a); 30 | int pthread_condattr_setpshared(pthread_condattr_t *a, int b); 31 | //unsupported (incompatible pointer): int pthread_create(pthread_t *restrict a, const pthread_attr_t *restrict b, void *(*c)(void*), void *restrict d); 32 | int pthread_detach(pthread_t a); 33 | int pthread_equal(pthread_t a, pthread_t b); 34 | //unsupported (never returns): void pthread_exit(void *a); 35 | int pthread_getconcurrency(void); 36 | int pthread_getschedparam(pthread_t a, int *restrict b, struct sched_param *restrict c); 37 | void *pthread_getspecific(pthread_key_t a); 38 | int pthread_join(pthread_t a, void **b); 39 | int pthread_key_create(pthread_key_t *a, void (*b)(void*)); 40 | int pthread_key_delete(pthread_key_t a); 41 | int pthread_mutex_destroy(pthread_mutex_t * a); 42 | int pthread_mutex_getprioceiling(const pthread_mutex_t *restrict a, int *restrict b); 43 | int pthread_mutex_init(pthread_mutex_t *restrict a, const pthread_mutexattr_t *restrict b); 44 | int pthread_mutex_lock(pthread_mutex_t * a); 45 | int pthread_mutex_setprioceiling(pthread_mutex_t *restrict a, int b, int *restrict c); 46 | int pthread_mutex_trylock(pthread_mutex_t * a); 47 | int pthread_mutex_unlock(pthread_mutex_t * a); 48 | int pthread_mutexattr_destroy(pthread_mutexattr_t * a); 49 | int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *restrict a, int *restrict b); 50 | int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *restrict a, int *restrict b); 51 | int pthread_mutexattr_getpshared(const pthread_mutexattr_t *restrict a, int *restrict b); 52 | int pthread_mutexattr_gettype(const pthread_mutexattr_t *restrict a, int *restrict b); 53 | int pthread_mutexattr_init(pthread_mutexattr_t * a); 54 | int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *a, int b); 55 | int pthread_mutexattr_setprotocol(pthread_mutexattr_t *a, int b); 56 | int pthread_mutexattr_setpshared(pthread_mutexattr_t *a, int b); 57 | int pthread_mutexattr_settype(pthread_mutexattr_t *a, int b); 58 | int pthread_once(pthread_once_t *a, void (*b)(void)); 59 | int pthread_rwlock_destroy(pthread_rwlock_t * a); 60 | int pthread_rwlock_init(pthread_rwlock_t *restrict a, const pthread_rwlockattr_t *restrict b); 61 | int pthread_rwlock_rdlock(pthread_rwlock_t * a); 62 | int pthread_rwlock_tryrdlock(pthread_rwlock_t * a); 63 | int pthread_rwlock_trywrlock(pthread_rwlock_t * a); 64 | int pthread_rwlock_unlock(pthread_rwlock_t * a); 65 | int pthread_rwlock_wrlock(pthread_rwlock_t * a); 66 | int pthread_rwlockattr_destroy(pthread_rwlockattr_t * a); 67 | int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *restrict a, int *restrict b); 68 | int pthread_rwlockattr_init(pthread_rwlockattr_t * a); 69 | int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *a, int b); 70 | //unsupported (internally used by cpuusage): pthread_t pthread_self(void); 71 | int pthread_setcancelstate(int a, int * b); 72 | int pthread_setcanceltype(int a, int * b); 73 | int pthread_setconcurrency(int a); 74 | int pthread_setschedparam(pthread_t a, int b, const struct sched_param * c); 75 | int pthread_setspecific(pthread_key_t a, const void * b); 76 | void pthread_testcancel(void); 77 | -------------------------------------------------------------------------------- /posixwrap/apple/sched.h: -------------------------------------------------------------------------------- 1 | int sched_get_priority_max(int a); 2 | int sched_get_priority_min(int a); 3 | int sched_yield(void); 4 | -------------------------------------------------------------------------------- /posixwrap/apple/search.h: -------------------------------------------------------------------------------- 1 | int hcreate(size_t a); 2 | void hdestroy(void); 3 | void insque(void *a, void *b); 4 | //unsupported (incompatible pointer): void *lfind(const void *a, const void *b, size_t *c, size_t d, int (*e)(const void *, const void *)); 5 | //unsupported (incompatible pointer): void *lsearch(const void *a, void *b, size_t *c, size_t d, int (*e)(const void *, const void *)); 6 | void remque(void *a); 7 | //unsupported (incompatible pointer): void *tdelete(const void *restrict a, void **restrict b, int(*c)(const void *, const void *)); 8 | //unsupported (incompatible pointer): void *tfind(const void *a, void *const *b, int(*c)(const void *, const void *)); 9 | //unsupported (incompatible pointer): void *tsearch(const void *a, void **b, int(*c)(const void *, const void *)); 10 | void twalk(const void *a, void (*b)(const void *, VISIT, int )); 11 | -------------------------------------------------------------------------------- /posixwrap/apple/semaphore.h: -------------------------------------------------------------------------------- 1 | int sem_close(sem_t *a); 2 | //unsupported (variable args): sem_t *sem_open(const char *a, int b, ...); 3 | int sem_post(sem_t *a); 4 | int sem_trywait(sem_t *a); 5 | int sem_unlink(const char *a); 6 | int sem_wait(sem_t *a); 7 | -------------------------------------------------------------------------------- /posixwrap/apple/signal.h: -------------------------------------------------------------------------------- 1 | int kill(pid_t a, int b); 2 | int killpg(pid_t a, int b); 3 | void psignal(int a, const char *b); 4 | int pthread_kill(pthread_t a, int b); 5 | int pthread_sigmask(int a, const sigset_t *restrict b, sigset_t *restrict c); 6 | int raise(int a); 7 | int sigaction(int a, const struct sigaction *restrict b, struct sigaction *restrict c); 8 | //unsupported (undefined symbol sigbits): int sigaddset(sigset_t *a, int b); 9 | int sigaltstack(const stack_t *restrict a, stack_t *restrict b); 10 | //unsupported (undefined symbol sigbits): int sigdelset(sigset_t *a, int b); 11 | int sigemptyset(sigset_t *a); 12 | int sigfillset(sigset_t *a); 13 | int sighold(int a); 14 | int sigignore(int a); 15 | int siginterrupt(int a, int b); 16 | //unsupported (undefined symbol sigbits): int sigismember(const sigset_t *a, int b); 17 | sig_t signal(int a, sig_t b); 18 | int sigpause(int a); 19 | int sigpending(sigset_t *a); 20 | int sigprocmask(int a, const sigset_t *restrict b, sigset_t *restrict c); 21 | int sigrelse(int a); 22 | sig_t sigset(int a, sig_t b); 23 | int sigsuspend(const sigset_t *a); 24 | int sigwait(const sigset_t *restrict a, int *restrict b); 25 | -------------------------------------------------------------------------------- /posixwrap/apple/spawn.h: -------------------------------------------------------------------------------- 1 | int posix_spawn(pid_t *restrict a, const char *restrict b, const posix_spawn_file_actions_t *c, const posix_spawnattr_t *restrict d, char *const e[restrict], char *const f[restrict]); 2 | int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *a, int b); 3 | int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *a, int b, int c); 4 | int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *restrict a, int b, const char *restrict c, int d, mode_t e); 5 | int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *a); 6 | int posix_spawn_file_actions_init(posix_spawn_file_actions_t *a); 7 | int posix_spawnattr_destroy(posix_spawnattr_t *a); 8 | int posix_spawnattr_getflags(const posix_spawnattr_t *restrict a, short *restrict b); 9 | int posix_spawnattr_getpgroup(const posix_spawnattr_t *restrict a, pid_t *restrict b); 10 | int posix_spawnattr_getsigdefault(const posix_spawnattr_t *restrict a, sigset_t *restrict b); 11 | int posix_spawnattr_getsigmask(const posix_spawnattr_t *restrict a, sigset_t *restrict b); 12 | int posix_spawnattr_init(posix_spawnattr_t *a); 13 | int posix_spawnattr_setflags(posix_spawnattr_t *a, short b); 14 | int posix_spawnattr_setpgroup(posix_spawnattr_t *a, pid_t b); 15 | int posix_spawnattr_setsigdefault(posix_spawnattr_t *restrict a, const sigset_t *restrict b); 16 | int posix_spawnattr_setsigmask(posix_spawnattr_t *restrict a, const sigset_t *restrict b); 17 | int posix_spawnp(pid_t *restrict a, const char *restrict b, const posix_spawn_file_actions_t *c, const posix_spawnattr_t *restrict d, char *const e[restrict], char *const f[restrict]); 18 | -------------------------------------------------------------------------------- /posixwrap/apple/stdio.h: -------------------------------------------------------------------------------- 1 | void clearerr(FILE *a); 2 | char *ctermid(char *a); 3 | int dprintf(int a, const char *restrict b, ...) 4 | int fclose(FILE *a); 5 | FILE *fdopen(int a, const char *b); 6 | int feof(FILE *a); 7 | int ferror(FILE *a); 8 | int fflush(FILE *a); 9 | int fgetc(FILE *a); 10 | int fgetpos(FILE *restrict a, fpos_t *restrict b); 11 | char *fgets(char *restrict a, int b, FILE *restrict c); 12 | int fileno(FILE *a); 13 | void flockfile(FILE *a); 14 | FILE *fopen(const char *restrict a, const char *restrict b); 15 | int fprintf(FILE *restrict a, const char *restrict b, ...); 16 | int fputc(int a, FILE *b); 17 | int fputs(const char *restrict a, FILE *restrict b); 18 | size_t fread(void *restrict a, size_t b, size_t c, FILE *restrict d); 19 | FILE *freopen(const char *restrict a, const char *restrict b, FILE *restrict c); 20 | int fscanf(FILE *restrict a, const char *restrict b, ...); 21 | int fseek(FILE *a, long b, int c); 22 | int fseeko(FILE *a, off_t b, int c); 23 | int fsetpos(FILE *a, const fpos_t *b); 24 | long ftell(FILE *a); 25 | off_t ftello(FILE *a); 26 | int ftrylockfile(FILE *a); 27 | void funlockfile(FILE *a); 28 | size_t fwrite(const void *restrict a, size_t b, size_t c, FILE *restrict d); 29 | int getc(FILE *a); 30 | int getchar(void); 31 | int getc_unlocked(FILE *a); 32 | int getchar_unlocked(void); 33 | ssize_t getdelim(char **restrict a, size_t *restrict b, int c, FILE *restrict d); 34 | ssize_t getline(char **restrict a, size_t *restrict b, FILE *restrict c); 35 | char *gets(char *a); 36 | int pclose(FILE *a); 37 | void perror(const char *a); 38 | FILE *popen(const char *a, const char *b); 39 | int printf(const char *restrict a, ...); 40 | int putc(int a, FILE *b); 41 | int putchar(int a); 42 | //unsupported (undefined symbol sputc): int putc_unlocked(int a, FILE *b); 43 | //unsupported (undefined symbol sputc): int putchar_unlocked(int a); 44 | int puts(const char *a); 45 | int remove(const char *a); 46 | int rename(const char *a, const char *b); 47 | int renameat(int a, const char *b, int c, const char *d); 48 | void rewind(FILE *a); 49 | int scanf(const char *restrict a, ...); 50 | void setbuf(FILE *restrict a, char *restrict b); 51 | int setvbuf(FILE *restrict a, char *restrict b, int c, size_t d); 52 | int snprintf(char *restrict a, size_t b, const char *restrict c, ...); 53 | int sprintf(char *restrict a, const char *restrict b, ...); 54 | int sscanf(const char *restrict a, const char *restrict b, ...); 55 | //unsupported (deprecated warning): char *tempnam(const char *a, const char *b); 56 | FILE *tmpfile(void); 57 | //unsupported (deprecated warning): char *tmpnam(char *a); 58 | int ungetc(int a, FILE *b); 59 | int vdprintf(int a, const char *restrict b, va_list c); 60 | int vfprintf(FILE *restrict a, const char *restrict b, va_list c); 61 | int vfscanf(FILE *restrict a, const char *restrict b, va_list c); 62 | int vprintf(const char *restrict a, va_list b); 63 | int vscanf(const char *restrict a, va_list b); 64 | int vsnprintf(char *restrict a, size_t b, const char *restrict c, va_list d); 65 | int vsprintf(char *restrict a, const char *restrict b, va_list c); 66 | int vsscanf(const char *restrict a, const char *restrict b, va_list c); 67 | -------------------------------------------------------------------------------- /posixwrap/apple/stdlib.h: -------------------------------------------------------------------------------- 1 | //unsupported (never returns): void _Exit(int a); 2 | long a64l(const char *a); 3 | //unsupported (never returns): void abort(void); 4 | int abs(int a); 5 | int atexit(void (*a)(void)); 6 | double atof(const char *a); 7 | int atoi(const char *a); 8 | long atol(const char *a); 9 | long long atoll(const char *a); 10 | //unsupported (incompatible pointer): void *bsearch(const void *a, const void *b, size_t c, size_t d, int (*e)(const void *, const void *)); 11 | void *calloc(size_t a, size_t b); 12 | div_t div(int a, int b); 13 | double drand48(void); 14 | double erand48(unsigned short a[3]); 15 | //unsupported (never returns): void exit(int a); 16 | void free(void *a); 17 | char *getenv(const char *a); 18 | int getsubopt(char **a, char *const *b, char **c); 19 | int grantpt(int a); 20 | char *initstate(unsigned a, char *b, size_t c); 21 | long jrand48(unsigned short a[3]); 22 | char *l64a(long a); 23 | long labs(long a); 24 | void lcong48(unsigned short a[7]); 25 | ldiv_t ldiv(long a, long b); 26 | long long llabs(long long a); 27 | lldiv_t lldiv(long long a, long long b); 28 | long lrand48(void); 29 | void *malloc(size_t a); 30 | int mblen(const char *a, size_t b); 31 | size_t mbstowcs(wchar_t *restrict a, const char *restrict b, size_t c); 32 | int mbtowc(wchar_t *restrict a, const char *restrict b, size_t c); 33 | char *mkdtemp(char *a); 34 | int mkstemp(char *a); 35 | long mrand48(void); 36 | long nrand48(unsigned short a[3]); 37 | int posix_memalign(void **a, size_t b, size_t c); 38 | int posix_openpt(int a); 39 | char *ptsname(int a); 40 | int putenv(char *a); 41 | //unsupported (incompatible pointer): void qsort(void *a, size_t b, size_t c, int (*d)(const void *, const void *)); 42 | int rand(void); 43 | int rand_r(unsigned *a); 44 | long random(void); 45 | void *realloc(void *a, size_t b); 46 | char *realpath(const char *restrict a, char *restrict b); 47 | unsigned short *seed48(unsigned short a[3]); 48 | int setenv(const char *a, const char *b, int c); 49 | void setkey(const char *a); 50 | char *setstate(char *a); 51 | void srand(unsigned a); 52 | void srand48(long a); 53 | void srandom(unsigned a); 54 | double strtod(const char *restrict a, char **restrict b); 55 | float strtof(const char *restrict a, char **restrict b); 56 | long strtol(const char *restrict a, char **restrict b, int c); 57 | long double strtold(const char *restrict a, char **restrict b); 58 | long long strtoll(const char *restrict a, char **restrict b, int c); 59 | unsigned long strtoul(const char *restrict a, char **restrict b, int c); 60 | unsigned long long strtoull(const char *restrict a, char **restrict b, int c); 61 | int system(const char *a); 62 | int unlockpt(int a); 63 | int unsetenv(const char *a); 64 | size_t wcstombs(char *restrict a, const wchar_t *restrict b, size_t c); 65 | int wctomb(char *a, wchar_t b); 66 | -------------------------------------------------------------------------------- /posixwrap/apple/string.h: -------------------------------------------------------------------------------- 1 | void *memccpy(void *restrict a, const void *restrict b, int c, size_t d); 2 | void *memchr(const void *a, int b, size_t c); 3 | int memcmp(const void *a, const void *b, size_t c); 4 | //unsupported (used by cpuusage): void *memcpy(void *restrict a, const void *restrict b, size_t c); 5 | //unsupported (used by cpuusage): void *memmove(void *a, const void *b, size_t c); 6 | //unsupported (used by cpuusage): void *memset(void *a, int b, size_t c); 7 | char *stpcpy(char *restrict a, const char *restrict b); 8 | char *stpncpy(char *restrict a, const char *restrict b, size_t c); 9 | char *strcat(char *restrict a, const char *restrict b); 10 | char *strchr(const char *a, int b); 11 | int strcmp(const char *a, const char *b); 12 | int strcoll(const char *a, const char *b); 13 | char *strcpy(char *restrict a, const char *restrict b); 14 | size_t strcspn(const char *a, const char *b); 15 | char *strdup(const char *a); 16 | char *strerror(int a); 17 | //unsupported (not common for platforms): int strerror_r(int a, char *b, size_t c); 18 | size_t strlen(const char *a); 19 | char *strncat(char *restrict a, const char *restrict b, size_t c); 20 | int strncmp(const char *a, const char *b, size_t c); 21 | char *strncpy(char *restrict a, const char *restrict b, size_t c); 22 | char *strndup(const char *a, size_t b); 23 | size_t strnlen(const char *a, size_t b); 24 | char *strpbrk(const char *a, const char *b); 25 | char *strrchr(const char *a, int b); 26 | char *strsignal(int a); 27 | size_t strspn(const char *a, const char *b); 28 | char *strstr(const char *a, const char *b); 29 | char *strtok(char *restrict a, const char *restrict b); 30 | char *strtok_r(char *restrict a, const char *restrict b, char **restrict c); 31 | size_t strxfrm(char *restrict a, const char *restrict b, size_t c); 32 | -------------------------------------------------------------------------------- /posixwrap/apple/strings.h: -------------------------------------------------------------------------------- 1 | int ffs(int a); 2 | int strcasecmp(const char *a, const char *b); 3 | int strncasecmp(const char *a, const char *b, size_t c); 4 | -------------------------------------------------------------------------------- /posixwrap/apple/sys/mman.h: -------------------------------------------------------------------------------- 1 | int mlock(const void *a, size_t b); 2 | int mlockall(int a); 3 | void *mmap(void *a, size_t b, int c, int d, int e, off_t f); 4 | int mprotect(void *a, size_t b, int c); 5 | int msync(void *a, size_t b, int c); 6 | int munlock(const void *a, size_t b); 7 | int munlockall(void); 8 | int munmap(void *a, size_t b); 9 | int posix_madvise(void *a, size_t b, int c); 10 | //unsupported (missing type on Linux): int posix_typed_mem_get_info(int a, struct posix_typed_mem_info *b); 11 | int shm_open(const char *a, int b, mode_t c); 12 | int shm_unlink(const char *a); 13 | -------------------------------------------------------------------------------- /posixwrap/apple/sys/stat.h: -------------------------------------------------------------------------------- 1 | int chmod(const char *a, mode_t b); 2 | int fchmod(int a, mode_t b); 3 | int fchmodat(int a, const char *b, mode_t c, int d); 4 | int fstat(int a, struct stat *b); 5 | int fstatat(int a, const char *restrict b, struct stat *restrict c, int d); 6 | int lstat(const char *restrict a, struct stat *restrict b); 7 | int mkdir(const char *a, mode_t b); 8 | int mkdirat(int a, const char *b, mode_t c); 9 | int mkfifo(const char *a, mode_t b); 10 | int mknod(const char *a, mode_t b, dev_t c); 11 | int stat(const char *restrict a, struct stat *restrict b); 12 | mode_t umask(mode_t a); 13 | -------------------------------------------------------------------------------- /posixwrap/apple/time.h: -------------------------------------------------------------------------------- 1 | char *asctime(const struct tm *a); 2 | char *asctime_r(const struct tm *restrict a, char *restrict b); 3 | clock_t clock(void); 4 | int clock_getres(clockid_t a, struct timespec *b); 5 | int clock_gettime(clockid_t a, struct timespec *b); 6 | int clock_settime(clockid_t a, const struct timespec *b); 7 | char *ctime(const time_t *a); 8 | char *ctime_r(const time_t *a, char *b); 9 | double difftime(time_t a, time_t b); 10 | struct tm *getdate(const char *a); 11 | struct tm *gmtime(const time_t *a); 12 | struct tm *gmtime_r(const time_t *restrict a, struct tm *restrict b); 13 | struct tm *localtime(const time_t *a); 14 | struct tm *localtime_r(const time_t *restrict a, struct tm *restrict b); 15 | time_t mktime(struct tm *a); 16 | int nanosleep(const struct timespec *a, struct timespec *b); 17 | size_t strftime(char *restrict a, size_t b, const char *restrict c, const struct tm *restrict d); 18 | char *strptime(const char *restrict a, const char *restrict b, struct tm *restrict c); 19 | time_t time(time_t *a); 20 | void tzset(void); 21 | -------------------------------------------------------------------------------- /posixwrap/apple/unistd.h: -------------------------------------------------------------------------------- 1 | int access(const char *a, int b); 2 | unsigned alarm(unsigned a); 3 | int chdir(const char *a); 4 | int chown(const char *a, uid_t b, gid_t c); 5 | int close(int a); 6 | size_t confstr(int a, char *b, size_t c); 7 | char *crypt(const char *a, const char *b); 8 | int dup(int a); 9 | int dup2(int a, int b); 10 | //unsupported (never returns): void _exit(int a); 11 | void encrypt(char a[64], int b); 12 | //unsupported (variable args): int execl(const char *a, const char *b, ...); 13 | //unsupported (variable args): int execle(const char *a, const char *b, ...); 14 | //unsupported (variable args): int execlp(const char *a, const char *b, ...); 15 | int execv(const char *a, char *const b[]); 16 | int execve(const char *a, char *const b[], char *const c[]); 17 | int execvp(const char *a, char *const b[]); 18 | int faccessat(int a, const char *b, int c, int d); 19 | int fchdir(int a); 20 | int fchown(int a, uid_t b, gid_t c); 21 | int fchownat(int a, const char *b, uid_t c, gid_t d, int e); 22 | pid_t fork(void); 23 | long fpathconf(int a, int b); 24 | int fsync(int a); 25 | int ftruncate(int a, off_t b); 26 | char *getcwd(char *a, size_t b); 27 | gid_t getegid(void); 28 | uid_t geteuid(void); 29 | gid_t getgid(void); 30 | int getgroups(int a, gid_t b[]); 31 | long gethostid(void); 32 | int gethostname(char *a, size_t b); 33 | char *getlogin(void); 34 | int getlogin_r(char *a, size_t b); 35 | int getopt(int a, char * const b[], const char *c); 36 | pid_t getpgid(pid_t a); 37 | pid_t getpgrp(void); 38 | pid_t getpid(void); 39 | pid_t getppid(void); 40 | pid_t getsid(pid_t a); 41 | uid_t getuid(void); 42 | int isatty(int a); 43 | int lchown(const char *a, uid_t b, gid_t c); 44 | int link(const char *a, const char *b); 45 | int linkat(int a, const char *b, int c, const char *d, int e); 46 | int lockf(int a, int b, off_t c); 47 | off_t lseek(int a, off_t b, int c); 48 | int nice(int a); 49 | long pathconf(const char *a, int b); 50 | int pause(void); 51 | int pipe(int a[2]); 52 | ssize_t pread(int a, void *b, size_t c, off_t d); 53 | ssize_t pwrite(int a, const void *b, size_t c, off_t d); 54 | ssize_t read(int a, void *b, size_t c); 55 | ssize_t readlink(const char *restrict a, char *restrict b, size_t c); 56 | ssize_t readlinkat(int a, const char *restrict b, char *restrict c, size_t d); 57 | int rmdir(const char *a); 58 | int setegid(gid_t a); 59 | int seteuid(uid_t a); 60 | int setgid(gid_t a); 61 | int setpgid(pid_t a, pid_t b); 62 | pid_t setpgrp(void); 63 | int setregid(gid_t a, gid_t b); 64 | int setreuid(uid_t a, uid_t b); 65 | int setuid(uid_t a); 66 | unsigned sleep(unsigned a); 67 | void swab(const void *restrict a, void *restrict b, ssize_t c); 68 | int symlink(const char *a, const char *b); 69 | int symlinkat(const char *a, int b, const char *c); 70 | void sync(void); 71 | long sysconf(int a); 72 | pid_t tcgetpgrp(int a); 73 | int tcsetpgrp(int a, pid_t b); 74 | int truncate(const char *a, off_t b); 75 | char *ttyname(int a); 76 | int ttyname_r(int a, char *b, size_t c); 77 | int unlink(const char *a); 78 | int unlinkat(int a, const char *b, int c); 79 | ssize_t write(int a, const void *b, size_t c); 80 | -------------------------------------------------------------------------------- /posixwrap/apple/wchar.h: -------------------------------------------------------------------------------- 1 | #include 2 | wint_t btowc(int a); 3 | wint_t fgetwc(FILE *a); 4 | wchar_t *fgetws(wchar_t *restrict a, int b, FILE *restrict c); 5 | wint_t fputwc(wchar_t a, FILE *b); 6 | int fputws(const wchar_t *restrict a, FILE *restrict b); 7 | int fwide(FILE *a, int b); 8 | int fwprintf(FILE *restrict a, const wchar_t *restrict b, ...); 9 | int fwscanf(FILE *restrict a, const wchar_t *restrict b, ...); 10 | wint_t getwc(FILE *a); 11 | wint_t getwchar(void); 12 | int iswalnum(wint_t a); 13 | int iswalpha(wint_t a); 14 | int iswcntrl(wint_t a); 15 | int iswctype(wint_t a, wctype_t b); 16 | int iswdigit(wint_t a); 17 | int iswgraph(wint_t a); 18 | int iswlower(wint_t a); 19 | int iswprint(wint_t a); 20 | int iswpunct(wint_t a); 21 | int iswspace(wint_t a); 22 | int iswupper(wint_t a); 23 | int iswxdigit(wint_t a); 24 | size_t mbrlen(const char *restrict a, size_t b, mbstate_t *restrict c); 25 | size_t mbrtowc(wchar_t *restrict a, const char *restrict b, size_t c, mbstate_t *restrict d); 26 | int mbsinit(const mbstate_t *a); 27 | size_t mbsnrtowcs(wchar_t *restrict a, const char **restrict b, size_t c, size_t d, mbstate_t *restrict e); 28 | size_t mbsrtowcs(wchar_t *restrict a, const char **restrict b, size_t c, mbstate_t *restrict d); 29 | wint_t putwc(wchar_t a, FILE *b); 30 | wint_t putwchar(wchar_t a); 31 | int swprintf(wchar_t *restrict a, size_t b, const wchar_t *restrict c, ...); 32 | int swscanf(const wchar_t *restrict a, const wchar_t *restrict b, ...); 33 | wint_t towlower(wint_t a); 34 | wint_t towupper(wint_t a); 35 | wint_t ungetwc(wint_t a, FILE *b); 36 | int vfwprintf(FILE *restrict a, const wchar_t *restrict b, va_list c); 37 | int vfwscanf(FILE *restrict a, const wchar_t *restrict b, va_list c); 38 | int vswprintf(wchar_t *restrict a, size_t b, const wchar_t *restrict c, va_list d); 39 | int vswscanf(const wchar_t *restrict a, const wchar_t *restrict b, va_list c); 40 | int vwprintf(const wchar_t *restrict a, va_list b); 41 | int vwscanf(const wchar_t *restrict a, va_list b); 42 | wchar_t *wcpcpy(wchar_t *restrict a, const wchar_t *restrict b); 43 | wchar_t *wcpncpy(wchar_t *restrict a, const wchar_t *restrict b, size_t c); 44 | size_t wcrtomb(char *restrict a, wchar_t b, mbstate_t *restrict c); 45 | int wcscasecmp(const wchar_t *a, const wchar_t *b); 46 | wchar_t *wcscat(wchar_t *restrict a, const wchar_t *restrict b); 47 | wchar_t *wcschr(const wchar_t *a, wchar_t b); 48 | int wcscmp(const wchar_t *a, const wchar_t *b); 49 | int wcscoll(const wchar_t *a, const wchar_t *b); 50 | wchar_t *wcscpy(wchar_t *restrict a, const wchar_t *restrict b); 51 | size_t wcscspn(const wchar_t *a, const wchar_t *b); 52 | wchar_t *wcsdup(const wchar_t *a); 53 | size_t wcsftime(wchar_t *restrict a, size_t b, const wchar_t *restrict c, const struct tm *restrict d); 54 | size_t wcslen(const wchar_t *a); 55 | int wcsncasecmp(const wchar_t *a, const wchar_t *b, size_t c); 56 | wchar_t *wcsncat(wchar_t *restrict a, const wchar_t *restrict b, size_t c); 57 | int wcsncmp(const wchar_t *a, const wchar_t *b, size_t c); 58 | wchar_t *wcsncpy(wchar_t *restrict a, const wchar_t *restrict b, size_t c); 59 | size_t wcsnlen(const wchar_t *a, size_t b); 60 | size_t wcsnrtombs(char *restrict a, const wchar_t **restrict b, size_t c, size_t d, mbstate_t *restrict e); 61 | wchar_t *wcspbrk(const wchar_t *a, const wchar_t *b); 62 | wchar_t *wcsrchr(const wchar_t *a, wchar_t b); 63 | size_t wcsrtombs(char *restrict a, const wchar_t **restrict b, size_t c, mbstate_t *restrict d); 64 | size_t wcsspn(const wchar_t *a, const wchar_t *b); 65 | wchar_t *wcsstr(const wchar_t *restrict a, const wchar_t *restrict b); 66 | double wcstod(const wchar_t *restrict a, wchar_t **restrict b); 67 | float wcstof(const wchar_t *restrict a, wchar_t **restrict b); 68 | wchar_t *wcstok(wchar_t *restrict a, const wchar_t *restrict b, wchar_t **restrict c); 69 | long wcstol(const wchar_t *restrict a, wchar_t **restrict b, int c); 70 | long double wcstold(const wchar_t *restrict a, wchar_t **restrict b); 71 | long long wcstoll(const wchar_t *restrict a, wchar_t **restrict b, int c); 72 | unsigned long wcstoul(const wchar_t *restrict a, wchar_t **restrict b, int c); 73 | unsigned long long wcstoull(const wchar_t *restrict a, wchar_t **restrict b, int c); 74 | int wcswidth(const wchar_t *a, size_t b); 75 | size_t wcsxfrm(wchar_t *restrict a, const wchar_t *restrict b, size_t c); 76 | int wctob(wint_t a); 77 | wctype_t wctype(const char *a); 78 | int wcwidth(wchar_t a); 79 | wchar_t *wmemchr(const wchar_t *a, wchar_t b, size_t c); 80 | int wmemcmp(const wchar_t *a, const wchar_t *b, size_t c); 81 | wchar_t *wmemcpy(wchar_t *restrict a, const wchar_t *restrict b, size_t c); 82 | wchar_t *wmemmove(wchar_t *a, const wchar_t *b, size_t c); 83 | wchar_t *wmemset(wchar_t *a, wchar_t b, size_t c); 84 | int wprintf(const wchar_t *restrict a, ...); 85 | int wscanf(const wchar_t *restrict a, ...); 86 | -------------------------------------------------------------------------------- /posixwrap/apple/wctype.h: -------------------------------------------------------------------------------- 1 | int iswblank(wint_t a); 2 | wint_t iswascii(wint_t a); 3 | wint_t iswhexnumber(wint_t a); 4 | wint_t iswideogram(wint_t a); 5 | wint_t iswnumber(wint_t a); 6 | wint_t iswphonogram(wint_t a); 7 | wint_t iswrune(wint_t a); 8 | wint_t iswspecial(wint_t a); 9 | wint_t nextwctype(wint_t a, wctype_t b); 10 | wint_t towctrans(wint_t a, wctrans_t b); 11 | wctrans_t wctrans(const char *c); 12 | -------------------------------------------------------------------------------- /posixwrap/common/assert.h: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /posixwrap/common/complex.h: -------------------------------------------------------------------------------- 1 | double cabs(double complex a); 2 | float cabsf(float complex a); 3 | long double cabsl(long double complex a); 4 | double complex cacos(double complex a); 5 | float complex cacosf(float complex a); 6 | double complex cacosh(double complex a); 7 | float complex cacoshf(float complex a); 8 | long double complex cacoshl(long double complex a); 9 | long double complex cacosl(long double complex a); 10 | double carg(double complex a); 11 | float cargf(float complex a); 12 | long double cargl(long double complex a); 13 | double complex casin(double complex a); 14 | float complex casinf(float complex a); 15 | double complex casinh(double complex a); 16 | float complex casinhf(float complex a); 17 | long double complex casinhl(long double complex a); 18 | long double complex casinl(long double complex a); 19 | double complex catan(double complex a); 20 | float complex catanf(float complex a); 21 | double complex catanh(double complex a); 22 | float complex catanhf(float complex a); 23 | long double complex catanhl(long double complex a); 24 | long double complex catanl(long double complex a); 25 | double complex ccos(double complex a); 26 | float complex ccosf(float complex a); 27 | double complex ccosh(double complex a); 28 | float complex ccoshf(float complex a); 29 | long double complex ccoshl(long double complex a); 30 | long double complex ccosl(long double complex a); 31 | double complex cexp(double complex a); 32 | float complex cexpf(float complex a); 33 | long double complex cexpl(long double complex a); 34 | double cimag(double complex a); 35 | float cimagf(float complex a); 36 | long double cimagl(long double complex a); 37 | double complex clog(double complex a); 38 | float complex clogf(float complex a); 39 | long double complex clogl(long double complex a); 40 | double complex conj(double complex a); 41 | float complex conjf(float complex a); 42 | long double complex conjl(long double complex a); 43 | double complex cpow(double complex a, double complex b); 44 | float complex cpowf(float complex a, float complex b); 45 | long double complex cpowl(long double complex a, long double complex b); 46 | double complex cproj(double complex a); 47 | float complex cprojf(float complex a); 48 | long double complex cprojl(long double complex a); 49 | double creal(double complex a); 50 | float crealf(float complex a); 51 | long double creall(long double complex a); 52 | double complex csin(double complex a); 53 | float complex csinf(float complex a); 54 | double complex csinh(double complex a); 55 | float complex csinhf(float complex a); 56 | long double complex csinhl(long double complex a); 57 | long double complex csinl(long double complex a); 58 | double complex csqrt(double complex a); 59 | float complex csqrtf(float complex a); 60 | long double complex csqrtl(long double complex a); 61 | double complex ctan(double complex a); 62 | float complex ctanf(float complex a); 63 | double complex ctanh(double complex a); 64 | float complex ctanhf(float complex a); 65 | long double complex ctanhl(long double complex a); 66 | long double complex ctanl(long double complex a); 67 | -------------------------------------------------------------------------------- /posixwrap/common/cpio.h: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /posixwrap/common/ctype.h: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /posixwrap/common/dlfcn.h: -------------------------------------------------------------------------------- 1 | int dlclose(void *a); 2 | char *dlerror(void); 3 | void *dlopen(const char *a, int b); 4 | //unsupported (internally used by cpuusage): void *dlsym(void *restrict a, const char *restrict b); 5 | -------------------------------------------------------------------------------- /posixwrap/common/errno.h: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /posixwrap/common/fenv.h: -------------------------------------------------------------------------------- 1 | int feclearexcept(int a); 2 | int fegetenv(fenv_t *a); 3 | int fegetexceptflag(fexcept_t *a, int b); 4 | int fegetround(void); 5 | int feholdexcept(fenv_t *a); 6 | int feraiseexcept(int a); 7 | int fesetenv(const fenv_t *a); 8 | int fesetexceptflag(const fexcept_t *a, int b); 9 | int fesetround(int a); 10 | int fetestexcept(int a); 11 | int feupdateenv(const fenv_t *a); 12 | -------------------------------------------------------------------------------- /posixwrap/common/float.h: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /posixwrap/common/fmtmsg.h: -------------------------------------------------------------------------------- 1 | int fmtmsg(long a, const char *b, int c, const char *d, const char *e, const char *f); 2 | -------------------------------------------------------------------------------- /posixwrap/common/fnmatch.h: -------------------------------------------------------------------------------- 1 | int fnmatch(const char *a, const char *b, int c); 2 | -------------------------------------------------------------------------------- /posixwrap/common/grp.h: -------------------------------------------------------------------------------- 1 | void endgrent(void); 2 | struct group *getgrent(void); 3 | struct group *getgrgid(gid_t a); 4 | int getgrgid_r(gid_t a, struct group *b, char *c, size_t d, struct group **e); 5 | struct group *getgrnam(const char *a); 6 | int getgrnam_r(const char *a, struct group *b, char *c, size_t d, struct group **e); 7 | void setgrent(void); 8 | -------------------------------------------------------------------------------- /posixwrap/common/inttypes.h: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /posixwrap/common/iso646.h: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /posixwrap/common/libgen.h: -------------------------------------------------------------------------------- 1 | char *basename(char *a); 2 | char *dirname(char *a); 3 | -------------------------------------------------------------------------------- /posixwrap/common/limits.h: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /posixwrap/common/math.h: -------------------------------------------------------------------------------- 1 | double acos(double a); 2 | float acosf(float a); 3 | double acosh(double a); 4 | float acoshf(float a); 5 | long double acoshl(long double a); 6 | long double acosl(long double a); 7 | double asin(double a); 8 | float asinf(float a); 9 | double asinh(double a); 10 | float asinhf(float a); 11 | long double asinhl(long double a); 12 | long double asinl(long double a); 13 | double atan(double a); 14 | double atan2(double a, double b); 15 | float atan2f(float a, float b); 16 | long double atan2l(long double a, long double b); 17 | float atanf(float a); 18 | double atanh(double a); 19 | float atanhf(float a); 20 | long double atanhl(long double a); 21 | long double atanl(long double a); 22 | double cbrt(double a); 23 | float cbrtf(float a); 24 | long double cbrtl(long double a); 25 | double ceil(double a); 26 | float ceilf(float a); 27 | long double ceill(long double a); 28 | double copysign(double a, double b); 29 | float copysignf(float a, float b); 30 | long double copysignl(long double a, long double b); 31 | double cos(double a); 32 | float cosf(float a); 33 | double cosh(double a); 34 | float coshf(float a); 35 | long double coshl(long double a); 36 | long double cosl(long double a); 37 | double erf(double a); 38 | double erfc(double a); 39 | float erfcf(float a); 40 | long double erfcl(long double a); 41 | float erff(float a); 42 | long double erfl(long double a); 43 | double exp(double a); 44 | double exp2(double a); 45 | float exp2f(float a); 46 | long double exp2l(long double a); 47 | float expf(float a); 48 | long double expl(long double a); 49 | double expm1(double a); 50 | float expm1f(float a); 51 | long double expm1l(long double a); 52 | double fabs(double a); 53 | float fabsf(float a); 54 | long double fabsl(long double a); 55 | double fdim(double a, double b); 56 | float fdimf(float a, float b); 57 | long double fdiml(long double a, long double b); 58 | double floor(double a); 59 | float floorf(float a); 60 | long double floorl(long double a); 61 | double fma(double a, double b, double c); 62 | float fmaf(float a, float b, float c); 63 | long double fmal(long double a, long double b, long double c); 64 | double fmax(double a, double b); 65 | float fmaxf(float a, float b); 66 | long double fmaxl(long double a, long double b); 67 | double fmin(double a, double b); 68 | float fminf(float a, float b); 69 | long double fminl(long double a, long double b); 70 | double fmod(double a, double b); 71 | float fmodf(float a, float b); 72 | long double fmodl(long double a, long double b); 73 | double frexp(double a, int * b); 74 | float frexpf(float a, int * b); 75 | long double frexpl(long double a, int * b); 76 | double hypot(double a, double b); 77 | float hypotf(float a, float b); 78 | long double hypotl(long double a, long double b); 79 | int ilogb(double a); 80 | int ilogbf(float a); 81 | int ilogbl(long double a); 82 | double j0(double a); 83 | double j1(double a); 84 | double jn(int a, double b); 85 | double ldexp(double a, int b); 86 | float ldexpf(float a, int b); 87 | long double ldexpl(long double a, int b); 88 | double lgamma(double a); 89 | float lgammaf(float a); 90 | long double lgammal(long double a); 91 | long long llrint(double a); 92 | long long llrintf(float a); 93 | long long llrintl(long double a); 94 | long long llround(double a); 95 | long long llroundf(float a); 96 | long long llroundl(long double a); 97 | double log(double a); 98 | double log10(double a); 99 | float log10f(float a); 100 | long double log10l(long double a); 101 | double log1p(double a); 102 | float log1pf(float a); 103 | long double log1pl(long double a); 104 | double log2(double a); 105 | float log2f(float a); 106 | long double log2l(long double a); 107 | double logb(double a); 108 | float logbf(float a); 109 | long double logbl(long double a); 110 | float logf(float a); 111 | long double logl(long double a); 112 | long lrint(double a); 113 | long lrintf(float a); 114 | long lrintl(long double a); 115 | long lround(double a); 116 | long lroundf(float a); 117 | long lroundl(long double a); 118 | double modf(double a, double *b); 119 | float modff(float a, float *b); 120 | long double modfl(long double a, long double *b); 121 | double nan(const char * a); 122 | float nanf(const char * a); 123 | long double nanl(const char * a); 124 | double nearbyint(double a); 125 | float nearbyintf(float a); 126 | long double nearbyintl(long double a); 127 | double nextafter(double a, double b); 128 | float nextafterf(float a, float b); 129 | long double nextafterl(long double a, long double b); 130 | double nexttoward(double a, long double b); 131 | float nexttowardf(float a, long double b); 132 | long double nexttowardl(long double a, long double b); 133 | double pow(double a, double b); 134 | float powf(float a, float b); 135 | long double powl(long double a, long double b); 136 | double remainder(double a, double b); 137 | float remainderf(float a, float b); 138 | long double remainderl(long double a, long double b); 139 | double remquo(double a, double b, int * c); 140 | float remquof(float a, float b, int *c); 141 | long double remquol(long double a, long double b, int *c); 142 | double rint(double a); 143 | float rintf(float a); 144 | long double rintl(long double a); 145 | double round(double a); 146 | float roundf(float a); 147 | long double roundl(long double a); 148 | double scalbln(double a, long b); 149 | float scalblnf(float a, long b); 150 | long double scalblnl(long double a, long b); 151 | double scalbn(double a, int b); 152 | float scalbnf(float a, int b); 153 | long double scalbnl(long double a, int b); 154 | double sin(double a); 155 | float sinf(float a); 156 | double sinh(double a); 157 | float sinhf(float a); 158 | long double sinhl(long double a); 159 | long double sinl(long double a); 160 | double sqrt(double a); 161 | float sqrtf(float a); 162 | long double sqrtl(long double a); 163 | double tan(double a); 164 | float tanf(float a); 165 | double tanh(double a); 166 | float tanhf(float a); 167 | long double tanhl(long double a); 168 | long double tanl(long double a); 169 | double tgamma(double a); 170 | float tgammaf(float a); 171 | long double tgammal(long double a); 172 | double trunc(double a); 173 | float truncf(float a); 174 | long double truncl(long double a); 175 | double y0(double a); 176 | double y1(double a); 177 | double yn(int a, double b); 178 | -------------------------------------------------------------------------------- /posixwrap/common/monetary.h: -------------------------------------------------------------------------------- 1 | //unsupported (variable args): ssize_t strfmon(char *restrict a, size_t b, const char *restrict c, ...); 2 | //unsupported (variable args):ssize_t strfmon_l(char *restrict a, size_t b, locale_t, const char *restrict c, ...); 3 | -------------------------------------------------------------------------------- /posixwrap/common/net/if.h: -------------------------------------------------------------------------------- 1 | void if_freenameindex(struct if_nameindex *a); 2 | char *if_indextoname(unsigned a, char *b); 3 | struct if_nameindex *if_nameindex(void); 4 | unsigned if_nametoindex(const char *a); 5 | -------------------------------------------------------------------------------- /posixwrap/common/netdb.h: -------------------------------------------------------------------------------- 1 | void endhostent(void); 2 | void endnetent(void); 3 | void endprotoent(void); 4 | void endservent(void); 5 | void freeaddrinfo(struct addrinfo *a); 6 | const char *gai_strerror(int a); 7 | int getaddrinfo(const char *restrict a, const char *restrict b, const struct addrinfo *restrict c, struct addrinfo **restrict d); 8 | struct hostent *gethostent(void); 9 | int getnameinfo(const struct sockaddr *restrict a, socklen_t b, char *restrict c, socklen_t d, char *restrict e, socklen_t f, int g); 10 | struct netent *getnetbyaddr(uint32_t a, int b); 11 | struct netent *getnetbyname(const char *a); 12 | struct netent *getnetent(void); 13 | struct protoent *getprotobyname(const char *a); 14 | struct protoent *getprotobynumber(int a); 15 | struct protoent *getprotoent(void); 16 | struct servent *getservbyname(const char *a, const char *b); 17 | struct servent *getservbyport(int a, const char *b); 18 | struct servent *getservent(void); 19 | void sethostent(int a); 20 | void setnetent(int a); 21 | void setprotoent(int a); 22 | void setservent(int a); 23 | -------------------------------------------------------------------------------- /posixwrap/common/netinet/in.h: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /posixwrap/common/netinet/tcp.h: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /posixwrap/common/nl_types.h: -------------------------------------------------------------------------------- 1 | int catclose(nl_catd a); 2 | char *catgets(nl_catd a, int b, int c, const char *d); 3 | nl_catd catopen(const char *a, int b); 4 | -------------------------------------------------------------------------------- /posixwrap/common/poll.h: -------------------------------------------------------------------------------- 1 | int poll(struct pollfd a[], nfds_t b, int c); 2 | -------------------------------------------------------------------------------- /posixwrap/common/pwd.h: -------------------------------------------------------------------------------- 1 | void endpwent(void); 2 | struct passwd *getpwent(void); 3 | struct passwd *getpwnam(const char *a); 4 | int getpwnam_r(const char *a, struct passwd *b, char *c, size_t d, struct passwd **e); 5 | struct passwd *getpwuid(uid_t a); 6 | int getpwuid_r(uid_t a, struct passwd *b, char *c, size_t d, struct passwd **e); 7 | void setpwent(void); 8 | -------------------------------------------------------------------------------- /posixwrap/common/regex.h: -------------------------------------------------------------------------------- 1 | int regcomp(regex_t *restrict a, const char *restrict b, int c); 2 | size_t regerror(int a, const regex_t *restrict b, char *restrict c, size_t d); 3 | int regexec(const regex_t *restrict a, const char *restrict b, size_t c, regmatch_t d[restrict], int e); 4 | void regfree(regex_t *a); 5 | -------------------------------------------------------------------------------- /posixwrap/common/setjmp.h: -------------------------------------------------------------------------------- 1 | //unsupported (never returns): void longjmp(jmp_buf a, int b); 2 | //unsupported (never returns): void siglongjmp(sigjmp_buf a, int b); 3 | int setjmp(jmp_buf a); 4 | int sigsetjmp(sigjmp_buf a, int b); 5 | -------------------------------------------------------------------------------- /posixwrap/common/stdarg.h: -------------------------------------------------------------------------------- 1 | //unsupported (internally used by cpuusage): void va_start(va_list ap, argN); 2 | //unsupported (internally used by cpuusage): void va_copy(va_list dest, va_list src); 3 | //unsupported (internally used by cpuusage): type va_arg(va_list ap, type a); 4 | //unsupported (internally used by cpuusage): void va_end(va_list ap); 5 | -------------------------------------------------------------------------------- /posixwrap/common/stdbool.h: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /posixwrap/common/stddef.h: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /posixwrap/common/stdint.h: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /posixwrap/common/sys/ipc.h: -------------------------------------------------------------------------------- 1 | key_t ftok(const char *a, int b); 2 | -------------------------------------------------------------------------------- /posixwrap/common/sys/msg.h: -------------------------------------------------------------------------------- 1 | int msgctl(int a, int b, struct msqid_ds *c); 2 | int msgget(key_t a, int b); 3 | ssize_t msgrcv(int a, void *b, size_t c, long d, int e); 4 | int msgsnd(int a, const void *b, size_t c, int d); 5 | -------------------------------------------------------------------------------- /posixwrap/common/sys/resource.h: -------------------------------------------------------------------------------- 1 | //unsupported (not common for platforms): int getpriority(int a, id_t b); 2 | //unsupported (not common for platforms): int getrlimit(int a, struct rlimit *b); 3 | int getrusage(int a, struct rusage *b); 4 | //unsupported (not common for platforms): int setpriority(int a, id_t b, int c); 5 | //unsupported (not common for platforms): int setrlimit(int a, const struct rlimit *b); 6 | -------------------------------------------------------------------------------- /posixwrap/common/sys/select.h: -------------------------------------------------------------------------------- 1 | int pselect(int a, fd_set *restrict b, fd_set *restrict c, fd_set *restrict d, const struct timespec *restrict e, const sigset_t *restrict f); 2 | int select(int a, fd_set *restrict b, fd_set *restrict c, fd_set *restrict d, struct timeval *restrict e); 3 | -------------------------------------------------------------------------------- /posixwrap/common/sys/sem.h: -------------------------------------------------------------------------------- 1 | //unsupported (variable args): int semctl(int a, int b, int c, ...); 2 | int semget(key_t a, int b, int c); 3 | int semop(int a, struct sembuf *b, size_t c); 4 | -------------------------------------------------------------------------------- /posixwrap/common/sys/shm.h: -------------------------------------------------------------------------------- 1 | void *shmat(int a, const void *b, int c); 2 | int shmctl(int a, int b, struct shmid_ds *c); 3 | int shmdt(const void *a); 4 | int shmget(key_t a, size_t b, int c); 5 | -------------------------------------------------------------------------------- /posixwrap/common/sys/socket.h: -------------------------------------------------------------------------------- 1 | int accept(int a, struct sockaddr *restrict b, socklen_t *restrict c); 2 | int bind(int a, const struct sockaddr *b, socklen_t c); 3 | int connect(int a, const struct sockaddr *b, socklen_t c); 4 | int getpeername(int a, struct sockaddr *restrict b, socklen_t *restrict c); 5 | int getsockname(int a, struct sockaddr *restrict b, socklen_t *restrict c); 6 | int getsockopt(int a, int b, int c, void *restrict d, socklen_t *restrict e); 7 | int listen(int a, int b); 8 | ssize_t recv(int a, void *b, size_t c, int d); 9 | ssize_t recvfrom(int a, void *restrict b, size_t c, int d, struct sockaddr *restrict e, socklen_t *restrict f); 10 | ssize_t recvmsg(int a, struct msghdr *b, int c); 11 | ssize_t send(int a, const void *b, size_t c, int d); 12 | ssize_t sendmsg(int a, const struct msghdr *b, int c); 13 | ssize_t sendto(int a, const void *b, size_t c, int d, const struct sockaddr *e, socklen_t f); 14 | int setsockopt(int a, int b, int c, const void *d, socklen_t e); 15 | int shutdown(int a, int b); 16 | int sockatmark(int a); 17 | int socket(int a, int b, int c); 18 | int socketpair(int a, int b, int c, int d[2]); 19 | -------------------------------------------------------------------------------- /posixwrap/common/sys/statvfs.h: -------------------------------------------------------------------------------- 1 | int fstatvfs(int a, struct statvfs *b); 2 | int statvfs(const char *restrict a, struct statvfs *restrict b); 3 | -------------------------------------------------------------------------------- /posixwrap/common/sys/time.h: -------------------------------------------------------------------------------- 1 | //unsupported (not common for platforms): int getitimer(int a, struct itimerval *b); 2 | //unsupported (internally used by cpuusage): int gettimeofday(struct timeval *restrict a, void *restrict b); 3 | //unsupported (not common for platforms): int setitimer(int a, const struct itimerval *restrict b, struct itimerval *restrict c); 4 | int utimes(const char *a, const struct timeval b[2]); 5 | -------------------------------------------------------------------------------- /posixwrap/common/sys/times.h: -------------------------------------------------------------------------------- 1 | clock_t times(struct tms *a); 2 | -------------------------------------------------------------------------------- /posixwrap/common/sys/types.h: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /posixwrap/common/sys/uio.h: -------------------------------------------------------------------------------- 1 | ssize_t readv(int a, const struct iovec *b, int c); 2 | ssize_t writev(int a, const struct iovec *b, int c); 3 | -------------------------------------------------------------------------------- /posixwrap/common/sys/un.h: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /posixwrap/common/sys/utsname.h: -------------------------------------------------------------------------------- 1 | int uname(struct utsname *a); 2 | -------------------------------------------------------------------------------- /posixwrap/common/sys/wait.h: -------------------------------------------------------------------------------- 1 | pid_t wait(int *a); 2 | int waitid(idtype_t a, id_t b, siginfo_t *c, int d); 3 | pid_t waitpid(pid_t a, int *b, int c); 4 | -------------------------------------------------------------------------------- /posixwrap/common/syslog.h: -------------------------------------------------------------------------------- 1 | void closelog(void); 2 | void openlog(const char *a, int b, int c); 3 | int setlogmask(int a); 4 | //unsupported (variable args): void syslog(int a, const char *b, ...); 5 | -------------------------------------------------------------------------------- /posixwrap/common/tar.h: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /posixwrap/common/termios.h: -------------------------------------------------------------------------------- 1 | speed_t cfgetispeed(const struct termios *a); 2 | speed_t cfgetospeed(const struct termios *a); 3 | int cfsetispeed(struct termios *a, speed_t b); 4 | int cfsetospeed(struct termios *a, speed_t b); 5 | int tcdrain(int a); 6 | int tcflow(int a, int b); 7 | int tcflush(int a, int b); 8 | int tcgetattr(int a, struct termios *b); 9 | pid_t tcgetsid(int a); 10 | int tcsendbreak(int a, int b); 11 | int tcsetattr(int a, int b, const struct termios *c); 12 | -------------------------------------------------------------------------------- /posixwrap/common/ulimit.h: -------------------------------------------------------------------------------- 1 | //unsupported (variable args): long ulimit(int a, ...); 2 | -------------------------------------------------------------------------------- /posixwrap/common/utime.h: -------------------------------------------------------------------------------- 1 | int utime(const char *a, const struct utimbuf *b); 2 | -------------------------------------------------------------------------------- /posixwrap/common/utmpx.h: -------------------------------------------------------------------------------- 1 | void endutxent(void); 2 | struct utmpx *getutxent(void); 3 | struct utmpx *getutxid(const struct utmpx *a); 4 | struct utmpx *getutxline(const struct utmpx *a); 5 | struct utmpx *pututxline(const struct utmpx *a); 6 | void setutxent(void); 7 | -------------------------------------------------------------------------------- /posixwrap/common/wordexp.h: -------------------------------------------------------------------------------- 1 | int wordexp(const char *restrict a, wordexp_t *restrict b, int c); 2 | void wordfree(wordexp_t *a); 3 | -------------------------------------------------------------------------------- /posixwrap/linux/aio.h: -------------------------------------------------------------------------------- 1 | int aio_cancel(int a, struct aiocb *b); 2 | int aio_error(const struct aiocb *a); 3 | int aio_fsync(int a, struct aiocb *b); 4 | int aio_read(struct aiocb *a); 5 | ssize_t aio_return(struct aiocb *b); 6 | int aio_suspend(const struct aiocb *const a[], int b, const struct timespec *c); 7 | int aio_write(struct aiocb *a); 8 | int lio_listio(int a, struct aiocb *const b[__restrict_arr], int c, struct sigevent *__restrict d); 9 | -------------------------------------------------------------------------------- /posixwrap/linux/arpa/inet.h: -------------------------------------------------------------------------------- 1 | uint32_t htonl(uint32_t a); 2 | uint16_t htons(uint16_t a); 3 | uint32_t ntohl(uint32_t a); 4 | uint16_t ntohs(uint16_t a); 5 | in_addr_t inet_addr(const char *a); 6 | char *inet_ntoa(struct in_addr a); 7 | const char *inet_ntop(int a, const void *restrict b, char *restrict c, socklen_t d); 8 | int inet_pton(int a, const char *restrict b, void *restrict c); 9 | -------------------------------------------------------------------------------- /posixwrap/linux/dirent.h: -------------------------------------------------------------------------------- 1 | int alphasort(const struct dirent **a, const struct dirent **b); 2 | int closedir(DIR *a); 3 | int dirfd(DIR *a); 4 | DIR *fdopendir(int a); 5 | DIR *opendir(const char *a); 6 | struct dirent *readdir(DIR *a); 7 | int readdir_r(DIR *restrict a, struct dirent *restrict b, struct dirent **restrict c); 8 | void rewinddir(DIR *a); 9 | int scandir(const char *a, struct dirent ***b, int (*c)(const struct dirent *), int (*d)(const struct dirent **, const struct dirent **)); 10 | void seekdir(DIR *a, long b); 11 | long telldir(DIR *a); 12 | -------------------------------------------------------------------------------- /posixwrap/linux/fcntl.h: -------------------------------------------------------------------------------- 1 | int creat(const char *a, mode_t b); 2 | //unsupported (variable args): int fcntl(int, int, ...); 3 | //unsupported (variable args): int open(const char *, int, ...); 4 | //unsupported (variable args): int openat(int, const char *, int, ...); 5 | int posix_fadvise(int a, off_t b, off_t c, int d); 6 | int posix_fallocate(int a, off_t b, off_t c); 7 | -------------------------------------------------------------------------------- /posixwrap/linux/ftw.h: -------------------------------------------------------------------------------- 1 | int ftw(const char *a, int (*b)(const char *, const struct stat *, int), int c); 2 | int nftw(const char *a, int (*b)(const char *, const struct stat *, int, struct FTW *), int c, int d); 3 | -------------------------------------------------------------------------------- /posixwrap/linux/glob.h: -------------------------------------------------------------------------------- 1 | int glob(const char *restrict a, int b, int(*c)(const char *, int), glob_t *restrict d); 2 | void globfree(glob_t *a); 3 | -------------------------------------------------------------------------------- /posixwrap/linux/iconv.h: -------------------------------------------------------------------------------- 1 | size_t iconv(iconv_t a, char **restrict b, size_t *restrict c, char **restrict d, size_t *restrict e); 2 | int iconv_close(iconv_t a); 3 | iconv_t iconv_open(const char *a, const char *b); 4 | -------------------------------------------------------------------------------- /posixwrap/linux/langinfo.h: -------------------------------------------------------------------------------- 1 | char *nl_langinfo(nl_item a); 2 | char *nl_langinfo_l(nl_item a, locale_t b); 3 | -------------------------------------------------------------------------------- /posixwrap/linux/locale.h: -------------------------------------------------------------------------------- 1 | locale_t duplocale(locale_t a); 2 | void freelocale(locale_t a); 3 | struct lconv *localeconv(void); 4 | locale_t newlocale(int a, const char *b, locale_t c); 5 | char *setlocale(int a, const char *b); 6 | locale_t uselocale(locale_t a); 7 | -------------------------------------------------------------------------------- /posixwrap/linux/mqueue.h: -------------------------------------------------------------------------------- 1 | int mq_close(mqd_t a); 2 | int mq_getattr(mqd_t a, struct mq_attr *b); 3 | int mq_notify(mqd_t a, const struct sigevent *b); 4 | //unsupported (variable args): mqd_t mq_open(const char *a, int b, ...); 5 | ssize_t mq_receive(mqd_t a, char *b, size_t c, unsigned *d); 6 | int mq_send(mqd_t a, const char *b, size_t c, unsigned d); 7 | int mq_setattr(mqd_t a, const struct mq_attr *restrict b, struct mq_attr *restrict c); 8 | ssize_t mq_timedreceive(mqd_t a, char *restrict b, size_t c, unsigned *restrict d, const struct timespec *restrict e); 9 | int mq_timedsend(mqd_t a, const char *b, size_t c, unsigned d, const struct timespec *e); 10 | int mq_unlink(const char *a); 11 | -------------------------------------------------------------------------------- /posixwrap/linux/pthread.h: -------------------------------------------------------------------------------- 1 | int pthread_atfork(void (*a)(void), void (*b)(void), void(*c)(void)); 2 | int pthread_attr_destroy(pthread_attr_t *a); 3 | int pthread_attr_getdetachstate(const pthread_attr_t *a, int *b); 4 | int pthread_attr_getguardsize(const pthread_attr_t *restrict a, size_t *restrict b); 5 | int pthread_attr_getinheritsched(const pthread_attr_t *restrict a, int *restrict b); 6 | int pthread_attr_getschedparam(const pthread_attr_t *restrict a, struct sched_param *restrict b); 7 | int pthread_attr_getschedpolicy(const pthread_attr_t *restrict a, int *restrict b); 8 | int pthread_attr_getscope(const pthread_attr_t *restrict a, int *restrict b); 9 | int pthread_attr_getstack(const pthread_attr_t *restrict a, void **restrict b, size_t *restrict c); 10 | int pthread_attr_getstacksize(const pthread_attr_t *restrict a, size_t *restrict b); 11 | int pthread_attr_init(pthread_attr_t *a); 12 | int pthread_attr_setdetachstate(pthread_attr_t *a, int b); 13 | int pthread_attr_setguardsize(pthread_attr_t *a, size_t b); 14 | int pthread_attr_setinheritsched(pthread_attr_t *a, int b); 15 | int pthread_attr_setschedparam(pthread_attr_t *restrict a, const struct sched_param *restrict b); 16 | int pthread_attr_setschedpolicy(pthread_attr_t *a, int b); 17 | int pthread_attr_setscope(pthread_attr_t *a, int b); 18 | int pthread_attr_setstack(pthread_attr_t *a, void *b, size_t c); 19 | int pthread_attr_setstacksize(pthread_attr_t *a, size_t b); 20 | int pthread_barrier_destroy(pthread_barrier_t *a); 21 | int pthread_barrier_init(pthread_barrier_t *restrict a, const pthread_barrierattr_t *restrict b, unsigned c); 22 | int pthread_barrier_wait(pthread_barrier_t *a); 23 | int pthread_barrierattr_destroy(pthread_barrierattr_t *a); 24 | int pthread_barrierattr_getpshared(const pthread_barrierattr_t *restrict a, int *restrict b); 25 | int pthread_barrierattr_init(pthread_barrierattr_t *a); 26 | int pthread_barrierattr_setpshared(pthread_barrierattr_t *a, int b); 27 | int pthread_cancel(pthread_t a); 28 | int pthread_cond_broadcast(pthread_cond_t *a); 29 | int pthread_cond_destroy(pthread_cond_t *a); 30 | int pthread_cond_init(pthread_cond_t *restrict a, const pthread_condattr_t *restrict b); 31 | int pthread_cond_signal(pthread_cond_t *a); 32 | int pthread_cond_timedwait(pthread_cond_t *restrict a, pthread_mutex_t *restrict b, const struct timespec *restrict c); 33 | int pthread_cond_wait(pthread_cond_t *restrict a, pthread_mutex_t *restrict b); 34 | int pthread_condattr_destroy(pthread_condattr_t *a); 35 | int pthread_condattr_getclock(const pthread_condattr_t *restrict a, clockid_t *restrict b); 36 | int pthread_condattr_getpshared(const pthread_condattr_t *restrict a, int *restrict b); 37 | int pthread_condattr_init(pthread_condattr_t *a); 38 | int pthread_condattr_setclock(pthread_condattr_t *a, clockid_t b); 39 | int pthread_condattr_setpshared(pthread_condattr_t *a, int b); 40 | int pthread_create(pthread_t *restrict a, const pthread_attr_t *restrict b, void *(*c)(void*), void *restrict d); 41 | int pthread_detach(pthread_t a); 42 | int pthread_equal(pthread_t a, pthread_t b); 43 | //unsupported (never returns): void pthread_exit(void *a); 44 | int pthread_getconcurrency(void); 45 | int pthread_getcpuclockid(pthread_t a, clockid_t *b); 46 | int pthread_getschedparam(pthread_t a, int *restrict b, struct sched_param *restrict c); 47 | void *pthread_getspecific(pthread_key_t a); 48 | int pthread_join(pthread_t a, void **b); 49 | int pthread_key_create(pthread_key_t *a, void (*b)(void*)); 50 | int pthread_key_delete(pthread_key_t a); 51 | int pthread_mutex_consistent(pthread_mutex_t * a); 52 | int pthread_mutex_destroy(pthread_mutex_t * a); 53 | int pthread_mutex_getprioceiling(const pthread_mutex_t *restrict a, int *restrict b); 54 | int pthread_mutex_init(pthread_mutex_t *restrict a, const pthread_mutexattr_t *restrict b); 55 | int pthread_mutex_lock(pthread_mutex_t * a); 56 | int pthread_mutex_setprioceiling(pthread_mutex_t *restrict a, int b, int *restrict c); 57 | int pthread_mutex_timedlock(pthread_mutex_t *restrict a, const struct timespec *restrict b); 58 | int pthread_mutex_trylock(pthread_mutex_t * a); 59 | int pthread_mutex_unlock(pthread_mutex_t * a); 60 | int pthread_mutexattr_destroy(pthread_mutexattr_t * a); 61 | int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *restrict a, int *restrict b); 62 | int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *restrict a, int *restrict b); 63 | int pthread_mutexattr_getpshared(const pthread_mutexattr_t *restrict a, int *restrict b); 64 | int pthread_mutexattr_getrobust(const pthread_mutexattr_t *restrict a, int *restrict b); 65 | int pthread_mutexattr_gettype(const pthread_mutexattr_t *restrict a, int *restrict b); 66 | int pthread_mutexattr_init(pthread_mutexattr_t * a); 67 | int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *a, int b); 68 | int pthread_mutexattr_setprotocol(pthread_mutexattr_t *a, int b); 69 | int pthread_mutexattr_setpshared(pthread_mutexattr_t *a, int b); 70 | int pthread_mutexattr_setrobust(pthread_mutexattr_t *a, int b); 71 | int pthread_mutexattr_settype(pthread_mutexattr_t *a, int b); 72 | int pthread_once(pthread_once_t *a, void (*b)(void)); 73 | int pthread_rwlock_destroy(pthread_rwlock_t * a); 74 | int pthread_rwlock_init(pthread_rwlock_t *restrict a, const pthread_rwlockattr_t *restrict b); 75 | int pthread_rwlock_rdlock(pthread_rwlock_t * a); 76 | int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict a, const struct timespec *restrict b); 77 | int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict a, const struct timespec *restrict b); 78 | int pthread_rwlock_tryrdlock(pthread_rwlock_t * a); 79 | int pthread_rwlock_trywrlock(pthread_rwlock_t * a); 80 | int pthread_rwlock_unlock(pthread_rwlock_t * a); 81 | int pthread_rwlock_wrlock(pthread_rwlock_t * a); 82 | int pthread_rwlockattr_destroy(pthread_rwlockattr_t * a); 83 | int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *restrict a, int *restrict b); 84 | int pthread_rwlockattr_init(pthread_rwlockattr_t * a); 85 | int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *a, int b); 86 | //unsupported (internally used by cpuusage): pthread_t pthread_self(void); 87 | int pthread_setcancelstate(int a, int * b); 88 | int pthread_setcanceltype(int a, int * b); 89 | int pthread_setconcurrency(int a); 90 | int pthread_setschedparam(pthread_t a, int b, const struct sched_param * c); 91 | int pthread_setschedprio(pthread_t a, int b); 92 | int pthread_setspecific(pthread_key_t a, const void * b); 93 | int pthread_spin_destroy(pthread_spinlock_t *a); 94 | int pthread_spin_init(pthread_spinlock_t *a, int b); 95 | int pthread_spin_lock(pthread_spinlock_t * a); 96 | int pthread_spin_trylock(pthread_spinlock_t * a); 97 | int pthread_spin_unlock(pthread_spinlock_t * a); 98 | void pthread_testcancel(void); 99 | -------------------------------------------------------------------------------- /posixwrap/linux/sched.h: -------------------------------------------------------------------------------- 1 | int sched_get_priority_max(int a); 2 | int sched_get_priority_min(int a); 3 | int sched_getparam(pid_t a, struct sched_param *b); 4 | int sched_getscheduler(pid_t a); 5 | int sched_rr_get_interval(pid_t a, struct timespec *b); 6 | int sched_setparam(pid_t a, const struct sched_param *b); 7 | int sched_setscheduler(pid_t a, int b, const struct sched_param *c); 8 | int sched_yield(void); 9 | -------------------------------------------------------------------------------- /posixwrap/linux/search.h: -------------------------------------------------------------------------------- 1 | int hcreate(size_t a); 2 | void hdestroy(void); 3 | void insque(void *a, void *b); 4 | void *lfind(const void *a, const void *b, size_t *c, size_t d, int (*e)(const void *, const void *)); 5 | void *lsearch(const void *a, void *b, size_t *c, size_t d, int (*e)(const void *, const void *)); 6 | void remque(void *a); 7 | void *tdelete(const void *restrict a, void **restrict b, int(*c)(const void *, const void *)); 8 | void *tfind(const void *a, void *const *b, int(*c)(const void *, const void *)); 9 | void *tsearch(const void *a, void **b, int(*c)(const void *, const void *)); 10 | void twalk(const void *a, void (*b)(const void *, VISIT, int )); 11 | -------------------------------------------------------------------------------- /posixwrap/linux/semaphore.h: -------------------------------------------------------------------------------- 1 | int sem_close(sem_t *a); 2 | int sem_destroy(sem_t *a); 3 | int sem_getvalue(sem_t *restrict a, int *restrict b); 4 | int sem_init(sem_t *a, int b, unsigned c); 5 | //unsupported (variable args): sem_t *sem_open(const char *a, int b, ...); 6 | int sem_post(sem_t *a); 7 | int sem_timedwait(sem_t *restrict a, const struct timespec *restrict b); 8 | int sem_trywait(sem_t *a); 9 | int sem_unlink(const char *a); 10 | int sem_wait(sem_t *a); 11 | -------------------------------------------------------------------------------- /posixwrap/linux/signal.h: -------------------------------------------------------------------------------- 1 | int kill(pid_t a, int b); 2 | int killpg(pid_t a, int b); 3 | void psiginfo(const siginfo_t *a, const char *b); 4 | void psignal(int a, const char *b); 5 | int pthread_kill(pthread_t a, int b); 6 | int pthread_sigmask(int a, const sigset_t *restrict b, sigset_t *restrict c); 7 | int raise(int a); 8 | int sigaction(int a, const struct sigaction *restrict b, struct sigaction *restrict c); 9 | int sigaddset(sigset_t *a, int b); 10 | int sigaltstack(const stack_t *restrict a, stack_t *restrict b); 11 | int sigdelset(sigset_t *a, int b); 12 | int sigemptyset(sigset_t *a); 13 | int sigfillset(sigset_t *a); 14 | int sighold(int a); 15 | int sigignore(int a); 16 | int siginterrupt(int a, int b); 17 | int sigismember(const sigset_t *a, int b); 18 | sighandler_t signal(int a, sighandler_t b); 19 | int sigpause(int a); 20 | int sigpending(sigset_t *a); 21 | int sigprocmask(int a, const sigset_t *restrict b, sigset_t *restrict c); 22 | int sigqueue(pid_t a, int b, union sigval c); 23 | int sigrelse(int a); 24 | sighandler_t sigset(int a, sighandler_t b); 25 | int sigsuspend(const sigset_t *a); 26 | int sigtimedwait(const sigset_t *restrict a, siginfo_t *restrict b, const struct timespec *restrict c); 27 | int sigwait(const sigset_t *restrict a, int *restrict b); 28 | int sigwaitinfo(const sigset_t *restrict a, siginfo_t *restrict b); 29 | -------------------------------------------------------------------------------- /posixwrap/linux/spawn.h: -------------------------------------------------------------------------------- 1 | int posix_spawn(pid_t *restrict a, const char *restrict b, const posix_spawn_file_actions_t *c, const posix_spawnattr_t *restrict d, char *const e[restrict], char *const f[restrict]); 2 | int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *a, int b); 3 | int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *a, int b, int c); 4 | int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *restrict a, int b, const char *restrict c, int d, mode_t e); 5 | int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *a); 6 | int posix_spawn_file_actions_init(posix_spawn_file_actions_t *a); 7 | int posix_spawnattr_destroy(posix_spawnattr_t *a); 8 | int posix_spawnattr_getflags(const posix_spawnattr_t *restrict a, short *restrict b); 9 | int posix_spawnattr_getpgroup(const posix_spawnattr_t *restrict a, pid_t *restrict b); 10 | int posix_spawnattr_getschedparam(const posix_spawnattr_t *restrict a, struct sched_param *restrict b); 11 | int posix_spawnattr_getschedpolicy(const posix_spawnattr_t *restrict a, int *restrict b); 12 | int posix_spawnattr_getsigdefault(const posix_spawnattr_t *restrict a, sigset_t *restrict b); 13 | int posix_spawnattr_getsigmask(const posix_spawnattr_t *restrict a, sigset_t *restrict b); 14 | int posix_spawnattr_init(posix_spawnattr_t *a); 15 | int posix_spawnattr_setflags(posix_spawnattr_t *a, short b); 16 | int posix_spawnattr_setpgroup(posix_spawnattr_t *a, pid_t b); 17 | int posix_spawnattr_setschedparam(posix_spawnattr_t *restrict a, const struct sched_param *restrict b); 18 | int posix_spawnattr_setschedpolicy(posix_spawnattr_t *a, int b); 19 | int posix_spawnattr_setsigdefault(posix_spawnattr_t *restrict a, const sigset_t *restrict b); 20 | int posix_spawnattr_setsigmask(posix_spawnattr_t *restrict a, const sigset_t *restrict b); 21 | int posix_spawnp(pid_t *restrict a, const char *restrict b, const posix_spawn_file_actions_t *c, const posix_spawnattr_t *restrict d, char *const e[restrict], char *const f[restrict]); 22 | -------------------------------------------------------------------------------- /posixwrap/linux/stdio.h: -------------------------------------------------------------------------------- 1 | void clearerr(FILE *a); 2 | char *ctermid(char *a); 3 | int dprintf(int a, const char *restrict b, ...) 4 | int fclose(FILE *a); 5 | FILE *fdopen(int a, const char *b); 6 | int feof(FILE *a); 7 | int ferror(FILE *a); 8 | int fflush(FILE *a); 9 | int fgetc(FILE *a); 10 | int fgetpos(FILE *restrict a, fpos_t *restrict b); 11 | char *fgets(char *restrict a, int b, FILE *restrict c); 12 | int fileno(FILE *a); 13 | void flockfile(FILE *a); 14 | FILE *fmemopen(void *restrict a, size_t b, const char *restrict c); 15 | FILE *fopen(const char *restrict a, const char *restrict b); 16 | int fprintf(FILE *restrict a, const char *restrict b, ...); 17 | int fputc(int a, FILE *b); 18 | int fputs(const char *restrict a, FILE *restrict b); 19 | size_t fread(void *restrict a, size_t b, size_t c, FILE *restrict d); 20 | FILE *freopen(const char *restrict a, const char *restrict b, FILE *restrict c); 21 | int fscanf(FILE *restrict a, const char *restrict b, ...); 22 | int fseek(FILE *a, long b, int c); 23 | int fseeko(FILE *a, off_t b, int c); 24 | int fsetpos(FILE *a, const fpos_t *b); 25 | long ftell(FILE *a); 26 | off_t ftello(FILE *a); 27 | int ftrylockfile(FILE *a); 28 | void funlockfile(FILE *a); 29 | size_t fwrite(const void *restrict a, size_t b, size_t c, FILE *restrict d); 30 | int getc(FILE *a); 31 | int getchar(void); 32 | int getc_unlocked(FILE *a); 33 | int getchar_unlocked(void); 34 | ssize_t getdelim(char **restrict a, size_t *restrict b, int c, FILE *restrict d); 35 | ssize_t getline(char **restrict a, size_t *restrict b, FILE *restrict c); 36 | char *gets(char *a); 37 | FILE *open_memstream(char **a, size_t *b); 38 | int pclose(FILE *a); 39 | void perror(const char *a); 40 | FILE *popen(const char *a, const char *b); 41 | int printf(const char *restrict a, ...); 42 | int putc(int a, FILE *b); 43 | int putchar(int a); 44 | int putc_unlocked(int a, FILE *b); 45 | int putchar_unlocked(int a); 46 | int puts(const char *a); 47 | int remove(const char *a); 48 | int rename(const char *a, const char *b); 49 | int renameat(int a, const char *b, int c, const char *d); 50 | void rewind(FILE *a); 51 | int scanf(const char *restrict a, ...); 52 | void setbuf(FILE *restrict a, char *restrict b); 53 | int setvbuf(FILE *restrict a, char *restrict b, int c, size_t d); 54 | int snprintf(char *restrict a, size_t b, const char *restrict c, ...); 55 | int sprintf(char *restrict a, const char *restrict b, ...); 56 | int sscanf(const char *restrict a, const char *restrict b, ...); 57 | char *tempnam(const char *a, const char *b); 58 | FILE *tmpfile(void); 59 | char *tmpnam(char *a); 60 | int ungetc(int a, FILE *b); 61 | int vdprintf(int a, const char *restrict b, va_list c); 62 | int vfprintf(FILE *restrict a, const char *restrict b, va_list c); 63 | int vfscanf(FILE *restrict a, const char *restrict b, va_list c); 64 | int vprintf(const char *restrict a, va_list b); 65 | int vscanf(const char *restrict a, va_list b); 66 | int vsnprintf(char *restrict a, size_t b, const char *restrict c, va_list d); 67 | int vsprintf(char *restrict a, const char *restrict b, va_list c); 68 | int vsscanf(const char *restrict a, const char *restrict b, va_list c); 69 | -------------------------------------------------------------------------------- /posixwrap/linux/stdlib.h: -------------------------------------------------------------------------------- 1 | //unsupported (never returns): void _Exit(int a); 2 | long a64l(const char *a); 3 | //unsupported (never returns): void abort(void); 4 | int abs(int a); 5 | int atexit(void (*a)(void)); 6 | double atof(const char *a); 7 | int atoi(const char *a); 8 | long atol(const char *a); 9 | long long atoll(const char *a); 10 | void *bsearch(const void *a, const void *b, size_t c, size_t d, int (*e)(const void *, const void *)); 11 | void *calloc(size_t a, size_t b); 12 | div_t div(int a, int b); 13 | double drand48(void); 14 | double erand48(unsigned short a[3]); 15 | //unsupported (never returns): void exit(int a); 16 | void free(void *a); 17 | char *getenv(const char *a); 18 | int getsubopt(char **a, char *const *b, char **c); 19 | int grantpt(int a); 20 | char *initstate(unsigned a, char *b, size_t c); 21 | long jrand48(unsigned short a[3]); 22 | char *l64a(long a); 23 | long labs(long a); 24 | void lcong48(unsigned short a[7]); 25 | ldiv_t ldiv(long a, long b); 26 | long long llabs(long long a); 27 | lldiv_t lldiv(long long a, long long b); 28 | long lrand48(void); 29 | void *malloc(size_t a); 30 | int mblen(const char *a, size_t b); 31 | size_t mbstowcs(wchar_t *restrict a, const char *restrict b, size_t c); 32 | int mbtowc(wchar_t *restrict a, const char *restrict b, size_t c); 33 | char *mkdtemp(char *a); 34 | int mkstemp(char *a); 35 | long mrand48(void); 36 | long nrand48(unsigned short a[3]); 37 | int posix_memalign(void **a, size_t b, size_t c); 38 | int posix_openpt(int a); 39 | char *ptsname(int a); 40 | int putenv(char *a); 41 | void qsort(void *a, size_t b, size_t c, int (*d)(const void *, const void *)); 42 | int rand(void); 43 | int rand_r(unsigned *a); 44 | long random(void); 45 | void *realloc(void *a, size_t b); 46 | char *realpath(const char *restrict a, char *restrict b); 47 | unsigned short *seed48(unsigned short a[3]); 48 | int setenv(const char *a, const char *b, int c); 49 | void setkey(const char *a); 50 | char *setstate(char *a); 51 | void srand(unsigned a); 52 | void srand48(long a); 53 | void srandom(unsigned a); 54 | double strtod(const char *restrict a, char **restrict b); 55 | float strtof(const char *restrict a, char **restrict b); 56 | long strtol(const char *restrict a, char **restrict b, int c); 57 | long double strtold(const char *restrict a, char **restrict b); 58 | long long strtoll(const char *restrict a, char **restrict b, int c); 59 | unsigned long strtoul(const char *restrict a, char **restrict b, int c); 60 | unsigned long long strtoull(const char *restrict a, char **restrict b, int c); 61 | int system(const char *a); 62 | int unlockpt(int a); 63 | int unsetenv(const char *a); 64 | size_t wcstombs(char *restrict a, const wchar_t *restrict b, size_t c); 65 | int wctomb(char *a, wchar_t b); 66 | -------------------------------------------------------------------------------- /posixwrap/linux/string.h: -------------------------------------------------------------------------------- 1 | void *memccpy(void *restrict a, const void *restrict b, int c, size_t d); 2 | void *memchr(const void *a, int b, size_t c); 3 | int memcmp(const void *a, const void *b, size_t c); 4 | void *memcpy(void *restrict a, const void *restrict b, size_t c); 5 | void *memmove(void *a, const void *b, size_t c); 6 | void *memset(void *a, int b, size_t c); 7 | char *stpcpy(char *restrict a, const char *restrict b); 8 | char *stpncpy(char *restrict a, const char *restrict b, size_t c); 9 | char *strcat(char *restrict a, const char *restrict b); 10 | char *strchr(const char *a, int b); 11 | int strcmp(const char *a, const char *b); 12 | int strcoll(const char *a, const char *b); 13 | int strcoll_l(const char *a, const char *b, locale_t c); 14 | char *strcpy(char *restrict a, const char *restrict b); 15 | size_t strcspn(const char *a, const char *b); 16 | char *strdup(const char *a); 17 | char *strerror(int a); 18 | char *strerror_l(int a, locale_t b); 19 | //unsupported (not common for platforms): int strerror_r(int a, char *b, size_t c); 20 | size_t strlen(const char *a); 21 | char *strncat(char *restrict a, const char *restrict b, size_t c); 22 | int strncmp(const char *a, const char *b, size_t c); 23 | char *strncpy(char *restrict a, const char *restrict b, size_t c); 24 | char *strndup(const char *a, size_t b); 25 | size_t strnlen(const char *a, size_t b); 26 | char *strpbrk(const char *a, const char *b); 27 | char *strrchr(const char *a, int b); 28 | char *strsignal(int a); 29 | size_t strspn(const char *a, const char *b); 30 | char *strstr(const char *a, const char *b); 31 | char *strtok(char *restrict a, const char *restrict b); 32 | char *strtok_r(char *restrict a, const char *restrict b, char **restrict c); 33 | size_t strxfrm(char *restrict a, const char *restrict b, size_t c); 34 | size_t strxfrm_l(char *restrict a, const char *restrict b, size_t c, locale_t d); 35 | -------------------------------------------------------------------------------- /posixwrap/linux/strings.h: -------------------------------------------------------------------------------- 1 | int ffs(int a); 2 | int strcasecmp(const char *a, const char *b); 3 | int strcasecmp_l(const char *a, const char *b, locale_t c); 4 | int strncasecmp(const char *a, const char *b, size_t c); 5 | int strncasecmp_l(const char *a, const char *b, size_t c, locale_t d); 6 | -------------------------------------------------------------------------------- /posixwrap/linux/sys/mman.h: -------------------------------------------------------------------------------- 1 | int mlock(const void *a, size_t b); 2 | int mlockall(int a); 3 | void *mmap(void *a, size_t b, int c, int d, int e, off_t f); 4 | int mprotect(void *a, size_t b, int c); 5 | int msync(void *a, size_t b, int c); 6 | int munlock(const void *a, size_t b); 7 | int munlockall(void); 8 | int munmap(void *a, size_t b); 9 | int posix_madvise(void *a, size_t b, int c); 10 | int posix_mem_offset(const void *restrict a, size_t b, off_t *restrict c, size_t *restrict d, int *restrict e); 11 | //unsupported (missing type on Linux): int posix_typed_mem_get_info(int a, struct posix_typed_mem_info *b); 12 | int posix_typed_mem_open(const char *a, int b, int c); 13 | int shm_open(const char *a, int b, mode_t c); 14 | int shm_unlink(const char *a); 15 | -------------------------------------------------------------------------------- /posixwrap/linux/sys/stat.h: -------------------------------------------------------------------------------- 1 | int chmod(const char *a, mode_t b); 2 | int fchmod(int a, mode_t b); 3 | int fchmodat(int a, const char *b, mode_t c, int d); 4 | int fstat(int a, struct stat *b); 5 | int fstatat(int a, const char *restrict b, struct stat *restrict c, int d); 6 | int futimens(int a, const struct timespec b[2]); 7 | int lstat(const char *restrict a, struct stat *restrict b); 8 | int mkdir(const char *a, mode_t b); 9 | int mkdirat(int a, const char *b, mode_t c); 10 | int mkfifo(const char *a, mode_t b); 11 | int mkfifoat(int a, const char *b, mode_t c); 12 | int mknod(const char *a, mode_t b, dev_t c); 13 | int mknodat(int a, const char *b, mode_t c, dev_t d); 14 | int stat(const char *restrict a, struct stat *restrict b); 15 | mode_t umask(mode_t a); 16 | int utimensat(int a, const char *b, const struct timespec c[2], int d); 17 | -------------------------------------------------------------------------------- /posixwrap/linux/time.h: -------------------------------------------------------------------------------- 1 | char *asctime(const struct tm *a); 2 | char *asctime_r(const struct tm *restrict a, char *restrict b); 3 | clock_t clock(void); 4 | int clock_getcpuclockid(pid_t a, clockid_t *b); 5 | int clock_getres(clockid_t a, struct timespec *b); 6 | int clock_gettime(clockid_t a, struct timespec *b); 7 | int clock_nanosleep(clockid_t a, int b, const struct timespec *c, struct timespec *d); 8 | int clock_settime(clockid_t a, const struct timespec *b); 9 | char *ctime(const time_t *a); 10 | char *ctime_r(const time_t *a, char *b); 11 | double difftime(time_t a, time_t b); 12 | struct tm *getdate(const char *a); 13 | struct tm *gmtime(const time_t *a); 14 | struct tm *gmtime_r(const time_t *restrict a, struct tm *restrict b); 15 | struct tm *localtime(const time_t *a); 16 | struct tm *localtime_r(const time_t *restrict a, struct tm *restrict b); 17 | time_t mktime(struct tm *a); 18 | int nanosleep(const struct timespec *a, struct timespec *b); 19 | size_t strftime(char *restrict a, size_t b, const char *restrict c, const struct tm *restrict d); 20 | size_t strftime_l(char *restrict a, size_t b, const char *restrict c, const struct tm *restrict d, locale_t e); 21 | char *strptime(const char *restrict a, const char *restrict b, struct tm *restrict c); 22 | time_t time(time_t *a); 23 | int timer_create(clockid_t a, struct sigevent *restrict b, timer_t *restrict c); 24 | int timer_delete(timer_t a); 25 | int timer_getoverrun(timer_t a); 26 | int timer_gettime(timer_t a, struct itimerspec *b); 27 | int timer_settime(timer_t a, int b, const struct itimerspec *restrict c, struct itimerspec *restrict d); 28 | void tzset(void); 29 | -------------------------------------------------------------------------------- /posixwrap/linux/unistd.h: -------------------------------------------------------------------------------- 1 | int access(const char *a, int b); 2 | unsigned alarm(unsigned a); 3 | int chdir(const char *a); 4 | int chown(const char *a, uid_t b, gid_t c); 5 | int close(int a); 6 | size_t confstr(int a, char *b, size_t c); 7 | char *crypt(const char *a, const char *b); 8 | int dup(int a); 9 | int dup2(int a, int b); 10 | //unsupported (never returns): void _exit(int a); 11 | void encrypt(char a[64], int b); 12 | //unsupported (variable args): int execl(const char *a, const char *b, ...); 13 | //unsupported (variable args): int execle(const char *a, const char *b, ...); 14 | //unsupported (variable args): int execlp(const char *a, const char *b, ...); 15 | int execv(const char *a, char *const b[]); 16 | int execve(const char *a, char *const b[], char *const c[]); 17 | int execvp(const char *a, char *const b[]); 18 | int faccessat(int a, const char *b, int c, int d); 19 | int fchdir(int a); 20 | int fchown(int a, uid_t b, gid_t c); 21 | int fchownat(int a, const char *b, uid_t c, gid_t d, int e); 22 | int fdatasync(int a); 23 | int fexecve(int a, char *const b[], char *const c[]); 24 | pid_t fork(void); 25 | long fpathconf(int a, int b); 26 | int fsync(int a); 27 | int ftruncate(int a, off_t b); 28 | char *getcwd(char *a, size_t b); 29 | gid_t getegid(void); 30 | uid_t geteuid(void); 31 | gid_t getgid(void); 32 | int getgroups(int a, gid_t b[]); 33 | long gethostid(void); 34 | int gethostname(char *a, size_t b); 35 | char *getlogin(void); 36 | int getlogin_r(char *a, size_t b); 37 | int getopt(int a, char * const b[], const char *c); 38 | pid_t getpgid(pid_t a); 39 | pid_t getpgrp(void); 40 | pid_t getpid(void); 41 | pid_t getppid(void); 42 | pid_t getsid(pid_t a); 43 | uid_t getuid(void); 44 | int isatty(int a); 45 | int lchown(const char *a, uid_t b, gid_t c); 46 | int link(const char *a, const char *b); 47 | int linkat(int a, const char *b, int c, const char *d, int e); 48 | int lockf(int a, int b, off_t c); 49 | off_t lseek(int a, off_t b, int c); 50 | int nice(int a); 51 | long pathconf(const char *a, int b); 52 | int pause(void); 53 | int pipe(int a[2]); 54 | ssize_t pread(int a, void *b, size_t c, off_t d); 55 | ssize_t pwrite(int a, const void *b, size_t c, off_t d); 56 | ssize_t read(int a, void *b, size_t c); 57 | ssize_t readlink(const char *restrict a, char *restrict b, size_t c); 58 | ssize_t readlinkat(int a, const char *restrict b, char *restrict c, size_t d); 59 | int rmdir(const char *a); 60 | int setegid(gid_t a); 61 | int seteuid(uid_t a); 62 | int setgid(gid_t a); 63 | int setpgid(pid_t a, pid_t b); 64 | pid_t setpgrp(void); 65 | int setregid(gid_t a, gid_t b); 66 | int setreuid(uid_t a, uid_t b); 67 | int setuid(uid_t a); 68 | unsigned sleep(unsigned a); 69 | void swab(const void *restrict a, void *restrict b, ssize_t c); 70 | int symlink(const char *a, const char *b); 71 | int symlinkat(const char *a, int b, const char *c); 72 | void sync(void); 73 | long sysconf(int a); 74 | pid_t tcgetpgrp(int a); 75 | int tcsetpgrp(int a, pid_t b); 76 | int truncate(const char *a, off_t b); 77 | char *ttyname(int a); 78 | int ttyname_r(int a, char *b, size_t c); 79 | int unlink(const char *a); 80 | int unlinkat(int a, const char *b, int c); 81 | ssize_t write(int a, const void *b, size_t c); 82 | -------------------------------------------------------------------------------- /posixwrap/linux/wchar.h: -------------------------------------------------------------------------------- 1 | #include 2 | wint_t btowc(int a); 3 | wint_t fgetwc(FILE *a); 4 | wchar_t *fgetws(wchar_t *restrict a, int b, FILE *restrict c); 5 | wint_t fputwc(wchar_t a, FILE *b); 6 | int fputws(const wchar_t *restrict a, FILE *restrict b); 7 | int fwide(FILE *a, int b); 8 | int fwprintf(FILE *restrict a, const wchar_t *restrict b, ...); 9 | int fwscanf(FILE *restrict a, const wchar_t *restrict b, ...); 10 | wint_t getwc(FILE *a); 11 | wint_t getwchar(void); 12 | int iswalnum(wint_t a); 13 | int iswalpha(wint_t a); 14 | int iswcntrl(wint_t a); 15 | int iswctype(wint_t a, wctype_t b); 16 | int iswdigit(wint_t a); 17 | int iswgraph(wint_t a); 18 | int iswlower(wint_t a); 19 | int iswprint(wint_t a); 20 | int iswpunct(wint_t a); 21 | int iswspace(wint_t a); 22 | int iswupper(wint_t a); 23 | int iswxdigit(wint_t a); 24 | size_t mbrlen(const char *restrict a, size_t b, mbstate_t *restrict c); 25 | size_t mbrtowc(wchar_t *restrict a, const char *restrict b, size_t c, mbstate_t *restrict d); 26 | int mbsinit(const mbstate_t *a); 27 | size_t mbsnrtowcs(wchar_t *restrict a, const char **restrict b, size_t c, size_t d, mbstate_t *restrict e); 28 | size_t mbsrtowcs(wchar_t *restrict a, const char **restrict b, size_t c, mbstate_t *restrict d); 29 | FILE *open_wmemstream(wchar_t **a, size_t *b); 30 | wint_t putwc(wchar_t a, FILE *b); 31 | wint_t putwchar(wchar_t a); 32 | int swprintf(wchar_t *restrict a, size_t b, const wchar_t *restrict c, ...); 33 | int swscanf(const wchar_t *restrict a, const wchar_t *restrict b, ...); 34 | wint_t towlower(wint_t a); 35 | wint_t towupper(wint_t a); 36 | wint_t ungetwc(wint_t a, FILE *b); 37 | int vfwprintf(FILE *restrict a, const wchar_t *restrict b, va_list c); 38 | int vfwscanf(FILE *restrict a, const wchar_t *restrict b, va_list c); 39 | int vswprintf(wchar_t *restrict a, size_t b, const wchar_t *restrict c, va_list d); 40 | int vswscanf(const wchar_t *restrict a, const wchar_t *restrict b, va_list c); 41 | int vwprintf(const wchar_t *restrict a, va_list b); 42 | int vwscanf(const wchar_t *restrict a, va_list b); 43 | wchar_t *wcpcpy(wchar_t *restrict a, const wchar_t *restrict b); 44 | wchar_t *wcpncpy(wchar_t *restrict a, const wchar_t *restrict b, size_t c); 45 | size_t wcrtomb(char *restrict a, wchar_t b, mbstate_t *restrict c); 46 | int wcscasecmp(const wchar_t *a, const wchar_t *b); 47 | int wcscasecmp_l(const wchar_t *a, const wchar_t *b, locale_t c); 48 | wchar_t *wcscat(wchar_t *restrict a, const wchar_t *restrict b); 49 | wchar_t *wcschr(const wchar_t *a, wchar_t b); 50 | int wcscmp(const wchar_t *a, const wchar_t *b); 51 | int wcscoll(const wchar_t *a, const wchar_t *b); 52 | int wcscoll_l(const wchar_t *a, const wchar_t *b, locale_t c); 53 | wchar_t *wcscpy(wchar_t *restrict a, const wchar_t *restrict b); 54 | size_t wcscspn(const wchar_t *a, const wchar_t *b); 55 | wchar_t *wcsdup(const wchar_t *a); 56 | size_t wcsftime(wchar_t *restrict a, size_t b, const wchar_t *restrict c, const struct tm *restrict d); 57 | size_t wcslen(const wchar_t *a); 58 | int wcsncasecmp(const wchar_t *a, const wchar_t *b, size_t c); 59 | int wcsncasecmp_l(const wchar_t *a, const wchar_t *b, size_t c, locale_t d); 60 | wchar_t *wcsncat(wchar_t *restrict a, const wchar_t *restrict b, size_t c); 61 | int wcsncmp(const wchar_t *a, const wchar_t *b, size_t c); 62 | wchar_t *wcsncpy(wchar_t *restrict a, const wchar_t *restrict b, size_t c); 63 | size_t wcsnlen(const wchar_t *a, size_t b); 64 | size_t wcsnrtombs(char *restrict a, const wchar_t **restrict b, size_t c, size_t d, mbstate_t *restrict e); 65 | wchar_t *wcspbrk(const wchar_t *a, const wchar_t *b); 66 | wchar_t *wcsrchr(const wchar_t *a, wchar_t b); 67 | size_t wcsrtombs(char *restrict a, const wchar_t **restrict b, size_t c, mbstate_t *restrict d); 68 | size_t wcsspn(const wchar_t *a, const wchar_t *b); 69 | wchar_t *wcsstr(const wchar_t *restrict a, const wchar_t *restrict b); 70 | double wcstod(const wchar_t *restrict a, wchar_t **restrict b); 71 | float wcstof(const wchar_t *restrict a, wchar_t **restrict b); 72 | wchar_t *wcstok(wchar_t *restrict a, const wchar_t *restrict b, wchar_t **restrict c); 73 | long wcstol(const wchar_t *restrict a, wchar_t **restrict b, int c); 74 | long double wcstold(const wchar_t *restrict a, wchar_t **restrict b); 75 | long long wcstoll(const wchar_t *restrict a, wchar_t **restrict b, int c); 76 | unsigned long wcstoul(const wchar_t *restrict a, wchar_t **restrict b, int c); 77 | unsigned long long wcstoull(const wchar_t *restrict a, wchar_t **restrict b, int c); 78 | int wcswidth(const wchar_t *a, size_t b); 79 | size_t wcsxfrm(wchar_t *restrict a, const wchar_t *restrict b, size_t c); 80 | size_t wcsxfrm_l(wchar_t *restrict a, const wchar_t *restrict b, size_t c, locale_t d); 81 | int wctob(wint_t a); 82 | wctype_t wctype(const char *a); 83 | int wcwidth(wchar_t a); 84 | wchar_t *wmemchr(const wchar_t *a, wchar_t b, size_t c); 85 | int wmemcmp(const wchar_t *a, const wchar_t *b, size_t c); 86 | wchar_t *wmemcpy(wchar_t *restrict a, const wchar_t *restrict b, size_t c); 87 | wchar_t *wmemmove(wchar_t *a, const wchar_t *b, size_t c); 88 | wchar_t *wmemset(wchar_t *a, wchar_t b, size_t c); 89 | int wprintf(const wchar_t *restrict a, ...); 90 | int wscanf(const wchar_t *restrict a, ...); 91 | -------------------------------------------------------------------------------- /posixwrap/linux/wctype.h: -------------------------------------------------------------------------------- 1 | int iswalnum_l(wint_t a, locale_t b); 2 | int iswalpha_l(wint_t a, locale_t b); 3 | int iswblank(wint_t a); 4 | int iswblank_l(wint_t a, locale_t b); 5 | int iswcntrl_l(wint_t a, locale_t b); 6 | int iswctype_l(wint_t a, wctype_t b, locale_t c); 7 | int iswdigit_l(wint_t a, locale_t b); 8 | int iswgraph_l(wint_t a, locale_t b); 9 | int iswlower_l(wint_t a, locale_t b); 10 | int iswprint_l(wint_t a, locale_t b); 11 | int iswpunct_l(wint_t a, locale_t b); 12 | int iswspace_l(wint_t a, locale_t b); 13 | int iswupper_l(wint_t a, locale_t b); 14 | int iswxdigit_l(wint_t a, locale_t b); 15 | wint_t towctrans(wint_t a, wctrans_t b); 16 | wint_t towctrans_l(wint_t a, wctrans_t b, locale_t c); 17 | wint_t towlower_l(wint_t a, locale_t b); 18 | wint_t towupper_l(wint_t a, locale_t b); 19 | wctrans_t wctrans(const char *a); 20 | wctrans_t wctrans_l(const char *a, locale_t b); 21 | wctype_t wctype_l(const char *a, locale_t b); 22 | -------------------------------------------------------------------------------- /src/cpuusage: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright (C) 2017-2025 Kristofer Berggren 4 | # All rights reserved. 5 | # 6 | # cpuusage is distributed under the BSD 3-Clause license, see LICENSE for 7 | # details. 8 | 9 | # Usage 10 | showusage() 11 | { 12 | echo "cpuusage is an instrumentation profiler enabling logging of the duration of" 13 | echo "internal function calls (for programs compiled with -finstrument-functions flag)" 14 | echo "or external standard POSIX function calls. It provides visualization in HTML" 15 | echo "format using Chromium Catapult." 16 | echo "" 17 | echo "Usage: cpuusage -a [OPTIONS] PROG [ARGS..]" 18 | echo " or: cpuusage -c [OPTIONS] PROG [ARGS..]" 19 | echo " or: cpuusage -f [OPTIONS] PROG [ARGS..]" 20 | echo " or: cpuusage -i [OPTIONS] PROG [ARGS..]" 21 | echo " or: cpuusage -p [OPTIONS] PROG [ARGS..]" 22 | echo " or: cpuusage -r JSONFILE [OPTIONS]" 23 | echo " or: cpuusage --help|-h" 24 | echo " or: cpuusage --version|-v" 25 | echo "" 26 | echo "Modes:" 27 | echo " -a trace all standard POSIX function calls" 28 | echo " -c trace internal function calls (requires PROG to" 29 | echo " be compiled with -finstrument-functions)" 30 | echo " -f trace specified POSIX functions" 31 | echo " -i trace functions in specified POSIX headers" 32 | echo " -p trace child process durations" 33 | echo " --help, -h display this help and exit" 34 | echo " --version, -v output version information and exit" 35 | echo "" 36 | echo "Options:" 37 | echo " -d debug mode, running program through debugger" 38 | echo " -e separate processes for child process trace" 39 | echo " -j write iterim JSON trace log to specified path" 40 | echo " -m minimum sample time in usec (default 0)" 41 | echo " -n only log up to specified number of samples" 42 | echo " (default 1000000)" 43 | echo " -o write HTML report to specified path, rather" 44 | echo " than default ./cutrace-PID.html" 45 | echo " -r read JSON file and convert to HTML report" 46 | echo " -s start tracing with SIGUSR1 and stop with" 47 | echo " SIGUSR2, instead of trace from process start" 48 | echo " -u trace only main-thread" 49 | echo " -v verbose mode" 50 | echo " -y auto-open resulting html file" 51 | echo " PROG program to run and profile" 52 | echo " [ARGS] optional arguments to the program" 53 | echo "" 54 | echo "Examples:" 55 | echo "cpuusage -o cutrace.html -a ./build/ex001" 56 | echo " trace all standard POSIX function calls and write" 57 | echo " log to cutrace.html" 58 | echo "" 59 | echo "cpuusage -o cutrace.html -c ./build/ex002" 60 | echo " trace instrumented functions and write log to" 61 | echo " cutrace.html" 62 | echo "" 63 | echo "cpuusage -o cutrace.html -f fopen,fclose,fread,fwrite ./build/ex001" 64 | echo " trace calls to fopen, fclose, fread and fwrite, and write" 65 | echo " log to cutrace.html" 66 | echo "" 67 | echo "cpuusage -o cutrace.html -i stdio.h ./build/ex001" 68 | echo " trace calls to all POSIX functions in stdio.h and write" 69 | echo " log to cutrace.html" 70 | echo "" 71 | echo "cpuusage -o cutrace.html -p ./build/ex005.sh" 72 | echo " trace process durations and write to cutrace.html" 73 | echo "" 74 | echo "Report bugs at https://github.com/d99kris/cpuusage" 75 | echo "" 76 | } 77 | 78 | # Version 79 | showversion() 80 | { 81 | echo "cpuusage v1.50" 82 | echo "" 83 | echo "Copyright (C) 2017-2025 Kristofer Berggren" 84 | echo "" 85 | echo "cpuusage is distributed under the BSD 3-Clause license." 86 | echo "" 87 | echo "Written by Kristofer Berggren" 88 | } 89 | 90 | # Arguments - special cases 91 | if [ "${1}" == "--help" ] ; then 92 | showusage 93 | exit 0 94 | elif [ "${1}" == "--version" ] ; then 95 | showversion 96 | exit 0 97 | elif [ "${#}" == "0" ] ; then 98 | showusage 99 | exit 1 100 | fi 101 | 102 | # Arguments - regular options 103 | ALL="0" 104 | MANUAL="0" 105 | DEBUG="0" 106 | FUNCS="" 107 | INCS="" 108 | INSTR="0" 109 | OUTPATH="" 110 | OUTJSONPATH="" 111 | PROC="" 112 | READ="" 113 | VERB="false" 114 | OPEN="0" 115 | while getopts "?acdef:i:j:m:n:o:pr:suvy" OPT; do 116 | case "${OPT}" in 117 | \?) 118 | showusage 119 | exit 1 120 | ;; 121 | a) 122 | ALL="1" 123 | ;; 124 | c) 125 | INSTR="1" 126 | ;; 127 | d) 128 | DEBUG="1" 129 | ;; 130 | e) 131 | CU_EXPAND_PROCESSES="1" 132 | export CU_EXPAND_PROCESSES 133 | ;; 134 | f) 135 | FUNCS="${OPTARG}" 136 | ;; 137 | i) 138 | INCS="${OPTARG}" 139 | ;; 140 | j) 141 | OUTJSONPATH="${OPTARG}" 142 | ;; 143 | m) 144 | CU_MIN_TIME="${OPTARG}" 145 | export CU_MIN_TIME 146 | ;; 147 | n) 148 | CU_MAX_SAMPLES="${OPTARG}" 149 | export CU_MAX_SAMPLES 150 | ;; 151 | o) 152 | OUTPATH="${OPTARG}" 153 | ;; 154 | p) 155 | PROC="1" 156 | ;; 157 | r) 158 | READ="${OPTARG}" 159 | ;; 160 | s) 161 | MANUAL="1" 162 | ;; 163 | u) 164 | CU_MAIN_THREAD_ONLY="1" 165 | export CU_MAIN_THREAD_ONLY 166 | ;; 167 | v) 168 | VERB="true" 169 | ;; 170 | y) 171 | OPEN="1" 172 | ;; 173 | esac 174 | done 175 | shift $((OPTIND-1)) 176 | [ "$1" = "--" ] && shift 177 | 178 | # Arguments - ensure program specified, or in read mode 179 | if [[ "${#}" == "0" ]] && [[ "${READ}" == "" ]] ; then 180 | showusage 181 | exit 1 182 | fi 183 | 184 | # Paths 185 | TMPDIR=$(mktemp -d) 186 | BINDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 187 | LIBDIR="${BINDIR}/../lib" 188 | CUDIR="${BINDIR}/../share/cpuusage" 189 | WRAPDIR="${CUDIR}/posixwrap" 190 | 191 | # Commands 192 | OPENCMD="" 193 | if [[ "${OPEN}" == "1" ]]; then 194 | if [[ "$(uname)" == "Linux" ]]; then 195 | OPENCMD="xdg-open" 196 | elif [[ "$(uname)" == "Darwin" ]]; then 197 | OPENCMD="open -Wn" 198 | else 199 | echo "cpuusage: warning - unknown platform ($(uname)), auto-open disabled." 200 | fi 201 | fi 202 | 203 | # Functions (-f) Mode 204 | if [ "${FUNCS}" != "" ]; then 205 | ${VERB} && echo "cpuusage: https://github.com/d99kris/cpuusage" 206 | ${VERB} && echo "cpuusage: initializing" 207 | touch ${TMPDIR}/allheaders.txt 208 | touch ${TMPDIR}/prototypes.txt 209 | IFS=',' read -r -a FUNCSARRAY <<< "${FUNCS}" 210 | for FUNC in "${FUNCSARRAY[@]}"; do 211 | HEADERPATH=$(grep -r "${FUNC}(" ${WRAPDIR} | head -1 | cut -d':' -f1) 212 | FUNCPROT=$(grep -r "${FUNC}(" ${WRAPDIR} | head -1 | cut -d':' -f2) 213 | if [ "${HEADERPATH}" != "" ] && [ "${FUNCPROT}" != "" ]; then 214 | HEADERNAME=${HEADERPATH:$((${#WRAPDIR} + 1))} 215 | echo "${HEADERNAME}" >> ${TMPDIR}/allheaders.txt 216 | echo "${FUNCPROT}" >> ${TMPDIR}/prototypes.txt 217 | else 218 | echo "cpuusage: warning - ${FUNC} not found in standard headers." 219 | fi 220 | done 221 | sort ${TMPDIR}/allheaders.txt | uniq > ${TMPDIR}/headers.txt 222 | rm ${TMPDIR}/allheaders.txt 2> /dev/null 223 | 224 | # Includes (-i) Mode 225 | elif [ "${INCS}" != "" ]; then 226 | ${VERB} && echo "cpuusage: https://github.com/d99kris/cpuusage" 227 | ${VERB} && echo "cpuusage: initializing" 228 | touch ${TMPDIR}/allheaders.txt 229 | touch ${TMPDIR}/prototypes.txt 230 | IFS=',' read -r -a INCSARRAY <<< "${INCS}" 231 | for INC in "${INCSARRAY[@]}"; do 232 | if [ -f "${WRAPDIR}/${INC}" ]; then 233 | cat ${WRAPDIR}/${INC} >> ${TMPDIR}/prototypes.txt 234 | echo "${INC}" >> ${TMPDIR}/allheaders.txt 235 | else 236 | echo "cpuusage: warning - ${INC} is not a standard header." 237 | fi 238 | done 239 | sort ${TMPDIR}/allheaders.txt | uniq > ${TMPDIR}/headers.txt 240 | rm ${TMPDIR}/allheaders.txt 2> /dev/null 241 | 242 | # All (-a) Mode 243 | elif [ "${ALL}" == "1" ]; then 244 | ${VERB} && echo "cpuusage: https://github.com/d99kris/cpuusage" 245 | ${VERB} && echo "cpuusage: initializing" 246 | touch ${TMPDIR}/allheaders.txt 247 | touch ${TMPDIR}/prototypes.txt 248 | (cd ${WRAPDIR} && find . -type f -name "*.h" | cut -c3- >> ${TMPDIR}/allheaders.txt) 249 | while read HEADER; do 250 | cat ${WRAPDIR}/${HEADER} >> ${TMPDIR}/prototypes.txt 251 | done < ${TMPDIR}/allheaders.txt 252 | sort ${TMPDIR}/allheaders.txt | uniq > ${TMPDIR}/headers.txt 253 | rm ${TMPDIR}/allheaders.txt 2> /dev/null 254 | 255 | # Instrumented Compile (-c) Mode 256 | elif [ "${INSTR}" == "1" ]; then 257 | ${VERB} && echo "cpuusage: https://github.com/d99kris/cpuusage" 258 | ${VERB} && echo "cpuusage: initializing" 259 | touch "${TMPDIR}/nowrappers.txt" 260 | 261 | # Read (-r) Mode 262 | elif [ "${READ}" != "" ]; then 263 | ${VERB} && echo "cpuusage: https://github.com/d99kris/cpuusage" 264 | ${VERB} && echo "cpuusage: initializing" 265 | touch "${TMPDIR}/read.txt" 266 | 267 | # Proc (-p) Mode 268 | elif [ "${PROC}" != "" ]; then 269 | ${VERB} && echo "cpuusage: https://github.com/d99kris/cpuusage" 270 | ${VERB} && echo "cpuusage: initializing" 271 | touch "${TMPDIR}/proc.txt" 272 | 273 | fi 274 | 275 | 276 | # Common 277 | if [ -f "${TMPDIR}/headers.txt" ] && [ -f "${TMPDIR}/prototypes.txt" ]; then 278 | # Generate H-file wrapper.h 279 | echo "#pragma once" >> ${TMPDIR}/wrapper.h 280 | while read HEADER; do 281 | echo "#include <${HEADER}>" >> ${TMPDIR}/wrapper.h 282 | done < ${TMPDIR}/headers.txt 283 | rm ${TMPDIR}/headers.txt 284 | echo "" >> ${TMPDIR}/wrapper.h 285 | while read PROTOTYPE; do 286 | echo "${PROTOTYPE}" >> ${TMPDIR}/wrapper.h 287 | done < ${TMPDIR}/prototypes.txt 288 | rm ${TMPDIR}/prototypes.txt 289 | 290 | # Generate C-file wrapper.c 291 | ${BINDIR}/cugenwrapper ${TMPDIR}/wrapper.h ${TMPDIR}/wrapper.c 292 | 293 | # Copy CMake and cpuusage library source 294 | cp ${CUDIR}/src/cumain.cpp ${TMPDIR}/cumain.cpp 295 | cp ${CUDIR}/src/libcpuusage_CMakeLists.txt ${TMPDIR}/CMakeLists.txt 296 | 297 | # Build 298 | mkdir -p ${TMPDIR}/build 299 | (cd ${TMPDIR}/build && cmake .. && make -s) > /dev/null 300 | 301 | # Start program with tracing 302 | ${VERB} && echo "cpuusage: starting program ${1}" 303 | JSONPATH="${TMPDIR}/cutrace.json" 304 | if [ "${DEBUG}" == "0" ]; then 305 | CU_FILE="${JSONPATH}" CU_MANUAL="${MANUAL}" \ 306 | LD_PRELOAD="${TMPDIR}/build/libwrapper.so" \ 307 | DYLD_INSERT_LIBRARIES="${TMPDIR}/build/libwrapper.dylib" \ 308 | DYLD_FORCE_FLAT_NAMESPACE=1 "${@:1}" & 309 | CHILDPID="${!}" 310 | wait ${CHILDPID} 311 | else 312 | LLDBCMDPATH="${TMPDIR}/lldb.cmd" 313 | echo "env CU_FILE=\"${JSONPATH}\"" > "${LLDBCMDPATH}" 314 | echo "env CU_MANUAL=\"${MANUAL}\"" >> "${LLDBCMDPATH}" 315 | echo "env LD_PRELOAD=\"${TMPDIR}/build/libwrapper.so\"" >> "${LLDBCMDPATH}" 316 | echo "env DYLD_INSERT_LIBRARIES=\"${TMPDIR}/build/libwrapper.dylib\"" >> "${LLDBCMDPATH}" 317 | echo "env DYLD_FORCE_FLAT_NAMESPACE=1" >> "${LLDBCMDPATH}" 318 | echo "settings set target.process.stop-on-exec false" >> "${LLDBCMDPATH}" 319 | echo "run ${@:2}" >> "${LLDBCMDPATH}" 320 | lldb "${1}" -s "${LLDBCMDPATH}" 321 | CHILDPID="dbg" 322 | fi 323 | 324 | if [ ! -f "${JSONPATH}" ]; then 325 | echo "cpuusage: error, json log data not created." 326 | exit 1 327 | fi 328 | 329 | # Save JSON if needed 330 | if [ "${OUTJSONPATH}" != "" ]; then 331 | cp ${JSONPATH} ${OUTJSONPATH} 332 | fi 333 | 334 | # Convert JSON trace to HTML 335 | ${VERB} && echo "cpuusage: processing output trace" 336 | if [ "${OUTPATH}" == "" ]; then 337 | OUTPATH="./cutrace-${CHILDPID}.html" 338 | fi 339 | python3 ${CUDIR}/catapult/tracing/bin/trace2html ${JSONPATH} --output="${OUTPATH}" > /dev/null 340 | RV="${?}" 341 | 342 | SAMPLECNT=$(grep '"cat":"perf"' ${JSONPATH} 2> /dev/null | wc -l) 343 | ${VERB} && printf "cpuusage: completed processing %d samples\n" ${SAMPLECNT} 344 | 345 | if [[ "${RV}" == "0" ]] && [[ "${OPENCMD}" != "" ]]; then 346 | ${OPENCMD} "${OUTPATH}" & 347 | fi 348 | 349 | elif [ -f "${TMPDIR}/nowrappers.txt" ]; then 350 | 351 | # Start program with tracing 352 | ${VERB} && echo "cpuusage: starting program ${1}" 353 | JSONPATH="${TMPDIR}/cutrace.json" 354 | if [ "${DEBUG}" == "0" ]; then 355 | CU_FILE="${JSONPATH}" CU_MANUAL="${MANUAL}" \ 356 | LD_PRELOAD="${LIBDIR}/libcpuusage.so" \ 357 | DYLD_INSERT_LIBRARIES="${LIBDIR}/libcpuusage.dylib" \ 358 | DYLD_FORCE_FLAT_NAMESPACE=1 "${@:1}" & 359 | CHILDPID="${!}" 360 | wait ${CHILDPID} 361 | else 362 | LLDBCMDPATH="${TMPDIR}/lldb.cmd" 363 | echo "env CU_FILE=\"${JSONPATH}\"" > "${LLDBCMDPATH}" 364 | echo "env CU_MANUAL=\"${MANUAL}\"" >> "${LLDBCMDPATH}" 365 | echo "env LD_PRELOAD=\"${LIBDIR}/libcpuusage.so\"" >> "${LLDBCMDPATH}" 366 | echo "env DYLD_INSERT_LIBRARIES=\"${LIBDIR}/libcpuusage.dylib\"" >> "${LLDBCMDPATH}" 367 | echo "env DYLD_FORCE_FLAT_NAMESPACE=1" >> "${LLDBCMDPATH}" 368 | echo "settings set target.process.stop-on-exec false" >> "${LLDBCMDPATH}" 369 | echo "run ${@:2}" >> "${LLDBCMDPATH}" 370 | lldb "${1}" -s "${LLDBCMDPATH}" 371 | CHILDPID="dbg" 372 | fi 373 | 374 | if [ ! -f "${JSONPATH}" ]; then 375 | echo "cpuusage: error, json log data not created." 376 | exit 1 377 | fi 378 | 379 | # Save JSON if needed 380 | if [ "${OUTJSONPATH}" != "" ]; then 381 | cp ${JSONPATH} ${OUTJSONPATH} 382 | fi 383 | 384 | # Convert JSON trace to HTML 385 | ${VERB} && echo "cpuusage: processing output trace" 386 | if [ "${OUTPATH}" == "" ]; then 387 | OUTPATH="./cutrace-${CHILDPID}.html" 388 | fi 389 | python3 ${CUDIR}/catapult/tracing/bin/trace2html ${JSONPATH} --output="${OUTPATH}" > /dev/null 390 | RV="${?}" 391 | 392 | SAMPLECNT=$(grep '"cat":"perf"' ${JSONPATH} 2> /dev/null | wc -l) 393 | ${VERB} && printf "cpuusage: completed processing %d samples\n" ${SAMPLECNT} 394 | 395 | if [[ "${RV}" == "0" ]] && [[ "${OPENCMD}" != "" ]]; then 396 | ${OPENCMD} "${OUTPATH}" & 397 | fi 398 | 399 | elif [ -f "${TMPDIR}/read.txt" ]; then 400 | 401 | # Set up JSON input path 402 | JSONPATH="${READ}" 403 | ${VERB} && echo "cpuusage: reading file ${JSONPATH}" 404 | 405 | # Save JSON if needed 406 | if [ "${OUTJSONPATH}" != "" ]; then 407 | cp ${JSONPATH} ${OUTJSONPATH} 408 | fi 409 | 410 | # Convert JSON trace to HTML 411 | ${VERB} && echo "cpuusage: processing output trace" 412 | if [ "${OUTPATH}" == "" ]; then 413 | CHILDPID=$(grep "\"pid\"" ${JSONPATH} | head -1 | sed "s/\"/,/g" | cut -d, -f14) 414 | OUTPATH="./cutrace-${CHILDPID}.html" 415 | fi 416 | python3 ${CUDIR}/catapult/tracing/bin/trace2html ${JSONPATH} --output="${OUTPATH}" > /dev/null 417 | RV="${?}" 418 | 419 | SAMPLECNT=$(grep '"cat":"perf"' ${JSONPATH} 2> /dev/null | wc -l) 420 | ${VERB} && printf "cpuusage: completed processing %d samples\n" ${SAMPLECNT} 421 | 422 | if [[ "${RV}" == "0" ]] && [[ "${OPENCMD}" != "" ]]; then 423 | ${OPENCMD} "${OUTPATH}" & 424 | fi 425 | 426 | elif [ -f "${TMPDIR}/proc.txt" ]; then # XXX: See if can make common with above nowrappers 427 | 428 | # Start program with tracing 429 | ${VERB} && echo "cpuusage: starting program ${1}" 430 | JSONPATH="${TMPDIR}/cutrace.json" 431 | #if [ "${DEBUG}" == "0" ]; then 432 | CU_FILE="${JSONPATH}" CU_MANUAL="${MANUAL}" \ 433 | LD_PRELOAD="${LIBDIR}/libcpuusageproc.so" \ 434 | DYLD_INSERT_LIBRARIES="${LIBDIR}/libcpuusageproc.dylib" \ 435 | DYLD_FORCE_FLAT_NAMESPACE=1 "${@:1}" & 436 | CHILDPID="${!}" 437 | wait ${CHILDPID} 438 | #else 439 | # LLDBCMDPATH="${TMPDIR}/lldb.cmd" 440 | # echo "env CU_FILE=\"${JSONPATH}\"" > "${LLDBCMDPATH}" 441 | # echo "env CU_MANUAL=\"${MANUAL}\"" >> "${LLDBCMDPATH}" 442 | # echo "env LD_PRELOAD=\"${LIBDIR}/libcpuusage.so\"" >> "${LLDBCMDPATH}" 443 | # echo "env DYLD_INSERT_LIBRARIES=\"${LIBDIR}/libcpuusage.dylib\"" >> "${LLDBCMDPATH}" 444 | # echo "env DYLD_FORCE_FLAT_NAMESPACE=1" >> "${LLDBCMDPATH}" 445 | # echo "run ${@:2}" >> "${LLDBCMDPATH}" 446 | # lldb "${1}" -s "${LLDBCMDPATH}" 447 | # CHILDPID="dbg" 448 | #fi 449 | 450 | if [ ! -f "${JSONPATH}" ]; then 451 | echo "cpuusage: error, json log data not created." 452 | exit 1 453 | fi 454 | 455 | # Save JSON if needed 456 | if [ "${OUTJSONPATH}" != "" ]; then 457 | cp ${JSONPATH} ${OUTJSONPATH} 458 | fi 459 | 460 | # Convert JSON trace to HTML 461 | ${VERB} && echo "cpuusage: processing output trace" 462 | if [ "${OUTPATH}" == "" ]; then 463 | OUTPATH="./cutrace-${CHILDPID}.html" 464 | fi 465 | python3 ${CUDIR}/catapult/tracing/bin/trace2html ${JSONPATH} --output="${OUTPATH}" > /dev/null 466 | RV="${?}" 467 | 468 | SAMPLECNT=$(grep '"cat":"perf"' ${JSONPATH} 2> /dev/null | wc -l) 469 | ${VERB} && printf "cpuusage: completed processing %d samples\n" ${SAMPLECNT} 470 | 471 | if [[ "${RV}" == "0" ]] && [[ "${OPENCMD}" != "" ]]; then 472 | ${OPENCMD} "${OUTPATH}" & 473 | fi 474 | 475 | else 476 | 477 | echo "cpuusage: error, no mode specified." 478 | exit 1 479 | 480 | fi 481 | 482 | # Cleanup 483 | rm -rf ${TMPDIR} 484 | 485 | exit 0 486 | 487 | -------------------------------------------------------------------------------- /src/cpuusage.1: -------------------------------------------------------------------------------- 1 | .\" DO NOT MODIFY THIS FILE! It was generated by help2man. 2 | .TH CPUUSAGE "1" "January 2025" "cpuusage v1.50" "User Commands" 3 | .SH NAME 4 | cpuusage \- instrumentation CPU profiler 5 | .SH SYNOPSIS 6 | .B cpuusage 7 | \fI\,-a \/\fR[\fI\,OPTIONS\/\fR] \fI\,PROG \/\fR[\fI\,ARGS\/\fR..] 8 | .br 9 | .B cpuusage 10 | \fI\,-c \/\fR[\fI\,OPTIONS\/\fR] \fI\,PROG \/\fR[\fI\,ARGS\/\fR..] 11 | .br 12 | .B cpuusage 13 | \fI\,-f \/\fR[\fI\,OPTIONS\/\fR] \fI\,PROG \/\fR[\fI\,ARGS\/\fR..] 14 | .br 15 | .B cpuusage 16 | \fI\,-i \/\fR[\fI\,OPTIONS\/\fR] \fI\,PROG \/\fR[\fI\,ARGS\/\fR..] 17 | .br 18 | .B cpuusage 19 | \fI\,-p \/\fR[\fI\,OPTIONS\/\fR] \fI\,PROG \/\fR[\fI\,ARGS\/\fR..] 20 | .br 21 | .B cpuusage 22 | \fI\,-r JSONFILE \/\fR[\fI\,OPTIONS\/\fR] 23 | .br 24 | .B cpuusage 25 | \fI\,--help|-h\/\fR 26 | .br 27 | .B cpuusage 28 | \fI\,--version|-v\/\fR 29 | .SH DESCRIPTION 30 | cpuusage is an instrumentation profiler enabling logging of the duration of 31 | internal function calls (for programs compiled with \fB\-finstrument\-functions\fR flag) 32 | or external standard POSIX function calls. It provides visualization in HTML 33 | format using Chromium Catapult. 34 | .SS "Modes:" 35 | .TP 36 | \fB\-a\fR 37 | trace all standard POSIX function calls 38 | .TP 39 | \fB\-c\fR 40 | trace internal function calls (requires PROG to 41 | be compiled with \fB\-finstrument\-functions\fR) 42 | .TP 43 | \fB\-f\fR 44 | trace specified POSIX functions 45 | .TP 46 | \fB\-i\fR 47 | trace functions in specified POSIX headers 48 | .TP 49 | \fB\-p\fR 50 | trace child process durations 51 | .TP 52 | \fB\-\-help\fR, \fB\-h\fR 53 | display this help and exit 54 | .TP 55 | \fB\-\-version\fR, \fB\-v\fR 56 | output version information and exit 57 | .SH OPTIONS 58 | .TP 59 | \fB\-d\fR 60 | debug mode, running program through debugger 61 | .TP 62 | \fB\-e\fR 63 | separate processes for child process trace 64 | .TP 65 | \fB\-j\fR 66 | write iterim JSON trace log to specified path 67 | .TP 68 | \fB\-m\fR 69 | minimum sample time in usec (default 0) 70 | .TP 71 | \fB\-n\fR 72 | only log up to specified number of samples 73 | (default 1000000) 74 | .TP 75 | \fB\-o\fR 76 | write HTML report to specified path, rather 77 | than default ./cutrace\-PID.html 78 | .TP 79 | \fB\-r\fR 80 | read JSON file and convert to HTML report 81 | .TP 82 | \fB\-s\fR 83 | start tracing with SIGUSR1 and stop with 84 | SIGUSR2, instead of trace from process start 85 | .TP 86 | \fB\-u\fR 87 | trace only main\-thread 88 | .TP 89 | \fB\-v\fR 90 | verbose mode 91 | .TP 92 | \fB\-y\fR 93 | auto\-open resulting html file 94 | .TP 95 | PROG 96 | program to run and profile 97 | .TP 98 | [ARGS] 99 | optional arguments to the program 100 | .SH EXAMPLES 101 | cpuusage \-o cutrace.html \-a ./build/ex001 102 | .IP 103 | trace all standard POSIX function calls and write 104 | log to cutrace.html 105 | .PP 106 | cpuusage \-o cutrace.html \-c ./build/ex002 107 | .IP 108 | trace instrumented functions and write log to 109 | cutrace.html 110 | .PP 111 | cpuusage \-o cutrace.html \-f fopen,fclose,fread,fwrite ./build/ex001 112 | .IP 113 | trace calls to fopen, fclose, fread and fwrite, and write 114 | log to cutrace.html 115 | .PP 116 | cpuusage \-o cutrace.html \-i stdio.h ./build/ex001 117 | .IP 118 | trace calls to all POSIX functions in stdio.h and write 119 | log to cutrace.html 120 | .PP 121 | cpuusage \-o cutrace.html \-p ./build/ex005.sh 122 | .IP 123 | trace process durations and write to cutrace.html 124 | .SH AUTHOR 125 | Written by Kristofer Berggren 126 | .SH "REPORTING BUGS" 127 | Report bugs at https://github.com/d99kris/cpuusage 128 | .SH COPYRIGHT 129 | Copyright \(co 2017\-2025 Kristofer Berggren 130 | .PP 131 | cpuusage is distributed under the BSD 3\-Clause license. 132 | -------------------------------------------------------------------------------- /src/cpuusage.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // C compatible API 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | void cu_start_tracing(); 8 | void cu_stop_tracing(); 9 | void cu_start_event_sym(void* sym_addr); 10 | void cu_end_event_sym(void* sym_addr); 11 | void cu_start_event(); 12 | void cu_end_event(); 13 | #ifdef __cplusplus 14 | } 15 | #endif 16 | 17 | // C++ only API 18 | #ifdef __cplusplus 19 | 20 | #if defined(__linux__) 21 | #define CTOR_RETURN_DEPTH 0 22 | #elif defined(__APPLE__) 23 | #define CTOR_RETURN_DEPTH 1 24 | #else 25 | #warning "Unsupported platform" 26 | #endif 27 | 28 | class cu_scoped_event 29 | { 30 | public: 31 | cu_scoped_event(void* sym_addr = NULL) 32 | : m_sym_addr((sym_addr != NULL) ? sym_addr : __builtin_return_address(CTOR_RETURN_DEPTH)) 33 | { 34 | cu_start_event_sym(m_sym_addr); 35 | } 36 | 37 | ~cu_scoped_event() 38 | { 39 | cu_end_event_sym(m_sym_addr); 40 | } 41 | 42 | private: 43 | void* m_sym_addr; 44 | }; 45 | #endif 46 | -------------------------------------------------------------------------------- /src/cugenwrapper: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (C) 2017-2025 Kristofer Berggren 4 | # All rights reserved. 5 | # 6 | # cpuusage is distributed under the BSD 3-Clause license, see LICENSE for details. 7 | # 8 | 9 | import re 10 | import sys 11 | 12 | def genwrapper(infilepath, outfilepath): 13 | infile = open(infilepath, 'r') 14 | outfile = open(outfilepath, 'w') 15 | # Target buffers 16 | headers = "#define _GNU_SOURCE\n#include \n" 17 | headers += "#include \n#include \n" 18 | globs = "static int inited = 0;" 19 | lin_wrapinit = "" 20 | lin_wrapdecl = "" 21 | lin_wrapbody = "" 22 | osx_wrapdecl = "" 23 | osx_wrapbody = "" 24 | for line in infile: 25 | if line.startswith("//"): 26 | # skip comments 27 | continue 28 | elif line.startswith("#include"): 29 | # copy include statements 30 | headers += line 31 | elif line.endswith(";\n"): 32 | paropen = line.find("(") 33 | parclose = line.rfind(")") 34 | semi = line.find(";") 35 | if (paropen > -1) and (parclose > -1) and (semi > -1): 36 | namestart = max(line[0:paropen].rfind(" "), line[0:paropen].rfind("*")) 37 | rtype = line[0:namestart+1] 38 | rcall = "return " 39 | if rtype.strip() == "void": 40 | rcall = "" 41 | name = line[namestart+1:paropen] 42 | realname = "real_" + name 43 | callname = realname 44 | args = line[paropen+1:parclose] 45 | precall = "" 46 | postcall = "" 47 | callargs = "" 48 | prevargname = "" 49 | orgargs = args 50 | 51 | # Clean up func pointers 52 | funptrsfindall = re.findall(r"\((.*?)\)\((.*?)\)", args) 53 | funptrscount = len(funptrsfindall) 54 | for funptrid in range(0, funptrscount): 55 | funptrsfind = re.search(r"\((.*?)\)\((.*?)\)", args) 56 | funptrs = re.compile(r"\((.*?)\)\((.*?)\)") 57 | args = re.sub(funptrs, " " + funptrsfind.group(1), args, count = 1) 58 | 59 | for arg in args.split(","): 60 | argname = "" 61 | if (arg.strip() == "..."): 62 | argname = "args"; 63 | precall = " va_list args;\n va_start(args, " + prevargname + ");\n" 64 | postcall = " va_end(args);\n" 65 | callname = "v" + name 66 | else: 67 | argnamestart = max(arg.rfind(" "), arg.rfind("*")) 68 | if argnamestart > 0: 69 | argname = arg[max(arg.rfind(" "), arg.rfind("*")) + 1:] 70 | brackets = re.compile(r"\[.*?\]") 71 | argname = re.sub(brackets, '', argname) 72 | 73 | if len(callargs) > 0: 74 | callargs += ", " 75 | 76 | if len(argname) > 0: 77 | callargs += argname 78 | prevargname = argname 79 | 80 | if (name == "malloc") or (name == "free") or (name == "calloc") or (name == "realloc"): 81 | lin_wrapdecl += "" + rtype + "__libc_" + name + "(" + args + ");\n" 82 | lin_wrapinit += "" 83 | lin_wrapbody += line[0:semi] + "\n{\n " + rcall + "__libc_" + name + "(" + callargs + ");\n}\n\n"; 84 | else: 85 | lin_wrapdecl += "static " + rtype + "(*" + realname + ") " + "(" + orgargs + ")" + " = NULL;\n" 86 | lin_wrapinit += " " + realname + " = dlsym(RTLD_NEXT, \"" + name + "\");\n" 87 | lin_wrapbody += line[0:semi] + "\n{\n if (!inited) { wrapper_init(); }\n" 88 | lin_wrapbody += precall 89 | if rcall != "": 90 | lin_wrapbody += " " + rtype + " rv = " + callname + "(" + callargs + ");\n" 91 | else: 92 | lin_wrapbody += " " + callname + "(" + callargs + ");\n" 93 | 94 | lin_wrapbody += postcall 95 | if rcall != "": 96 | lin_wrapbody += " return rv;\n" 97 | else: 98 | lin_wrapbody += " return;\n" 99 | lin_wrapbody += "}\n\n"; 100 | 101 | osx_wrapdecl += rtype + "wrap_" + name + "(" + args + ");\n" 102 | osx_wrapbody += rtype + "wrap_" + name + "(" + args + ")\n{\n" 103 | 104 | osx_wrapbody += precall 105 | if rcall != "": 106 | osx_wrapbody += " " + rtype + " rv = " + name + "(" + callargs + ");\n" 107 | else: 108 | osx_wrapbody += " " + name + "(" + callargs + ");\n" 109 | 110 | osx_wrapbody += postcall 111 | if rcall != "": 112 | osx_wrapbody += " return rv;\n" 113 | else: 114 | osx_wrapbody += " return;\n" 115 | 116 | osx_wrapbody += "} DYLD_INTERPOSE(wrap_" + name + ", " + name + ");\n\n" 117 | 118 | outfile.write(headers + "\n") 119 | 120 | outfile.write(globs + "\n") 121 | 122 | outfile.write("#ifdef __APPLE__\n") 123 | outfile.write("#define DYLD_INTERPOSE(_newfun, _orgfun) \\\n"); 124 | outfile.write("__attribute__((used)) static struct{ const void *newfun; const void *orgfun; } _interpose_##_orgfun \\\n"); 125 | outfile.write("__attribute__ ((section (\"__DATA,__interpose\"))) = { (const void *)(unsigned long)&_newfun, \\\n"); 126 | outfile.write(" (const void *)(unsigned long)&_orgfun }\n\n"); 127 | outfile.write(osx_wrapdecl + "\n") 128 | outfile.write("void __attribute__ ((constructor)) wrapper_init(void)\n"); 129 | outfile.write("{\n"); 130 | outfile.write(" inited = 1;\n") 131 | outfile.write("}\n\n"); 132 | outfile.write("void __attribute__ ((destructor)) wrapper_fini(void)\n"); 133 | outfile.write("{\n"); 134 | outfile.write("}\n\n"); 135 | outfile.write(osx_wrapbody) 136 | outfile.write("#endif\n\n\n") 137 | 138 | outfile.write("#ifdef __linux__\n") 139 | outfile.write(lin_wrapdecl + "\n") 140 | outfile.write("void __attribute__ ((constructor)) wrapper_init(void)\n"); 141 | outfile.write("{\n"); 142 | outfile.write(lin_wrapinit) 143 | outfile.write(" inited = 1;\n") 144 | outfile.write("}\n\n"); 145 | outfile.write("void __attribute__ ((destructor)) wrapper_fini(void)\n"); 146 | outfile.write("{\n"); 147 | outfile.write("}\n\n"); 148 | outfile.write(lin_wrapbody) 149 | outfile.write("#endif\n\n") 150 | 151 | 152 | if __name__ == "__main__": 153 | if len(sys.argv) > 1: 154 | genwrapper(sys.argv[1], sys.argv[2]) 155 | else: 156 | print("usage: cugenwrapper ") 157 | exit 158 | 159 | -------------------------------------------------------------------------------- /src/cumain.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * cumain.cpp 3 | * 4 | * Copyright (C) 2017-2025 Kristofer Berggren 5 | * All rights reserved. 6 | * 7 | * cpuusage is distributed under the BSD 3-Clause license, see LICENSE for details. 8 | * 9 | */ 10 | 11 | /* ----------- Includes ------------------------------------------ */ 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | 31 | /* ----------- Types --------------------------------------------- */ 32 | struct Sample 33 | { 34 | pthread_t thread; 35 | int64_t ts; 36 | void* func; 37 | bool enter; 38 | }; 39 | 40 | 41 | /* ----------- File Global Variables ----------------------------- */ 42 | static std::map* symbols = NULL; 43 | static std::vector* samples = NULL; 44 | static std::atomic_flag samples_lock = ATOMIC_FLAG_INIT; 45 | static std::atomic tracing_enabled(false); 46 | static int64_t count_samples = 0; 47 | static int64_t max_samples = 1000000; 48 | static int64_t min_time = 0; 49 | static bool main_thread_only = false; 50 | static pthread_t main_thread; 51 | 52 | 53 | /* ----------- Local Function Prototypes ------------------------- */ 54 | static void cu_start_tracing(int); 55 | static void cu_stop_tracing(int); 56 | static void cu_trace_report(); 57 | static inline void cu_log_event(void *func, bool enter); 58 | static std::string cu_get_timestamp_str(); 59 | static std::string cu_get_os_str(); 60 | static int cu_get_cores(); 61 | static std::string cu_addr_to_symbol(void *addr); 62 | 63 | 64 | /* ----------- Global Functions ---------------------------------- */ 65 | void __attribute__ ((constructor)) cu_init(void) 66 | { 67 | if (getenv("LD_PRELOAD") == NULL) return; 68 | 69 | main_thread = pthread_self(); 70 | 71 | char *manual = getenv("CU_MANUAL"); 72 | if ((manual != NULL) && (strncmp(manual, "1", 1) == 0)) 73 | { 74 | signal(SIGUSR1, cu_start_tracing); 75 | signal(SIGUSR2, cu_stop_tracing); 76 | } 77 | else 78 | { 79 | cu_start_tracing(0); 80 | } 81 | } 82 | 83 | void __attribute__ ((destructor)) cu_fini(void) 84 | { 85 | if (getenv("LD_PRELOAD") == NULL) return; 86 | 87 | cu_stop_tracing(0); 88 | } 89 | 90 | extern "C" 91 | { 92 | void __cyg_profile_func_enter(void *func, void * /*caller*/) 93 | { 94 | cu_log_event(func, true); 95 | } 96 | 97 | void __cyg_profile_func_exit(void *func, void * /*caller*/) 98 | { 99 | cu_log_event(func, false); 100 | } 101 | 102 | void cu_start_tracing() 103 | { 104 | cu_start_tracing(0); 105 | } 106 | 107 | void cu_stop_tracing() 108 | { 109 | cu_stop_tracing(0); 110 | } 111 | 112 | void cu_start_event_sym(void* sym_addr) 113 | { 114 | cu_log_event(sym_addr, true); 115 | } 116 | 117 | void cu_end_event_sym(void* sym_addr) 118 | { 119 | cu_log_event(sym_addr, false); 120 | } 121 | 122 | void cu_start_event(void) 123 | { 124 | cu_log_event(__builtin_return_address(0), true); 125 | } 126 | 127 | void cu_end_event(void) 128 | { 129 | cu_log_event(__builtin_return_address(0), false); 130 | } 131 | } 132 | 133 | 134 | /* ----------- Local Functions ----------------------------------- */ 135 | static void cu_start_tracing(int) 136 | { 137 | char *max_samples_str = getenv("CU_MAX_SAMPLES"); 138 | if (max_samples_str != NULL) 139 | { 140 | max_samples = strtoll(max_samples_str, NULL, 10); 141 | } 142 | 143 | min_time = 0; 144 | char *min_time_str = getenv("CU_MIN_TIME"); 145 | if (min_time_str != NULL) 146 | { 147 | min_time = strtoll(min_time_str, NULL, 10); 148 | } 149 | 150 | char *main_thread_only_str = getenv("CU_MAIN_THREAD_ONLY"); 151 | main_thread_only = (main_thread_only_str != NULL) && (strncmp(main_thread_only_str, "1", 1) == 0); 152 | 153 | if (samples == NULL) 154 | { 155 | samples = new std::vector; 156 | samples->reserve(max_samples); 157 | } 158 | 159 | if (symbols == NULL) 160 | { 161 | symbols = new std::map; 162 | } 163 | 164 | tracing_enabled = true; 165 | } 166 | 167 | static void cu_stop_tracing(int) 168 | { 169 | tracing_enabled = false; 170 | 171 | if ((samples != NULL) && (symbols != NULL)) 172 | { 173 | cu_trace_report(); 174 | delete samples; 175 | delete symbols; 176 | samples = NULL; 177 | symbols = NULL; 178 | count_samples = 0; 179 | } 180 | } 181 | 182 | static inline void cu_log_event(void *func, bool enter) 183 | { 184 | if (!tracing_enabled) return; 185 | 186 | if (main_thread_only && !pthread_equal(pthread_self(), main_thread)) return; 187 | 188 | // set function pointer, thread and type (enter / exit) 189 | Sample sample; 190 | sample.enter = enter; 191 | sample.func = func; 192 | sample.thread = pthread_self(); 193 | 194 | // set current time stamp 195 | struct timeval tv; 196 | gettimeofday(&tv, NULL); 197 | sample.ts = ((int64_t)tv.tv_sec * 1000000ll) + ((int64_t)tv.tv_usec); 198 | 199 | // acquire spin lock 200 | while (samples_lock.test_and_set(std::memory_order_acquire)) 201 | { 202 | } 203 | 204 | // for min_time (currently only supported for single thread trace), calculate duration from previous sample 205 | if (main_thread_only && (min_time > 0) && !enter && !samples->empty() && ((sample.ts - samples->back().ts) < min_time) && 206 | samples->back().enter && (samples->back().func == sample.func)) 207 | { 208 | // skip sample, drop last enter and update sample count 209 | samples->pop_back(); 210 | --count_samples; 211 | } 212 | else 213 | { 214 | // store sample, update sample count, and check upper limit 215 | samples->push_back(sample); 216 | ++count_samples; 217 | if (count_samples >= max_samples) tracing_enabled = false; 218 | } 219 | 220 | // release spin lock 221 | samples_lock.clear(std::memory_order_release); 222 | } 223 | 224 | static void cu_trace_report() 225 | { 226 | char default_path[32]; 227 | char *path = getenv("CU_FILE"); 228 | 229 | // determine report path 230 | if (path == NULL) 231 | { 232 | snprintf(default_path, sizeof(default_path), "./culog-%d.json", getpid()); 233 | path = default_path; 234 | } 235 | 236 | // open report file 237 | FILE *outfile = fopen(path, "w"); 238 | if (outfile == NULL) 239 | { 240 | fprintf(stderr, "cpuusage: unable to write to output path '%s'\n", path); 241 | return; 242 | } 243 | 244 | // report header 245 | fprintf(outfile, "{\n"); 246 | fprintf(outfile, "\"otherData\": {\n"); 247 | fprintf(outfile, " \"timestamp\":\"%s\",\n", cu_get_timestamp_str().c_str()); 248 | fprintf(outfile, " \"os\":\"%s\",\n", cu_get_os_str().c_str()); 249 | fprintf(outfile, " \"cores\":\"%d\"\n", cu_get_cores()); 250 | fprintf(outfile, "},\n"); 251 | 252 | // report samples 253 | fprintf(outfile, "\"traceEvents\": [\n"); 254 | bool first_sample = true; 255 | pid_t pid = getpid(); 256 | for (auto const& sample : *samples) 257 | { 258 | if (first_sample) 259 | { 260 | first_sample = false; 261 | fprintf(outfile, " "); 262 | } 263 | else 264 | { 265 | fprintf(outfile, ",\n "); 266 | } 267 | char type = sample.enter ? 'B' : 'E'; 268 | std::string name = cu_addr_to_symbol(sample.func); 269 | 270 | fprintf(outfile, "{ \"ph\":\"%c\", \"cat\":\"perf\", \"pid\":\"%d\", " 271 | "\"tid\":\"%p\", \"name\":\"%s\", \"ts\":%" PRId64 " }", 272 | type, pid, (void*)sample.thread, name.c_str(), sample.ts); 273 | } 274 | 275 | fprintf(outfile, "\n"); 276 | fprintf(outfile, "]\n"); 277 | fprintf(outfile, "}\n"); 278 | fclose(outfile); 279 | } 280 | 281 | static std::string cu_get_timestamp_str() 282 | { 283 | time_t global_time; 284 | struct tm* local_tm; 285 | char timestr[26]; 286 | 287 | time(&global_time); 288 | local_tm = localtime(&global_time); 289 | strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S %z", local_tm); 290 | 291 | return std::string(timestr); 292 | } 293 | 294 | static std::string cu_get_os_str() 295 | { 296 | struct utsname uts; 297 | 298 | if (uname(&uts) == 0) 299 | { 300 | return std::string(uts.sysname) + std::string(" ") + std::string(uts.release); 301 | } 302 | 303 | return std::string(); 304 | } 305 | 306 | static int cu_get_cores() 307 | { 308 | return std::thread::hardware_concurrency(); 309 | } 310 | 311 | static std::string cu_addr_to_symbol(void *addr) 312 | { 313 | std::string symbol; 314 | 315 | auto it = symbols->find(addr); 316 | if (it != symbols->end()) 317 | { 318 | symbol = it->second; 319 | } 320 | else 321 | { 322 | Dl_info dlinfo; 323 | if (dladdr(addr, &dlinfo) && dlinfo.dli_sname) 324 | { 325 | if (dlinfo.dli_sname[0] == '_') 326 | { 327 | int status = -1; 328 | char *demangled = NULL; 329 | demangled = abi::__cxa_demangle(dlinfo.dli_sname, NULL, 0, &status); 330 | if (demangled) 331 | { 332 | if (status == 0) 333 | { 334 | symbol = std::string(demangled); 335 | } 336 | free(demangled); 337 | } 338 | } 339 | 340 | if (symbol.empty()) 341 | { 342 | symbol = std::string(dlinfo.dli_sname); 343 | } 344 | 345 | if (!symbol.empty()) 346 | { 347 | symbol += std::string(" + "); 348 | symbol += std::string(std::to_string((char*)addr - (char*)dlinfo.dli_saddr)); 349 | } 350 | } 351 | else 352 | { 353 | std::stringstream ss; 354 | ss << "0x" << std::hex << (unsigned long long)addr; 355 | symbol = ss.str(); 356 | } 357 | 358 | (*symbols)[addr] = symbol; 359 | } 360 | 361 | return symbol; 362 | } 363 | 364 | -------------------------------------------------------------------------------- /src/cupmain.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * cupmain.cpp 3 | * 4 | * Copyright (C) 2020-2025 Kristofer Berggren 5 | * All rights reserved. 6 | * 7 | * cpuusage is distributed under the BSD 3-Clause license, see LICENSE for details. 8 | * 9 | */ 10 | 11 | /* ----------- Includes ------------------------------------------ */ 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | 34 | /* ----------- Local Functions ----------------------------------- */ 35 | static void cup_writeheader(const char* p_Path) 36 | { 37 | // open report file 38 | FILE *outfile = fopen(p_Path, "w"); 39 | if (outfile == NULL) 40 | { 41 | fprintf(stderr, "cpuusage: unable to write to output path '%s'\n", p_Path); 42 | return; 43 | } 44 | 45 | // lock file 46 | if (flock(fileno(outfile), LOCK_EX) != 0) 47 | { 48 | fprintf(stderr, "cpuusage: unable to lock output path '%s'\n", p_Path); 49 | return; 50 | } 51 | 52 | // header timestamp 53 | time_t global_time; 54 | struct tm* local_tm; 55 | char timestr[26] = { 0 }; 56 | time(&global_time); 57 | local_tm = localtime(&global_time); 58 | strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S %z", local_tm); 59 | 60 | // header os 61 | char osstr[256] = { 0 }; 62 | struct utsname uts; 63 | if (uname(&uts) == 0) 64 | { 65 | snprintf(osstr, sizeof(osstr), "%s %s", uts.sysname, uts.release); 66 | } 67 | 68 | // report header 69 | fprintf(outfile, "{\n"); 70 | fprintf(outfile, "\"otherData\": {\n"); 71 | fprintf(outfile, " \"timestamp\":\"%s\",\n", timestr); 72 | fprintf(outfile, " \"os\":\"%s\",\n", osstr); 73 | fprintf(outfile, " \"cores\":\"%d\"\n", std::thread::hardware_concurrency()); 74 | fprintf(outfile, "},\n"); 75 | 76 | // report samples 77 | fprintf(outfile, "\"traceEvents\": [\n "); 78 | 79 | // unlock file 80 | fflush(outfile); 81 | flock(fileno(outfile), LOCK_UN); 82 | 83 | // close file 84 | fclose(outfile); 85 | } 86 | 87 | static std::string cup_escapejson(const std::string& p_Str) 88 | { 89 | std::ostringstream oss; 90 | for (auto ch = p_Str.cbegin(); ch != p_Str.cend(); ch++) 91 | { 92 | if ((*ch == '"') || (*ch == '\\') || (('\x00' >= *ch) && (*ch <= '\x1f'))) 93 | { 94 | oss << "\\u" << std::hex << std::setw(4) << std::setfill('0') << (int)*ch; 95 | } 96 | else 97 | { 98 | oss << *ch; 99 | } 100 | } 101 | 102 | return oss.str(); 103 | } 104 | 105 | static std::string cup_getprocid() 106 | { 107 | pid_t pid = getpid(); 108 | std::string pidstr = std::to_string(pid); 109 | return pidstr; 110 | } 111 | 112 | static std::string cup_getproccmd() 113 | { 114 | pid_t pid = getpid(); 115 | std::string pidstr = std::to_string(pid); 116 | std::string pidbracketstr = "[" + pidstr + "]"; 117 | char tempname[] = "/tmp/cpuusage.XX" "XX" "XX"; 118 | int tmpfd = mkstemp(tempname); 119 | if (tmpfd == -1) 120 | { 121 | return pidbracketstr; 122 | } 123 | 124 | close(tmpfd); 125 | 126 | // spawn child process 127 | pid_t childpid = fork(); 128 | if (childpid == -1) 129 | { 130 | // failed to fork() 131 | return pidbracketstr; 132 | } 133 | else if (childpid > 0) 134 | { 135 | // parent 136 | int status = 0; 137 | waitpid(childpid, &status, 0); 138 | } 139 | else 140 | { 141 | // child 142 | int outfd = open(tempname, O_WRONLY | O_CREAT); 143 | if (outfd == -1) 144 | { 145 | fprintf(stderr, "cpuusage: open %s error\n", tempname); 146 | _exit(EXIT_FAILURE); 147 | } 148 | 149 | if (dup2(outfd, STDOUT_FILENO) == -1) 150 | { 151 | fprintf(stderr, "cpuusage: dup2(%d, %d) error\n", outfd, STDOUT_FILENO); 152 | _exit(EXIT_FAILURE); 153 | } 154 | 155 | // run ps 156 | execle("/bin/ps", "ps", "-p", pidstr.c_str(), "-o", "args", NULL, NULL); 157 | _exit(EXIT_FAILURE); // unreachable 158 | } 159 | 160 | // get second line from ps output 161 | std::string cmd; 162 | std::string line; 163 | std::ifstream infile(tempname); 164 | if (std::getline(infile, line) && std::getline(infile, line)) 165 | { 166 | // escape control chars for json 167 | line = cup_escapejson(line); 168 | cmd = line; 169 | } 170 | 171 | // clean up 172 | infile.close(); 173 | remove(tempname); 174 | 175 | return cmd; 176 | } 177 | 178 | static void cup_writeevent(bool p_IsFirstProcess, const char* p_Path, 179 | int64_t p_BeginTime, int64_t p_EndTime, 180 | bool p_IsExpandProcesses) 181 | { 182 | // get process id/cmd 183 | std::string id = cup_getprocid(); 184 | std::string cmd = cup_getproccmd(); 185 | 186 | // open report file 187 | FILE *outfile = fopen(p_Path, "a"); 188 | if (outfile == NULL) 189 | { 190 | fprintf(stderr, "cpuusage: unable to append to output path '%s'\n", p_Path); 191 | return; 192 | } 193 | 194 | // lock file 195 | if (flock(fileno(outfile), LOCK_EX) != 0) 196 | { 197 | fprintf(stderr, "cpuusage: unable to lock output path '%s'\n", p_Path); 198 | return; 199 | } 200 | 201 | // write entry 202 | const pid_t pid = 0; 203 | const bool isLogArgs = false; 204 | const pid_t tid = p_IsExpandProcesses ? getpid() : 0; 205 | const int64_t ts = p_BeginTime; 206 | const int64_t dur = p_EndTime - p_BeginTime; 207 | fprintf(outfile, "{ \"ph\":\"X\", \"cat\":\"perf\", \"pid\":%d, " 208 | "\"tid\":%d, \"ts\":%" PRId64 ", \"dur\":%" PRId64 ", \"name\":\"%s\"", 209 | pid, tid, ts, dur, cmd.c_str()); 210 | if (isLogArgs) 211 | { 212 | fprintf(outfile, ", \"args\": { \"cmd\":\"%s\", \"pid\":%d }", cmd.c_str(), getpid()); 213 | } 214 | 215 | fprintf(outfile, " }"); 216 | 217 | // special handling for first process / last event 218 | if (p_IsFirstProcess) 219 | { 220 | fprintf(outfile, " "); 221 | } 222 | else 223 | { 224 | fprintf(outfile, ",\n "); 225 | } 226 | 227 | // write report footer if it's the main process 228 | if (p_IsFirstProcess) 229 | { 230 | fprintf(outfile, "\n"); 231 | fprintf(outfile, "]\n"); 232 | fprintf(outfile, "}\n"); 233 | } 234 | 235 | // unlock file 236 | fflush(outfile); 237 | flock(fileno(outfile), LOCK_UN); 238 | 239 | // close file 240 | fclose(outfile); 241 | } 242 | 243 | static void cup_handleevent(bool p_IsStart) 244 | { 245 | if (getenv("LD_PRELOAD") == NULL) return; 246 | 247 | static char default_path[32]; 248 | static char* path = NULL; 249 | static int64_t beginTime = 0; 250 | 251 | // determine report path 252 | path = getenv("CU_FILE"); 253 | if (path == NULL) 254 | { 255 | snprintf(default_path, sizeof(default_path), "./culog-%d.json", getpid()); 256 | path = default_path; 257 | } 258 | 259 | if (p_IsStart) 260 | { 261 | // check if file does not exist 262 | if (access(path, F_OK) == -1) 263 | { 264 | // remember this is the main process 265 | std::string pid = std::to_string(getpid()); 266 | setenv("CU_FIRST_PROCESS", pid.c_str(), true); 267 | 268 | // write header 269 | cup_writeheader(path); 270 | } 271 | 272 | // store begin timestamp 273 | struct timeval tv; 274 | gettimeofday(&tv, NULL); 275 | beginTime = ((int64_t)tv.tv_sec * 1000000ll) + ((int64_t)tv.tv_usec); 276 | } 277 | else 278 | { 279 | // store end timestamp 280 | struct timeval tv; 281 | gettimeofday(&tv, NULL); 282 | const int64_t endTime = ((int64_t)tv.tv_sec * 1000000ll) + ((int64_t)tv.tv_usec); 283 | 284 | // read back first process id from environment 285 | std::string firstpid = std::string(getenv("CU_FIRST_PROCESS")); 286 | std::string pid = std::to_string(getpid()); 287 | const bool isFirstProcess = (pid == firstpid); 288 | 289 | char* isExpandStr = getenv("CU_EXPAND_PROCESSES"); 290 | bool isExpandProcesses = (isExpandStr != NULL) && (strncmp(isExpandStr, "1", 1) == 0); 291 | 292 | // write event to file 293 | cup_writeevent(isFirstProcess, path, beginTime, endTime, isExpandProcesses); 294 | } 295 | } 296 | 297 | 298 | /* ----------- Global Functions ---------------------------------- */ 299 | void __attribute__ ((constructor)) cup_init(void) 300 | { 301 | cup_handleevent(true); 302 | } 303 | 304 | void __attribute__ ((destructor)) cup_fini(void) 305 | { 306 | cup_handleevent(false); 307 | } 308 | -------------------------------------------------------------------------------- /src/libcpuusage_CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14...3.22 FATAL_ERROR) 2 | 3 | # general build setup 4 | set(CMAKE_BUILD_TYPE Debug) 5 | set(CMAKE_CXX_STANDARD 11) 6 | 7 | # cpuusage library 8 | project (cpuusage) 9 | file(GLOB SOURCES cumain.cpp) 10 | add_library(${PROJECT_NAME} SHARED ${SOURCES}) 11 | add_library(${PROJECT_NAME}static STATIC ${SOURCES}) 12 | set_property(TARGET ${PROJECT_NAME}static PROPERTY POSITION_INDEPENDENT_CODE 1) 13 | target_link_libraries(${PROJECT_NAME} dl) 14 | target_link_libraries(${PROJECT_NAME}static dl) 15 | set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "-g -Wall -Wextra -pedantic") 16 | set_target_properties(${PROJECT_NAME}static PROPERTIES COMPILE_FLAGS "-g -Wall -Wextra -pedantic") 17 | 18 | # wrapper library 19 | add_library(wrapper SHARED wrapper.c) 20 | set_property(TARGET wrapper PROPERTY C_STANDARD 99) 21 | target_link_libraries(wrapper cpuusagestatic dl) 22 | set_target_properties(wrapper PROPERTIES COMPILE_FLAGS "-finstrument-functions -g -Wall -Wextra -Wno-deprecated -Wno-array-parameter -Wno-vla-parameter") 23 | -------------------------------------------------------------------------------- /tests/ex.json: -------------------------------------------------------------------------------- 1 | { 2 | "otherData": { 3 | "timestamp":"2022-09-06 19:41:31 +0800", 4 | "os":"Darwin 21.6.0", 5 | "cores":"4" 6 | }, 7 | "traceEvents": [ 8 | { "ph":"B", "cat":"perf", "pid":"13441", "tid":"0x105cf3600", "name":"wrap_pthread_mutex_lock + 0", "ts":1662464491302117 }, 9 | { "ph":"E", "cat":"perf", "pid":"13441", "tid":"0x105cf3600", "name":"wrap_pthread_mutex_lock + 0", "ts":1662464491302122 } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /tests/ex001.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ex001.c 3 | * 4 | * Copyright (C) 2017 Kristofer Berggren 5 | * All rights reserved. 6 | * 7 | * cpuusage is distributed under the BSD 3-Clause license, see LICENSE for details. 8 | * 9 | */ 10 | 11 | /* ----------- Includes ------------------------------------------ */ 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | 20 | /* ----------- Function Prototypes ------------------------------- */ 21 | void copy_large_file(); 22 | void copy_medium_file(); 23 | void copy_small_file(); 24 | 25 | 26 | /* ----------- Global Functions ---------------------------------- */ 27 | int main(void) 28 | { 29 | copy_large_file(); 30 | copy_medium_file(); 31 | copy_small_file(); 32 | return 0; 33 | } 34 | 35 | void copy_large_file() 36 | { 37 | int large_size = 1024 * 1024 * 1024; 38 | char *buf = calloc(1, large_size); 39 | FILE* fin = fopen("/dev/null", "r"); 40 | FILE* fout = fopen("/dev/null", "w"); 41 | fread(buf, large_size, 1, fin); 42 | fclose(fin); 43 | fwrite(buf, large_size, 1, fout); 44 | fclose(fout); 45 | free(buf); 46 | } 47 | 48 | void copy_medium_file() 49 | { 50 | int medium_size = 128 * 1024 * 1024; 51 | char *buf = calloc(1, medium_size); 52 | FILE* fin = fopen("/dev/null", "r"); 53 | FILE* fout = fopen("/dev/null", "w"); 54 | fread(buf, medium_size, 1, fin); 55 | fclose(fin); 56 | fwrite(buf, medium_size, 1, fout); 57 | fclose(fout); 58 | free(buf); 59 | } 60 | 61 | void copy_small_file() 62 | { 63 | int small_size = 1024 * 1024; 64 | char *buf = calloc(1, small_size); 65 | FILE* fin = fopen("/dev/null", "r"); 66 | FILE* fout = fopen("/dev/null", "w"); 67 | fread(buf, small_size, 1, fin); 68 | fclose(fin); 69 | fwrite(buf, small_size, 1, fout); 70 | fclose(fout); 71 | free(buf); 72 | } 73 | 74 | -------------------------------------------------------------------------------- /tests/ex002.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ex002.c 3 | * 4 | * Copyright (C) 2017 Kristofer Berggren 5 | * All rights reserved. 6 | * 7 | * cpuusage is distributed under the BSD 3-Clause license, see LICENSE for details. 8 | * 9 | */ 10 | 11 | /* ----------- Includes ------------------------------------------ */ 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | 20 | /* ----------- Function Prototypes ------------------------------- */ 21 | void copy_large_file(); 22 | void copy_medium_file(); 23 | void copy_small_file(); 24 | 25 | 26 | /* ----------- Global Functions ---------------------------------- */ 27 | int main(void) 28 | { 29 | copy_large_file(); 30 | copy_medium_file(); 31 | copy_small_file(); 32 | return 0; 33 | } 34 | 35 | void copy_large_file() 36 | { 37 | int large_size = 1024 * 1024 * 1024; 38 | char *buf = calloc(1, large_size); 39 | FILE* fin = fopen("/dev/null", "r"); 40 | FILE* fout = fopen("/dev/null", "w"); 41 | fread(buf, large_size, 1, fin); 42 | fclose(fin); 43 | fwrite(buf, large_size, 1, fout); 44 | fclose(fout); 45 | free(buf); 46 | } 47 | 48 | void copy_medium_file() 49 | { 50 | int medium_size = 128 * 1024 * 1024; 51 | char *buf = calloc(1, medium_size); 52 | FILE* fin = fopen("/dev/null", "r"); 53 | FILE* fout = fopen("/dev/null", "w"); 54 | fread(buf, medium_size, 1, fin); 55 | fclose(fin); 56 | fwrite(buf, medium_size, 1, fout); 57 | fclose(fout); 58 | free(buf); 59 | } 60 | 61 | void copy_small_file() 62 | { 63 | int small_size = 1024 * 1024; 64 | char *buf = calloc(1, small_size); 65 | FILE* fin = fopen("/dev/null", "r"); 66 | FILE* fout = fopen("/dev/null", "w"); 67 | fread(buf, small_size, 1, fin); 68 | fclose(fin); 69 | fwrite(buf, small_size, 1, fout); 70 | fclose(fout); 71 | free(buf); 72 | } 73 | 74 | -------------------------------------------------------------------------------- /tests/ex003.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * ex003.cpp 3 | * 4 | * Copyright (C) 2018 Kristofer Berggren 5 | * All rights reserved. 6 | * 7 | * cpuusage is distributed under the BSD 3-Clause license, see LICENSE for details. 8 | * 9 | */ 10 | 11 | /* ----------- Includes ------------------------------------------ */ 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "cpuusage.h" 20 | 21 | 22 | /* ----------- Function Prototypes ------------------------------- */ 23 | void copy_large_file(); 24 | void copy_medium_file(); 25 | void copy_small_file(); 26 | void copy_tiny_file(); 27 | 28 | 29 | /* ----------- Global Functions ---------------------------------- */ 30 | int main(void) 31 | { 32 | setenv("CU_MAX_SAMPLES", "1000", 1); 33 | setenv("CU_FILE", "culog.json", 1); 34 | 35 | cu_start_tracing(); 36 | 37 | copy_large_file(); 38 | copy_medium_file(); 39 | copy_small_file(); 40 | copy_tiny_file(); 41 | 42 | cu_stop_tracing(); 43 | 44 | return 0; 45 | } 46 | 47 | void copy_large_file() 48 | { 49 | cu_start_event(); 50 | 51 | int large_size = 1024 * 1024 * 1024; 52 | char* buf = (char*) calloc(1, large_size); 53 | FILE* fin = fopen("/dev/null", "r"); 54 | FILE* fout = fopen("/dev/null", "w"); 55 | fread(buf, large_size, 1, fin); 56 | fclose(fin); 57 | fwrite(buf, large_size, 1, fout); 58 | fclose(fout); 59 | free(buf); 60 | 61 | cu_end_event(); 62 | } 63 | 64 | void copy_medium_file() 65 | { 66 | cu_start_event_sym((void*) ©_medium_file); 67 | 68 | int medium_size = 128 * 1024 * 1024; 69 | char* buf = (char*) calloc(1, medium_size); 70 | FILE* fin = fopen("/dev/null", "r"); 71 | FILE* fout = fopen("/dev/null", "w"); 72 | fread(buf, medium_size, 1, fin); 73 | fclose(fin); 74 | fwrite(buf, medium_size, 1, fout); 75 | fclose(fout); 76 | free(buf); 77 | 78 | cu_end_event_sym((void*) ©_medium_file); 79 | } 80 | 81 | void copy_small_file() 82 | { 83 | cu_scoped_event scoped_event; 84 | 85 | int small_size = 1024 * 1024; 86 | char* buf = (char*) calloc(1, small_size); 87 | FILE* fin = fopen("/dev/null", "r"); 88 | FILE* fout = fopen("/dev/null", "w"); 89 | fread(buf, small_size, 1, fin); 90 | fclose(fin); 91 | fwrite(buf, small_size, 1, fout); 92 | fclose(fout); 93 | free(buf); 94 | } 95 | 96 | void copy_tiny_file() 97 | { 98 | cu_scoped_event scoped_event((void*) ©_tiny_file); 99 | 100 | int tiny_size = 256 * 1024; 101 | char* buf = (char*)calloc(1, tiny_size); 102 | FILE* fin = fopen("/dev/null", "r"); 103 | FILE* fout = fopen("/dev/null", "w"); 104 | fread(buf, tiny_size, 1, fin); 105 | fclose(fin); 106 | fwrite(buf, tiny_size, 1, fout); 107 | fclose(fout); 108 | free(buf); 109 | } 110 | -------------------------------------------------------------------------------- /tests/ex004.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * ex004.cpp 3 | * 4 | * Copyright (C) 2020 Kristofer Berggren 5 | * All rights reserved. 6 | * 7 | * cpuusage is distributed under the BSD 3-Clause license, see LICENSE for details. 8 | * 9 | */ 10 | 11 | /* ----------- Includes ------------------------------------------ */ 12 | #include 13 | 14 | 15 | /* ----------- Global Functions ---------------------------------- */ 16 | int main(void) 17 | { 18 | sleep(1); 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /tests/ex005.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # ex005.sh 4 | 5 | sleep 1 6 | SCRIPTPATH="$(cd -- "$(dirname "$0")" >/dev/null 2>&1; pwd -P)" 7 | ${SCRIPTPATH}/ex005b.sh 8 | sleep 2 9 | -------------------------------------------------------------------------------- /tests/ex005b.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # ex005b.sh 4 | 5 | sleep 1 6 | -------------------------------------------------------------------------------- /tests/test001: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Environment 4 | RV=0 5 | TMPDIR=$(mktemp -d) 6 | 7 | # Run application 8 | ./bin/cpuusage -v -o out.html -f fopen,fwrite,fread,fclose ./ex001 > ${TMPDIR}/out.txt 9 | 10 | # Expected 11 | # cpuusage: https://github.com/d99kris/cpuusage 12 | # cpuusage: initializing 13 | # cpuusage: starting program ./ex001 14 | # cpuusage: processing output trace 15 | # cpuusage: completed processing 36 samples 16 | 17 | # Check result 18 | LINE=$(cat ${TMPDIR}/out.txt | head -1 | tail -1) 19 | EXPT="cpuusage: https://github.com/d99kris/cpuusage" 20 | if [ "${LINE}" != "${EXPT}" ]; then 21 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 22 | echo "Full test output:" 23 | cat ${TMPDIR}/out.txt 24 | RV=1 25 | fi 26 | 27 | LINE=$(cat ${TMPDIR}/out.txt | head -2 | tail -1) 28 | EXPT="cpuusage: initializing" 29 | if [ "${LINE}" != "${EXPT}" ]; then 30 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 31 | echo "Full test output:" 32 | cat ${TMPDIR}/out.txt 33 | RV=1 34 | fi 35 | 36 | LINE=$(cat ${TMPDIR}/out.txt | head -3 | tail -1) 37 | EXPT="cpuusage: starting program ./ex001" 38 | if [ "${LINE}" != "${EXPT}" ]; then 39 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 40 | echo "Full test output:" 41 | cat ${TMPDIR}/out.txt 42 | RV=1 43 | fi 44 | 45 | LINE=$(cat ${TMPDIR}/out.txt | head -4 | tail -1) 46 | EXPT="cpuusage: processing output trace" 47 | if [ "${LINE}" != "${EXPT}" ]; then 48 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 49 | echo "Full test output:" 50 | cat ${TMPDIR}/out.txt 51 | RV=1 52 | fi 53 | 54 | LINE=$(cat ${TMPDIR}/out.txt | head -5 | tail -1) 55 | EXPT="cpuusage: completed processing 36 samples" 56 | if [ "${LINE}" != "${EXPT}" ]; then 57 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 58 | echo "Full test output:" 59 | cat ${TMPDIR}/out.txt 60 | RV=1 61 | fi 62 | 63 | # Cleanup 64 | rm -rf ${TMPDIR} 65 | 66 | # Exit 67 | exit ${RV} 68 | 69 | -------------------------------------------------------------------------------- /tests/test002: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Environment 4 | RV=0 5 | TMPDIR=$(mktemp -d) 6 | 7 | # Run application 8 | ./bin/cpuusage -v -o out.html -c ./ex002 > ${TMPDIR}/out.txt 9 | 10 | # Expected 11 | # cpuusage: https://github.com/d99kris/cpuusage 12 | # cpuusage: initializing 13 | # cpuusage: starting program ./ex002 14 | # cpuusage: processing output trace 15 | # cpuusage: completed processing 8 samples 16 | 17 | # Check result 18 | LINE=$(cat ${TMPDIR}/out.txt | head -1 | tail -1) 19 | EXPT="cpuusage: https://github.com/d99kris/cpuusage" 20 | if [ "${LINE}" != "${EXPT}" ]; then 21 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 22 | echo "Full test output:" 23 | cat ${TMPDIR}/out.txt 24 | RV=1 25 | fi 26 | 27 | LINE=$(cat ${TMPDIR}/out.txt | head -2 | tail -1) 28 | EXPT="cpuusage: initializing" 29 | if [ "${LINE}" != "${EXPT}" ]; then 30 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 31 | echo "Full test output:" 32 | cat ${TMPDIR}/out.txt 33 | RV=1 34 | fi 35 | 36 | LINE=$(cat ${TMPDIR}/out.txt | head -3 | tail -1) 37 | EXPT="cpuusage: starting program ./ex002" 38 | if [ "${LINE}" != "${EXPT}" ]; then 39 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 40 | echo "Full test output:" 41 | cat ${TMPDIR}/out.txt 42 | RV=1 43 | fi 44 | 45 | LINE=$(cat ${TMPDIR}/out.txt | head -4 | tail -1) 46 | EXPT="cpuusage: processing output trace" 47 | if [ "${LINE}" != "${EXPT}" ]; then 48 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 49 | echo "Full test output:" 50 | cat ${TMPDIR}/out.txt 51 | RV=1 52 | fi 53 | 54 | LINE=$(cat ${TMPDIR}/out.txt | head -5 | tail -1) 55 | EXPT="cpuusage: completed processing 8 samples" 56 | if [ "${LINE}" != "${EXPT}" ]; then 57 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 58 | echo "Full test output:" 59 | cat ${TMPDIR}/out.txt 60 | RV=1 61 | fi 62 | 63 | # Cleanup 64 | rm -rf ${TMPDIR} 65 | 66 | # Exit 67 | exit ${RV} 68 | 69 | -------------------------------------------------------------------------------- /tests/test003: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Environment 4 | RV=0 5 | TMPDIR=$(mktemp -d) 6 | BUILDDIR=$(pwd) 7 | pushd ${TMPDIR} > /dev/null 8 | 9 | # Run application 10 | ${BUILDDIR}/ex003 11 | ${BUILDDIR}/bin/cpuusage -v -r culog.json > ${TMPDIR}/out.txt 12 | 13 | # Expected 14 | # cpuusage: https://github.com/d99kris/cpuusage 15 | # cpuusage: initializing 16 | # cpuusage: starting program ./ex002 17 | # cpuusage: processing output trace 18 | # cpuusage: completed processing 8 samples 19 | 20 | # Check result 21 | LINE=$(cat ${TMPDIR}/out.txt | head -1 | tail -1) 22 | EXPT="cpuusage: https://github.com/d99kris/cpuusage" 23 | if [ "${LINE}" != "${EXPT}" ]; then 24 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 25 | echo "Full test output:" 26 | cat ${TMPDIR}/out.txt 27 | RV=1 28 | fi 29 | 30 | LINE=$(cat ${TMPDIR}/out.txt | head -2 | tail -1) 31 | EXPT="cpuusage: initializing" 32 | if [ "${LINE}" != "${EXPT}" ]; then 33 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 34 | echo "Full test output:" 35 | cat ${TMPDIR}/out.txt 36 | RV=1 37 | fi 38 | 39 | LINE=$(cat ${TMPDIR}/out.txt | head -3 | tail -1) 40 | EXPT="cpuusage: reading file culog.json" 41 | if [ "${LINE}" != "${EXPT}" ]; then 42 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 43 | echo "Full test output:" 44 | cat ${TMPDIR}/out.txt 45 | RV=1 46 | fi 47 | 48 | LINE=$(cat ${TMPDIR}/out.txt | head -4 | tail -1) 49 | EXPT="cpuusage: processing output trace" 50 | if [ "${LINE}" != "${EXPT}" ]; then 51 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 52 | echo "Full test output:" 53 | cat ${TMPDIR}/out.txt 54 | RV=1 55 | fi 56 | 57 | LINE=$(cat ${TMPDIR}/out.txt | head -5 | tail -1) 58 | EXPT="cpuusage: completed processing 8 samples" 59 | if [ "${LINE}" != "${EXPT}" ]; then 60 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 61 | echo "Full test output:" 62 | cat ${TMPDIR}/out.txt 63 | RV=1 64 | fi 65 | 66 | # Cleanup 67 | popd > /dev/null 68 | rm -rf ${TMPDIR} 69 | 70 | # Exit 71 | exit ${RV} 72 | 73 | -------------------------------------------------------------------------------- /tests/test004: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Environment 4 | RV=0 5 | TMPDIR=$(mktemp -d) 6 | 7 | # Run application 8 | ./bin/cpuusage -v -o ${TMPDIR}/out.html -j ${TMPDIR}/out.json -p ./ex004 > ${TMPDIR}/out.txt 9 | 10 | # Expected 11 | # cpuusage: https://github.com/d99kris/cpuusage 12 | # cpuusage: initializing 13 | # cpuusage: starting program ./ex004 14 | # cpuusage: processing output trace 15 | # cpuusage: completed processing 36 samples 16 | 17 | # Check result 18 | LINE=$(cat ${TMPDIR}/out.txt | head -1 | tail -1) 19 | EXPT="cpuusage: https://github.com/d99kris/cpuusage" 20 | if [ "${LINE}" != "${EXPT}" ]; then 21 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 22 | echo "Full test output:" 23 | cat ${TMPDIR}/out.txt 24 | RV=1 25 | fi 26 | 27 | LINE=$(cat ${TMPDIR}/out.txt | head -2 | tail -1) 28 | EXPT="cpuusage: initializing" 29 | if [ "${LINE}" != "${EXPT}" ]; then 30 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 31 | echo "Full test output:" 32 | cat ${TMPDIR}/out.txt 33 | RV=1 34 | fi 35 | 36 | LINE=$(cat ${TMPDIR}/out.txt | head -3 | tail -1) 37 | EXPT="cpuusage: starting program ./ex004" 38 | if [ "${LINE}" != "${EXPT}" ]; then 39 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 40 | echo "Full test output:" 41 | cat ${TMPDIR}/out.txt 42 | RV=1 43 | fi 44 | 45 | LINE=$(cat ${TMPDIR}/out.txt | head -4 | tail -1) 46 | EXPT="cpuusage: processing output trace" 47 | if [ "${LINE}" != "${EXPT}" ]; then 48 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 49 | echo "Full test output:" 50 | cat ${TMPDIR}/out.txt 51 | RV=1 52 | fi 53 | 54 | LINE=$(cat ${TMPDIR}/out.txt | head -5 | tail -1) 55 | EXPT="cpuusage: completed processing 1 samples" 56 | if [ "${LINE}" != "${EXPT}" ]; then 57 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 58 | echo "Full test output:" 59 | cat ${TMPDIR}/out.txt 60 | RV=1 61 | fi 62 | 63 | # Cleanup 64 | rm -rf ${TMPDIR} 65 | 66 | # Exit 67 | exit ${RV} 68 | 69 | -------------------------------------------------------------------------------- /tests/test005: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Environment 4 | RV=0 5 | TMPDIR=$(mktemp -d) 6 | 7 | # Run application 8 | ./bin/cpuusage -v -o ${TMPDIR}/out.html -j ${TMPDIR}/out.json -p ./ex005.sh > ${TMPDIR}/out.txt 9 | 10 | # Expected 11 | # cpuusage: https://github.com/d99kris/cpuusage 12 | # cpuusage: initializing 13 | # cpuusage: starting program ./ex004 14 | # cpuusage: processing output trace 15 | # cpuusage: completed processing 36 samples 16 | 17 | # Check result 18 | LINE=$(cat ${TMPDIR}/out.txt | head -1 | tail -1) 19 | EXPT="cpuusage: https://github.com/d99kris/cpuusage" 20 | if [ "${LINE}" != "${EXPT}" ]; then 21 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 22 | echo "Full test output:" 23 | cat ${TMPDIR}/out.txt 24 | RV=1 25 | fi 26 | 27 | LINE=$(cat ${TMPDIR}/out.txt | head -2 | tail -1) 28 | EXPT="cpuusage: initializing" 29 | if [ "${LINE}" != "${EXPT}" ]; then 30 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 31 | echo "Full test output:" 32 | cat ${TMPDIR}/out.txt 33 | RV=1 34 | fi 35 | 36 | LINE=$(cat ${TMPDIR}/out.txt | head -3 | tail -1) 37 | EXPT="cpuusage: starting program ./ex005.sh" 38 | if [ "${LINE}" != "${EXPT}" ]; then 39 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 40 | echo "Full test output:" 41 | cat ${TMPDIR}/out.txt 42 | RV=1 43 | fi 44 | 45 | LINE=$(cat ${TMPDIR}/out.txt | head -4 | tail -1) 46 | EXPT="cpuusage: processing output trace" 47 | if [ "${LINE}" != "${EXPT}" ]; then 48 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 49 | echo "Full test output:" 50 | cat ${TMPDIR}/out.txt 51 | RV=1 52 | fi 53 | 54 | LINE=$(cat ${TMPDIR}/out.txt | head -5 | tail -1) 55 | EXPT="cpuusage: completed processing 7 samples" 56 | if [ "${LINE}" != "${EXPT}" ]; then 57 | echo "Output mismatch: \"${LINE}\" != \"${EXPT}\"" 58 | echo "Full test output:" 59 | cat ${TMPDIR}/out.txt 60 | RV=1 61 | fi 62 | 63 | # Cleanup 64 | rm -rf ${TMPDIR} 65 | 66 | # Exit 67 | exit ${RV} 68 | 69 | --------------------------------------------------------------------------------