diff --git a/.gitmodules b/.gitmodules index 0ba40610..7368e703 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,6 @@ [submodule "Testing/driver/kwsys"] path = Testing/driver/kwsys url = https://github.com/mercury-hpc/kwsys.git -[submodule "src/mchecksum"] - path = src/mchecksum - url = https://github.com/mercury-hpc/mchecksum.git [submodule "src/boost"] path = src/boost url = https://github.com/mercury-hpc/preprocessor.git diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 93898d0f..52bff113 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -180,6 +180,8 @@ set(MERCURY_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/mercury_core_header.c ${CMAKE_CURRENT_SOURCE_DIR}/mercury_header.c ${CMAKE_CURRENT_SOURCE_DIR}/mercury_proc.c + ${CMAKE_CURRENT_SOURCE_DIR}/mercury_prof_interface.c + ${CMAKE_CURRENT_SOURCE_DIR}/mercury_prof_pvar_impl.c ${CMAKE_CURRENT_SOURCE_DIR}/mercury_proc_bulk.c ${CMAKE_CURRENT_SOURCE_DIR}/proc_extra/mercury_proc_string.c ${CMAKE_CURRENT_SOURCE_DIR}/proc_extra/mercury_string_object.c @@ -237,6 +239,8 @@ set(MERCURY_HEADERS ${CMAKE_CURRENT_BINARY_DIR}/mercury_config.h ${CMAKE_CURRENT_SOURCE_DIR}/mercury.h ${CMAKE_CURRENT_SOURCE_DIR}/mercury_bulk.h + ${CMAKE_CURRENT_SOURCE_DIR}/mercury_prof_interface.h + ${CMAKE_CURRENT_SOURCE_DIR}/mercury_prof_types.h ${CMAKE_CURRENT_SOURCE_DIR}/mercury_core.h ${CMAKE_CURRENT_SOURCE_DIR}/mercury_core_header.h ${CMAKE_CURRENT_SOURCE_DIR}/mercury_core_types.h diff --git a/src/mchecksum b/src/mchecksum deleted file mode 160000 index 5b64750b..00000000 --- a/src/mchecksum +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5b64750b315a6b758012314c0be7b1776154692f diff --git a/src/mchecksum/CMake/CheckSSE42.c b/src/mchecksum/CMake/CheckSSE42.c new file mode 100644 index 00000000..4adee943 --- /dev/null +++ b/src/mchecksum/CMake/CheckSSE42.c @@ -0,0 +1,11 @@ +#include + +int main(void) +{ + unsigned int result = ~(unsigned int)0; + + result = _mm_crc32_u8(result, 0x0); + + return result; +} + diff --git a/src/mchecksum/CMake/FindISAL.cmake b/src/mchecksum/CMake/FindISAL.cmake new file mode 100644 index 00000000..229acbe2 --- /dev/null +++ b/src/mchecksum/CMake/FindISAL.cmake @@ -0,0 +1,22 @@ +# - Try to find ISA-L +# Once done this will define +# ISAL_FOUND - System has ISA-L +# ISAL_INCLUDE_DIRS - The ISA-L include directories +# ISAL_LIBRARIES - The libraries needed to use ISA-L + +find_path(ISAL_INCLUDE_DIR isa-l.h + HINTS /usr/local/include /usr/include) + +find_library(ISAL_LIBRARY NAMES isal + HINTS /usr/local/lib /usr/lib) + +set(ISAL_LIBRARIES ${ISAL_LIBRARY}) +set(ISAL_INCLUDE_DIRS ${ISAL_INCLUDE_DIR}) + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set ISAL_FOUND to TRUE +# if all listed variables are TRUE +find_package_handle_standard_args(ISAL DEFAULT_MSG + ISAL_LIBRARY ISAL_INCLUDE_DIR) + +mark_as_advanced(ISAL_INCLUDE_DIR ISAL_LIBRARY) diff --git a/src/mchecksum/CMake/Git/Git.cmake b/src/mchecksum/CMake/Git/Git.cmake new file mode 100644 index 00000000..4142fff5 --- /dev/null +++ b/src/mchecksum/CMake/Git/Git.cmake @@ -0,0 +1,31 @@ +#============================================================================= +# Copyright 2011 Kitware, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= + +# Check for a hint left by the 'GitInfo' script. +if(NOT GIT_EXECUTABLE) + get_filename_component(_Git_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) + include(${_Git_DIR}/GitInfo.cmake OPTIONAL) + if(GitInfo_GIT_EXECUTABLE) + if(EXISTS "${GitInfo_GIT_EXECUTABLE}") + set(GIT_EXECUTABLE "${GitInfo_GIT_EXECUTABLE}") + elseif(EXISTS "${GitInfo_GIT_EXECUTABLE}.exe") + set(GIT_EXECUTABLE "${GitInfo_GIT_EXECUTABLE}.exe") + endif() + endif() +endif() + +# Find Git. +find_package(Git) diff --git a/src/mchecksum/CMake/Git/GitInfo b/src/mchecksum/CMake/Git/GitInfo new file mode 100755 index 00000000..9e51b39c --- /dev/null +++ b/src/mchecksum/CMake/Git/GitInfo @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +#============================================================================= +# Copyright 2011 Kitware, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= + +# Path conversion function. +case "$(uname)" in + *CYGWIN*) + native_path() { + cygpath -m "$1" + } + ;; + *MINGW*) + native_path() { + cmd //c echo "$1" | sed 's/^"//;s/"$//' + } + ;; + *) + native_path() { + echo "$1" + } + ;; +esac + +# Compute native path to "git" executable. +if git="$(type -p git)"; then + git="$(native_path "${git}")" +else + git='' +fi + +# Compute native path to ".git" dir. +if dir="$(git rev-parse --git-dir)"; then + dir="$(cd "$dir"; pwd)" + git_dir="$(native_path "${dir}")" +else + git_dir='' +fi + +# Store the values in a CMake file next to this script. +echo >"${BASH_SOURCE%/*}/GitInfo.cmake" '# Generated by GitInfo +set(GitInfo 1) +set(GitInfo_GIT_EXECUTABLE "'"$git"'") +set(GitInfo_GIT_DIR "'"$git_dir"'") +' diff --git a/src/mchecksum/CMake/Git/LICENSE b/src/mchecksum/CMake/Git/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/src/mchecksum/CMake/Git/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/src/mchecksum/CMake/Git/NOTICE b/src/mchecksum/CMake/Git/NOTICE new file mode 100644 index 00000000..8f2a7bce --- /dev/null +++ b/src/mchecksum/CMake/Git/NOTICE @@ -0,0 +1,5 @@ +Git Support Scripts +Copyright 2011 Kitware, Inc. + +This product includes software developed at Kitware, Inc. +(http://www.kitware.com/). diff --git a/src/mchecksum/CMake/MChecksumDetermineVersion.cmake b/src/mchecksum/CMake/MChecksumDetermineVersion.cmake new file mode 100644 index 00000000..3dbfe1a0 --- /dev/null +++ b/src/mchecksum/CMake/MChecksumDetermineVersion.cmake @@ -0,0 +1,97 @@ +#========================================================================= +# +# Copyright (c) Kitware, Inc. +# All rights reserved. +# +# This software is distributed WITHOUT ANY WARRANTY; without even +# the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the above copyright notice for more information. +# +#========================================================================= + +# Used to determine the version using "git describe", if git +# is found. On success sets following variables in caller's scope: +# ${var_prefix}_VERSION +# ${var_prefix}_VERSION_MAJOR +# ${var_prefix}_VERSION_MINOR +# ${var_prefix}_VERSION_PATCH +# ${var_prefix}_VERSION_PATCH_EXTRA +# ${var_prefix}_VERSION_FULL +# ${var_prefix}_VERSION_IS_RELEASE is true, if patch-extra is empty. +# +# If git is not found, or git describe cannot be run successfully, then these +# variables are left unchanged and status message is printed. +# +# Arguments are: +# source_dir : Source directory +# git_command : git executable +# var_prefix : prefix for variables e.g. "MCHECKSUM". +function(determine_version source_dir git_command var_prefix) + if ("$Format:$" STREQUAL "") + # We are in an exported tarball and should use the shipped version + # information. Just return here to avoid the warning message at the end of + # this function. + return () + elseif (NOT ${var_prefix}_GIT_DESCRIBE AND + EXISTS ${git_command} AND + EXISTS ${source_dir}/.git) + execute_process( + COMMAND ${git_command} describe + WORKING_DIRECTORY ${source_dir} + RESULT_VARIABLE result + OUTPUT_VARIABLE output + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_STRIP_TRAILING_WHITESPACE) + if (NOT result EQUAL 0) + # git describe failed (bad return code). + set(output "") + endif() + else () + # note, output may be set to empty if ${var_prefix}_GIT_DESCRIBE is not defined. + set(output "${${var_prefix}_GIT_DESCRIBE}") + endif() + + unset(tmp_VERSION) + extract_version_components("${output}" tmp) + if(DEFINED tmp_VERSION) + if (NOT "${tmp_VERSION}" STREQUAL "${${var_prefix}_VERSION}") + message(WARNING + "Version from git (${tmp_VERSION}) disagrees with hard coded version (${${var_prefix}_VERSION}). Either update the git tags or version.txt.") + endif() + foreach(suffix VERSION VERSION_MAJOR VERSION_MINOR VERSION_PATCH + VERSION_PATCH_EXTRA VERSION_FULL VERSION_IS_RELEASE) + set(${var_prefix}_${suffix} ${tmp_${suffix}} PARENT_SCOPE) + endforeach() + else() + message(STATUS + "Could not use git to determine source version, using version ${${var_prefix}_VERSION_FULL}") + endif() +endfunction() + +# Extracts components from a version string. See determine_version() for usage. +function(extract_version_components version_string var_prefix) + string(REGEX MATCH "^v?(([0-9]+)\\.([0-9]+)\\.([0-9]+)-?(.*))$" + version_matches "${version_string}") + if(CMAKE_MATCH_0) + # note, we don't use CMAKE_MATCH_0 for `full` since it may or may not have + # the `v` prefix. + set(full ${CMAKE_MATCH_1}) + set(major ${CMAKE_MATCH_2}) + set(minor ${CMAKE_MATCH_3}) + set(patch ${CMAKE_MATCH_4}) + set(patch_extra ${CMAKE_MATCH_5}) + + set(${var_prefix}_VERSION "${major}.${minor}" PARENT_SCOPE) + set(${var_prefix}_VERSION_MAJOR ${major} PARENT_SCOPE) + set(${var_prefix}_VERSION_MINOR ${minor} PARENT_SCOPE) + set(${var_prefix}_VERSION_PATCH ${patch} PARENT_SCOPE) + set(${var_prefix}_VERSION_PATCH_EXTRA ${patch_extra} PARENT_SCOPE) + set(${var_prefix}_VERSION_FULL ${full} PARENT_SCOPE) + if("${major}.${minor}.${patch}" MATCHES "${full}") + set(${var_prefix}_VERSION_IS_RELEASE TRUE PARENT_SCOPE) + else() + set(${var_prefix}_VERSION_IS_RELEASE FALSE PARENT_SCOPE) + endif() + endif() +endfunction() diff --git a/src/mchecksum/CMake/mchecksum-config-version.cmake.in b/src/mchecksum/CMake/mchecksum-config-version.cmake.in new file mode 100644 index 00000000..1f9a0982 --- /dev/null +++ b/src/mchecksum/CMake/mchecksum-config-version.cmake.in @@ -0,0 +1,13 @@ +#----------------------------------------------------------------------------- +# Version file for install directory +#----------------------------------------------------------------------------- +set(PACKAGE_VERSION @MCHECKSUM_VERSION_MAJOR@.@MCHECKSUM_VERSION_MINOR@.@MCHECKSUM_VERSION_PATCH@) + +if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if ("${PACKAGE_VERSION}" STREQUAL "${PACKAGE_FIND_VERSION}") + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() diff --git a/src/mchecksum/CMake/mchecksum-config.cmake.in b/src/mchecksum/CMake/mchecksum-config.cmake.in new file mode 100644 index 00000000..03d7b3ac --- /dev/null +++ b/src/mchecksum/CMake/mchecksum-config.cmake.in @@ -0,0 +1,31 @@ +#----------------------------------------------------------------------------- +# mchecksum-config.cmake - MChecksum CMake configuration file for external projects. +#----------------------------------------------------------------------------- +set(__mchecksum_install_tree @MCHECKSUM_CONFIG_INSTALLED@) +if(__mchecksum_install_tree) + get_filename_component(location "${CMAKE_CURRENT_LIST_FILE}" PATH) + set(MCHECKSUM_CONFIG_TARGETS_FILE "${location}/@MCHECKSUM_PACKAGE@-targets.cmake") +else() + # This is the build location. + set(MCHECKSUM_CONFIG_TARGETS_FILE "@MCHECKSUM_BINARY_DIR@/src/@MCHECKSUM_PACKAGE@-targets.cmake") +endif() + +#----------------------------------------------------------------------------- +# Version information for MChecksum +#----------------------------------------------------------------------------- +set(MCHECKSUM_VERSION_MAJOR @MCHECKSUM_VERSION_MAJOR@) +set(MCHECKSUM_VERSION_MINOR @MCHECKSUM_VERSION_MINOR@) +set(MCHECKSUM_VERSION_PATCH @MCHECKSUM_VERSION_PATCH@) +set(MCHECKSUM_VERSION_FULL @MCHECKSUM_VERSION_FULL@) +set(MCHECKSUM_VERSION @MCHECKSUM_VERSION@) + +#----------------------------------------------------------------------------- +# Don't include targets if this file is being picked up by another +# project which has already built MChecksum as a subproject +#----------------------------------------------------------------------------- +if(NOT TARGET "mchecksum" AND NOT MCHECKSUM_INSTALL_SKIP_TARGETS) + include(${MCHECKSUM_CONFIG_TARGETS_FILE}) +endif() + +# cleanup +unset(__mchecksum_install_tree) diff --git a/src/mchecksum/CMake/mchecksum.pc.in b/src/mchecksum/CMake/mchecksum.pc.in new file mode 100644 index 00000000..6bb055ab --- /dev/null +++ b/src/mchecksum/CMake/mchecksum.pc.in @@ -0,0 +1,14 @@ +# This gives access to the mchecksum header files +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@CMAKE_INSTALL_PREFIX@ +libdir=@MCHECKSUM_INSTALL_LIB_DIR@ +includedir=@MCHECKSUM_INSTALL_INCLUDE_DIR@ + +Name: @MCHECKSUM_PACKAGE@ +Description: @MCHECKSUM_PACKAGE_DESCRIPTION@ +Version: @MCHECKSUM_VERSION_MAJOR@.@MCHECKSUM_VERSION_MINOR@.@MCHECKSUM_VERSION_PATCH@ +URL: @MCHECKSUM_PACKAGE_URL@ +Requires: +Libs: -L${libdir} @MCHECKSUM_LIBRARIES@ +Libs.private: @MCHECKSUM_LIB_DEPENDENCIES@ +Cflags: -I${includedir} @MCHECKSUM_INCLUDE_DEPENDENCIES@ diff --git a/src/mchecksum/CMakeLists.txt b/src/mchecksum/CMakeLists.txt new file mode 100644 index 00000000..6136358b --- /dev/null +++ b/src/mchecksum/CMakeLists.txt @@ -0,0 +1,343 @@ +cmake_minimum_required(VERSION 2.8.12.2 FATAL_ERROR) + +# Setup cmake policies. +foreach(p + CMP0012 + CMP0013 + CMP0014 + CMP0022 # CMake 2.8.12 + CMP0025 # CMake 3.0 + CMP0053 # CMake 3.1 + CMP0054 # CMake 3.1 + CMP0074 # CMake 3.12 + CMP0075 # CMake 3.12 + CMP0083 # CMake 3.14 + ) + if(POLICY ${p}) + cmake_policy(SET ${p} NEW) + endif() +endforeach() + +# Set a consistent MACOSX_RPATH default across all CMake versions. +# When CMake 2.8.12 is required, change this default to 1. +# When CMake 3.0.0 is required, remove this block (see CMP0042). +if(NOT DEFINED CMAKE_MACOSX_RPATH) + set(CMAKE_MACOSX_RPATH 0) +endif() + +project(MCHECKSUM C) + +#------------------------------------------------------------------------------ +# Setup install and output Directories +#------------------------------------------------------------------------------ +if(NOT MCHECKSUM_INSTALL_BIN_DIR) + set(MCHECKSUM_INSTALL_BIN_DIR ${CMAKE_INSTALL_PREFIX}/bin) +endif() +if(NOT MCHECKSUM_INSTALL_LIB_DIR) + set(MCHECKSUM_INSTALL_LIB_DIR ${CMAKE_INSTALL_PREFIX}/lib) +endif() +if(NOT MCHECKSUM_INSTALL_INCLUDE_DIR) + # Interface include will default to prefix/include + set(MCHECKSUM_INSTALL_INCLUDE_INTERFACE include) + set(MCHECKSUM_INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_PREFIX}/include) +else() + set(MCHECKSUM_INSTALL_INCLUDE_INTERFACE ${MCHECKSUM_INSTALL_INCLUDE_DIR}) +endif() +if(NOT MCHECKSUM_INSTALL_DATA_DIR) + set(MCHECKSUM_INSTALL_DATA_DIR ${CMAKE_INSTALL_PREFIX}/share) +endif() + +# Setting this ensures that "make install" will leave rpaths to external +# libraries intact on "make install". This ensures that one can install a +# version of Mercury on the build machine without any issues. If this not +# desired, simply specify CMAKE_INSTALL_RPATH_USE_LINK_PATH when configuring +# Mercury and "make install" will strip all rpaths, which is default behavior. +if(NOT CMAKE_INSTALL_RPATH_USE_LINK_PATH) + set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) +endif() + +#------------------------------------------------------------------------------ +# Set module path +#------------------------------------------------------------------------------ +set(MCHECKSUM_CMAKE_MODULE_PATH "${MCHECKSUM_SOURCE_DIR}/CMake") +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${MCHECKSUM_CMAKE_MODULE_PATH}) + +#------------------------------------------------------------------------------ +# Version information +#------------------------------------------------------------------------------ +include(${MCHECKSUM_CMAKE_MODULE_PATH}/Git/Git.cmake) +include(MChecksumDetermineVersion) +# Hard-coded version variables are read-in from a separate file. This makes it +# easier to have a script to update version numbers automatically. +file(STRINGS version.txt version_txt) +extract_version_components("${version_txt}" "${PROJECT_NAME}") +determine_version(${MCHECKSUM_SOURCE_DIR} ${GIT_EXECUTABLE} "${PROJECT_NAME}") +set(MCHECKSUM_PACKAGE "mchecksum") +set(MCHECKSUM_PACKAGE_NAME "MChecksum") +set(MCHECKSUM_PACKAGE_DESCRIPTION "Mercury Checksum Library") +set(MCHECKSUM_PACKAGE_URL "https://github.com/mercury-hpc/mchecksum") +set(MCHECKSUM_PACKAGE_VENDOR "Argonne National Laboratory / The HDF Group") +message(STATUS "Configuring ${MCHECKSUM_PACKAGE} v${MCHECKSUM_VERSION_FULL}") + +#------------------------------------------------------------------------------ +# Setup CMake Environment +#------------------------------------------------------------------------------ +if(APPLE AND NOT MCHECKSUM_EXTERNALLY_CONFIGURED) + # We are doing a unix-style install i.e. everything will be installed in + # CMAKE_INSTALL_PREFIX/bin and CMAKE_INSTALL_PREFIX/lib etc. as on other unix + # platforms. We still need to setup CMAKE_INSTALL_NAME_DIR correctly so that + # the binaries point to appropriate location for the libraries. + + # 1. Make CMAKE_INSTALL_PREFIX publicly accessible, if it was hidden in + # previous pass + get_property(is_internal CACHE CMAKE_INSTALL_PREFIX PROPERTY TYPE) + if(is_internal STREQUAL "INTERNAL") + set(CMAKE_INSTALL_PREFIX ${CACHED_CMAKE_INSTALL_PREFIX} CACHE PATH "Install prefix" FORCE) + else() + set(CMAKE_INSTALL_PREFIX ${CACHED_CMAKE_INSTALL_PREFIX} CACHE PATH "Install prefix") + endif() + unset(MACOSX_APP_INSTALL_PREFIX CACHE) + + set(CMAKE_INSTALL_NAME_DIR "@rpath") + mark_as_advanced( + CMAKE_OSX_ARCHITECTURES + CMAKE_OSX_DEPLOYMENT_TARGET + CMAKE_OSX_SYSROOT + ) +endif() + +#------------------------------------------------------------------------------ +if(NOT MCHECKSUM_EXTERNALLY_CONFIGURED) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY + ${PROJECT_BINARY_DIR}/bin CACHE PATH "Single Directory for all Executables." + ) + set(EXECUTABLE_OUTPUT_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY + ${PROJECT_BINARY_DIR}/bin CACHE PATH "Single Directory for all Libraries" + ) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY + ${PROJECT_BINARY_DIR}/bin CACHE PATH "Single Directory for all static libraries." + ) +endif() + +#------------------------------------------------------------------------------ +# Disallow in-source build +#------------------------------------------------------------------------------ +if("${MCHECKSUM_SOURCE_DIR}" STREQUAL "${MCHECKSUM_BINARY_DIR}") + message(FATAL_ERROR + "MChecksum requires an out of source Build. " + "Please create a separate binary directory and run CMake there.") +endif() + +#------------------------------------------------------------------------------ +# Set a default build type if none was specified +#------------------------------------------------------------------------------ +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + message(STATUS "Setting build type to 'RelWithDebInfo' as none was specified.") + set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE) + # Set the possible values of build type for cmake-gui + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" + "MinSizeRel" "RelWithDebInfo") +endif() + +if(NOT CMAKE_C_FLAGS AND CMAKE_COMPILER_IS_GNUCC) + message(STATUS "GCC detected, setting additional flags") + set(CMAKE_C_FLAGS "-Wall -Wextra -Winline -Wcast-qual -std=gnu99 -Wshadow" CACHE STRING "Flags used by the compiler during all build types." FORCE) +endif() + +#----------------------------------------------------------------------------- +# Targets built within this project are exported at Install time for use +# by other projects. +#----------------------------------------------------------------------------- +if(NOT MCHECKSUM_EXPORTED_TARGETS) + set(MCHECKSUM_EXPORTED_TARGETS "${MCHECKSUM_PACKAGE}-targets") +endif() + +#------------------------------------------------------------------------------ +# Choose static or shared libraries. +#------------------------------------------------------------------------------ +option(BUILD_SHARED_LIBS "Build with shared libraries." OFF) +if(BUILD_SHARED_LIBS) + set(MCHECKSUM_BUILD_SHARED_LIBS 1) + set(MCHECKSUM_LIBTYPE SHARED) +else() + set(MCHECKSUM_BUILD_SHARED_LIBS 0) + set(MCHECKSUM_LIBTYPE STATIC) +endif() + +#------------------------------------------------------------------------------ +# Enable verbose error. +#------------------------------------------------------------------------------ +option(MCHECKSUM_ENABLE_VERBOSE_ERROR "Print error messages to stderr." ON) +if(MCHECKSUM_ENABLE_VERBOSE_ERROR) + set(MCHECKSUM_HAS_VERBOSE_ERROR 1) +else() + set(MCHECKSUM_HAS_VERBOSE_ERROR 0) +endif() + +#------------------------------------------------------------------------------- +function(mchecksum_set_lib_options libtarget libname libtype) + if(${libtype} MATCHES "SHARED") + if(WIN32 AND NOT MINGW) + set(LIB_RELEASE_NAME "${libname}") + set(LIB_DEBUG_NAME "${libname}_D") + else() + set(LIB_RELEASE_NAME "${libname}") + set(LIB_DEBUG_NAME "${libname}_debug") + endif() + set(LIB_VERSION ${MCHECKSUM_VERSION}.${MCHECKSUM_VERSION_PATCH}) + set(API_VERSION ${MCHECKSUM_VERSION_MAJOR}) + else() + if(WIN32 AND NOT MINGW) + set(LIB_RELEASE_NAME "lib${libname}") + set(LIB_DEBUG_NAME "lib${libname}_D") + else() + # if the generator supports configuration types or if the CMAKE_BUILD_TYPE has a value + if(CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) + set(LIB_RELEASE_NAME "${libname}") + set(LIB_DEBUG_NAME "${libname}_debug") + else() + set(LIB_RELEASE_NAME "lib${libname}") + set(LIB_DEBUG_NAME "lib${libname}_debug") + endif() + endif() + endif() + + set_target_properties(${libtarget} + PROPERTIES + OUTPUT_NAME_DEBUG ${LIB_DEBUG_NAME} + OUTPUT_NAME_RELEASE ${LIB_RELEASE_NAME} + OUTPUT_NAME_MINSIZEREL ${LIB_RELEASE_NAME} + OUTPUT_NAME_RELWITHDEBINFO ${LIB_RELEASE_NAME} + OUTPUT_NAME_ASAN ${LIB_DEBUG_NAME} + OUTPUT_NAME_TSAN ${LIB_DEBUG_NAME} + VERSION ${LIB_VERSION} + SOVERSION ${API_VERSION} + ) + + #----- Use MSVC Naming conventions for Shared Libraries + if(MINGW AND ${libtype} MATCHES "SHARED") + set_target_properties(${libtarget} + PROPERTIES + IMPORT_SUFFIX ".lib" + IMPORT_PREFIX "" + PREFIX "" + ) + endif() +endfunction() + +# Avoid explicitly including system include paths +set(MCHECKSUM_SYSTEM_INCLUDE_PATH ${CMAKE_SYSTEM_INCLUDE_PATH} + ${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES}) + +#----------------------------------------------------------------------------- +# Coverage +#----------------------------------------------------------------------------- +if(NOT MCHECKSUM_EXTERNALLY_CONFIGURED) + option(MCHECKSUM_ENABLE_COVERAGE "Enable coverage." OFF) + if(MCHECKSUM_ENABLE_COVERAGE) + set(COVERAGE_FLAGS "-fprofile-arcs -ftest-coverage" CACHE STRING + "Flags to the coverage program that CTest uses to perform coverage inspection" + ) + mark_as_advanced(COVERAGE_FLAGS) + endif() + + macro(set_coverage_flags target) + set_target_properties(${target} + PROPERTIES + COMPILE_FLAGS ${COVERAGE_FLAGS} + LINK_FLAGS ${COVERAGE_FLAGS} + ) + endmacro() +endif() + +#----------------------------------------------------------------------------- +# Source +#----------------------------------------------------------------------------- +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src) + +#----------------------------------------------------------------------------- +# Testing +#----------------------------------------------------------------------------- +option(BUILD_TESTING "Build testing." OFF) +if(NOT MCHECKSUM_EXTERNALLY_CONFIGURED AND BUILD_TESTING) + enable_testing() +# include(CTest) + add_subdirectory(Testing) +endif() + +#----------------------------------------------------------------------------- +# Configure the config.cmake file for the build directory +#----------------------------------------------------------------------------- +set(MCHECKSUM_CONFIG_INSTALLED FALSE) +configure_file( + ${MCHECKSUM_SOURCE_DIR}/CMake/${MCHECKSUM_PACKAGE}-config.cmake.in + ${MCHECKSUM_BINARY_DIR}/${MCHECKSUM_PACKAGE}-config.cmake @ONLY +) + +#----------------------------------------------------------------------------- +# Configure the config.cmake file for the install directory +#----------------------------------------------------------------------------- +set(MCHECKSUM_CONFIG_INSTALLED TRUE) +configure_file( + ${MCHECKSUM_SOURCE_DIR}/CMake/${MCHECKSUM_PACKAGE}-config.cmake.in + ${MCHECKSUM_BINARY_DIR}/CMakeFiles/mchecksum-config.cmake @ONLY +) + +install( + FILES + ${MCHECKSUM_BINARY_DIR}/CMakeFiles/${MCHECKSUM_PACKAGE}-config.cmake + DESTINATION + ${MCHECKSUM_INSTALL_DATA_DIR}/cmake/${MCHECKSUM_PACKAGE} +) + +#----------------------------------------------------------------------------- +# Configure the mchecksum-config-version .cmake file for the install directory +#----------------------------------------------------------------------------- +configure_file( + ${MCHECKSUM_SOURCE_DIR}/CMake/${MCHECKSUM_PACKAGE}-config-version.cmake.in + ${MCHECKSUM_BINARY_DIR}/CMakeFiles/${MCHECKSUM_PACKAGE}-config-version.cmake @ONLY +) + +install( + FILES + ${MCHECKSUM_BINARY_DIR}/CMakeFiles/${MCHECKSUM_PACKAGE}-config-version.cmake + DESTINATION + ${MCHECKSUM_INSTALL_DATA_DIR}/cmake/${MCHECKSUM_PACKAGE} +) + +#----------------------------------------------------------------------------- +# For automake compatibility, also a provide a pkgconfig file +#----------------------------------------------------------------------------- +if(NOT WIN32) + configure_file( + ${MCHECKSUM_SOURCE_DIR}/CMake/${MCHECKSUM_PACKAGE}.pc.in + ${MCHECKSUM_BINARY_DIR}/CMakeFiles/${MCHECKSUM_PACKAGE}.pc @ONLY + ) + + install( + FILES + ${MCHECKSUM_BINARY_DIR}/CMakeFiles/${MCHECKSUM_PACKAGE}.pc + DESTINATION + ${MCHECKSUM_INSTALL_LIB_DIR}/pkgconfig + ) +endif() + +#----------------------------------------------------------------------------- +# CPack +#----------------------------------------------------------------------------- +if(NOT MCHECKSUM_EXTERNALLY_CONFIGURED) + set(CPACK_PACKAGE_DESCRIPTION_FILE ${MCHECKSUM_SOURCE_DIR}/README.md) + set(CPACK_RESOURCE_FILE_LICENSE ${MCHECKSUM_SOURCE_DIR}/COPYING) + set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${MCHECKSUM_PACKAGE_DESCRIPTION}) + set(CPACK_PACKAGE_NAME ${MCHECKSUM_PACKAGE_NAME}) + set(CPACK_PACKAGE_VENDOR ${MCHECKSUM_PACKAGE_VENDOR}) + set(CPACK_PACKAGE_VERSION_MAJOR ${MCHECKSUM_VERSION_MAJOR}) + set(CPACK_PACKAGE_VERSION_MINOR ${MCHECKSUM_VERSION_MINOR}) + set(CPACK_PACKAGE_VERSION_PATCH ${MCHECKSUM_VERSION_PATCH}) + set(CPACK_GENERATOR "TBZ2") + set(CPACK_SOURCE_PACKAGE_FILE_NAME ${MCHECKSUM_PACKAGE}-${MCHECKSUM_VERSION_FULL}) + set(CPACK_SOURCE_IGNORE_FILES ".git*;/GitSetup/;/.git/;.swp$;.#;/#;.*~") + set(CPACK_SOURCE_STRIP_FILES "") + include(CPack) +endif() diff --git a/src/mchecksum/COPYING b/src/mchecksum/COPYING new file mode 100644 index 00000000..e035e496 --- /dev/null +++ b/src/mchecksum/COPYING @@ -0,0 +1,39 @@ +Copyright (C) 2013-2019, Argonne National Laboratory, Department of Energy, + UChicago Argonne, LLC and The HDF Group. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted for any purpose (including commercial purposes) +provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or materials provided with the distribution. + +3. In addition, redistributions of modified forms of the source or binary + code must carry prominent notices stating that the original code was + changed and the date of the change. + +4. All publications or advertising materials mentioning features or use of + this software are asked, but not required, to acknowledge that it was + developed by ANL / the university of Chicago / The HDF Group and credit + the contributors. + +5. Neither the name of ANL / the university of Chicago / The HDF Group, nor + the name of any Contributor may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/src/mchecksum/README.md b/src/mchecksum/README.md new file mode 100644 index 00000000..e52c3dfd --- /dev/null +++ b/src/mchecksum/README.md @@ -0,0 +1,102 @@ +What is mchecksum? +================== + +MChecksum is a generic checksum library. + +Please see the accompanying COPYING file for license details. + +Supported platforms +=================== + +Linux / MacOS / Windows + +Documentation +============= + +Please see the documentation available on the mercury [website][documentation] +for a quick introduction to mchecksum. + +Software requirements +===================== + +CRC32 and Adler32 checksums require ZLIB to be installed on your system. +CRC32C can be used with or without HW acceleration -- SSE4.2 acceleration +requires the SSE4.2 instruction set to be supported by your CPU, improved +performance can be achieved using the Intel(R) [ISA-L][isal] library but +requires the PCLMULQDQ instruction to be supported by your CPU as well as +this library to be installed on your system. + +Building +======== + +If you install the full sources, put the tarball in a directory where you +have permissions (e.g., your home directory) and unpack it: + + gzip -cd mchecksum-X.tar.gz | tar xvf - + + or + + bzip2 -dc mchecksum-X.tar.bz2 | tar xvf - + +Replace "X" with the version number of the package. + +MChecksum makes use of the CMake build-system and requires that you do an +out-of-source build. In order to do that, you must create a new build +directory and run the 'ccmake' command from it: + + cd mchecksum-X + mkdir build + cd build + ccmake .. (where ".." is the relative path to the mchecksum-X directory) + +Type 'c' multiple times and choose suitable options. Recommended options are: + + BUILD_SHARED_LIBS ON (or OFF if the library you link + against requires static libraries) + BUILD_TESTING ON + CMAKE_INSTALL_PREFIX /path/to/install/directory + MCHECKSUM_USE_ISAL OFF (Optional) + MCHECKSUM_USE_SSE4_2 ON + MCHECKSUM_USE_ZLIB OFF (Optional) + +Setting include directory and library paths may require you to toggle to +the advanced mode by typing 't'. Once you are done and do not see any +errors, type 'g' to generate makefiles. Once you exit the CMake +configuration screen and are ready to build the targets, do: + + make + +(Optional) Verbose compile/build output: + +This is done by inserting "VERBOSE=1" in the "make" command. E.g.: + + make VERBOSE=1 + +Installing +========== + +Assuming that the CMAKE_INSTALL_PREFIX has been set (see previous step) +and that you have write permissions to the destination directory, do +from the build directory: + + make install + +Testing +======= + +CTest is used to run the tests, simply run from the build directory: + + ctest . + +(Optional) Verbose testing: + +This is done by inserting "-V" in the "ctest" command. E.g.: + + ctest -V . + +Extra verbose information can be displayed by inserting "-VV". E.g.: + + ctest -VV . + +[documentation]: http://mercury-hpc.github.io/documentation/2018/10/24/mchecksum.html +[isal]: https://github.com/01org/isa-l diff --git a/src/mchecksum/Testing/CMakeLists.txt b/src/mchecksum/Testing/CMakeLists.txt new file mode 100644 index 00000000..468d2824 --- /dev/null +++ b/src/mchecksum/Testing/CMakeLists.txt @@ -0,0 +1,30 @@ +#------------------------------------------------------------------------------ +# Set up test options +#------------------------------------------------------------------------------ + +# mchecksum_prefix is added to executable +function(add_mchecksum_test test_name) + add_executable(mchecksum_test_${test_name} test_${test_name}.c) + target_link_libraries(mchecksum_test_${test_name} mchecksum) + if(MCHECKSUM_ENABLE_COVERAGE) + set_coverage_flags(mchecksum_test_${test_name}) + endif() + foreach(hash_type ${MCHECKSUM_HASH_TYPES}) + add_test(NAME mchecksum_test_${test_name}_${hash_type} + COMMAND $ "${hash_type}") + endforeach() +endfunction() + +#------------------------------------------------------------------------------ +# Dependencies +#------------------------------------------------------------------------------ +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} +) + +#------------------------------------------------------------------------------ +# Set up tests +#------------------------------------------------------------------------------ +add_mchecksum_test(simple) +add_mchecksum_test(perf) \ No newline at end of file diff --git a/src/mchecksum/Testing/test_perf.c b/src/mchecksum/Testing/test_perf.c new file mode 100644 index 00000000..66c85ad9 --- /dev/null +++ b/src/mchecksum/Testing/test_perf.c @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2013-2019 Argonne National Laboratory, Department of Energy, + * UChicago Argonne, LLC and The HDF Group. + * All rights reserved. + * + * The full copyright notice, including terms governing use, modification, + * and redistribution, is contained in the COPYING file that can be + * found at the root of the source code distribution tree. + */ + +#include "mchecksum.h" +#include "mchecksum_error.h" + +#include +#include +#include +#include + +/* Maximum size of buffer used */ +#define MAX_BUF_SIZE (1<<24) + +/* Width of field used to report numbers */ +#define FIELD_WIDTH 20 + +/* Precision of reported numbers */ +#define FLOAT_PRECISION 2 + +#define BENCHMARK "MChecksum Perf Test" + +#define MAX_LOOP 20 + +/* #define USE_MEMSET */ + +typedef struct my_time +{ + long tv_sec; + long tv_usec; +} my_time_t; + +/*---------------------------------------------------------------------------*/ +static int +my_time_get_current(my_time_t *tv) +{ + int ret = 0; + struct timespec tp; + + if (!tv) { + ret = -1; + return ret; + } + + if (clock_gettime(CLOCK_MONOTONIC, &tp)) { + ret = -1; + return ret; + } + tv->tv_sec = tp.tv_sec; + tv->tv_usec = tp.tv_nsec / 1000; + + return ret; +} + +/*---------------------------------------------------------------------------*/ +static double +my_time_to_double(my_time_t tv) +{ + return (double) tv.tv_sec + (double) (tv.tv_usec) * 0.000001; +} + +/*---------------------------------------------------------------------------*/ +static my_time_t +my_time_add(my_time_t in1, my_time_t in2) +{ + my_time_t out; + + out.tv_sec = in1.tv_sec + in2.tv_sec; + out.tv_usec = in1.tv_usec + in2.tv_usec; + if(out.tv_usec > 1000000) { + out.tv_usec -= 1000000; + out.tv_sec += 1; + } + + return out; +} + +/*---------------------------------------------------------------------------*/ +static my_time_t +my_time_subtract(my_time_t in1, my_time_t in2) +{ + my_time_t out; + + out.tv_sec = in1.tv_sec - in2.tv_sec; + out.tv_usec = in1.tv_usec - in2.tv_usec; + if(out.tv_usec < 0) { + out.tv_usec += 1000000; + out.tv_sec -= 1; + } + + return out; +} + +/*---------------------------------------------------------------------------*/ +int +main(int argc, char *argv[]) +{ + mchecksum_object_t checksum; + char *buf = NULL, *hash = NULL; + size_t hash_size; + const char *hash_method; + unsigned int size; + int ret = EXIT_SUCCESS; + int i; + + if (argc < 2) { + fprintf(stderr, "Usage:\n%s [method]\n", argv[0]); + ret = EXIT_FAILURE; + goto done; + } + + hash_method = argv[1]; + + /* Initialize buf */ + buf = malloc(MAX_BUF_SIZE); + if (!buf) { + fprintf(stderr, "Could not allocate buffer\n"); + ret = EXIT_FAILURE; + goto done; + } + for (i = 0; i < MAX_BUF_SIZE; i++) { + buf[i] = (char) i; + } + + fprintf(stdout, "# %s\n", BENCHMARK); + fprintf(stdout, "%-*s%*s%*s\n", 10, "# Size", FIELD_WIDTH, + "Bandwidth (MB/s)", FIELD_WIDTH, "Average Time (ms)"); + fflush(stdout); + + if (mchecksum_init(hash_method, &checksum) != MCHECKSUM_SUCCESS) + { + fprintf (stderr, "Error in mchecksum_init!\n"); + ret = EXIT_FAILURE; + goto done; + } + + hash_size = mchecksum_get_size(checksum); + hash = malloc(hash_size); + if (!hash) { + fprintf(stderr, "Could not allocate hash\n"); + ret = EXIT_FAILURE; + goto done; + } + + /* Initialize the buffers */ + for (size = 1; size <= MAX_BUF_SIZE; size *= 2) { + my_time_t t = {0, 0}; + + for (i = 0; i < MAX_LOOP; i++) { + my_time_t t_start = {0, 0}, t_end = {0, 0}; + + mchecksum_reset(checksum); + + my_time_get_current(&t_start); +#ifdef USE_MEMSET + memset(buf, 'B', size); +#else + mchecksum_update(checksum, buf, size); +#endif + my_time_get_current(&t_end); + + /* t = t + (t_end - t_start) */ + t = my_time_add(t, my_time_subtract(t_end, t_start)); + } + + fprintf(stdout, "%-*d%*.*f%*.*f\n", 10, size, FIELD_WIDTH, + FLOAT_PRECISION, (size * MAX_LOOP) / (my_time_to_double(t) * 1e6), + FIELD_WIDTH, FLOAT_PRECISION, my_time_to_double(t) * 1e3 / MAX_LOOP); + fflush(stdout); + mchecksum_get(checksum, hash, hash_size, MCHECKSUM_FINALIZE); + } + + mchecksum_destroy(checksum); + +done: + free(hash); + free(buf); + + return ret; +} diff --git a/src/mchecksum/Testing/test_simple.c b/src/mchecksum/Testing/test_simple.c new file mode 100644 index 00000000..46251060 --- /dev/null +++ b/src/mchecksum/Testing/test_simple.c @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2013-2019 Argonne National Laboratory, Department of Energy, + * UChicago Argonne, LLC and The HDF Group. + * All rights reserved. + * + * The full copyright notice, including terms governing use, modification, + * and redistribution, is contained in the COPYING file that can be + * found at the root of the source code distribution tree. + */ + +#include "mchecksum.h" + +#include +#include +#include + +#define BUF_SIZE 512 +#define BUF_SIZE_X 32 +#define BUF_SIZE_Y 16 + +int +main(int argc, char *argv[]) +{ + int buf1[BUF_SIZE]; + int buf2[BUF_SIZE_X][BUF_SIZE_Y]; + int i, j; + mchecksum_object_t checksum1, checksum2; + void *hash1 = NULL, *hash2 = NULL; + size_t hash_size; + const char *hash_method; + int ret = EXIT_SUCCESS; + + if (argc < 2) { + fprintf(stderr, "Usage:\n%s [method]\n", argv[0]); + ret = EXIT_FAILURE; + return ret; + } + + if (strcmp(argv[1], "crc16") + && strcmp(argv[1], "crc64") + && strcmp(argv[1], "crc32") + && strcmp(argv[1], "adler32") + && strcmp(argv[1], "crc32c")) { + fprintf(stderr, "%s is not a valid parameter\n", argv[1]); + ret = EXIT_FAILURE; + return ret; + } + + hash_method = argv[1]; + + /* Initialize buf1 */ + for (i = 0; i < BUF_SIZE; i++) { + buf1[i] = i; + } + + /* Initialize buf2 */ + for (i = 0; i < BUF_SIZE_X; i++) { + for (j = 0; j < BUF_SIZE_Y; j++) { + buf2[i][j] = i * BUF_SIZE_Y + j; + } + } + + /* Initialize checksums */ + mchecksum_init(hash_method, &checksum1); + mchecksum_init(hash_method, &checksum2); + + /* Update checksums */ + mchecksum_update(checksum1, buf1, BUF_SIZE * sizeof(int)); + + for (i = 0; i < BUF_SIZE_X; i++) { + mchecksum_update(checksum2, buf2[i], BUF_SIZE_Y * sizeof(int)); + } + + /* Get size of checksums */ + hash_size = mchecksum_get_size(checksum1); + + hash1 = malloc(hash_size); + hash2 = malloc(hash_size); + + mchecksum_get(checksum1, hash1, hash_size, MCHECKSUM_FINALIZE); + mchecksum_get(checksum2, hash2, hash_size, MCHECKSUM_FINALIZE); + + /* + printf("Checksum of buf1 is: %016lX\n", + *(mchecksum_uint64_t*)hash1); + + printf("Checksum of buf2 is: %016lX\n", + *(mchecksum_uint64_t*)hash2); + + printf("Checksum of buf1 is: %04X\n", + *(mchecksum_uint16_t*)hash1); + + printf("Checksum of buf2 is: %04X\n", + *(mchecksum_uint16_t*)hash2); + */ + + if (strncmp(hash1, hash2, hash_size) != 0) { + fprintf(stderr, "Checksums do not match\n"); + ret = EXIT_FAILURE; + } + + /* Corrupting buf2 and recomputing checksum */ + buf2[0][0] = 1; + + mchecksum_reset(checksum2); + for (i = 0; i < BUF_SIZE_X; i++) { + mchecksum_update(checksum2, buf2[i], BUF_SIZE_Y * sizeof(int)); + } + mchecksum_get(checksum2, hash2, hash_size, MCHECKSUM_FINALIZE); + + if (strncmp(hash1, hash2, hash_size) == 0) { + fprintf(stderr, "Checksums should not match\n"); + ret = EXIT_FAILURE; + } + + /* Destroy checksums and free hash buffers */ + mchecksum_destroy(checksum1); + mchecksum_destroy(checksum2); + free(hash1); + free(hash2); + + return ret; +} diff --git a/src/mchecksum/src/CMakeLists.txt b/src/mchecksum/src/CMakeLists.txt new file mode 100644 index 00000000..543a2b2c --- /dev/null +++ b/src/mchecksum/src/CMakeLists.txt @@ -0,0 +1,258 @@ +#------------------------------------------------------------------------------ +# Include source and build directories +#------------------------------------------------------------------------------ +set(MCHECKSUM_BUILD_INCLUDE_DEPENDENCIES + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} +) + +#------------------------------------------------------------------------------ +# External dependencies +#------------------------------------------------------------------------------ +# ZLIB +option(MCHECKSUM_USE_ZLIB "Use ZLIB checksum." OFF) +if(MCHECKSUM_USE_ZLIB) + find_package(ZLIB REQUIRED) + if(ZLIB_FOUND) + message(STATUS "ZLIB include directory: ${ZLIB_INCLUDE_DIRS}") + set(MCHECKSUM_HAS_ZLIB 1) + set(MCHECKSUM_INT_INCLUDE_DEPENDENCIES + ${MCHECKSUM_INT_INCLUDE_DEPENDENCIES} + ${ZLIB_INCLUDE_DIRS} + ) + set(MCHECKSUM_EXT_LIB_DEPENDENCIES + ${MCHECKSUM_EXT_LIB_DEPENDENCIES} + ${ZLIB_LIBRARIES} + ) + else() + message(FATAL_ERROR "Could not find ZLIB, please check ZLIB_INCLUDE_DIRS.") + endif() +endif() + +# SSE 4.2 +if(WIN32) + set(MCHECKSUM_SSE4_2_OPTIONS /arch:SSE4.2) +else() + set(MCHECKSUM_SSE4_2_OPTIONS -msse4.2) +endif() +try_compile(MCHECKSUM_CAN_COMPILE_SSE4_2 + ${CMAKE_BINARY_DIR} ${MCHECKSUM_CMAKE_MODULE_PATH}/CheckSSE42.c + COMPILE_DEFINITIONS ${MCHECKSUM_SSE4_2_OPTIONS} + OUTPUT_VARIABLE CHECK_SSE4_2_OUTPUT) +option(MCHECKSUM_USE_SSE4_2 "Use SSE 4.2 instruction set." ${MCHECKSUM_CAN_COMPILE_SSE4_2}) +if(MCHECKSUM_USE_SSE4_2) + message(STATUS "Using SSE 4.2 instruction set.") + if(NOT ${MCHECKSUM_CAN_COMPILE_SSE4_2}) + message(FATAL_ERROR "This platform is not capable of compiling with SSE 4.2 instructions.") + endif() + add_compile_options(${MCHECKSUM_SSE4_2_OPTIONS}) + set(MCHECKSUM_HAS_SSE4_2 1) +endif(MCHECKSUM_USE_SSE4_2) + +# ISA-L +option(MCHECKSUM_USE_ISAL "Use Intel(R) ISA-L library." OFF) +if(MCHECKSUM_USE_ISAL) + find_package(ISAL REQUIRED) + if(ISAL_FOUND) + message(STATUS "ISA-L include directory: ${ISAL_INCLUDE_DIRS}") + set(MCHECKSUM_HAS_ISAL 1) + set(MCHECKSUM_INT_INCLUDE_DEPENDENCIES + ${MCHECKSUM_INT_INCLUDE_DEPENDENCIES} + ${ISAL_INCLUDE_DIRS} + ) + set(MCHECKSUM_EXT_LIB_DEPENDENCIES + ${MCHECKSUM_EXT_LIB_DEPENDENCIES} + ${ISAL_LIBRARIES} + ) + else() + message(FATAL_ERROR "Could not find ISAL, please check ISAL_INCLUDE_DIRS.") + endif() +endif() + +#------------------------------------------------------------------------------ +# Configure module header files +#------------------------------------------------------------------------------ +# Set unique var used in the autogenerated config file (symbol import/export) +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/mchecksum_config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/mchecksum_config.h +) + +#------------------------------------------------------------------------------ +# Set sources +#------------------------------------------------------------------------------ +set(MCHECKSUM_SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/mchecksum.c + ${CMAKE_CURRENT_SOURCE_DIR}/mchecksum_crc16.c + ${CMAKE_CURRENT_SOURCE_DIR}/mchecksum_crc32c.c + ${CMAKE_CURRENT_SOURCE_DIR}/mchecksum_crc64.c +) + +if(MCHECKSUM_HAS_ZLIB) + set(MCHECKSUM_SRCS + ${MCHECKSUM_SRCS} + ${CMAKE_CURRENT_SOURCE_DIR}/mchecksum_zlib.c + ) +endif() + +set(MCHECKSUM_HASH_TYPES crc16 crc32c crc64) +if(MCHECKSUM_HAS_ZLIB) + set(MCHECKSUM_HASH_TYPES ${MCHECKSUM_HASH_TYPES} crc32 adler32) +endif() + +#---------------------------------------------------------------------------- +# Libraries +#---------------------------------------------------------------------------- + +# Clean up system include path first +foreach(item ${MCHECKSUM_SYSTEM_INCLUDE_PATH}) + if(MCHECKSUM_INT_INCLUDE_DEPENDENCIES) + list(REMOVE_ITEM MCHECKSUM_INT_INCLUDE_DEPENDENCIES ${item}) + endif() +endforeach() + +# mchecksum +add_library(mchecksum ${MCHECKSUM_SRCS}) +target_include_directories(mchecksum + PUBLIC "$" + $ +) +target_include_directories(mchecksum + SYSTEM PRIVATE ${MCHECKSUM_INT_INCLUDE_DEPENDENCIES} +) +target_link_libraries(mchecksum + ${MCHECKSUM_EXT_LIB_DEPENDENCIES} +) +mchecksum_set_lib_options(mchecksum "mchecksum" ${MCHECKSUM_LIBTYPE}) +if(MCHECKSUM_ENABLE_COVERAGE) + set_coverage_flags(mchecksum) +endif() + +set(MCHECKSUM_EXPORTED_LIBS mchecksum ${MCHECKSUM_EXPORTED_LIBS}) + +#----------------------------------------------------------------------------- +# Specify project header files to be installed +#----------------------------------------------------------------------------- +set(MCHECKSUM_HEADERS + ${CMAKE_CURRENT_SOURCE_DIR}/mchecksum.h + ${CMAKE_CURRENT_SOURCE_DIR}/mchecksum_error.h + ${CMAKE_CURRENT_BINARY_DIR}/mchecksum_config.h +) + +#----------------------------------------------------------------------------- +# Add file(s) to CMake Install +#----------------------------------------------------------------------------- +install( + FILES + ${MCHECKSUM_HEADERS} + DESTINATION + ${MCHECKSUM_INSTALL_INCLUDE_DIR} + COMPONENT + headers +) + +#--------------------------------------------------------------------------- +# Add Target(s) to CMake Install +#--------------------------------------------------------------------------- +install( + TARGETS + mchecksum + EXPORT + ${MCHECKSUM_EXPORTED_TARGETS} + LIBRARY DESTINATION ${MCHECKSUM_INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${MCHECKSUM_INSTALL_LIB_DIR} + RUNTIME DESTINATION ${MCHECKSUM_INSTALL_BIN_DIR} +) + +# This may not be the conventional way of doing things but we need a dirty hack +# to have targets exported into multiple locations +if(MCHECKSUM_EXTERNALLY_CONFIGURED AND MCHECKSUM_EXTERNAL_EXPORTED_TARGETS) +install( + TARGETS + mchecksum + EXPORT + ${MCHECKSUM_EXTERNAL_EXPORTED_TARGETS} + LIBRARY DESTINATION ${MCHECKSUM_INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${MCHECKSUM_INSTALL_LIB_DIR} + RUNTIME DESTINATION ${MCHECKSUM_INSTALL_BIN_DIR} +) +endif() + +#----------------------------------------------------------------------------- +# Add Target(s) to CMake Install for import into other projects +#----------------------------------------------------------------------------- +install( + EXPORT + ${MCHECKSUM_EXPORTED_TARGETS} + DESTINATION + ${MCHECKSUM_INSTALL_DATA_DIR}/cmake/${MCHECKSUM_PACKAGE} + FILE + ${MCHECKSUM_EXPORTED_TARGETS}.cmake +) + +#----------------------------------------------------------------------------- +# Export all exported targets to the build tree for use by parent project +#----------------------------------------------------------------------------- +if(NOT MCHECKSUM_EXTERNALLY_CONFIGURED) +export( + TARGETS + ${MCHECKSUM_EXPORTED_LIBS} + FILE + ${MCHECKSUM_EXPORTED_TARGETS}.cmake +) +endif() + +#------------------------------------------------------------------------------ +# Set variables for parent scope +#------------------------------------------------------------------------------ +set(MCHECKSUM_HASH_TYPES ${MCHECKSUM_HASH_TYPES} PARENT_SCOPE) + +# Pkg-config configuration +if(NOT WIN32) + if(CMAKE_BUILD_TYPE) + string(TOLOWER ${CMAKE_BUILD_TYPE} lower_cmake_build_type) + endif() + + # Mchecksum private library dependencies + foreach(exported_lib ${MCHECKSUM_EXPORTED_LIBS}) + if(lower_cmake_build_type MATCHES "debug") + get_target_property(MCHECKSUM_LIBRARY ${exported_lib} OUTPUT_DEBUG_NAME) + else() + get_target_property(MCHECKSUM_LIBRARY ${exported_lib} OUTPUT_RELEASE_NAME) + endif() + set(MCHECKSUM_LIBRARIES "${MCHECKSUM_LIBRARIES} -l${MCHECKSUM_LIBRARY}") + endforeach() + set(MCHECKSUM_LIBRARIES ${MCHECKSUM_LIBRARIES} PARENT_SCOPE) + + # Mchecksum external library dependencies + # Need to generate -llib if not already passed + foreach(lib_dep ${MCHECKSUM_EXT_LIB_DEPENDENCIES}) + # get library name + get_filename_component(lib_name ${lib_dep} NAME_WE) + if(lib_name MATCHES "^-l") + # lib_name found is -lxxx + set(MCHECKSUM_EXT_LIB_DEPENDENCIES_LIST ${MCHECKSUM_EXT_LIB_DEPENDENCIES_LIST} ${lib_name}) + else() + # lib_name is /path/to/lib so get library path and name + get_filename_component(lib_path ${lib_dep} PATH) + string(REGEX REPLACE "^lib" "" lib_name ${lib_name}) + set(MCHECKSUM_EXT_LIB_DEPENDENCIES_LIST ${MCHECKSUM_EXT_LIB_DEPENDENCIES_LIST} -L${lib_path} -l${lib_name}) + endif() + endforeach() + if(MCHECKSUM_EXT_LIB_DEPENDENCIES_LIST) + list(REMOVE_DUPLICATES MCHECKSUM_EXT_LIB_DEPENDENCIES_LIST) + endif() + foreach(lib_dep ${MCHECKSUM_EXT_LIB_DEPENDENCIES_LIST}) + set(MCHECKSUM_LIB_DEPENDENCIES "${MCHECKSUM_LIB_DEPENDENCIES} ${lib_dep}") + endforeach() + set(MCHECKSUM_LIB_DEPENDENCIES ${MCHECKSUM_LIB_DEPENDENCIES} PARENT_SCOPE) + + # External include dependencies + if(MCHECKSUM_EXT_INCLUDE_DEPENDENCIES) + list(REMOVE_DUPLICATES MCHECKSUM_EXT_INCLUDE_DEPENDENCIES) + endif() + foreach(inc_dep ${MCHECKSUM_EXT_INCLUDE_DEPENDENCIES}) + set(MCHECKSUM_INCLUDE_DEPENDENCIES "${MCHECKSUM_INCLUDE_DEPENDENCIES} -I${inc_dep}") + endforeach() + set(MCHECKSUM_INCLUDE_DEPENDENCIES ${MCHECKSUM_INCLUDE_DEPENDENCIES} PARENT_SCOPE) +endif() diff --git a/src/mchecksum/src/mchecksum.c b/src/mchecksum/src/mchecksum.c new file mode 100644 index 00000000..834ec99f --- /dev/null +++ b/src/mchecksum/src/mchecksum.c @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2013-2019 Argonne National Laboratory, Department of Energy, + * UChicago Argonne, LLC and The HDF Group. + * All rights reserved. + * + * The full copyright notice, including terms governing use, modification, + * and redistribution, is contained in the COPYING file that can be + * found at the root of the source code distribution tree. + */ + +#include "mchecksum_crc64.h" +#include "mchecksum_crc16.h" +#include "mchecksum_crc32c.h" +#ifdef MCHECKSUM_HAS_ZLIB +#include "mchecksum_zlib.h" +#endif + +#include "mchecksum_error.h" + +#include +#include + +/*---------------------------------------------------------------------------*/ +int +mchecksum_init(const char *hash_method, mchecksum_object_t *checksum) +{ + struct mchecksum_class *checksum_class = NULL; + int ret = MCHECKSUM_SUCCESS; + + checksum_class = (struct mchecksum_class *) malloc(sizeof(struct mchecksum_class)); + if (!checksum_class) { + MCHECKSUM_ERROR_DEFAULT("Could not allocate checksum class"); + ret = MCHECKSUM_FAIL; + goto done; + } + + if (strcmp(hash_method, "crc64") == 0) { + if (mchecksum_crc64_init(checksum_class) != MCHECKSUM_SUCCESS) { + MCHECKSUM_ERROR_DEFAULT("Could not initialize crc64 checksum"); + ret = MCHECKSUM_FAIL; + goto done; + } + } else if (strcmp(hash_method, "crc16") == 0) { + if (mchecksum_crc16_init(checksum_class) != MCHECKSUM_SUCCESS) { + MCHECKSUM_ERROR_DEFAULT("Could not initialize crc16 checksum"); + ret = MCHECKSUM_FAIL; + goto done; + } + } else if (strcmp(hash_method, "crc32c") == 0) { + if (mchecksum_crc32c_init(checksum_class) != MCHECKSUM_SUCCESS) { + MCHECKSUM_ERROR_DEFAULT("Could not initialize crc32c checksum"); + ret = MCHECKSUM_FAIL; + goto done; + } +#ifdef MCHECKSUM_HAS_ZLIB + } else if (strcmp(hash_method, "crc32") == 0) { + if (mchecksum_crc32_init(checksum_class) != MCHECKSUM_SUCCESS) { + MCHECKSUM_ERROR_DEFAULT("Could not initialize crc32 checksum"); + ret = MCHECKSUM_FAIL; + goto done; + } + } else if (strcmp(hash_method, "adler32") == 0) { + if (mchecksum_adler32_init(checksum_class) != MCHECKSUM_SUCCESS) { + MCHECKSUM_ERROR_DEFAULT("Could not initialize adler32 checksum"); + ret = MCHECKSUM_FAIL; + goto done; + } +#endif + } else { + MCHECKSUM_ERROR_DEFAULT("Unknown hash method"); + ret = MCHECKSUM_FAIL; + goto done; + } + + *checksum = (mchecksum_object_t) checksum_class; + +done: + if (ret != MCHECKSUM_SUCCESS) { + free(checksum_class); + } + + return ret; +} + +/*---------------------------------------------------------------------------*/ +int +mchecksum_destroy(mchecksum_object_t checksum) +{ + struct mchecksum_class *checksum_class = (struct mchecksum_class *) checksum; + int ret = MCHECKSUM_SUCCESS; + + if (!checksum_class) { + MCHECKSUM_ERROR_DEFAULT("Checksum not initialized"); + ret = MCHECKSUM_FAIL; + goto done; + } + + if (checksum_class->destroy(checksum_class) != MCHECKSUM_SUCCESS) { + MCHECKSUM_ERROR_DEFAULT("Could not destroy checksum"); + ret = MCHECKSUM_FAIL; + goto done; + } + + free(checksum_class); + +done: + return ret; +} + +/*---------------------------------------------------------------------------*/ +int +mchecksum_reset(mchecksum_object_t checksum) +{ + struct mchecksum_class *checksum_class = (struct mchecksum_class *) checksum; + + if (!checksum_class) { + MCHECKSUM_ERROR_DEFAULT("Checksum not initialized"); + return MCHECKSUM_FAIL; + } + + return checksum_class->reset(checksum_class); +} + +/*---------------------------------------------------------------------------*/ +size_t +mchecksum_get_size(mchecksum_object_t checksum) +{ + struct mchecksum_class *checksum_class = (struct mchecksum_class *) checksum; + + if (!checksum_class) { + MCHECKSUM_ERROR_DEFAULT("Checksum not initialized"); + return 0; + } + + return checksum_class->get_size(checksum_class); +} + +/*---------------------------------------------------------------------------*/ +int +mchecksum_get(mchecksum_object_t checksum, void *buf, size_t size, int finalize) +{ + struct mchecksum_class *checksum_class = (struct mchecksum_class *) checksum; + + if (!checksum_class) { + MCHECKSUM_ERROR_DEFAULT("Checksum not initialized"); + return MCHECKSUM_FAIL; + } + + return checksum_class->get(checksum_class, buf, size, finalize); +} + +/*---------------------------------------------------------------------------*/ +int +mchecksum_update(mchecksum_object_t checksum, const void *data, size_t size) +{ + struct mchecksum_class *checksum_class = (struct mchecksum_class *) checksum; + + if (!checksum_class) { + MCHECKSUM_ERROR_DEFAULT("Checksum not initialized"); + return MCHECKSUM_FAIL; + } + + return checksum_class->update(checksum_class, data, size); +} diff --git a/src/mchecksum/src/mchecksum.h b/src/mchecksum/src/mchecksum.h new file mode 100644 index 00000000..e3a2d6f7 --- /dev/null +++ b/src/mchecksum/src/mchecksum.h @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2013-2019 Argonne National Laboratory, Department of Energy, + * UChicago Argonne, LLC and The HDF Group. + * All rights reserved. + * + * The full copyright notice, including terms governing use, modification, + * and redistribution, is contained in the COPYING file that can be + * found at the root of the source code distribution tree. + */ + +#ifndef MCHECKSUM_H +#define MCHECKSUM_H + +#include "mchecksum_config.h" + +/*************************************/ +/* Public Type and Struct Definition */ +/*************************************/ + +typedef void *mchecksum_object_t; + +/*****************/ +/* Public Macros */ +/*****************/ + +#define MCHECKSUM_OBJECT_NULL ((mchecksum_object_t)0) + +#define MCHECKSUM_NOFINALIZE 0 +#define MCHECKSUM_FINALIZE 1 + +/*********************/ +/* Public Prototypes */ +/*********************/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Initialize the checksum with the specified hash method. + * + * \param hash_method [IN] hash method string + * Available methods are: "crc16", "crc64" + * \param checksum [OUT] pointer to abstract checksum + * + * \return Non-negative on success or negative on failure + */ +MCHECKSUM_EXPORT int +mchecksum_init(const char *hash_method, mchecksum_object_t *checksum); + +/** + * Destroy the checksum. + * + * \param checksum [IN/OUT] abstract checksum + * + * \return Non-negative on success or negative on failure + */ +MCHECKSUM_EXPORT int +mchecksum_destroy(mchecksum_object_t checksum); + +/** + * Reset the checksum. + * + * \param checksum [IN/OUT] abstract checksum + * + * \return Non-negative on success or negative on failure + */ +MCHECKSUM_EXPORT int +mchecksum_reset(mchecksum_object_t checksum); + +/** + * Get size of checksum. + * + * \param checksum [IN] abstract checksum + * + * \return Non-negative value + */ +MCHECKSUM_EXPORT size_t +mchecksum_get_size(mchecksum_object_t checksum); + +/** + * Get checksum and copy it into buf. + * + * \param checksum [IN/OUT] abstract checksum + * \param buf [IN] pointer to buffer + * \param size [IN] size of buffer + * \param finalize [IN] one of: + * MCHECKSUM_FINALIZE no more data will be added to this checksum + * (only valid call to follow is reset or + * destroy) + * MCHECKSUM_NOFINALIZE More data might be added to this checksum + * later + * + * \return Non-negative on success or negative on failure + */ +MCHECKSUM_EXPORT int +mchecksum_get(mchecksum_object_t checksum, void *buf, size_t size, int finalize); + +/** + * Accumulates a partial checksum of the input data. + * + * \param checksum [IN/OUT] abstract checksum + * \param data [IN] pointer to buffer + * \param size [IN] size of buffer + * + * \return Non-negative on success or negative on failure + */ +MCHECKSUM_EXPORT int +mchecksum_update(mchecksum_object_t checksum, const void *data, size_t size); + +#ifdef __cplusplus +} +#endif + +#endif /* MCHECKSUM_H */ diff --git a/src/mchecksum/src/mchecksum_config.h.in b/src/mchecksum/src/mchecksum_config.h.in new file mode 100644 index 00000000..e44fec6d --- /dev/null +++ b/src/mchecksum/src/mchecksum_config.h.in @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2013-2019 Argonne National Laboratory, Department of Energy, + * UChicago Argonne, LLC and The HDF Group. + * All rights reserved. + * + * The full copyright notice, including terms governing use, modification, + * and redistribution, is contained in the COPYING file that can be + * found at the root of the source code distribution tree. + */ + +/* Generated file. Only edit mchecksum_config.h.in. */ + +#ifndef MCHECKSUM_CONFIG_H +#define MCHECKSUM_CONFIG_H + +/*************************************/ +/* Public Type and Struct Definition */ +/*************************************/ + +#ifdef _WIN32 + typedef signed __int64 mchecksum_int64_t; + typedef signed __int32 mchecksum_int32_t; + typedef signed __int16 mchecksum_int16_t; + typedef signed __int8 mchecksum_int8_t; + typedef unsigned __int64 mchecksum_uint64_t; + typedef unsigned __int32 mchecksum_uint32_t; + typedef unsigned __int16 mchecksum_uint16_t; + typedef unsigned __int8 mchecksum_uint8_t; +#else +# include +# include + typedef int64_t mchecksum_int64_t; + typedef int32_t mchecksum_int32_t; + typedef int16_t mchecksum_int16_t; + typedef int8_t mchecksum_int8_t; + typedef uint64_t mchecksum_uint64_t; + typedef uint32_t mchecksum_uint32_t; + typedef uint16_t mchecksum_uint16_t; + typedef uint8_t mchecksum_uint8_t; +#endif + +/* True / false */ +#define MCHECKSUM_TRUE 1 +#define MCHECKSUM_FALSE 0 + +/*****************/ +/* Public Macros */ +/*****************/ + +/* Reflects major releases of MChecksum */ +#define MCHECKSUM_VERSION_MAJOR @MCHECKSUM_VERSION_MAJOR@ +/* Reflects any API changes */ +#define MCHECKSUM_VERSION_MINOR @MCHECKSUM_VERSION_MINOR@ +/* Reflects any library code changes */ +#define MCHECKSUM_VERSION_PATCH @MCHECKSUM_VERSION_PATCH@ + +/* Visibility of symbols */ +#if defined(_WIN32) +# define MCHECKSUM_ABI_IMPORT __declspec(dllimport) +# define MCHECKSUM_ABI_EXPORT __declspec(dllexport) +# define MCHECKSUM_ABI_HIDDEN +#elif defined(__GNUC__) && (__GNUC__ >= 4) +# define MCHECKSUM_ABI_IMPORT __attribute__((visibility("default"))) +# define MCHECKSUM_ABI_EXPORT __attribute__((visibility("default"))) +# define MCHECKSUM_ABI_HIDDEN __attribute__((visibility("hidden"))) +#else +# define MCHECKSUM_ABI_IMPORT +# define MCHECKSUM_ABI_EXPORT +# define MCHECKSUM_ABI_HIDDEN +#endif + +/* Inline macro */ +#ifdef _WIN32 +# define MCHECKSUM_INLINE __inline +#else +# define MCHECKSUM_INLINE __inline__ +#endif + +/* Shared libraries */ +#cmakedefine MCHECKSUM_BUILD_SHARED_LIBS +#ifdef MCHECKSUM_BUILD_SHARED_LIBS +# ifdef mchecksum_EXPORTS +# define MCHECKSUM_EXPORT MCHECKSUM_ABI_EXPORT +# else +# define MCHECKSUM_EXPORT MCHECKSUM_ABI_IMPORT +# endif +#else +# define MCHECKSUM_EXPORT +#endif + +/* Build Options */ +#cmakedefine MCHECKSUM_HAS_ISAL +#cmakedefine MCHECKSUM_HAS_SSE4_2 +#cmakedefine MCHECKSUM_HAS_ZLIB + +#cmakedefine MCHECKSUM_HAS_VERBOSE_ERROR + +#endif /* MCHECKSUM_CONFIG_H */ diff --git a/src/mchecksum/src/mchecksum_crc16.c b/src/mchecksum/src/mchecksum_crc16.c new file mode 100644 index 00000000..92aa8fa0 --- /dev/null +++ b/src/mchecksum/src/mchecksum_crc16.c @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2013-2019 Argonne National Laboratory, Department of Energy, + * UChicago Argonne, LLC and The HDF Group. + * All rights reserved. + * + * The full copyright notice, including terms governing use, modification, + * and redistribution, is contained in the COPYING file that can be + * found at the root of the source code distribution tree. + */ + +#include "mchecksum_crc16.h" +#include "mchecksum_error.h" + +#include +#ifdef MCHECKSUM_HAS_ISAL +# include +#endif + +/****************/ +/* Local Macros */ +/****************/ + +/************************************/ +/* Local Type and Struct Definition */ +/************************************/ + +/********************/ +/* Local Prototypes */ +/********************/ + +static int mchecksum_crc16_destroy(struct mchecksum_class *checksum_class); +static int mchecksum_crc16_reset(struct mchecksum_class *checksum_class); +static size_t mchecksum_crc16_get_size(struct mchecksum_class *checksum_class); +static int mchecksum_crc16_get(struct mchecksum_class *checksum_class, + void *buf, size_t size, int finalize); +static int mchecksum_crc16_update(struct mchecksum_class *checksum_class, + const void *data, size_t size); + +/*******************/ +/* Local Variables */ +/*******************/ + +static const struct mchecksum_class mchecksum_crc16_g = { + NULL, + mchecksum_crc16_destroy, + mchecksum_crc16_reset, + mchecksum_crc16_get_size, + mchecksum_crc16_get, + mchecksum_crc16_update +}; + +#ifndef MCHECKSUM_HAS_ISAL +static const mchecksum_uint16_t table_[256] = { + 0x0000, 0x8BB7, 0x9CD9, 0x176E, 0xB205, 0x39B2, 0x2EDC, 0xA56B, + 0xEFBD, 0x640A, 0x7364, 0xF8D3, 0x5DB8, 0xD60F, 0xC161, 0x4AD6, + 0x54CD, 0xDF7A, 0xC814, 0x43A3, 0xE6C8, 0x6D7F, 0x7A11, 0xF1A6, + 0xBB70, 0x30C7, 0x27A9, 0xAC1E, 0x0975, 0x82C2, 0x95AC, 0x1E1B, + 0xA99A, 0x222D, 0x3543, 0xBEF4, 0x1B9F, 0x9028, 0x8746, 0x0CF1, + 0x4627, 0xCD90, 0xDAFE, 0x5149, 0xF422, 0x7F95, 0x68FB, 0xE34C, + 0xFD57, 0x76E0, 0x618E, 0xEA39, 0x4F52, 0xC4E5, 0xD38B, 0x583C, + 0x12EA, 0x995D, 0x8E33, 0x0584, 0xA0EF, 0x2B58, 0x3C36, 0xB781, + 0xD883, 0x5334, 0x445A, 0xCFED, 0x6A86, 0xE131, 0xF65F, 0x7DE8, + 0x373E, 0xBC89, 0xABE7, 0x2050, 0x853B, 0x0E8C, 0x19E2, 0x9255, + 0x8C4E, 0x07F9, 0x1097, 0x9B20, 0x3E4B, 0xB5FC, 0xA292, 0x2925, + 0x63F3, 0xE844, 0xFF2A, 0x749D, 0xD1F6, 0x5A41, 0x4D2F, 0xC698, + 0x7119, 0xFAAE, 0xEDC0, 0x6677, 0xC31C, 0x48AB, 0x5FC5, 0xD472, + 0x9EA4, 0x1513, 0x027D, 0x89CA, 0x2CA1, 0xA716, 0xB078, 0x3BCF, + 0x25D4, 0xAE63, 0xB90D, 0x32BA, 0x97D1, 0x1C66, 0x0B08, 0x80BF, + 0xCA69, 0x41DE, 0x56B0, 0xDD07, 0x786C, 0xF3DB, 0xE4B5, 0x6F02, + 0x3AB1, 0xB106, 0xA668, 0x2DDF, 0x88B4, 0x0303, 0x146D, 0x9FDA, + 0xD50C, 0x5EBB, 0x49D5, 0xC262, 0x6709, 0xECBE, 0xFBD0, 0x7067, + 0x6E7C, 0xE5CB, 0xF2A5, 0x7912, 0xDC79, 0x57CE, 0x40A0, 0xCB17, + 0x81C1, 0x0A76, 0x1D18, 0x96AF, 0x33C4, 0xB873, 0xAF1D, 0x24AA, + 0x932B, 0x189C, 0x0FF2, 0x8445, 0x212E, 0xAA99, 0xBDF7, 0x3640, + 0x7C96, 0xF721, 0xE04F, 0x6BF8, 0xCE93, 0x4524, 0x524A, 0xD9FD, + 0xC7E6, 0x4C51, 0x5B3F, 0xD088, 0x75E3, 0xFE54, 0xE93A, 0x628D, + 0x285B, 0xA3EC, 0xB482, 0x3F35, 0x9A5E, 0x11E9, 0x0687, 0x8D30, + 0xE232, 0x6985, 0x7EEB, 0xF55C, 0x5037, 0xDB80, 0xCCEE, 0x4759, + 0x0D8F, 0x8638, 0x9156, 0x1AE1, 0xBF8A, 0x343D, 0x2353, 0xA8E4, + 0xB6FF, 0x3D48, 0x2A26, 0xA191, 0x04FA, 0x8F4D, 0x9823, 0x1394, + 0x5942, 0xD2F5, 0xC59B, 0x4E2C, 0xEB47, 0x60F0, 0x779E, 0xFC29, + 0x4BA8, 0xC01F, 0xD771, 0x5CC6, 0xF9AD, 0x721A, 0x6574, 0xEEC3, + 0xA415, 0x2FA2, 0x38CC, 0xB37B, 0x1610, 0x9DA7, 0x8AC9, 0x017E, + 0x1F65, 0x94D2, 0x83BC, 0x080B, 0xAD60, 0x26D7, 0x31B9, 0xBA0E, + 0xF0D8, 0x7B6F, 0x6C01, 0xE7B6, 0x42DD, 0xC96A, 0xDE04, 0x55B3 +}; +#endif + +/*---------------------------------------------------------------------------*/ +int +mchecksum_crc16_init(struct mchecksum_class *checksum_class) +{ + int ret = MCHECKSUM_SUCCESS; + + if (!checksum_class) { + MCHECKSUM_ERROR_DEFAULT("NULL checksum class"); + ret = MCHECKSUM_FAIL; + goto done; + } + + *checksum_class = mchecksum_crc16_g; + + checksum_class->data = malloc(sizeof(mchecksum_uint16_t)); + if (!checksum_class->data) { + MCHECKSUM_ERROR_DEFAULT("Could not allocate private data"); + ret = MCHECKSUM_FAIL; + goto done; + } + + mchecksum_crc16_reset(checksum_class); + +done: + return ret; +} + +/*---------------------------------------------------------------------------*/ +static int +mchecksum_crc16_destroy(struct mchecksum_class *checksum_class) +{ + free(checksum_class->data); + + return MCHECKSUM_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +static int +mchecksum_crc16_reset(struct mchecksum_class *checksum_class) +{ + *(mchecksum_uint16_t *) checksum_class->data = (mchecksum_uint16_t)0; + + return MCHECKSUM_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +static size_t +mchecksum_crc16_get_size(struct mchecksum_class MCHECKSUM_UNUSED *checksum_class) +{ + return sizeof(mchecksum_uint16_t); +} + +/*---------------------------------------------------------------------------*/ +static int +mchecksum_crc16_get(struct mchecksum_class *checksum_class, + void *buf, size_t size, int MCHECKSUM_UNUSED finalize) +{ + int ret = MCHECKSUM_SUCCESS; + + if (size < sizeof(mchecksum_uint16_t)) { + MCHECKSUM_ERROR_DEFAULT("Buffer is too small to store checksum"); + ret = MCHECKSUM_FAIL; + goto done; + } + + *(mchecksum_uint16_t *) buf = *(mchecksum_uint16_t *) checksum_class->data; + +done: + return ret; +} + +/*---------------------------------------------------------------------------*/ +static int +mchecksum_crc16_update(struct mchecksum_class *checksum_class, + const void *data, size_t size) +{ + mchecksum_uint16_t *state = (mchecksum_uint16_t *) checksum_class->data; +#ifdef MCHECKSUM_HAS_ISAL + *state = crc16_t10dif(*state, (const unsigned char *) data, size); +#else + const unsigned char *cur = (const unsigned char *) data; + const unsigned char *end = cur + size; + + while (cur < end) { + *state = ((mchecksum_uint16_t) (*state << 8)) + ^ table_[((*state >> 8) ^ *cur++) & 0xff]; + } +#endif + + return MCHECKSUM_SUCCESS; +} diff --git a/src/mchecksum/src/mchecksum_crc16.h b/src/mchecksum/src/mchecksum_crc16.h new file mode 100644 index 00000000..f7a1de4d --- /dev/null +++ b/src/mchecksum/src/mchecksum_crc16.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2013-2019 Argonne National Laboratory, Department of Energy, + * UChicago Argonne, LLC and The HDF Group. + * All rights reserved. + * + * The full copyright notice, including terms governing use, modification, + * and redistribution, is contained in the COPYING file that can be + * found at the root of the source code distribution tree. + */ + +#ifndef MCHECKSUM_CRC16_H +#define MCHECKSUM_CRC16_H + +#include "mchecksum_plugin.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Initialize the checksum with the CRC16 hash method. + * + * \param checksum_class [IN/OUT] pointer to checksum class + * + * \return Non-negative on success or negative on failure + */ +MCHECKSUM_EXPORT int +mchecksum_crc16_init(struct mchecksum_class *checksum_class); + +#ifdef __cplusplus +} +#endif + +#endif /* MCHECKSUM_CRC16_H */ diff --git a/src/mchecksum/src/mchecksum_crc32c.c b/src/mchecksum/src/mchecksum_crc32c.c new file mode 100644 index 00000000..62bfa5e1 --- /dev/null +++ b/src/mchecksum/src/mchecksum_crc32c.c @@ -0,0 +1,318 @@ +/* + * Copyright (C) 2013-2019 Argonne National Laboratory, Department of Energy, + * UChicago Argonne, LLC and The HDF Group. + * All rights reserved. + * + * The full copyright notice, including terms governing use, modification, + * and redistribution, is contained in the COPYING file that can be + * found at the root of the source code distribution tree. + */ + +#include "mchecksum_crc32c.h" +#include "mchecksum_error.h" + +#include +#if defined(MCHECKSUM_HAS_ISAL) +# include +#elif defined(MCHECKSUM_HAS_SSE4_2) +# include +# ifdef __x86_64__ +# define MAX_SIZE 8 +# else +# define MAX_SIZE 4 +# endif +#endif + +/****************/ +/* Local Macros */ +/****************/ + +/* Check for SSE 4.2. SSE 4.2 was first supported in Nehalem processors + * introduced in November, 2008. This does not check for the existence of the + * cpuid instruction itself, which was introduced on the 486SL in 1992, so this + * will fail on earlier x86 processors. cpuid works on all Pentium and later + * processors. */ +#define CHECK_SSE42(have) do { \ + unsigned int eax, ecx; \ + eax = 1; \ + __asm__("cpuid" : "=c"(ecx) : "a"(eax) : "%ebx", "%edx"); \ + (have) = (ecx >> 20) & 1; \ +} while (0) + +/************************************/ +/* Local Type and Struct Definition */ +/************************************/ + +/********************/ +/* Local Prototypes */ +/********************/ + +static int mchecksum_crc32c_destroy(struct mchecksum_class *checksum_class); +static int mchecksum_crc32c_reset(struct mchecksum_class *checksum_class); +static size_t mchecksum_crc32c_get_size(struct mchecksum_class *checksum_class); +static int mchecksum_crc32c_get(struct mchecksum_class *checksum_class, + void *buf, size_t size, int finalize); +static int mchecksum_crc32c_update(struct mchecksum_class *checksum_class, + const void *data, size_t size); +#if !defined(MCHECKSUM_HAS_ISAL) && defined(MCHECKSUM_HAS_SSE4_2) +static int mchecksum_crc32c_update_sse42(struct mchecksum_class *checksum_class, + const void *data, size_t size); +#endif + +/*******************/ +/* Local Variables */ +/*******************/ + +static const struct mchecksum_class mchecksum_crc32_g = { + NULL, + mchecksum_crc32c_destroy, + mchecksum_crc32c_reset, + mchecksum_crc32c_get_size, + mchecksum_crc32c_get, + mchecksum_crc32c_update +}; + +#ifndef MCHECKSUM_HAS_ISAL +static const mchecksum_uint32_t table_[256] = { + 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L, 0xC79A971FL, + 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL, 0x8AD958CFL, 0x78B2DBCCL, + 0x6BE22838L, 0x9989AB3BL, 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, + 0x5E133C24L, 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL, + 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L, 0x9A879FA0L, + 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L, 0x5D1D08BFL, 0xAF768BBCL, + 0xBC267848L, 0x4E4DFB4BL, 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, + 0x33ED7D2AL, 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L, + 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L, 0x6DFE410EL, + 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL, 0x30E349B1L, 0xC288CAB2L, + 0xD1D83946L, 0x23B3BA45L, 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, + 0xE4292D5AL, 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL, + 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L, 0x417B1DBCL, + 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L, 0x86E18AA3L, 0x748A09A0L, + 0x67DAFA54L, 0x95B17957L, 0xCBA24573L, 0x39C9C670L, 0x2A993584L, + 0xD8F2B687L, 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L, + 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L, 0x96BF4DCCL, + 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L, 0xDBFC821CL, 0x2997011FL, + 0x3AC7F2EBL, 0xC8AC71E8L, 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, + 0x0F36E6F7L, 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L, + 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L, 0xEB1FCBADL, + 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L, 0x2C855CB2L, 0xDEEEDFB1L, + 0xCDBE2C45L, 0x3FD5AF46L, 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, + 0x62C8A7F9L, 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L, + 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L, 0x3CDB9BDDL, + 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L, 0x82F63B78L, 0x709DB87BL, + 0x63CD4B8FL, 0x91A6C88CL, 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, + 0x563C5F93L, 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L, + 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL, 0x92A8FC17L, + 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L, 0x55326B08L, 0xA759E80BL, + 0xB4091BFFL, 0x466298FCL, 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, + 0x0B21572CL, 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L, + 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L, 0x65D122B9L, + 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL, 0x2892ED69L, 0xDAF96E6AL, + 0xC9A99D9EL, 0x3BC21E9DL, 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, + 0xFC588982L, 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL, + 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L, 0x38CC2A06L, + 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L, 0xFF56BD19L, 0x0D3D3E1AL, + 0x1E6DCDEEL, 0xEC064EEDL, 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, + 0xD0DDD530L, 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL, + 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL, 0x8ECEE914L, + 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L, 0xD3D3E1ABL, 0x21B862A8L, + 0x32E8915CL, 0xC083125FL, 0x144976B4L, 0xE622F5B7L, 0xF5720643L, + 0x07198540L, 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L, + 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL, 0xE330A81AL, + 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL, 0x24AA3F05L, 0xD6C1BC06L, + 0xC5914FF2L, 0x37FACCF1L, 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, + 0x7AB90321L, 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL, + 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L, 0x34F4F86AL, + 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL, 0x79B737BAL, 0x8BDCB4B9L, + 0x988C474DL, 0x6AE7C44EL, 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, + 0xAD7D5351L +}; +#endif + +/** + * Initialize the CRC table. + */ +/* CRC-32C Poly is 0x1EDC6F41 -> Rev Poly is 0x82F63B78 */ +/* +#define POLYREV 0x82F63B78L + +static void +gen_table(void) +{ + unsigned int i, j; + unsigned int col = 0; + + for (i = 0; i < 256; i++) { + mchecksum_uint32_t part = i; + + for (j = 0; j < 8; j++) { + if (part & 1) + part = (part >> 1) ^ POLYREV; + else + part >>= 1; + } + col++; + printf("0x%08lXL, ", part); + if (col == 2) { + printf("\n"); + col = 0; + } + } + printf("\n"); +} +*/ + +/*---------------------------------------------------------------------------*/ +int +mchecksum_crc32c_init(struct mchecksum_class *checksum_class) +{ + int ret = MCHECKSUM_SUCCESS; +#if !defined(MCHECKSUM_HAS_ISAL) && defined(MCHECKSUM_HAS_SSE4_2) + int has_sse42; +#endif + + if (!checksum_class) { + MCHECKSUM_ERROR_DEFAULT("NULL checksum class"); + ret = MCHECKSUM_FAIL; + goto done; + } + + *checksum_class = mchecksum_crc32_g; +#if !defined(MCHECKSUM_HAS_ISAL) && defined(MCHECKSUM_HAS_SSE4_2) + /* Verify support for SSE 4.2 at runtime to prevent cross-compile issues */ + CHECK_SSE42(has_sse42); + if (has_sse42) + checksum_class->update = mchecksum_crc32c_update_sse42; +#endif + + checksum_class->data = malloc(sizeof(mchecksum_uint32_t)); + if (!checksum_class->data) { + MCHECKSUM_ERROR_DEFAULT("Could not allocate private data"); + ret = MCHECKSUM_FAIL; + goto done; + } + + mchecksum_crc32c_reset(checksum_class); + +done: + return ret; +} + +/*---------------------------------------------------------------------------*/ +static int +mchecksum_crc32c_destroy(struct mchecksum_class *checksum_class) +{ + free(checksum_class->data); + + return MCHECKSUM_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +static int +mchecksum_crc32c_reset(struct mchecksum_class *checksum_class) +{ + *(mchecksum_uint32_t *) checksum_class->data = ~(mchecksum_uint32_t)0; + + return MCHECKSUM_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +static size_t +mchecksum_crc32c_get_size(struct mchecksum_class MCHECKSUM_UNUSED *checksum_class) +{ + return sizeof(mchecksum_uint32_t); +} + +/*---------------------------------------------------------------------------*/ +static int +mchecksum_crc32c_get(struct mchecksum_class *checksum_class, + void *buf, size_t size, int finalize) +{ + int ret = MCHECKSUM_SUCCESS; + + if (size < sizeof(mchecksum_uint32_t)) { + MCHECKSUM_ERROR_DEFAULT("Buffer is too small to store checksum"); + ret = MCHECKSUM_FAIL; + goto done; + } + + if (finalize == MCHECKSUM_FINALIZE) + *(mchecksum_uint32_t *) checksum_class->data = + (*(mchecksum_uint32_t *) checksum_class->data) + ^ ~(mchecksum_uint32_t) 0; + + *(mchecksum_uint32_t *) buf = *(mchecksum_uint32_t *) checksum_class->data; + +done: + return ret; +} + +#ifndef MCHECKSUM_HAS_ISAL +/*---------------------------------------------------------------------------*/ +static int +mchecksum_crc32c_update(struct mchecksum_class *checksum_class, + const void *data, size_t size) +{ + mchecksum_uint32_t *state = (mchecksum_uint32_t *) checksum_class->data; + const unsigned char *cur = (const unsigned char *) data; + + while (size--) + *state = (*state >> 8) ^ table_[(*state ^ *cur++) & 0xFFL]; + + return MCHECKSUM_SUCCESS; +} + +#ifdef MCHECKSUM_HAS_SSE4_2 +/*---------------------------------------------------------------------------*/ +static MCHECKSUM_INLINE void +mchecksum_crc32c_update_byte_sse42(struct mchecksum_class *checksum_class, + const void *data, size_t size) +{ + mchecksum_uint32_t *state = (mchecksum_uint32_t *) checksum_class->data; + const unsigned char *cur = (const unsigned char *) data; + + while (size--) + *state = _mm_crc32_u8(*state, *cur++); +} + +/*---------------------------------------------------------------------------*/ +static int +mchecksum_crc32c_update_sse42(struct mchecksum_class *checksum_class, + const void *data, size_t size) +{ + mchecksum_uint32_t *state = (mchecksum_uint32_t *) checksum_class->data; +#ifdef __x86_64__ + const unsigned long long *cur = (const unsigned long long *) data; +#else + const unsigned int *cur = (const unsigned int *) data; +#endif /* __x86_64__ */ + unsigned int quotient = (unsigned int) (size / MAX_SIZE); + unsigned int remainder = size % MAX_SIZE; + + while (quotient--) +#ifdef __x86_64__ + *state = (mchecksum_uint32_t) _mm_crc32_u64(*state, *cur++); +#else + *state = _mm_crc32_u32(*state, *cur++); +#endif /* __x86_64__ */ + + if (remainder) + mchecksum_crc32c_update_byte_sse42(checksum_class, cur, remainder); + + return MCHECKSUM_SUCCESS; +} + +#endif /* MCHECKSUM_HAS_SSE4_2 */ +#else +/*---------------------------------------------------------------------------*/ +static int +mchecksum_crc32c_update(struct mchecksum_class *checksum_class, + const void *data, size_t size) +{ + mchecksum_uint32_t *state = (mchecksum_uint32_t *) checksum_class->data; + + *state = crc32_iscsi((unsigned char *) data, (int) size, *state); + + return MCHECKSUM_SUCCESS; +} +#endif diff --git a/src/mchecksum/src/mchecksum_crc32c.h b/src/mchecksum/src/mchecksum_crc32c.h new file mode 100644 index 00000000..79ac622a --- /dev/null +++ b/src/mchecksum/src/mchecksum_crc32c.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2013-2019 Argonne National Laboratory, Department of Energy, + * UChicago Argonne, LLC and The HDF Group. + * All rights reserved. + * + * The full copyright notice, including terms governing use, modification, + * and redistribution, is contained in the COPYING file that can be + * found at the root of the source code distribution tree. + */ + +#ifndef MCHECKSUM_CRC32C_H +#define MCHECKSUM_CRC32C_H + +#include "mchecksum_plugin.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \param checksum_class [IN/OUT] pointer to checksum class + * + * \return Non-negative on success or negative on failure + */ +MCHECKSUM_EXPORT int +mchecksum_crc32c_init(struct mchecksum_class *checksum_class); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/mchecksum/src/mchecksum_crc64.c b/src/mchecksum/src/mchecksum_crc64.c new file mode 100644 index 00000000..020a600c --- /dev/null +++ b/src/mchecksum/src/mchecksum_crc64.c @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2013-2019 Argonne National Laboratory, Department of Energy, + * UChicago Argonne, LLC and The HDF Group. + * All rights reserved. + * + * The full copyright notice, including terms governing use, modification, + * and redistribution, is contained in the COPYING file that can be + * found at the root of the source code distribution tree. + */ + +#include "mchecksum_crc64.h" +#include "mchecksum_error.h" + +#include +#if defined(MCHECKSUM_HAS_ISAL) +# include +#endif + +/****************/ +/* Local Macros */ +/****************/ + +/************************************/ +/* Local Type and Struct Definition */ +/************************************/ + +/********************/ +/* Local Prototypes */ +/********************/ + +static int mchecksum_crc64_destroy(struct mchecksum_class *checksum_class); +static int mchecksum_crc64_reset(struct mchecksum_class *checksum_class); +static size_t mchecksum_crc64_get_size(struct mchecksum_class *checksum_class); +static int mchecksum_crc64_get(struct mchecksum_class *checksum_class, + void *buf, size_t size, int finalize); +static int mchecksum_crc64_update(struct mchecksum_class *checksum_class, + const void *data, size_t size); + +/*******************/ +/* Local Variables */ +/*******************/ + +static const struct mchecksum_class mchecksum_crc64_g = { + NULL, + mchecksum_crc64_destroy, + mchecksum_crc64_reset, + mchecksum_crc64_get_size, + mchecksum_crc64_get, + mchecksum_crc64_update +}; + +#if !defined(MCHECKSUM_HAS_ISAL) +static const mchecksum_uint64_t table_[256] = { + 0x0000000000000000ULL, 0xB32E4CBE03A75F6FULL, 0xF4843657A840A05BULL, + 0x47AA7AE9ABE7FF34ULL, 0x7BD0C384FF8F5E33ULL, 0xC8FE8F3AFC28015CULL, + 0x8F54F5D357CFFE68ULL, 0x3C7AB96D5468A107ULL, 0xF7A18709FF1EBC66ULL, + 0x448FCBB7FCB9E309ULL, 0x0325B15E575E1C3DULL, 0xB00BFDE054F94352ULL, + 0x8C71448D0091E255ULL, 0x3F5F08330336BD3AULL, 0x78F572DAA8D1420EULL, + 0xCBDB3E64AB761D61ULL, 0x7D9BA13851336649ULL, 0xCEB5ED8652943926ULL, + 0x891F976FF973C612ULL, 0x3A31DBD1FAD4997DULL, 0x064B62BCAEBC387AULL, + 0xB5652E02AD1B6715ULL, 0xF2CF54EB06FC9821ULL, 0x41E11855055BC74EULL, + 0x8A3A2631AE2DDA2FULL, 0x39146A8FAD8A8540ULL, 0x7EBE1066066D7A74ULL, + 0xCD905CD805CA251BULL, 0xF1EAE5B551A2841CULL, 0x42C4A90B5205DB73ULL, + 0x056ED3E2F9E22447ULL, 0xB6409F5CFA457B28ULL, 0xFB374270A266CC92ULL, + 0x48190ECEA1C193FDULL, 0x0FB374270A266CC9ULL, 0xBC9D3899098133A6ULL, + 0x80E781F45DE992A1ULL, 0x33C9CD4A5E4ECDCEULL, 0x7463B7A3F5A932FAULL, + 0xC74DFB1DF60E6D95ULL, 0x0C96C5795D7870F4ULL, 0xBFB889C75EDF2F9BULL, + 0xF812F32EF538D0AFULL, 0x4B3CBF90F69F8FC0ULL, 0x774606FDA2F72EC7ULL, + 0xC4684A43A15071A8ULL, 0x83C230AA0AB78E9CULL, 0x30EC7C140910D1F3ULL, + 0x86ACE348F355AADBULL, 0x3582AFF6F0F2F5B4ULL, 0x7228D51F5B150A80ULL, + 0xC10699A158B255EFULL, 0xFD7C20CC0CDAF4E8ULL, 0x4E526C720F7DAB87ULL, + 0x09F8169BA49A54B3ULL, 0xBAD65A25A73D0BDCULL, 0x710D64410C4B16BDULL, + 0xC22328FF0FEC49D2ULL, 0x85895216A40BB6E6ULL, 0x36A71EA8A7ACE989ULL, + 0x0ADDA7C5F3C4488EULL, 0xB9F3EB7BF06317E1ULL, 0xFE5991925B84E8D5ULL, + 0x4D77DD2C5823B7BAULL, 0x64B62BCAEBC387A1ULL, 0xD7986774E864D8CEULL, + 0x90321D9D438327FAULL, 0x231C512340247895ULL, 0x1F66E84E144CD992ULL, + 0xAC48A4F017EB86FDULL, 0xEBE2DE19BC0C79C9ULL, 0x58CC92A7BFAB26A6ULL, + 0x9317ACC314DD3BC7ULL, 0x2039E07D177A64A8ULL, 0x67939A94BC9D9B9CULL, + 0xD4BDD62ABF3AC4F3ULL, 0xE8C76F47EB5265F4ULL, 0x5BE923F9E8F53A9BULL, + 0x1C4359104312C5AFULL, 0xAF6D15AE40B59AC0ULL, 0x192D8AF2BAF0E1E8ULL, + 0xAA03C64CB957BE87ULL, 0xEDA9BCA512B041B3ULL, 0x5E87F01B11171EDCULL, + 0x62FD4976457FBFDBULL, 0xD1D305C846D8E0B4ULL, 0x96797F21ED3F1F80ULL, + 0x2557339FEE9840EFULL, 0xEE8C0DFB45EE5D8EULL, 0x5DA24145464902E1ULL, + 0x1A083BACEDAEFDD5ULL, 0xA9267712EE09A2BAULL, 0x955CCE7FBA6103BDULL, + 0x267282C1B9C65CD2ULL, 0x61D8F8281221A3E6ULL, 0xD2F6B4961186FC89ULL, + 0x9F8169BA49A54B33ULL, 0x2CAF25044A02145CULL, 0x6B055FEDE1E5EB68ULL, + 0xD82B1353E242B407ULL, 0xE451AA3EB62A1500ULL, 0x577FE680B58D4A6FULL, + 0x10D59C691E6AB55BULL, 0xA3FBD0D71DCDEA34ULL, 0x6820EEB3B6BBF755ULL, + 0xDB0EA20DB51CA83AULL, 0x9CA4D8E41EFB570EULL, 0x2F8A945A1D5C0861ULL, + 0x13F02D374934A966ULL, 0xA0DE61894A93F609ULL, 0xE7741B60E174093DULL, + 0x545A57DEE2D35652ULL, 0xE21AC88218962D7AULL, 0x5134843C1B317215ULL, + 0x169EFED5B0D68D21ULL, 0xA5B0B26BB371D24EULL, 0x99CA0B06E7197349ULL, + 0x2AE447B8E4BE2C26ULL, 0x6D4E3D514F59D312ULL, 0xDE6071EF4CFE8C7DULL, + 0x15BB4F8BE788911CULL, 0xA6950335E42FCE73ULL, 0xE13F79DC4FC83147ULL, + 0x521135624C6F6E28ULL, 0x6E6B8C0F1807CF2FULL, 0xDD45C0B11BA09040ULL, + 0x9AEFBA58B0476F74ULL, 0x29C1F6E6B3E0301BULL, 0xC96C5795D7870F42ULL, + 0x7A421B2BD420502DULL, 0x3DE861C27FC7AF19ULL, 0x8EC62D7C7C60F076ULL, + 0xB2BC941128085171ULL, 0x0192D8AF2BAF0E1EULL, 0x4638A2468048F12AULL, + 0xF516EEF883EFAE45ULL, 0x3ECDD09C2899B324ULL, 0x8DE39C222B3EEC4BULL, + 0xCA49E6CB80D9137FULL, 0x7967AA75837E4C10ULL, 0x451D1318D716ED17ULL, + 0xF6335FA6D4B1B278ULL, 0xB199254F7F564D4CULL, 0x02B769F17CF11223ULL, + 0xB4F7F6AD86B4690BULL, 0x07D9BA1385133664ULL, 0x4073C0FA2EF4C950ULL, + 0xF35D8C442D53963FULL, 0xCF273529793B3738ULL, 0x7C0979977A9C6857ULL, + 0x3BA3037ED17B9763ULL, 0x888D4FC0D2DCC80CULL, 0x435671A479AAD56DULL, + 0xF0783D1A7A0D8A02ULL, 0xB7D247F3D1EA7536ULL, 0x04FC0B4DD24D2A59ULL, + 0x3886B22086258B5EULL, 0x8BA8FE9E8582D431ULL, 0xCC0284772E652B05ULL, + 0x7F2CC8C92DC2746AULL, 0x325B15E575E1C3D0ULL, 0x8175595B76469CBFULL, + 0xC6DF23B2DDA1638BULL, 0x75F16F0CDE063CE4ULL, 0x498BD6618A6E9DE3ULL, + 0xFAA59ADF89C9C28CULL, 0xBD0FE036222E3DB8ULL, 0x0E21AC88218962D7ULL, + 0xC5FA92EC8AFF7FB6ULL, 0x76D4DE52895820D9ULL, 0x317EA4BB22BFDFEDULL, + 0x8250E80521188082ULL, 0xBE2A516875702185ULL, 0x0D041DD676D77EEAULL, + 0x4AAE673FDD3081DEULL, 0xF9802B81DE97DEB1ULL, 0x4FC0B4DD24D2A599ULL, + 0xFCEEF8632775FAF6ULL, 0xBB44828A8C9205C2ULL, 0x086ACE348F355AADULL, + 0x34107759DB5DFBAAULL, 0x873E3BE7D8FAA4C5ULL, 0xC094410E731D5BF1ULL, + 0x73BA0DB070BA049EULL, 0xB86133D4DBCC19FFULL, 0x0B4F7F6AD86B4690ULL, + 0x4CE50583738CB9A4ULL, 0xFFCB493D702BE6CBULL, 0xC3B1F050244347CCULL, + 0x709FBCEE27E418A3ULL, 0x3735C6078C03E797ULL, 0x841B8AB98FA4B8F8ULL, + 0xADDA7C5F3C4488E3ULL, 0x1EF430E13FE3D78CULL, 0x595E4A08940428B8ULL, + 0xEA7006B697A377D7ULL, 0xD60ABFDBC3CBD6D0ULL, 0x6524F365C06C89BFULL, + 0x228E898C6B8B768BULL, 0x91A0C532682C29E4ULL, 0x5A7BFB56C35A3485ULL, + 0xE955B7E8C0FD6BEAULL, 0xAEFFCD016B1A94DEULL, 0x1DD181BF68BDCBB1ULL, + 0x21AB38D23CD56AB6ULL, 0x9285746C3F7235D9ULL, 0xD52F0E859495CAEDULL, + 0x6601423B97329582ULL, 0xD041DD676D77EEAAULL, 0x636F91D96ED0B1C5ULL, + 0x24C5EB30C5374EF1ULL, 0x97EBA78EC690119EULL, 0xAB911EE392F8B099ULL, + 0x18BF525D915FEFF6ULL, 0x5F1528B43AB810C2ULL, 0xEC3B640A391F4FADULL, + 0x27E05A6E926952CCULL, 0x94CE16D091CE0DA3ULL, 0xD3646C393A29F297ULL, + 0x604A2087398EADF8ULL, 0x5C3099EA6DE60CFFULL, 0xEF1ED5546E415390ULL, + 0xA8B4AFBDC5A6ACA4ULL, 0x1B9AE303C601F3CBULL, 0x56ED3E2F9E224471ULL, + 0xE5C372919D851B1EULL, 0xA26908783662E42AULL, 0x114744C635C5BB45ULL, + 0x2D3DFDAB61AD1A42ULL, 0x9E13B115620A452DULL, 0xD9B9CBFCC9EDBA19ULL, + 0x6A978742CA4AE576ULL, 0xA14CB926613CF817ULL, 0x1262F598629BA778ULL, + 0x55C88F71C97C584CULL, 0xE6E6C3CFCADB0723ULL, 0xDA9C7AA29EB3A624ULL, + 0x69B2361C9D14F94BULL, 0x2E184CF536F3067FULL, 0x9D36004B35545910ULL, + 0x2B769F17CF112238ULL, 0x9858D3A9CCB67D57ULL, 0xDFF2A94067518263ULL, + 0x6CDCE5FE64F6DD0CULL, 0x50A65C93309E7C0BULL, 0xE388102D33392364ULL, + 0xA4226AC498DEDC50ULL, 0x170C267A9B79833FULL, 0xDCD7181E300F9E5EULL, + 0x6FF954A033A8C131ULL, 0x28532E49984F3E05ULL, 0x9B7D62F79BE8616AULL, + 0xA707DB9ACF80C06DULL, 0x14299724CC279F02ULL, 0x5383EDCD67C06036ULL, + 0xE0ADA17364673F59ULL +}; +#endif + +/** + * Initialize the CRC table. + */ +/* CRC-64 ECMA Poly is 0x42F0E1EBA9EA3693 -> Rev Poly is 0xC96C5795D7870F42 */ +/* +#define POLYREV 0xC96C5795D7870F42ULL + +static void +gen_table(void) +{ + unsigned int i, j; + unsigned int col = 0; + + for (i = 0; i < 256; i++) { + mchecksum_uint64_t part = i; + + for (j = 0; j < 8; j++) { + if (part & 1) + part = (part >> 1) ^ POLYREV; + else + part >>= 1; + } + col++; + printf("0x%016lXULL, ", part); + if (col == 2) { + printf("\n"); + col = 0; + } + } + printf("\n"); +} +*/ + +/*---------------------------------------------------------------------------*/ +int +mchecksum_crc64_init(struct mchecksum_class *checksum_class) +{ + int ret = MCHECKSUM_SUCCESS; + + if (!checksum_class) { + MCHECKSUM_ERROR_DEFAULT("NULL checksum class"); + ret = MCHECKSUM_FAIL; + goto done; + } + + *checksum_class = mchecksum_crc64_g; + + checksum_class->data = malloc(sizeof(mchecksum_uint64_t)); + if (!checksum_class->data) { + MCHECKSUM_ERROR_DEFAULT("Could not allocate private data"); + ret = MCHECKSUM_FAIL; + goto done; + } + + mchecksum_crc64_reset(checksum_class); + +done: + return ret; +} + +/*---------------------------------------------------------------------------*/ +static int +mchecksum_crc64_destroy(struct mchecksum_class *checksum_class) +{ + free(checksum_class->data); + + return MCHECKSUM_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +static int +mchecksum_crc64_reset(struct mchecksum_class *checksum_class) +{ + *(mchecksum_uint64_t*) checksum_class->data = ~(mchecksum_uint64_t)0; + + return MCHECKSUM_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +static size_t +mchecksum_crc64_get_size(struct mchecksum_class MCHECKSUM_UNUSED *checksum_class) +{ + return sizeof(mchecksum_uint64_t); +} + +/*---------------------------------------------------------------------------*/ +static int +mchecksum_crc64_get(struct mchecksum_class *checksum_class, + void *buf, size_t size, int MCHECKSUM_UNUSED finalize) +{ + int ret = MCHECKSUM_SUCCESS; + + if (size < sizeof(mchecksum_uint64_t)) { + MCHECKSUM_ERROR_DEFAULT("Buffer is too small to store checksum"); + ret = MCHECKSUM_FAIL; + goto done; + } + + *(mchecksum_uint64_t*) buf = *(mchecksum_uint64_t*) checksum_class->data; + +done: + return ret; +} + +/*---------------------------------------------------------------------------*/ +static int +mchecksum_crc64_update(struct mchecksum_class *checksum_class, + const void *data, size_t size) +{ + mchecksum_uint64_t *state = (mchecksum_uint64_t*) checksum_class->data; +#if defined(MCHECKSUM_HAS_ISAL) + *state = ~crc64_ecma_refl(~*state, (const unsigned char *) data, size); +#else + const unsigned char *cur = (const unsigned char *) data; + const unsigned char *end = cur + size; + + while (cur < end) + *state = ((*state >> 8) ^ table_[(*state ^ *cur++) & 0xff]); +#endif + + return MCHECKSUM_SUCCESS; +} diff --git a/src/mchecksum/src/mchecksum_crc64.h b/src/mchecksum/src/mchecksum_crc64.h new file mode 100644 index 00000000..f98ffc26 --- /dev/null +++ b/src/mchecksum/src/mchecksum_crc64.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2013-2019 Argonne National Laboratory, Department of Energy, + * UChicago Argonne, LLC and The HDF Group. + * All rights reserved. + * + * The full copyright notice, including terms governing use, modification, + * and redistribution, is contained in the COPYING file that can be + * found at the root of the source code distribution tree. + */ + +#ifndef MCHECKSUM_CRC64_H +#define MCHECKSUM_CRC64_H + +#include "mchecksum_plugin.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Initialize the checksum with the CRC64 ECMA hash method. + * + * \param checksum_class [IN/OUT] pointer to checksum class + * + * \return Non-negative on success or negative on failure + */ +MCHECKSUM_EXPORT int +mchecksum_crc64_init(struct mchecksum_class *checksum_class); + +#ifdef __cplusplus +} +#endif + +#endif /* MCHECKSUM_CRC64_H */ diff --git a/src/mchecksum/src/mchecksum_error.h b/src/mchecksum/src/mchecksum_error.h new file mode 100644 index 00000000..9917f58e --- /dev/null +++ b/src/mchecksum/src/mchecksum_error.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2013-2019 Argonne National Laboratory, Department of Energy, + * UChicago Argonne, LLC and The HDF Group. + * All rights reserved. + * + * The full copyright notice, including terms governing use, modification, + * and redistribution, is contained in the COPYING file that can be + * found at the root of the source code distribution tree. + */ + +#ifndef MCHECKSUM_ERROR_H +#define MCHECKSUM_ERROR_H + +#include "mchecksum_config.h" + +/*****************/ +/* Public Macros */ +/*****************/ + +#define MCHECKSUM_SUCCESS 1 +#define MCHECKSUM_FAIL -1 + +/* For compatibility */ +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ < 199901L) +# if defined(__GNUC__) && (__GNUC__ >= 2) +# define __func__ __FUNCTION__ +# else +# define __func__ "" +# endif +#elif defined(_WIN32) +# define __func__ __FUNCTION__ +#endif + +/* Default error macro */ +#ifdef MCHECKSUM_HAS_VERBOSE_ERROR +# include +# define MCHECKSUM_ERROR_DEFAULT(x) do { \ + fprintf(stderr, "Error " \ + "in %s:%d (%s): " \ + "%s.\n", \ + __FILE__, __LINE__, __func__, x); \ + } while(0) +#else +# define MCHECKSUM_ERROR_DEFAULT(x) (void)0 +#endif + +#endif /* MCHECKSUM_ERROR_H */ diff --git a/src/mchecksum/src/mchecksum_plugin.h b/src/mchecksum/src/mchecksum_plugin.h new file mode 100644 index 00000000..fe2c531b --- /dev/null +++ b/src/mchecksum/src/mchecksum_plugin.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2013-2019 Argonne National Laboratory, Department of Energy, + * UChicago Argonne, LLC and The HDF Group. + * All rights reserved. + * + * The full copyright notice, including terms governing use, modification, + * and redistribution, is contained in the COPYING file that can be + * found at the root of the source code distribution tree. + */ + +#ifndef MCHECKSUM_PRIVATE_H +#define MCHECKSUM_PRIVATE_H + +#include "mchecksum.h" + +/*************************************/ +/* Public Type and Struct Definition */ +/*************************************/ + +/* Checksum class definition */ +struct mchecksum_class { + /* Private data */ + void *data; + /* Callbacks */ + int (*destroy)(struct mchecksum_class *checksum_class); + int (*reset)(struct mchecksum_class *checksum_class); + size_t (*get_size)(struct mchecksum_class *checksum_class); + int (*get)(struct mchecksum_class *checksum_class, + void *buf, size_t size, int finalize); + int (*update)(struct mchecksum_class *checksum_class, + const void *data, size_t size); +}; + +/*****************/ +/* Public Macros */ +/*****************/ + +/* Remove warnings when plugin does not use callback arguments */ +#if defined(__cplusplus) +# define MCHECKSUM_UNUSED +#elif defined(__GNUC__) && (__GNUC__ >= 4) +# define MCHECKSUM_UNUSED __attribute__((unused)) +#else +# define MCHECKSUM_UNUSED +#endif + +#endif /* MCHECKSUM_PRIVATE_H */ diff --git a/src/mchecksum/src/mchecksum_zlib.c b/src/mchecksum/src/mchecksum_zlib.c new file mode 100644 index 00000000..74e58342 --- /dev/null +++ b/src/mchecksum/src/mchecksum_zlib.c @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2013-2019 Argonne National Laboratory, Department of Energy, + * UChicago Argonne, LLC and The HDF Group. + * All rights reserved. + * + * The full copyright notice, including terms governing use, modification, + * and redistribution, is contained in the COPYING file that can be + * found at the root of the source code distribution tree. + */ + +#include "mchecksum_zlib.h" +#include "mchecksum_error.h" + +#include +#include + +/****************/ +/* Local Macros */ +/****************/ + +/************************************/ +/* Local Type and Struct Definition */ +/************************************/ + +/********************/ +/* Local Prototypes */ +/********************/ + +static int mchecksum_crc32_destroy(struct mchecksum_class *checksum_class); +static int mchecksum_crc32_reset(struct mchecksum_class *checksum_class); +static size_t mchecksum_crc32_get_size(struct mchecksum_class *checksum_class); +static int mchecksum_crc32_get(struct mchecksum_class *checksum_class, + void *buf, size_t size, int finalize); +static int mchecksum_crc32_update(struct mchecksum_class *checksum_class, + const void *data, size_t size); + +static int mchecksum_adler32_destroy(struct mchecksum_class *checksum_class); +static int mchecksum_adler32_reset(struct mchecksum_class *checksum_class); +static size_t mchecksum_adler32_get_size(struct mchecksum_class *checksum_class); +static int mchecksum_adler32_get(struct mchecksum_class *checksum_class, + void *buf, size_t size, int finalize); +static int mchecksum_adler32_update(struct mchecksum_class *checksum_class, + const void *data, size_t size); + +/*******************/ +/* Local Variables */ +/*******************/ + +static const struct mchecksum_class mchecksum_crc32_g = { + NULL, + mchecksum_crc32_destroy, + mchecksum_crc32_reset, + mchecksum_crc32_get_size, + mchecksum_crc32_get, + mchecksum_crc32_update +}; + +static const struct mchecksum_class mchecksum_adler32_g = { + NULL, + mchecksum_adler32_destroy, + mchecksum_adler32_reset, + mchecksum_adler32_get_size, + mchecksum_adler32_get, + mchecksum_adler32_update +}; + +/*---------------------------------------------------------------------------*/ +int +mchecksum_crc32_init(struct mchecksum_class *checksum_class) +{ + int ret = MCHECKSUM_SUCCESS; + + if (!checksum_class) { + MCHECKSUM_ERROR_DEFAULT("NULL checksum class"); + ret = MCHECKSUM_FAIL; + goto done; + } + + *checksum_class = mchecksum_crc32_g; + + checksum_class->data = malloc(sizeof(mchecksum_uint32_t)); + if (!checksum_class->data) { + MCHECKSUM_ERROR_DEFAULT("Could not allocate private data"); + ret = MCHECKSUM_FAIL; + goto done; + } + + + mchecksum_crc32_reset (checksum_class); + +done: + return ret; +} + +/*---------------------------------------------------------------------------*/ +static int +mchecksum_crc32_destroy(struct mchecksum_class *checksum_class) +{ + free(checksum_class->data); + + return MCHECKSUM_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +static int +mchecksum_crc32_reset(struct mchecksum_class *checksum_class) +{ + *(mchecksum_uint32_t*) checksum_class->data = + (mchecksum_uint32_t) crc32(0L, Z_NULL, 0); + + return MCHECKSUM_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +static size_t +mchecksum_crc32_get_size(struct mchecksum_class MCHECKSUM_UNUSED *checksum_class) +{ + return sizeof(mchecksum_uint32_t); +} + +/*---------------------------------------------------------------------------*/ +static int +mchecksum_crc32_get(struct mchecksum_class *checksum_class, + void *buf, size_t size, int MCHECKSUM_UNUSED finalize) +{ + int ret = MCHECKSUM_SUCCESS; + + if (size < sizeof(mchecksum_uint32_t)) { + MCHECKSUM_ERROR_DEFAULT("Buffer is too small to store checksum"); + ret = MCHECKSUM_FAIL; + goto done; + } + + *(mchecksum_uint32_t*) buf = *(mchecksum_uint32_t*) checksum_class->data; + +done: + return ret; +} + +/*---------------------------------------------------------------------------*/ +static int +mchecksum_crc32_update(struct mchecksum_class *checksum_class, + const void *data, size_t size) +{ + mchecksum_uint32_t *state = (mchecksum_uint32_t*) checksum_class->data; + + *state = (mchecksum_uint32_t) crc32(*state, data, (unsigned int) size); + + return MCHECKSUM_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +int +mchecksum_adler32_init(struct mchecksum_class *checksum_class) +{ + int ret = MCHECKSUM_SUCCESS; + + if (!checksum_class) { + MCHECKSUM_ERROR_DEFAULT("NULL checksum class"); + ret = MCHECKSUM_FAIL; + goto done; + } + + *checksum_class = mchecksum_adler32_g; + + checksum_class->data = malloc(sizeof(mchecksum_uint32_t)); + if (!checksum_class->data) { + MCHECKSUM_ERROR_DEFAULT("Could not allocate private data"); + ret = MCHECKSUM_FAIL; + goto done; + } + + mchecksum_adler32_reset (checksum_class); + +done: + return ret; +} + +/*---------------------------------------------------------------------------*/ +static int +mchecksum_adler32_destroy(struct mchecksum_class *checksum_class) +{ + free(checksum_class->data); + + return MCHECKSUM_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +static int +mchecksum_adler32_reset(struct mchecksum_class *checksum_class) +{ + *(mchecksum_uint32_t*) checksum_class->data = + (mchecksum_uint32_t) adler32(0L, Z_NULL, 0); + + return MCHECKSUM_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +static size_t +mchecksum_adler32_get_size(struct mchecksum_class MCHECKSUM_UNUSED *checksum_class) +{ + return sizeof(mchecksum_uint32_t); +} + +/*---------------------------------------------------------------------------*/ +static int +mchecksum_adler32_get(struct mchecksum_class *checksum_class, + void *buf, size_t size, int MCHECKSUM_UNUSED finalize) +{ + int ret = MCHECKSUM_SUCCESS; + + if (size < sizeof(mchecksum_uint32_t)) { + MCHECKSUM_ERROR_DEFAULT("Buffer is too small to store checksum"); + ret = MCHECKSUM_FAIL; + goto done; + } + + *(mchecksum_uint32_t*) buf = *(mchecksum_uint32_t*) checksum_class->data; + +done: + return ret; +} + +/*---------------------------------------------------------------------------*/ +static int +mchecksum_adler32_update(struct mchecksum_class *checksum_class, + const void *data, size_t size) +{ + mchecksum_uint32_t *state = (mchecksum_uint32_t*) checksum_class->data; + + *state = (mchecksum_uint32_t) adler32(*state, data, (unsigned int) size); + + return MCHECKSUM_SUCCESS; +} diff --git a/src/mchecksum/src/mchecksum_zlib.h b/src/mchecksum/src/mchecksum_zlib.h new file mode 100644 index 00000000..57c37545 --- /dev/null +++ b/src/mchecksum/src/mchecksum_zlib.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2013-2019 Argonne National Laboratory, Department of Energy, + * UChicago Argonne, LLC and The HDF Group. + * All rights reserved. + * + * The full copyright notice, including terms governing use, modification, + * and redistribution, is contained in the COPYING file that can be + * found at the root of the source code distribution tree. + */ + +#ifndef MCHECKSUM_ZLIB_H +#define MCHECKSUM_ZLIB_H + +#include "mchecksum_plugin.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \param checksum_class [IN/OUT] pointer to checksum class + * + * \return Non-negative on success or negative on failure + */ +MCHECKSUM_EXPORT int +mchecksum_crc32_init(struct mchecksum_class *checksum_class); + +MCHECKSUM_EXPORT int +mchecksum_adler32_init(struct mchecksum_class *checksum_class); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/mchecksum/version.txt b/src/mchecksum/version.txt new file mode 100644 index 00000000..3eefcb9d --- /dev/null +++ b/src/mchecksum/version.txt @@ -0,0 +1 @@ +1.0.0 diff --git a/src/mercury.c b/src/mercury.c index 1933405e..0cece056 100644 --- a/src/mercury.c +++ b/src/mercury.c @@ -22,6 +22,10 @@ #include #include +/* PVAR profiling support */ +#include "mercury_prof_pvar_impl.h" +#include "mercury_time.h" + /****************/ /* Local Macros */ /****************/ @@ -55,22 +59,29 @@ struct hg_proc_info { /* HG handle */ struct hg_private_handle { - struct hg_handle handle; /* Must remain as first field */ - struct hg_header hg_header; /* Header for input/output */ - hg_cb_t forward_cb; /* Forward callback */ - hg_cb_t respond_cb; /* Respond callback */ - hg_return_t (*extra_bulk_transfer_cb)( - hg_core_handle_t); /* Bulk transfer callback */ - void *forward_arg; /* Forward callback args */ - void *respond_arg; /* Respond callback args */ - void *in_extra_buf; /* Extra input buffer */ - void *out_extra_buf; /* Extra output buffer */ - hg_proc_t in_proc; /* Proc for input */ - hg_proc_t out_proc; /* Proc for output */ - hg_bulk_t in_extra_bulk; /* Extra input bulk handle */ - hg_bulk_t out_extra_bulk; /* Extra output bulk handle */ - hg_size_t in_extra_buf_size; /* Extra input buffer size */ - hg_size_t out_extra_buf_size; /* Extra output buffer size */ + struct hg_handle handle; /* Must remain as first field */ + struct hg_header hg_header; /* Header for input/output */ + hg_cb_t forward_cb; /* Forward callback */ + hg_cb_t respond_cb; /* Respond callback */ + hg_return_t (*extra_bulk_transfer_cb)(hg_core_handle_t); /* Bulk transfer callback */ + void *forward_arg; /* Forward callback args */ + void *respond_arg; /* Respond callback args */ + void *in_extra_buf; /* Extra input buffer */ + void *out_extra_buf; /* Extra output buffer */ + hg_proc_t in_proc; /* Proc for input */ + hg_proc_t out_proc; /* Proc for output */ + hg_bulk_t in_extra_bulk; /* Extra input bulk handle */ + hg_bulk_t out_extra_bulk; /* Extra output bulk handle */ + hg_size_t in_extra_buf_size; /* Extra input buffer size */ + hg_size_t out_extra_buf_size; /* Extra output buffer size */ + /* PVAR */ + double hg_pvar_hg_input_serial_time; + double hg_pvar_hg_output_serial_time; + double hg_pvar_hg_input_deserial_time; + double hg_pvar_hg_output_deserial_time; + double hg_pvar_hg_internal_rdma_transfer_time; + size_t hg_pvar_hg_internal_rdma_transfer_size; + }; /* HG op id */ @@ -208,6 +219,36 @@ static const char *const hg_return_name[] = {HG_RETURN_VALUES}; unsigned int HG_LOG_MASK = HG_LOG_TYPE_ERROR | HG_LOG_TYPE_WARNING; #endif +/*---------------------------------------------------------------------------*/ +void hg_get_handle_pvar_data(int index, hg_handle_t handle, void *buf) +{ + + HG_PROF_PVAR_GET_INDEX_BY_NAME(hg_pvar_hg_input_serial_time, input_serial_time_pvar_index); + HG_PROF_PVAR_GET_INDEX_BY_NAME(hg_pvar_hg_output_serial_time, output_serial_time_pvar_index); + HG_PROF_PVAR_GET_INDEX_BY_NAME(hg_pvar_hg_input_deserial_time, input_deserial_time_pvar_index); + HG_PROF_PVAR_GET_INDEX_BY_NAME(hg_pvar_hg_output_deserial_time, output_deserial_time_pvar_index); + HG_PROF_PVAR_GET_INDEX_BY_NAME(hg_pvar_hg_internal_rdma_transfer_time, internal_rdma_transfer_time_pvar_index); + HG_PROF_PVAR_GET_INDEX_BY_NAME(hg_pvar_hg_internal_rdma_transfer_size, internal_rdma_transfer_size_pvar_index); + + struct hg_private_handle *private_handle = (struct hg_private_handle *)handle; + + if(index == input_serial_time_pvar_index) { + *(double *)buf = private_handle->hg_pvar_hg_input_serial_time; + } else if (index == output_serial_time_pvar_index) { + *(double *)buf = private_handle->hg_pvar_hg_output_serial_time; + } else if (index == input_deserial_time_pvar_index) { + *(double *)buf = private_handle->hg_pvar_hg_input_deserial_time; + } else if (index == output_deserial_time_pvar_index) { + *(double *)buf = private_handle->hg_pvar_hg_output_deserial_time; + } else if(index == internal_rdma_transfer_time_pvar_index) { + *(double *)buf = private_handle->hg_pvar_hg_internal_rdma_transfer_time; + } else if (index == internal_rdma_transfer_size_pvar_index) { + *(size_t *)buf = private_handle->hg_pvar_hg_internal_rdma_transfer_size; + } else { + HG_Core_get_handle_pvar_data(index, handle->core_handle, buf); + } +} + /*---------------------------------------------------------------------------*/ /** * Free function for value in function map. @@ -754,6 +795,10 @@ hg_get_extra_payload(struct hg_private_handle *hg_handle, hg_op_t op, hg_bulk_t local_handle = HG_BULK_NULL; hg_return_t ret = HG_SUCCESS; + hg_time_t t1, t2; + + hg_time_get_current(&t1); + switch (op) { case HG_INPUT: /* Use custom header offset */ @@ -826,6 +871,11 @@ hg_get_extra_payload(struct hg_private_handle *hg_handle, hg_op_t op, HG_Bulk_free(*extra_bulk); *extra_bulk = HG_BULK_NULL; } + + hg_time_get_current(&t2); + hg_handle->hg_pvar_hg_internal_rdma_transfer_time = hg_time_to_double(hg_time_subtract(t2, t1)); + hg_handle->hg_pvar_hg_internal_rdma_transfer_size = *extra_buf_size; + return ret; } @@ -976,6 +1026,12 @@ HG_Init_opt(const char *na_info_string, hg_bool_t na_listen, HG_Core_set_more_data_callback( hg_class->hg_class.core_class, hg_more_data_cb, hg_more_data_free_cb); + + /* Initialize PVAR profiling data structures */ + int ret = hg_prof_pvar_init(); + + assert(ret == HG_SUCCESS); + return (hg_class_t *) hg_class; error: @@ -1000,6 +1056,9 @@ HG_Finalize(hg_class_t *hg_class) hg_thread_spin_destroy(&private_class->register_lock); free(private_class); + /* Finalize PVAR data structures */ + hg_prof_pvar_finalize(); + done: return ret; } @@ -1663,6 +1722,9 @@ HG_Reset(hg_handle_t handle, hg_addr_t addr, hg_id_t id) hg_return_t HG_Get_input(hg_handle_t handle, void *in_struct) { + hg_time_t t1, t2; + hg_time_get_current(&t1); + const struct hg_proc_info *hg_proc_info; hg_return_t ret = HG_SUCCESS; @@ -1683,6 +1745,9 @@ HG_Get_input(hg_handle_t handle, void *in_struct) HG_CHECK_HG_ERROR( done, ret, "Could not get input (%s)", HG_Error_to_string(ret)); + hg_time_get_current(&t2); + struct hg_private_handle * private_handle = (struct hg_private_handle *) handle; + private_handle->hg_pvar_hg_input_deserial_time = hg_time_to_double(hg_time_subtract(t2, t1)); done: return ret; } @@ -1719,6 +1784,9 @@ HG_Free_input(hg_handle_t handle, void *in_struct) hg_return_t HG_Get_output(hg_handle_t handle, void *out_struct) { + hg_time_t t1, t2; + hg_time_get_current(&t1); + const struct hg_proc_info *hg_proc_info; hg_return_t ret = HG_SUCCESS; @@ -1739,6 +1807,11 @@ HG_Get_output(hg_handle_t handle, void *out_struct) HG_CHECK_HG_ERROR( done, ret, "Could not get output (%s)", HG_Error_to_string(ret)); + hg_time_get_current(&t2); + + struct hg_private_handle * private_handle = (struct hg_private_handle *) handle; + private_handle->hg_pvar_hg_output_deserial_time = hg_time_to_double(hg_time_subtract(t2, t1)); + done: return ret; } @@ -1887,8 +1960,10 @@ HG_Forward(hg_handle_t handle, hg_cb_t callback, void *arg, void *in_struct) hg_uint8_t flags = 0; hg_return_t ret = HG_SUCCESS; - HG_CHECK_ERROR( - handle == HG_HANDLE_NULL, done, ret, HG_INVALID_ARG, "NULL HG handle"); + HG_PROF_PVAR_UINT_COUNTER(hg_pvar_hg_forward_count); + + HG_CHECK_ERROR(handle == HG_HANDLE_NULL, done, ret, HG_INVALID_ARG, + "NULL HG handle"); /* Set callback data */ private_handle->forward_cb = callback; @@ -1901,10 +1976,16 @@ HG_Forward(hg_handle_t handle, hg_cb_t callback, void *arg, void *in_struct) hg_proc_info == NULL, done, ret, HG_FAULT, "Could not get proc info"); /* Set input struct */ + hg_time_t t1, t2; + hg_time_get_current(&t1); ret = hg_set_struct(private_handle, hg_proc_info, HG_INPUT, in_struct, &payload_size, &more_data); - HG_CHECK_HG_ERROR( - done, ret, "Could not set input (%s)", HG_Error_to_string(ret)); + + hg_time_get_current(&t2); + private_handle->hg_pvar_hg_input_serial_time = hg_time_to_double(hg_time_subtract(t2, t1)); + + HG_CHECK_HG_ERROR(done, ret, "Could not set input (%s)", + HG_Error_to_string(ret)); /* Set more data flag on handle so that handle_more_callback is triggered */ if (more_data) @@ -1922,6 +2003,9 @@ HG_Forward(hg_handle_t handle, hg_cb_t callback, void *arg, void *in_struct) HG_CHECK_HG_ERROR( done, ret, "Could not forward call (%s)", HG_Error_to_string(ret)); + /* PVAR profiling support: Increment the value of the PVAR with the name "hg_pvar_hg_forward_count" */ + HG_PROF_PVAR_UINT_COUNTER_INC(hg_pvar_hg_forward_count, 1); + done: return ret; } @@ -1938,8 +2022,10 @@ HG_Respond(hg_handle_t handle, hg_cb_t callback, void *arg, void *out_struct) hg_uint8_t flags = 0; hg_return_t ret = HG_SUCCESS; - HG_CHECK_ERROR( - handle == HG_HANDLE_NULL, done, ret, HG_INVALID_ARG, "NULL HG handle"); + hg_time_t t1, t2; + + HG_CHECK_ERROR(handle == HG_HANDLE_NULL, done, ret, HG_INVALID_ARG, + "NULL HG handle"); /* Set callback data */ private_handle->respond_cb = callback; @@ -1952,10 +2038,15 @@ HG_Respond(hg_handle_t handle, hg_cb_t callback, void *arg, void *out_struct) hg_proc_info == NULL, done, ret, HG_FAULT, "Could not get proc info"); /* Set output struct */ + hg_time_get_current(&t1); ret = hg_set_struct(private_handle, hg_proc_info, HG_OUTPUT, out_struct, &payload_size, &more_data); - HG_CHECK_HG_ERROR( - done, ret, "Could not set output (%s)", HG_Error_to_string(ret)); + hg_time_get_current(&t2); + + private_handle->hg_pvar_hg_output_serial_time = hg_time_to_double(hg_time_subtract(t2, t1)); + + HG_CHECK_HG_ERROR(done, ret, "Could not set output (%s)", + HG_Error_to_string(ret)); /* Set more data flag on handle so that handle_more_callback is triggered */ if (more_data) diff --git a/src/mercury_core.c b/src/mercury_core.c index d5b4947a..486c11f3 100644 --- a/src/mercury_core.c +++ b/src/mercury_core.c @@ -27,6 +27,9 @@ #include "mercury_thread_spin.h" #include "mercury_time.h" +/* PVAR profiling support */ +#include "mercury_prof_pvar_impl.h" + #ifdef HG_HAS_SM_ROUTING # include #endif @@ -185,6 +188,8 @@ typedef enum { /* HG core handle */ struct hg_core_private_handle { + + /* PVAR */ struct hg_core_handle core_handle; /* Must remain as first field */ struct hg_completion_entry hg_completion_entry; /* Entry in completion queue */ @@ -227,6 +232,8 @@ struct hg_core_private_handle { hg_bool_t repost; /* Repost handle on completion (listen) */ hg_bool_t is_self; /* Self processed */ hg_bool_t no_response; /* Require response or not */ + hg_time_t completion_add_time; + double hg_pvar_hg_origin_callback_completion_time; }; /* HG op id */ @@ -627,6 +634,19 @@ static hg_core_stat_t hg_core_rpc_extra_count_g = HG_CORE_STAT_INIT(0); static hg_core_stat_t hg_core_bulk_count_g = HG_CORE_STAT_INIT(0); #endif +/*---------------------------------------------------------------------------*/ +void HG_Core_get_handle_pvar_data(int index, hg_core_handle_t handle, void *buf) +{ + + HG_PROF_PVAR_GET_INDEX_BY_NAME(hg_pvar_hg_origin_callback_completion_time, origin_callback_completion_time_pvar_index); + + struct hg_core_private_handle *private_handle = (struct hg_core_private_handle *)handle; + + if(index == origin_callback_completion_time_pvar_index) { + *(double *)buf = private_handle->hg_pvar_hg_origin_callback_completion_time; + } +} + /*---------------------------------------------------------------------------*/ #ifdef HG_HAS_COLLECT_STATS static void @@ -1571,6 +1591,7 @@ hg_core_reset( hg_core_handle->na_op_count = 1; /* Default (no response) */ hg_atomic_set32(&hg_core_handle->na_op_completed_count, 0); hg_core_handle->no_response = HG_FALSE; + hg_core_handle->hg_pvar_hg_origin_callback_completion_time = 0; /* Free extra data here if needed */ if (HG_CORE_HANDLE_CLASS(hg_core_handle)->more_data_release) @@ -1919,6 +1940,10 @@ hg_core_recv_input_cb(const struct na_cb_info *callback_info) hg_bool_t completed = HG_TRUE; hg_return_t ret; + + HG_PROF_PVAR_UINT_COUNTER(hg_pvar_num_posted_handles); + HG_PROF_PVAR_UINT_COUNTER_INC(hg_pvar_num_posted_handles, 1); + /* Remove handle from pending list */ hg_thread_spin_lock( &HG_CORE_HANDLE_CONTEXT(hg_core_handle)->pending_list_lock); @@ -2400,11 +2425,12 @@ hg_core_complete(hg_core_handle_t handle) hg_completion_entry->op_type = HG_RPC; hg_completion_entry->op_id.hg_core_handle = handle; - ret = hg_core_completion_add( - context, hg_completion_entry, hg_core_handle->is_self); - HG_CHECK_HG_ERROR( - done, ret, "Could not add HG completion entry to completion queue"); - + /* PVAR */ + hg_time_get_current(&(hg_core_handle->completion_add_time)); + ret = hg_core_completion_add(context, hg_completion_entry, + hg_core_handle->is_self); + HG_CHECK_HG_ERROR(done, ret, + "Could not add HG completion entry to completion queue"); done: return ret; } @@ -2418,6 +2444,9 @@ hg_core_completion_add(struct hg_core_context *context, (struct hg_core_private_context *) context; hg_return_t ret = HG_SUCCESS; + HG_PROF_PVAR_UINT_COUNTER(hg_pvar_hg_backfill_queue_count); + HG_PROF_PVAR_UINT_COUNTER(hg_pvar_hg_completion_queue_count); + #ifdef HG_HAS_COLLECT_STATS /* Increment counter */ if (hg_completion_entry->op_type == HG_BULK) @@ -2432,8 +2461,12 @@ hg_core_completion_add(struct hg_core_context *context, &private_context->backfill_queue, hg_completion_entry, entry); hg_atomic_incr32(&private_context->backfill_queue_count); hg_thread_mutex_unlock(&private_context->completion_queue_mutex); + + HG_PROF_PVAR_UINT_COUNTER_INC(hg_pvar_hg_backfill_queue_count, 1); } + HG_PROF_PVAR_UINT_COUNTER_INC(hg_pvar_hg_completion_queue_count, 1); + if (hg_atomic_get32(&private_context->trigger_waiting)) { hg_thread_mutex_lock(&private_context->completion_queue_mutex); /* Callback is pushed to the completion queue when something completes @@ -2526,6 +2559,8 @@ hg_core_post(struct hg_core_private_handle *hg_core_handle) /* Handle is now in use */ hg_atomic_set32(&hg_core_handle->in_use, HG_TRUE); + HG_PROF_PVAR_UINT_COUNTER(hg_pvar_num_posted_handles); + HG_PROF_PVAR_UINT_COUNTER_DECR(hg_pvar_num_posted_handles, 1); #ifdef HG_HAS_SM_ROUTING if (hg_core_handle->na_class == @@ -2857,6 +2892,9 @@ hg_core_trigger(struct hg_core_private_context *context, unsigned int timeout, unsigned int count = 0; hg_return_t ret = HG_SUCCESS; + HG_PROF_PVAR_UINT_COUNTER(hg_pvar_hg_backfill_queue_count); + HG_PROF_PVAR_UINT_COUNTER(hg_pvar_hg_completion_queue_count); + while (count < max_count) { struct hg_completion_entry *hg_completion_entry = NULL; @@ -2869,6 +2907,7 @@ hg_core_trigger(struct hg_core_private_context *context, unsigned int timeout, HG_QUEUE_POP_HEAD(&context->backfill_queue, entry); hg_atomic_decr32(&context->backfill_queue_count); hg_thread_mutex_unlock(&context->completion_queue_mutex); + HG_PROF_PVAR_UINT_COUNTER_DECR(hg_pvar_hg_backfill_queue_count, 1); if (!hg_completion_entry) continue; /* Give another change to grab it */ } else { @@ -2911,6 +2950,8 @@ hg_core_trigger(struct hg_core_private_context *context, unsigned int timeout, } } + HG_PROF_PVAR_UINT_COUNTER_DECR(hg_pvar_hg_completion_queue_count, 1); + /* Completion queue should not be empty now */ HG_CHECK_ERROR(hg_completion_entry == NULL, done, ret, HG_FAULT, "NULL completion entry"); @@ -2986,6 +3027,11 @@ hg_core_trigger_entry(struct hg_core_private_handle *hg_core_handle) /* Take another reference to make sure the handle does not get freed */ hg_atomic_incr32(&hg_core_handle->ref_count); + /* PVAR */ + hg_time_t t2; + hg_time_get_current(&t2); + hg_core_handle->hg_pvar_hg_origin_callback_completion_time = hg_time_to_double(hg_time_subtract(t2, hg_core_handle->completion_add_time)); + /* Run RPC callback */ ret = hg_core_process(hg_core_handle); if (ret != HG_SUCCESS && !hg_core_handle->no_response) { diff --git a/src/mercury_core.h b/src/mercury_core.h index 575cf4eb..3a63b808 100644 --- a/src/mercury_core.h +++ b/src/mercury_core.h @@ -830,6 +830,18 @@ HG_PUBLIC hg_return_t HG_Core_trigger(hg_core_context_t *context, unsigned int timeout, unsigned int max_count, unsigned int *actual_count); +/** + * Get PVAR data associated with the core handle + * + * \param index [IN] PVAR index + * \param handle [IN] core handle + * \param buf [OUT] buffer containing PVAR data + * + * \return void + */ +HG_PUBLIC void +HG_Core_get_handle_pvar_data(int index, hg_core_handle_t handle, void *buf); + /** * Cancel an ongoing operation. * diff --git a/src/mercury_prof_interface.c b/src/mercury_prof_interface.c new file mode 100644 index 00000000..4e0fdaef --- /dev/null +++ b/src/mercury_prof_interface.c @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2013-2020 Argonne National Laboratory, Department of Energy, + * UChicago Argonne, LLC and The HDF Group. + * All rights reserved. + * + * The full copyright notice, including terms governing use, modification, + * and redistribution, is contained in the COPYING file that can be + * found at the root of the source code distribution tree. + */ + +#include "mercury.h" +#include "mercury_bulk.h" +#include "mercury_core.h" +#include "mercury_private.h" +#include "mercury_error.h" + +#include "mercury_atomic.h" +#include "mercury_types.h" +#include "mercury_prof_interface.h" +#include "mercury_prof_pvar_impl.h" + +#include +#include +#include + +/************************************/ +/* Local Type and Struct Definition */ +/************************************/ + +/* HG profiling PVAR handle object concrete definition */ +struct hg_prof_pvar_handle { + hg_prof_class_t pvar_class; /* PVAR class */ + hg_prof_datatype_t pvar_datatype; /* PVAR datatype */ + hg_prof_bind_t pvar_bind; /* PVAR binding */ + int continuous; /* is PVAR continuous or not */ + void * addr; /* actual address of PVAR */ + int is_started; /* if continuous, has PVAR been started? */ + int count; /* number of values associated with PVAR */ + char name[128]; /* PVAR name */ + char description[128]; /* PVAR description */ + int index; /* PVAR index */ +}; + +/* HG profiling session object concrete definition */ +struct hg_prof_pvar_session { + hg_prof_pvar_handle_t * pvar_handle_array; /* PVAR handle array */ + int is_initialized; /* Is profiling initialized */ +}; + +/* HG class */ +struct hg_private_class { + struct hg_class hg_class; /* Must remain as first field */ + int hg_prof_is_initialized; /* Is profiling initialized */ + int num_pvars; /* No of PVARs currently supported */ + hg_prof_pvar_session_t session; /* Is profiling initialized on the session */ +}; + +/*******************/ +/* Externs */ +/*******************/ +extern void * hg_get_handle_pvar_data(int index, hg_handle_t mercury_handle, void * buf); + +/*******************/ +/* Local Variables */ +/*******************/ + +/*---------------------------------------------------------------------------*/ +static void +hg_prof_set_is_initialized(struct hg_private_class * hg_private_class) +{ + hg_private_class->hg_prof_is_initialized = 1; +} + +/*---------------------------------------------------------------------------*/ +static int +hg_prof_get_is_initialized(struct hg_private_class * hg_private_class) { + return hg_private_class->hg_prof_is_initialized; +} + +/*---------------------------------------------------------------------------*/ +static void +hg_prof_set_session_is_initialized(struct hg_prof_pvar_session * session) +{ + session->is_initialized = 1; +} + +/*---------------------------------------------------------------------------*/ +static int +hg_prof_get_session_is_initialized(struct hg_prof_pvar_session * session) { + return session->is_initialized; +} + +/*---------------------------------------------------------------------------*/ +hg_return_t +HG_Prof_init(hg_class_t *hg_class) { + + struct hg_private_class *hg_private_class = (struct hg_private_class *)(hg_class); + + hg_prof_set_is_initialized(hg_private_class); + hg_private_class->num_pvars = NUM_PVARS; + hg_private_class->session = NULL; + + return HG_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +hg_return_t +HG_Prof_finalize(hg_class_t *hg_class) { + + struct hg_private_class *hg_private_class = (struct hg_private_class *)(hg_class); + + if(hg_prof_get_is_initialized(hg_private_class)) { + hg_prof_set_is_initialized(hg_private_class); + hg_private_class->session = NULL; + } + + return HG_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +int +HG_Prof_pvar_get_num(hg_class_t *hg_class) { + struct hg_private_class *hg_private_class = (struct hg_private_class *)(hg_class); + + if(hg_prof_get_is_initialized(hg_private_class)) { + return hg_private_class->num_pvars; + } else { + return 0; + } +} + +/*---------------------------------------------------------------------------*/ +hg_return_t +HG_Prof_pvar_get_info(hg_class_t *hg_class, int pvar_index, char *name, int *name_len, hg_prof_class_t *var_class, hg_prof_datatype_t *datatype, char *desc, int *desc_len, hg_prof_bind_t *bind, int *continuous) { + + struct hg_private_class *hg_private_class = (struct hg_private_class *)(hg_class); + + if(!hg_prof_get_is_initialized(hg_private_class)) + return HG_NA_ERROR; + + assert(pvar_index < NUM_PVARS); + + unsigned int key = pvar_index; + hg_prof_pvar_data_t * val; + + /* Lookup the internal PVAR hash table to gather information about this PVAR */ + val = hg_prof_pvar_table_lookup(key); + strcpy(name, (*val).name); + *name_len = strlen(name); + strcpy(desc, (*val).description); + *desc_len = strlen(desc); + *var_class = (*val).pvar_class; + *datatype = (*val).pvar_datatype; + *bind = (*val).pvar_bind; + *continuous = (*val).continuous; + + return HG_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +hg_return_t +HG_Prof_pvar_session_create(hg_class_t *hg_class, hg_prof_pvar_session_t *session) { + + struct hg_private_class *hg_private_class = (struct hg_private_class *)(hg_class); + + if(!hg_prof_get_is_initialized(hg_private_class)) + return HG_NA_ERROR; + + (*session) = (hg_prof_pvar_session_t)malloc(sizeof(struct hg_prof_pvar_session)); + (*session)->pvar_handle_array = (hg_prof_pvar_handle_t *)malloc(sizeof(hg_prof_pvar_handle_t)*NUM_PVARS); + hg_private_class->session = (*session); + + hg_prof_set_session_is_initialized((*session)); + + return HG_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +hg_return_t +HG_Prof_pvar_session_destroy(hg_class_t *hg_class, hg_prof_pvar_session_t *session) { + + struct hg_private_class *hg_private_class = (struct hg_private_class *)(hg_class); + + if(!hg_prof_get_is_initialized(hg_private_class)) + return HG_NA_ERROR; + + free((*session)->pvar_handle_array); + free((*session)); + hg_private_class->session = NULL; + + return HG_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +hg_return_t +HG_Prof_pvar_handle_alloc(hg_prof_pvar_session_t session, int pvar_index, void *obj_handle, hg_prof_pvar_handle_t *handle, int *count) { + + if(!hg_prof_get_session_is_initialized(session)) + return HG_NA_ERROR; + + /* Only supporting a null bind type at the moment */ + assert(obj_handle == NULL); + + struct hg_prof_pvar_session s = *session; + unsigned int key = pvar_index; + hg_prof_pvar_data_t * val; + + s.pvar_handle_array[pvar_index] = (hg_prof_pvar_handle_t)malloc(sizeof(struct hg_prof_pvar_handle)); + val = hg_prof_pvar_table_lookup(key); + + /* Copy out information from the internal PVAR hash table */ + (*s.pvar_handle_array[pvar_index]).pvar_class = (*val).pvar_class; + (*s.pvar_handle_array[pvar_index]).pvar_datatype = (*val).pvar_datatype; + (*s.pvar_handle_array[pvar_index]).pvar_bind = (*val).pvar_bind; + (*s.pvar_handle_array[pvar_index]).continuous = (*val).continuous; + (*s.pvar_handle_array[pvar_index]).is_started = 0; + (*s.pvar_handle_array[pvar_index]).index = pvar_index; + (*s.pvar_handle_array[pvar_index]).addr = (*val).addr; + if((*val).continuous) + (*s.pvar_handle_array[pvar_index]).is_started = 1; + strcpy((*s.pvar_handle_array[pvar_index]).name, (*val).name); + strcpy((*s.pvar_handle_array[pvar_index]).description, (*val).description); + *count = (*val).count; + + /* Return handle */ + *handle = s.pvar_handle_array[pvar_index]; + + return HG_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +hg_return_t +HG_Prof_pvar_handle_free(hg_prof_pvar_session_t session, int pvar_index, hg_prof_pvar_handle_t *handle) { + + if(!hg_prof_get_session_is_initialized(session)) + return HG_NA_ERROR; + + + struct hg_prof_pvar_session s = *session; + assert(s.pvar_handle_array[pvar_index] == *handle); + free(s.pvar_handle_array[pvar_index]); + s.pvar_handle_array[pvar_index] = NULL; + *handle = NULL; + + return HG_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +hg_return_t +HG_Prof_pvar_start(hg_prof_pvar_session_t session, hg_prof_pvar_handle_t handle) { + if(!hg_prof_get_session_is_initialized(session)) + return HG_NA_ERROR; + + if (!(*handle).continuous && !((*handle).is_started)) + (*handle).is_started = 1; + return HG_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +hg_return_t +HG_Prof_pvar_stop(hg_prof_pvar_session_t session, hg_prof_pvar_handle_t handle) { + if(!hg_prof_get_session_is_initialized(session)) + return HG_NA_ERROR; + + if (!(*handle).continuous && ((*handle).is_started)) + (*handle).is_started = 0; + return HG_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +hg_return_t +HG_Prof_pvar_read(hg_prof_pvar_session_t session, hg_prof_pvar_handle_t handle, hg_handle_t mercury_handle, void *buf) { + if(!hg_prof_get_session_is_initialized(session)) + return HG_NA_ERROR; + + /* Assert first that handle belongs to the session provided. NOT DOING THIS HERE FOR NOW */ + struct hg_prof_pvar_handle h = (*handle); + + if(h.pvar_bind == HG_PROF_BIND_NO_OBJECT) { + switch(h.pvar_datatype) { + case HG_UINT: + /*for(int i = 0; i < h.count; h++)*/ /* Need to support PVAR arrays, just a placeholder that assumes PVAR count is 1 */ + *((unsigned int *)buf) = *((unsigned int *)h.addr); + break; + case HG_DOUBLE: + *((double *)buf) = *((double *)h.addr); + break; + } + } else { + /*for(int i = 0; i < h.count; h++)*/ /* Need to support PVAR arrays, just a placeholder that assumes PVAR count is 1 */ + hg_get_handle_pvar_data(h.index, mercury_handle, buf); + } + return HG_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ diff --git a/src/mercury_prof_interface.h b/src/mercury_prof_interface.h new file mode 100644 index 00000000..bea7b8f5 --- /dev/null +++ b/src/mercury_prof_interface.h @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2013-2020 Argonne National Laboratory, Department of Energy, + * UChicago Argonne, LLC and The HDF Group. + * All rights reserved. + * + * The full copyright notice, including terms governing use, modification, + * and redistribution, is contained in the COPYING file that can be + * found at the root of the source code distribution tree. + */ + +#ifndef MERCURY_PROF_INTERFACE_H +#define MERCURY_PROF_INTERFACE_H + +#include "mercury_types.h" +#include "mercury_prof_types.h" + + +/*************************************/ +/* Note */ +/*************************************/ + +/* Refer to: https://www.mpi-forum.org/docs/mpi-3.1/mpi31-report/node372.htm#Node372 + * for the corresponding MPI 3.1 PVAR interface specification that this implementation is largely based off of. + * + * Notable differences with MPI (implementation, not interface spec): + * 1. PVAR sessions in Mercury are associated with the hg_class object to avoid the use of global variables. + * 2. Similarly, PVARs themselves are not global variables and aren't declared globally and used as such. + * Instead, each module interested in exporting PVARs must register these PVARs and refer to them by the + * use of handles (that internally fetch the address of the PVAR) within the local function where these PVARs are updated. + * 3. We used atomics for updating counter PVARs where MPI does not. + */ + +/*************************************/ +/* Public Type and Struct Definition */ +/*************************************/ + +/* See mercury_prof_types.h */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Client-side API to initialize the PVAR profiling interface. + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t +HG_Prof_init(hg_class_t *hg_class); + +/** + * Client-side API to finalize the PVAR profiling interface. + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t +HG_Prof_finalize(hg_class_t *hg_class); + +/** + * Create a session. + * + * \param hg_class [IN/OUT] pointer to HG_CLASS + * \param session [IN/OUT] pointer to PVAR session object + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t +HG_Prof_pvar_session_create(hg_class_t *hg_class, hg_prof_pvar_session_t *session); + +/** + * Destroy a session. + * + * \param hg_class [IN/OUT] pointer to HG_CLASS + * \param session [IN/OUT] pointer to PVAR session object + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t +HG_Prof_pvar_session_destroy(hg_class_t *hg_class, hg_prof_pvar_session_t *session); + +/** + * Client-side API to retrieve the number of PVARs currently exported. + * + * \return int representing the number of PVARs + */ +HG_PUBLIC int +HG_Prof_pvar_get_num(hg_class_t* hg_class); + +/** + * Gather information about every PVAR exported. This API is necessary in order for the client to discover the types, bindings, etc. + * The client can then allocate the necessary data structures using this information. + * + * \param pvar_index [IN] PVAR index + * \param name [IN/OUT] pointer to the string array containing the PVAR name + * \param name_len [IN/OUT] pointer to the integer address holding the number of characters in the name array + * \param var_class [IN/OUT] pointer to the object denoting the PVAR class + * \param datatype [IN/OUT] pointer to the object denoting the PVAR datatype + * \param desc [IN/OUT] pointer to the string array containing the PVAR description + * \param desc_len [IN/OUT] pointer to the integer address holding the number of characters in the description array + * \param bind [IN/OUT] pointer to the object denoting PVAR binding + * \param continuous [IN/OUT] pointer to the integer address denoting if the PVAR is continuous or not + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t +HG_Prof_pvar_get_info(hg_class_t *hg_class, int pvar_index, char *name, int *name_len, + hg_prof_class_t *var_class, hg_prof_datatype_t *datatype, + char *desc, int *desc_len, hg_prof_bind_t *bind, int *continuous); + +/** + * Allocate a handle for a PVAR at a given index. + * This handle will later be used by the client to query the value for the PVAR. + * This handle is an opaque object. + * + * \param session [IN] opaque PVAR session object + * \param pvar_index [IN] PVAR index + * \param obj_handle [IN] pointer to the object handle with which the PVAR is associated; can be NULL + * \param handle [IN/OUT] pointer to the opaque PVAR handle object that is returned to the calling client + * \param count [IN/OUT] pointer to the integer address representing the number of values associated with the PVAR + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t +HG_Prof_pvar_handle_alloc(hg_prof_pvar_session_t session, + int pvar_index, void *obj_handle, hg_prof_pvar_handle_t *handle, int *count); + +/** + * Free handle for a PVAR at a given index. + * + * \param session [IN] opaque PVAR session object + * \param pvar_index [IN] PVAR index + * \param handle [IN/OUT] pointer to the opaque PVAR handle object that is returned to the calling client + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t +HG_Prof_pvar_handle_free(hg_prof_pvar_session_t session, + int pvar_index, hg_prof_pvar_handle_t *handle); + +/** + * Start the PVAR is it is not continuous and has not been started yet. + * + * \param session [IN] opaque PVAR session object + * \param handle [IN] opaque PVAR handle object + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t +HG_Prof_pvar_start(hg_prof_pvar_session_t session, hg_prof_pvar_handle_t handle); + +/** + * Stop the PVAR is it is not continuous and has been started. + * + * \param session [IN] opaque PVAR session object + * \param handle [IN] opaque PVAR handle object + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t +HG_Prof_pvar_stop(hg_prof_pvar_session_t session, hg_prof_pvar_handle_t handle); + +/** + * Read the value of the PVAR when the client supplies the handle. + * Note that the handle is necessary as the input (instead of the pvar_index) because there may be multiple PVAR sessions in flight. + * + * \param session [IN] opaque PVAR session object + * \param handle [IN] opaque PVAR handle object + * \param mercury_handle [IN] opaque hg_handle object, can be NULL + * \param buf [IN/OUT] buffer that contains the PVAR data + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t +HG_Prof_pvar_read(hg_prof_pvar_session_t session, hg_prof_pvar_handle_t handle, hg_handle_t mercury_handle, void *buf); + +#ifdef __cplusplus +} +#endif + +#endif /* MERCURY_PROF_INTERFACE_H */ diff --git a/src/mercury_prof_pvar_impl.c b/src/mercury_prof_pvar_impl.c new file mode 100644 index 00000000..c85043d4 --- /dev/null +++ b/src/mercury_prof_pvar_impl.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2013-2020 Argonne National Laboratory, Department of Energy, + * UChicago Argonne, LLC and The HDF Group. + * All rights reserved. + * + * The full copyright notice, including terms governing use, modification, + * and redistribution, is contained in the COPYING file that can be + * found at the root of the source code distribution tree. + */ + +#include "mercury_bulk.h" +#include "mercury_core.h" +#include "mercury_private.h" +#include "mercury_error.h" + +#include "mercury_atomic.h" +#include "mercury_prof_interface.h" +#include "mercury_prof_pvar_impl.h" + +#include +#include +#include + +/*******************/ +/* Local Variables */ +/*******************/ + +static hg_hash_table_t *pvar_table; /* Internal hash table containing all PVAR info */ + +/* Internal routines for the hash tables */ +static HG_INLINE int +hg_prof_uint_equal(void *vlocation1, void *vlocation2) +{ + return *((unsigned int *) vlocation1) == *((unsigned int *) vlocation2); +} + +/*---------------------------------------------------------------------------*/ +static HG_INLINE unsigned int +hg_prof_uint_hash(void *vlocation) +{ + return *((unsigned int *) vlocation); +} + +/*---------------------------------------------------------------------------*/ +hg_prof_pvar_data_t * +hg_prof_pvar_table_lookup(unsigned int key) +{ + return hg_hash_table_lookup(pvar_table, (hg_hash_table_key_t)(&key)); +} + +/*---------------------------------------------------------------------------*/ +hg_atomic_int32_t * +hg_prof_get_pvar_addr_from_name(const char* name) +{ + hg_prof_pvar_data_t * value = NULL; + + for(unsigned int i = 0; i < hg_hash_table_num_entries(pvar_table); i++) { + value = hg_hash_table_lookup(pvar_table, (hg_hash_table_key_t)(&i)); + if(strcmp(value->name, name)==0) { + break; + } + value = NULL; + } + + if(value != NULL) { + return (hg_atomic_int32_t *)value->addr; + } else { + return NULL; + } +} + +/*---------------------------------------------------------------------------*/ +int +hg_prof_get_pvar_index_from_name(const char* name) +{ + hg_prof_pvar_data_t * value = NULL; + int index = -1; + for(unsigned int i = 0; i < hg_hash_table_num_entries(pvar_table); i++) { + value = hg_hash_table_lookup(pvar_table, (hg_hash_table_key_t)(&i)); + if(strcmp(value->name, name)==0) { + index = i; + break; + } + value = NULL; + } + + return index; +} + +/*---------------------------------------------------------------------------*/ +void +HG_PROF_PVAR_REGISTER_impl(hg_prof_class_t varclass, hg_prof_datatype_t dtype, const char* name, void *addr, int count, + hg_prof_bind_t bind, int continuous, const char * desc) { + + unsigned int * key = NULL; + key = (unsigned int *)malloc(sizeof(unsigned int)); + *key = hg_hash_table_num_entries(pvar_table); + hg_prof_pvar_data_t * pvar_info = NULL; + pvar_info = (hg_prof_pvar_data_t *)malloc(sizeof(hg_prof_pvar_data_t)); + + (*pvar_info).pvar_class = varclass; + (*pvar_info).pvar_datatype = dtype; + (*pvar_info).pvar_bind = bind; + (*pvar_info).count = count; + (*pvar_info).addr = addr; + strcpy((*pvar_info).name, name); + strcpy((*pvar_info).description, desc); + (*pvar_info).continuous = continuous; + + hg_hash_table_insert(pvar_table, (hg_hash_table_key_t)key, (hg_hash_table_value_t)(pvar_info)); +} + +/*---------------------------------------------------------------------------*/ +hg_return_t +hg_prof_pvar_init() { + + /*Initialize internal PVAR data structures*/ + pvar_table = hg_hash_table_new(hg_prof_uint_hash, hg_prof_uint_equal); + /* Register available PVARs */ + HG_PROF_PVAR_UINT_COUNTER_REGISTER(HG_UINT, HG_PROF_BIND_NO_OBJECT, hg_pvar_num_posted_handles, "Number of posted handles", 256); + HG_PROF_PVAR_UINT_COUNTER_REGISTER(HG_UINT, HG_PROF_BIND_NO_OBJECT, hg_pvar_hg_backfill_queue_count, "Backfill queue size", 0); + HG_PROF_PVAR_UINT_COUNTER_REGISTER(HG_UINT, HG_PROF_BIND_NO_OBJECT, hg_pvar_hg_completion_queue_count, "Completion queue size", 0); + HG_PROF_PVAR_UINT_COUNTER_REGISTER(HG_UINT, HG_PROF_BIND_NO_OBJECT, hg_pvar_hg_na_ofi_completion_count, "Number of actual events during a fi_cq_read operation", 0); + HG_PROF_PVAR_UINT_COUNTER_REGISTER(HG_UINT, HG_PROF_BIND_NO_OBJECT, hg_pvar_hg_forward_count, "Number of times HG_Forward has been invoked", 0); + HG_PROF_PVAR_DOUBLE_COUNTER_REGISTER(HG_DOUBLE, HG_PROF_BIND_HANDLE, hg_pvar_hg_origin_callback_completion_time, "Time taken for origin to trigger callback(s)", 0); + HG_PROF_PVAR_DOUBLE_COUNTER_REGISTER(HG_DOUBLE, HG_PROF_BIND_HANDLE, hg_pvar_hg_internal_rdma_transfer_time, "Time taken for internal RDMA transfer(s)", 0); + HG_PROF_PVAR_UINT_COUNTER_REGISTER(HG_UINT, HG_PROF_BIND_HANDLE, hg_pvar_hg_internal_rdma_transfer_size, "Size of internal RDMA transfer (bytes)", 0); + HG_PROF_PVAR_DOUBLE_COUNTER_REGISTER(HG_DOUBLE, HG_PROF_BIND_HANDLE, hg_pvar_hg_input_serial_time, "Time taken to serialize input (s)", 0); + HG_PROF_PVAR_DOUBLE_COUNTER_REGISTER(HG_DOUBLE, HG_PROF_BIND_HANDLE, hg_pvar_hg_input_deserial_time, "Time taken to de-serialize input (s)", 0); + HG_PROF_PVAR_DOUBLE_COUNTER_REGISTER(HG_DOUBLE, HG_PROF_BIND_HANDLE, hg_pvar_hg_output_deserial_time, "Time taken to de-serialize output (s)", 0); + HG_PROF_PVAR_DOUBLE_COUNTER_REGISTER(HG_DOUBLE, HG_PROF_BIND_HANDLE, hg_pvar_hg_output_serial_time, "Time taken to serialize output (s)", 0); + +return HG_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +hg_return_t +hg_prof_pvar_finalize() { + + /*Finalize internal PVAR data structures*/ + hg_hash_table_free(pvar_table); + pvar_table = NULL; + +return HG_SUCCESS; +} diff --git a/src/mercury_prof_pvar_impl.h b/src/mercury_prof_pvar_impl.h new file mode 100644 index 00000000..5d7359b4 --- /dev/null +++ b/src/mercury_prof_pvar_impl.h @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2013-2020 Argonne National Laboratory, Department of Energy, + * UChicago Argonne, LLC and The HDF Group. + * All rights reserved. + * + * The full copyright notice, including terms governing use, modification, + * and redistribution, is contained in the COPYING file that can be + * found at the root of the source code distribution tree. + */ + +#ifndef MERCURY_PROF_PVAR_IMPL_H +#define MERCURY_PROF_PVAR_IMPL_H + +#include "mercury_prof_types.h" +#include "mercury_hash_table.h" +#include "mercury_atomic.h" + +/*************************************/ +/* Public Type and Struct Definition */ + +/*************************************/ + +/* Internal PVAR data structure used to store PVAR data */ +struct hg_prof_pvar_data_t { + hg_prof_class_t pvar_class; /* PVAR class */ + hg_prof_datatype_t pvar_datatype; /* PVAR datatype */ + hg_prof_bind_t pvar_bind; /* PVAR binding */ + int continuous; /* Is PVAR continuous or not */ + void *addr; /* PVAR address */ + int count; /* count of PVAR values */ + char name[128]; /* PVAR name */ + char description[128]; /* PVAR description */ +}; + +typedef struct hg_prof_pvar_data_t hg_prof_pvar_data_t; + +/*****************/ +/* Public Macros */ +/*****************/ + +#define NUM_PVARS 12 /* Number of PVARs currently exported. PVAR indices go from 0......(NUM_PVARS - 1). */ + +/* PVAR handle declaration and registration macros */ +# define HG_PROF_PVAR_GET_INDEX_BY_NAME(name, index) \ + static int index = -1; \ + index = (index == -1)? hg_prof_get_pvar_index_from_name(#name): index; + +#define HG_PROF_PVAR_UINT_COUNTER(name) \ + static hg_atomic_int32_t * addr_##name = NULL; + +#define HG_PROF_PVAR_DOUBLE_COUNTER(name) \ + static double * addr_##name = NULL; + +#define HG_PROF_PVAR_UINT_COUNTER_REGISTER(dtype, bind,\ + name, desc, val) \ + hg_atomic_int32_t *addr_##name = NULL;\ + if(bind == HG_PROF_BIND_NO_OBJECT) {\ + addr_##name = (hg_atomic_int32_t *)malloc(sizeof(hg_atomic_int32_t)); \ + /* Set initial value */ \ + hg_atomic_init32(addr_##name, val); \ + }\ + HG_PROF_PVAR_REGISTER_impl(HG_PVAR_CLASS_COUNTER, dtype, #name, \ + (void *)addr_##name, 1, bind, 1, desc); + +#define HG_PROF_PVAR_DOUBLE_COUNTER_REGISTER(dtype, bind,\ + name, desc, val) \ + double *addr_##name = NULL;\ + if(bind == HG_PROF_BIND_NO_OBJECT) {\ + addr_##name = (double *)malloc(sizeof(double)); \ + /* Set initial value */ \ + *(addr_##name) = val; \ + }\ + HG_PROF_PVAR_REGISTER_impl(HG_PVAR_CLASS_COUNTER, dtype, #name, \ + (void *)addr_##name, 1, bind, 1, desc); + +/* Change the value of a PVAR */ +#define HG_PROF_PVAR_UINT_COUNTER_INC(name, val) \ + addr_##name = (addr_##name == NULL ? hg_prof_get_pvar_addr_from_name(#name): addr_##name); \ + for(int i=0; i < val; i++) \ + hg_atomic_incr32(addr_##name); + +#define HG_PROF_PVAR_UINT_COUNTER_DECR(name, val) \ + addr_##name = (addr_##name == NULL ? hg_prof_get_pvar_addr_from_name(#name): addr_##name); \ + for(int i=0; i < val; i++) \ + hg_atomic_decr32(addr_##name); + +#define HG_PROF_PVAR_DOUBLE_COUNTER_INC(name, val) \ + addr_##name = (addr_##name == NULL ? hg_prof_get_pvar_addr_from_name(#name): addr_##name); \ + *(addr_##name) += val; + +#define HG_PROF_PVAR_UINT_COUNTER_SET(name, val) \ + addr_##name = (addr_##name == NULL ? hg_prof_get_pvar_addr_from_name(#name): addr_##name); \ + hg_atomic_set32(addr_##name, val); + +/** + * Internal routine that gets invoked during Mercury's own initialization routine. + * General routine for initializing the PVAR data structures and registering any PVARs that are not bound to a specific module. + * + * \return HG_SUCCESS or corresponding HG error code + */ +hg_return_t +hg_prof_pvar_init(); + +/** + * Internal routine that gets invoked during Mercury's own finalization routine. + * General routine for finalizing and freeing the internal PVAR data structures. + * + * \return HG_SUCCESS or corresponding HG error code + */ +hg_return_t +hg_prof_pvar_finalize(); + +/** + * Internal routine that returns the PVAR address associated with the name. + * + * \param name [IN] PVAR name + * \return hg_atomic_int32_t* that represents the PVAR addr + */ +hg_atomic_int32_t * +hg_prof_get_pvar_addr_from_name(const char* name); + +/** + * Internal routine that returns the PVAR index associated with the name. + * + * \param name [IN] PVAR name + * \return int that represents the PVAR index + */ +int +hg_prof_get_pvar_index_from_name(const char* name); + +/** + * Internal routine that returns the PVAR data associated with a key representing index. + * + * \param key [IN] PVAR index key + * \return hg_prof_pvar_data_t that represents the PVAR data + */ +hg_prof_pvar_data_t * +hg_prof_pvar_table_lookup(unsigned int key); + + +/** + * PVAR registration function. Used by internal Mercury modules to register any PVARs that they export. + * \param varclass [IN] PVAR class + * \param dtype [IN] PVAR datatype + * \param name [IN] PVAR name + * \param addr [IN] PVAR address + * \param count [IN] PVAR count + * \param bind [IN] PVAR binding + * \param continuous [IN] Is PVAR continuous or not + * \param desc [IN] PVAR description + */ +extern void +HG_PROF_PVAR_REGISTER_impl( + hg_prof_class_t varclass, hg_prof_datatype_t dtype, const char* name, void *addr, int count, + hg_prof_bind_t bind, int continuous, const char * desc); + +#endif /* MERCURY_PROF_PVAR_IMPL_H */ diff --git a/src/mercury_prof_types.h b/src/mercury_prof_types.h new file mode 100644 index 00000000..d346fd9d --- /dev/null +++ b/src/mercury_prof_types.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2013-2020 Argonne National Laboratory, Department of Energy, + * UChicago Argonne, LLC and The HDF Group. + * All rights reserved. + * + * The full copyright notice, including terms governing use, modification, + * and redistribution, is contained in the COPYING file that can be + * found at the root of the source code distribution tree. + */ + +#ifndef MERCURY_PROF_TYPES_H +#define MERCURY_PROF_TYPES_H + +/*************************************/ +/* Public Type and Struct Definition */ +/*************************************/ +typedef struct hg_prof_pvar_handle * hg_prof_pvar_handle_t; +typedef struct hg_prof_pvar_session * hg_prof_pvar_session_t; + +/* Enumerate the type of PVAR bindings available */ +typedef enum { + HG_PROF_BIND_NO_OBJECT, /* PVARs that are not bound to any object */ + HG_PROF_BIND_HANDLE /* PVARs that are bound to Mercury handles */ +} hg_prof_bind_t; + +/* Enumerate the various types of PVAR classes */ +typedef enum { + HG_PVAR_CLASS_STATE, /* PVAR that represents any one of a set of discrete states */ + HG_PVAR_CLASS_COUNTER, /* PVAR that represents a regular monotonic counter */ + HG_PVAR_CLASS_LEVEL, /* PVAR that represents a utilization level (in percentage) of a given resource */ + HG_PVAR_CLASS_SIZE, /* PVAR that represents the size of a given resource at any given point in time */ + HG_PVAR_CLASS_HIGHWATERMARK, /* PVAR that represents a high watermark value */ + HG_PVAR_CLASS_LOWWATERMARK /* PVAR that represents a low watermark value */ +} hg_prof_class_t; + +/* Datatypes allowable with the PVAR interface */ +typedef enum { + HG_UINT, /* PVAR of type unsigned integer */ + HG_DOUBLE /* PVAR of type double */ +} hg_prof_datatype_t; + +#endif /* MERCURY_PROF_TYPES_H */ diff --git a/src/na/na_ofi.c b/src/na/na_ofi.c index cb672b88..bc3fb767 100644 --- a/src/na/na_ofi.c +++ b/src/na/na_ofi.c @@ -55,6 +55,10 @@ #include "mercury_thread_spin.h" #include "mercury_time.h" +/* PVAR profiling support */ +#include "../mercury_types.h" +#include "../mercury_prof_pvar_impl.h" + #include #include #include @@ -181,6 +185,9 @@ static unsigned long const na_ofi_prov_flags[] = {NA_OFI_PROV_TYPES}; /* Number of retries when receiving FI_EINTR error */ #define NA_OFI_MAX_EINTR_RETRY (1000) +/* The magic number for na_ofi_op_id verification */ +#define NA_OFI_OP_ID_MAGIC_1 (0x1928374655627384ULL) +#define NA_OFI_OP_ID_MAGIC_2 (0x8171615141312111ULL) /* The predefined RMA KEY for MR_SCALABLE */ #define NA_OFI_RMA_KEY (0x0F1B0F1BULL) @@ -1835,24 +1842,16 @@ na_ofi_domain_open(struct na_ofi_class *priv, enum na_ofi_prov_type prov_type, #ifdef NA_OFI_HAS_EXT_GNI_H if (na_ofi_domain->prov_type == NA_OFI_PROV_GNI) { - int32_t enable = 1; -# ifdef NA_OFI_GNI_HAS_UDREG + int enable = 1; +# ifdef NA_OFI_GNI_HAS_UDREG char *other_reg_type = "udreg"; - int32_t udreg_limit = 1024; /* Enable use of udreg instead of internal MR cache */ - ret = na_ofi_gni_set_domain_op_value( - na_ofi_domain, GNI_MR_CACHE, &other_reg_type); - NA_CHECK_NA_ERROR( - error, ret, "Could not set domain op value for GNI_MR_CACHE"); - - /* Experiments on Theta showed default value of 2048 too high if - * launching multiple clients on one node */ - ret = na_ofi_gni_set_domain_op_value( - na_ofi_domain, GNI_MR_UDREG_REG_LIMIT, &udreg_limit); + ret = na_ofi_gni_set_domain_op_value(na_ofi_domain, GNI_MR_CACHE, + &other_reg_type); NA_CHECK_NA_ERROR(error, ret, - "Could not set domain op value for GNI_MR_UDREG_REG_LIMIT"); -# endif + "Could not set domain op value for GNI_MR_CACHE"); +# endif /* Enable lazy deregistration in MR cache */ ret = na_ofi_gni_set_domain_op_value( @@ -4634,6 +4633,8 @@ na_ofi_progress( double remaining = timeout / 1000.0; na_return_t ret = NA_TIMEOUT; + HG_PROF_PVAR_UINT_COUNTER(hg_pvar_hg_na_ofi_completion_count); + do { struct fi_cq_tagged_entry cq_events[NA_OFI_CQ_EVENT_NUM]; fi_addr_t src_addrs[NA_OFI_CQ_EVENT_NUM] = {FI_ADDR_UNSPEC}; @@ -4650,15 +4651,9 @@ na_ofi_progress( if (wait_hdl) { /* Wait in wait set if provider does not support wait on FDs */ - int rc = 0, retry_cnt = 0; - do { - rc = fi_wait(wait_hdl, (int) (remaining * 1000.0)); - } while ( - rc == -FI_EINTR && retry_cnt++ < NA_OFI_MAX_EINTR_RETRY); - + int rc = fi_wait(wait_hdl, (int) (remaining * 1000.0)); if (rc == -FI_ETIMEDOUT) break; - NA_CHECK_ERROR(rc != 0, out, ret, NA_PROTOCOL_ERROR, "fi_wait() failed, rc: %d (%s)", rc, fi_strerror((int) -rc)); @@ -4668,7 +4663,10 @@ na_ofi_progress( /* Read from CQ */ ret = na_ofi_cq_read(context, NA_OFI_CQ_EVENT_NUM, cq_events, src_addrs, &src_err_addr_ptr, &src_err_addrlen, &actual_count); - NA_CHECK_NA_ERROR(out, ret, "Could not read events from context CQ"); + HG_PROF_PVAR_UINT_COUNTER_SET(hg_pvar_hg_na_ofi_completion_count, actual_count); + + NA_CHECK_NA_ERROR(out, ret, + "Could not read events from context CQ"); /* Attempt to process retries */ ret = na_ofi_cq_process_retries(context);