From 60de74982f8f033019cce1253b414b10274b99ba Mon Sep 17 00:00:00 2001 From: Nicolas Hardy Date: Thu, 23 Jul 2020 16:44:25 -0400 Subject: [PATCH 1/9] test suite and autotools --- autogen.sh | 11 + config/ar-lib | 270 ++++++++++ config/ax_code_coverage.m4 | 264 ++++++++++ config/tap-driver.sh | 678 ++++++++++++++++++++++++++ tests/Makefile.am | 22 + tests/README.md | 53 ++ tests/coral-ea.c | 12 + tests/coral-lassen.c | 12 + tests/epyc-corona.c | 12 + tests/error.c | 97 ++++ tests/expected/expected.coral-ea | 88 ++++ tests/expected/expected.coral-lassen | 87 ++++ tests/expected/expected.coral-rzansel | 86 ++++ tests/expected/expected.epyc-corona | 84 ++++ tests/tap.c | 362 ++++++++++++++ tests/tap.h | 115 +++++ tests/test_utils.c | 449 +++++++++++++++++ tests/test_utils.h | 81 +++ 18 files changed, 2783 insertions(+) create mode 100755 autogen.sh create mode 100755 config/ar-lib create mode 100644 config/ax_code_coverage.m4 create mode 100755 config/tap-driver.sh create mode 100644 tests/Makefile.am create mode 100644 tests/README.md create mode 100644 tests/coral-ea.c create mode 100644 tests/coral-lassen.c create mode 100644 tests/epyc-corona.c create mode 100644 tests/error.c create mode 100644 tests/expected/expected.coral-ea create mode 100644 tests/expected/expected.coral-lassen create mode 100644 tests/expected/expected.coral-rzansel create mode 100644 tests/expected/expected.epyc-corona create mode 100644 tests/tap.c create mode 100644 tests/tap.h create mode 100644 tests/test_utils.c create mode 100644 tests/test_utils.h diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..15729eb --- /dev/null +++ b/autogen.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# +# Run an extra libtoolize before autoreconf to ensure that +# libtool macros can be found if libtool is in PATH, but its +# macros are not in default aclocal search path. +# +echo "Running libtoolize --automake --copy ... " +libtoolize --automake --copy || exit +echo "Running autoreconf --verbose --install" +autoreconf --verbose --install || exit +echo "Now run ./configure." diff --git a/config/ar-lib b/config/ar-lib new file mode 100755 index 0000000..0baa4f6 --- /dev/null +++ b/config/ar-lib @@ -0,0 +1,270 @@ +#! /bin/sh +# Wrapper for Microsoft lib.exe + +me=ar-lib +scriptversion=2012-03-01.08; # UTC + +# Copyright (C) 2010-2018 Free Software Foundation, Inc. +# Written by Peter Rosin . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + + +# func_error message +func_error () +{ + echo "$me: $1" 1>&2 + exit 1 +} + +file_conv= + +# func_file_conv build_file +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv in + mingw) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_at_file at_file operation archive +# Iterate over all members in AT_FILE performing OPERATION on ARCHIVE +# for each of them. +# When interpreting the content of the @FILE, do NOT use func_file_conv, +# since the user would need to supply preconverted file names to +# binutils ar, at least for MinGW. +func_at_file () +{ + operation=$2 + archive=$3 + at_file_contents=`cat "$1"` + eval set x "$at_file_contents" + shift + + for member + do + $AR -NOLOGO $operation:"$member" "$archive" || exit $? + done +} + +case $1 in + '') + func_error "no command. Try '$0 --help' for more information." + ;; + -h | --h*) + cat <. + +#serial 25 + +AC_DEFUN([AX_CODE_COVERAGE],[ + dnl Check for --enable-code-coverage + AC_REQUIRE([AC_PROG_SED]) + + # allow to override gcov location + AC_ARG_WITH([gcov], + [AS_HELP_STRING([--with-gcov[=GCOV]], [use given GCOV for coverage (GCOV=gcov).])], + [_AX_CODE_COVERAGE_GCOV_PROG_WITH=$with_gcov], + [_AX_CODE_COVERAGE_GCOV_PROG_WITH=gcov]) + + AC_MSG_CHECKING([whether to build with code coverage support]) + AC_ARG_ENABLE([code-coverage], + AS_HELP_STRING([--enable-code-coverage], + [Whether to enable code coverage support]),, + enable_code_coverage=no) + + AM_CONDITIONAL([CODE_COVERAGE_ENABLED], [test x$enable_code_coverage = xyes]) + AC_SUBST([CODE_COVERAGE_ENABLED], [$enable_code_coverage]) + AC_MSG_RESULT($enable_code_coverage) + + AS_IF([ test "$enable_code_coverage" = "yes" ], [ + # check for gcov + AC_CHECK_TOOL([GCOV], + [$_AX_CODE_COVERAGE_GCOV_PROG_WITH], + [:]) + AS_IF([test "X$GCOV" = "X:"], + [AC_MSG_ERROR([gcov is needed to do coverage])]) + AC_SUBST([GCOV]) + + dnl Check if gcc is being used + AS_IF([ test "$GCC" = "no" ], [ + AC_MSG_ERROR([not compiling with gcc, which is required for gcov code coverage]) + ]) + + AC_CHECK_PROG([LCOV], [lcov], [lcov]) + AC_CHECK_PROG([GENHTML], [genhtml], [genhtml]) + + AS_IF([ test -z "$LCOV" ], [ + AC_MSG_ERROR([To enable code coverage reporting you must have lcov installed]) + ]) + + AS_IF([ test -z "$GENHTML" ], [ + AC_MSG_ERROR([Could not find genhtml from the lcov package]) + ]) + + dnl Build the code coverage flags + dnl Define CODE_COVERAGE_LDFLAGS for backwards compatibility + CODE_COVERAGE_CPPFLAGS="-DNDEBUG" + CODE_COVERAGE_CFLAGS="-O0 -g -fprofile-arcs -ftest-coverage" + CODE_COVERAGE_CXXFLAGS="-O0 -g -fprofile-arcs -ftest-coverage" + CODE_COVERAGE_LIBS="-lgcov" + CODE_COVERAGE_LDFLAGS="$CODE_COVERAGE_LIBS" + + AC_SUBST([CODE_COVERAGE_CPPFLAGS]) + AC_SUBST([CODE_COVERAGE_CFLAGS]) + AC_SUBST([CODE_COVERAGE_CXXFLAGS]) + AC_SUBST([CODE_COVERAGE_LIBS]) + AC_SUBST([CODE_COVERAGE_LDFLAGS]) + + [CODE_COVERAGE_RULES_CHECK=' + -$(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) -k check + $(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) code-coverage-capture +'] + [CODE_COVERAGE_RULES_CAPTURE=' + $(code_coverage_v_lcov_cap)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --capture --output-file "$(CODE_COVERAGE_OUTPUT_FILE).tmp" --test-name "$(call code_coverage_sanitize,$(PACKAGE_NAME)-$(PACKAGE_VERSION))" --no-checksum --compat-libtool $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_OPTIONS) + $(code_coverage_v_lcov_ign)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --remove "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "/tmp/*" $(CODE_COVERAGE_IGNORE_PATTERN) --output-file "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_RMOPTS) + -@rm -f $(CODE_COVERAGE_OUTPUT_FILE).tmp + $(code_coverage_v_genhtml)LANG=C $(GENHTML) $(code_coverage_quiet) $(addprefix --prefix ,$(CODE_COVERAGE_DIRECTORY)) --output-directory "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" --title "$(PACKAGE_NAME)-$(PACKAGE_VERSION) Code Coverage" --legend --show-details "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_GENHTML_OPTIONS) + @echo "file://$(abs_builddir)/$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html" +'] + [CODE_COVERAGE_RULES_CLEAN=' +clean: code-coverage-clean +distclean: code-coverage-clean +code-coverage-clean: + -$(LCOV) --directory $(top_builddir) -z + -rm -rf $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_FILE).tmp $(CODE_COVERAGE_OUTPUT_DIRECTORY) + -find . \( -name "*.gcda" -o -name "*.gcno" -o -name "*.gcov" \) -delete +'] + ], [ + [CODE_COVERAGE_RULES_CHECK=' + @echo "Need to reconfigure with --enable-code-coverage" +'] + CODE_COVERAGE_RULES_CAPTURE="$CODE_COVERAGE_RULES_CHECK" + CODE_COVERAGE_RULES_CLEAN='' + ]) + +[CODE_COVERAGE_RULES=' +# Code coverage +# +# Optional: +# - CODE_COVERAGE_DIRECTORY: Top-level directory for code coverage reporting. +# Multiple directories may be specified, separated by whitespace. +# (Default: $(top_builddir)) +# - CODE_COVERAGE_OUTPUT_FILE: Filename and path for the .info file generated +# by lcov for code coverage. (Default: +# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info) +# - CODE_COVERAGE_OUTPUT_DIRECTORY: Directory for generated code coverage +# reports to be created. (Default: +# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage) +# - CODE_COVERAGE_BRANCH_COVERAGE: Set to 1 to enforce branch coverage, +# set to 0 to disable it and leave empty to stay with the default. +# (Default: empty) +# - CODE_COVERAGE_LCOV_SHOPTS_DEFAULT: Extra options shared between both lcov +# instances. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE) +# - CODE_COVERAGE_LCOV_SHOPTS: Extra options to shared between both lcov +# instances. (Default: $CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) +# - CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH: --gcov-tool pathtogcov +# - CODE_COVERAGE_LCOV_OPTIONS_DEFAULT: Extra options to pass to the +# collecting lcov instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) +# - CODE_COVERAGE_LCOV_OPTIONS: Extra options to pass to the collecting lcov +# instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) +# - CODE_COVERAGE_LCOV_RMOPTS_DEFAULT: Extra options to pass to the filtering +# lcov instance. (Default: empty) +# - CODE_COVERAGE_LCOV_RMOPTS: Extra options to pass to the filtering lcov +# instance. (Default: $CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) +# - CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT: Extra options to pass to the +# genhtml instance. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE) +# - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml +# instance. (Default: $CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) +# - CODE_COVERAGE_IGNORE_PATTERN: Extra glob pattern of files to ignore +# +# The generated report will be titled using the $(PACKAGE_NAME) and +# $(PACKAGE_VERSION). In order to add the current git hash to the title, +# use the git-version-gen script, available online. + +# Optional variables +CODE_COVERAGE_DIRECTORY ?= $(top_builddir) +CODE_COVERAGE_OUTPUT_FILE ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info +CODE_COVERAGE_OUTPUT_DIRECTORY ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage +CODE_COVERAGE_BRANCH_COVERAGE ?= +CODE_COVERAGE_LCOV_SHOPTS_DEFAULT ?= $(if $(CODE_COVERAGE_BRANCH_COVERAGE),\ +--rc lcov_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE)) +CODE_COVERAGE_LCOV_SHOPTS ?= $(CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) +CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH ?= --gcov-tool "$(GCOV)" +CODE_COVERAGE_LCOV_OPTIONS_DEFAULT ?= $(CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) +CODE_COVERAGE_LCOV_OPTIONS ?= $(CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) +CODE_COVERAGE_LCOV_RMOPTS_DEFAULT ?= +CODE_COVERAGE_LCOV_RMOPTS ?= $(CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) +CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT ?=\ +$(if $(CODE_COVERAGE_BRANCH_COVERAGE),\ +--rc genhtml_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE)) +CODE_COVERAGE_GENHTML_OPTIONS ?= $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) +CODE_COVERAGE_IGNORE_PATTERN ?= + +GITIGNOREFILES ?= +GITIGNOREFILES += $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_DIRECTORY) + +code_coverage_v_lcov_cap = $(code_coverage_v_lcov_cap_$(V)) +code_coverage_v_lcov_cap_ = $(code_coverage_v_lcov_cap_$(AM_DEFAULT_VERBOSITY)) +code_coverage_v_lcov_cap_0 = @echo " LCOV --capture"\ + $(CODE_COVERAGE_OUTPUT_FILE); +code_coverage_v_lcov_ign = $(code_coverage_v_lcov_ign_$(V)) +code_coverage_v_lcov_ign_ = $(code_coverage_v_lcov_ign_$(AM_DEFAULT_VERBOSITY)) +code_coverage_v_lcov_ign_0 = @echo " LCOV --remove /tmp/*"\ + $(CODE_COVERAGE_IGNORE_PATTERN); +code_coverage_v_genhtml = $(code_coverage_v_genhtml_$(V)) +code_coverage_v_genhtml_ = $(code_coverage_v_genhtml_$(AM_DEFAULT_VERBOSITY)) +code_coverage_v_genhtml_0 = @echo " GEN " $(CODE_COVERAGE_OUTPUT_DIRECTORY); +code_coverage_quiet = $(code_coverage_quiet_$(V)) +code_coverage_quiet_ = $(code_coverage_quiet_$(AM_DEFAULT_VERBOSITY)) +code_coverage_quiet_0 = --quiet + +# sanitizes the test-name: replaces with underscores: dashes and dots +code_coverage_sanitize = $(subst -,_,$(subst .,_,$(1))) + +# Use recursive makes in order to ignore errors during check +check-code-coverage:'"$CODE_COVERAGE_RULES_CHECK"' + +# Capture code coverage data +code-coverage-capture: code-coverage-capture-hook'"$CODE_COVERAGE_RULES_CAPTURE"' + +# Hook rule executed before code-coverage-capture, overridable by the user +code-coverage-capture-hook: + +'"$CODE_COVERAGE_RULES_CLEAN"' + +A''M_DISTCHECK_CONFIGURE_FLAGS ?= +A''M_DISTCHECK_CONFIGURE_FLAGS += --disable-code-coverage + +.PHONY: check-code-coverage code-coverage-capture code-coverage-capture-hook code-coverage-clean +'] + + AC_SUBST([CODE_COVERAGE_RULES]) + m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([CODE_COVERAGE_RULES])]) +]) diff --git a/config/tap-driver.sh b/config/tap-driver.sh new file mode 100755 index 0000000..4a687e2 --- /dev/null +++ b/config/tap-driver.sh @@ -0,0 +1,678 @@ +#! /bin/sh +# Copyright (C) 2011-2013 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +scriptversion=2013-12-23.17; # UTC + +# Make unconditional expansion of undefined variables an error. This +# helps a lot in preventing typo-related bugs. +set -u + +me=tap-driver.sh + +fatal () +{ + echo "$me: fatal: $*" >&2 + exit 1 +} + +usage_error () +{ + echo "$me: $*" >&2 + print_usage >&2 + exit 2 +} + +print_usage () +{ + cat < + # + trap : 1 3 2 13 15 + if test $merge -gt 0; then + exec 2>&1 + else + exec 2>&3 + fi + "$@" + echo $? + ) | LC_ALL=C ${AM_TAP_AWK-awk} \ + -v me="$me" \ + -v test_script_name="$test_name" \ + -v log_file="$log_file" \ + -v trs_file="$trs_file" \ + -v expect_failure="$expect_failure" \ + -v merge="$merge" \ + -v ignore_exit="$ignore_exit" \ + -v comments="$comments" \ + -v diag_string="$diag_string" \ + -v quiet="$TAP_DRIVER_QUIET" \ +' +# TODO: the usages of "cat >&3" below could be optimized when using +# GNU awk, and/on on systems that supports /dev/fd/. + +# Implementation note: in what follows, `result_obj` will be an +# associative array that (partly) simulates a TAP result object +# from the `TAP::Parser` perl module. + +## ----------- ## +## FUNCTIONS ## +## ----------- ## + +function fatal(msg) +{ + print me ": " msg | "cat >&2" + exit 1 +} + +function abort(where) +{ + fatal("internal error " where) +} + +# Convert a boolean to a "yes"/"no" string. +function yn(bool) +{ + return bool ? "yes" : "no"; +} + +function add_test_result(result) +{ + if (!test_results_index) + test_results_index = 0 + test_results_list[test_results_index] = result + test_results_index += 1 + test_results_seen[result] = 1; +} + +# Whether the test script should be re-run by "make recheck". +function must_recheck() +{ + for (k in test_results_seen) + if (k != "XFAIL" && k != "PASS" && k != "SKIP") + return 1 + return 0 +} + +# Whether the content of the log file associated to this test should +# be copied into the "global" test-suite.log. +function copy_in_global_log() +{ + for (k in test_results_seen) + if (k != "PASS") + return 1 + return 0 +} + +function get_global_test_result() +{ + if ("ERROR" in test_results_seen) + return "ERROR" + if ("FAIL" in test_results_seen || "XPASS" in test_results_seen) + return "FAIL" + all_skipped = 1 + for (k in test_results_seen) + if (k != "SKIP") + all_skipped = 0 + if (all_skipped) + return "SKIP" + return "PASS"; +} + +function summarize_global_test_result() +{ + i = 0 + for (k in test_results_list) { + i += 1 + totals[ test_results_list[k] ] += 1 + } + res = sprintf ("N=%-3d PASS=%-3d FAIL=%d SKIP=%d XPASS=%d XFAIL=%d", + i, totals["PASS"], totals["FAIL"], + totals["SKIP"], totals["XPASS"], + totals["XFAIL"]) + return res +} + +function stringify_result_obj(result_obj) +{ + if (result_obj["is_unplanned"] || result_obj["number"] != testno) + return "ERROR" + + if (plan_seen == LATE_PLAN) + return "ERROR" + + if (result_obj["directive"] == "TODO") + return result_obj["is_ok"] ? "XPASS" : "XFAIL" + + if (result_obj["directive"] == "SKIP") + return result_obj["is_ok"] ? "SKIP" : COOKED_FAIL; + + if (length(result_obj["directive"])) + abort("in function stringify_result_obj()") + + return result_obj["is_ok"] ? COOKED_PASS : COOKED_FAIL +} + +function decorate_result(result) +{ + color_name = color_for_result[result] + if (color_name) + return color_map[color_name] "" result "" color_map["std"] + # If we are not using colorized output, or if we do not know how + # to colorize the given result, we should return it unchanged. + return result +} + +function report(result, details) +{ + if (result ~ /^(X?(PASS|FAIL)|SKIP|ERROR)/) + { + msg = ": " test_script_name + add_test_result(result) + } + else if (result == "#") + { + msg = " " test_script_name ":" + } + else + { + abort("in function report()") + } + if (length(details)) + msg = msg " " details + # Output on console might be colorized. + if (!quiet || result ~ /^(FAIL|ERROR)/) + print decorate_result(result) msg + # Log the result in the log file too, to help debugging (this is + # especially true when said result is a TAP error or "Bail out!"). + print result msg | "cat >&3"; +} + +function testsuite_error(error_message) +{ + report("ERROR", "- " error_message) +} + +function handle_tap_result() +{ + details = result_obj["number"]; + if (length(result_obj["description"])) + details = details " " result_obj["description"] + + if (plan_seen == LATE_PLAN) + { + details = details " # AFTER LATE PLAN"; + } + else if (result_obj["is_unplanned"]) + { + details = details " # UNPLANNED"; + } + else if (result_obj["number"] != testno) + { + details = sprintf("%s # OUT-OF-ORDER (expecting %d)", + details, testno); + } + else if (result_obj["directive"]) + { + details = details " # " result_obj["directive"]; + if (length(result_obj["explanation"])) + details = details " " result_obj["explanation"] + } + + report(stringify_result_obj(result_obj), details) +} + +# `skip_reason` should be empty whenever planned > 0. +function handle_tap_plan(planned, skip_reason) +{ + planned += 0 # Avoid getting confused if, say, `planned` is "00" + if (length(skip_reason) && planned > 0) + abort("in function handle_tap_plan()") + if (plan_seen) + { + # Error, only one plan per stream is acceptable. + testsuite_error("multiple test plans") + return; + } + planned_tests = planned + # The TAP plan can come before or after *all* the TAP results; we speak + # respectively of an "early" or a "late" plan. If we see the plan line + # after at least one TAP result has been seen, assume we have a late + # plan; in this case, any further test result seen after the plan will + # be flagged as an error. + plan_seen = (testno >= 1 ? LATE_PLAN : EARLY_PLAN) + # If testno > 0, we have an error ("too many tests run") that will be + # automatically dealt with later, so do not worry about it here. If + # $plan_seen is true, we have an error due to a repeated plan, and that + # has already been dealt with above. Otherwise, we have a valid "plan + # with SKIP" specification, and should report it as a particular kind + # of SKIP result. + if (planned == 0 && testno == 0) + { + if (length(skip_reason)) + skip_reason = "- " skip_reason; + report("SKIP", skip_reason); + } +} + +function extract_tap_comment(line) +{ + if (index(line, diag_string) == 1) + { + # Strip leading `diag_string` from `line`. + line = substr(line, length(diag_string) + 1) + # And strip any leading and trailing whitespace left. + sub("^[ \t]*", "", line) + sub("[ \t]*$", "", line) + # Return what is left (if any). + return line; + } + return ""; +} + +# When this function is called, we know that line is a TAP result line, +# so that it matches the (perl) RE "^(not )?ok\b". +function setup_result_obj(line) +{ + # Get the result, and remove it from the line. + result_obj["is_ok"] = (substr(line, 1, 2) == "ok" ? 1 : 0) + sub("^(not )?ok[ \t]*", "", line) + + # If the result has an explicit number, get it and strip it; otherwise, + # automatically assing the next progresive number to it. + if (line ~ /^[0-9]+$/ || line ~ /^[0-9]+[^a-zA-Z0-9_]/) + { + match(line, "^[0-9]+") + # The final `+ 0` is to normalize numbers with leading zeros. + result_obj["number"] = substr(line, 1, RLENGTH) + 0 + line = substr(line, RLENGTH + 1) + } + else + { + result_obj["number"] = testno + } + + if (plan_seen == LATE_PLAN) + # No further test results are acceptable after a "late" TAP plan + # has been seen. + result_obj["is_unplanned"] = 1 + else if (plan_seen && testno > planned_tests) + result_obj["is_unplanned"] = 1 + else + result_obj["is_unplanned"] = 0 + + # Strip trailing and leading whitespace. + sub("^[ \t]*", "", line) + sub("[ \t]*$", "", line) + + # This will have to be corrected if we have a "TODO"/"SKIP" directive. + result_obj["description"] = line + result_obj["directive"] = "" + result_obj["explanation"] = "" + + if (index(line, "#") == 0) + return # No possible directive, nothing more to do. + + # Directives are case-insensitive. + rx = "[ \t]*#[ \t]*([tT][oO][dD][oO]|[sS][kK][iI][pP])[ \t]*" + + # See whether we have the directive, and if yes, where. + pos = match(line, rx "$") + if (!pos) + pos = match(line, rx "[^a-zA-Z0-9_]") + + # If there was no TAP directive, we have nothing more to do. + if (!pos) + return + + # Let`s now see if the TAP directive has been escaped. For example: + # escaped: ok \# SKIP + # not escaped: ok \\# SKIP + # escaped: ok \\\\\# SKIP + # not escaped: ok \ # SKIP + if (substr(line, pos, 1) == "#") + { + bslash_count = 0 + for (i = pos; i > 1 && substr(line, i - 1, 1) == "\\"; i--) + bslash_count += 1 + if (bslash_count % 2) + return # Directive was escaped. + } + + # Strip the directive and its explanation (if any) from the test + # description. + result_obj["description"] = substr(line, 1, pos - 1) + # Now remove the test description from the line, that has been dealt + # with already. + line = substr(line, pos) + # Strip the directive, and save its value (normalized to upper case). + sub("^[ \t]*#[ \t]*", "", line) + result_obj["directive"] = toupper(substr(line, 1, 4)) + line = substr(line, 5) + # Now get the explanation for the directive (if any), with leading + # and trailing whitespace removed. + sub("^[ \t]*", "", line) + sub("[ \t]*$", "", line) + result_obj["explanation"] = line +} + +function get_test_exit_message(status) +{ + if (status == 0) + return "" + if (status !~ /^[1-9][0-9]*$/) + abort("getting exit status") + if (status < 127) + exit_details = "" + else if (status == 127) + exit_details = " (command not found?)" + else if (status >= 128 && status <= 255) + exit_details = sprintf(" (terminated by signal %d?)", status - 128) + else if (status > 256 && status <= 384) + # We used to report an "abnormal termination" here, but some Korn + # shells, when a child process die due to signal number n, can leave + # in $? an exit status of 256+n instead of the more standard 128+n. + # Apparently, both behaviours are allowed by POSIX (2008), so be + # prepared to handle them both. See also Austing Group report ID + # 0000051 + exit_details = sprintf(" (terminated by signal %d?)", status - 256) + else + # Never seen in practice. + exit_details = " (abnormal termination)" + return sprintf("exited with status %d%s", status, exit_details) +} + +function write_test_results() +{ + print ":global-test-result: " get_global_test_result() > trs_file + print ":recheck: " yn(must_recheck()) > trs_file + print ":copy-in-global-log: " yn(copy_in_global_log()) > trs_file + for (i = 0; i < test_results_index; i += 1) + print ":test-result: " test_results_list[i] > trs_file + close(trs_file); +} + +BEGIN { + +## ------- ## +## SETUP ## +## ------- ## + +'"$init_colors"' + +# Properly initialized once the TAP plan is seen. +planned_tests = 0 + +COOKED_PASS = expect_failure ? "XPASS": "PASS"; +COOKED_FAIL = expect_failure ? "XFAIL": "FAIL"; + +# Enumeration-like constants to remember which kind of plan (if any) +# has been seen. It is important that NO_PLAN evaluates "false" as +# a boolean. +NO_PLAN = 0 +EARLY_PLAN = 1 +LATE_PLAN = 2 + +testno = 0 # Number of test results seen so far. +bailed_out = 0 # Whether a "Bail out!" directive has been seen. + +# Whether the TAP plan has been seen or not, and if yes, which kind +# it is ("early" is seen before any test result, "late" otherwise). +plan_seen = NO_PLAN + +## --------- ## +## PARSING ## +## --------- ## + +is_first_read = 1 + +while (1) + { + # Involutions required so that we are able to read the exit status + # from the last input line. + st = getline + if (st < 0) # I/O error. + fatal("I/O error while reading from input stream") + else if (st == 0) # End-of-input + { + if (is_first_read) + abort("in input loop: only one input line") + break + } + if (is_first_read) + { + is_first_read = 0 + nextline = $0 + continue + } + else + { + curline = nextline + nextline = $0 + $0 = curline + } + # Copy any input line verbatim into the log file. + print | "cat >&3" + # Parsing of TAP input should stop after a "Bail out!" directive. + if (bailed_out) + continue + + # TAP test result. + if ($0 ~ /^(not )?ok$/ || $0 ~ /^(not )?ok[^a-zA-Z0-9_]/) + { + testno += 1 + setup_result_obj($0) + handle_tap_result() + } + # TAP plan (normal or "SKIP" without explanation). + else if ($0 ~ /^1\.\.[0-9]+[ \t]*$/) + { + # The next two lines will put the number of planned tests in $0. + sub("^1\\.\\.", "") + sub("[^0-9]*$", "") + handle_tap_plan($0, "") + continue + } + # TAP "SKIP" plan, with an explanation. + else if ($0 ~ /^1\.\.0+[ \t]*#/) + { + # The next lines will put the skip explanation in $0, stripping + # any leading and trailing whitespace. This is a little more + # tricky in truth, since we want to also strip a potential leading + # "SKIP" string from the message. + sub("^[^#]*#[ \t]*(SKIP[: \t][ \t]*)?", "") + sub("[ \t]*$", ""); + handle_tap_plan(0, $0) + } + # "Bail out!" magic. + # Older versions of prove and TAP::Harness (e.g., 3.17) did not + # recognize a "Bail out!" directive when preceded by leading + # whitespace, but more modern versions (e.g., 3.23) do. So we + # emulate the latter, "more modern" behaviour. + else if ($0 ~ /^[ \t]*Bail out!/) + { + bailed_out = 1 + # Get the bailout message (if any), with leading and trailing + # whitespace stripped. The message remains stored in `$0`. + sub("^[ \t]*Bail out![ \t]*", ""); + sub("[ \t]*$", ""); + # Format the error message for the + bailout_message = "Bail out!" + if (length($0)) + bailout_message = bailout_message " " $0 + testsuite_error(bailout_message) + } + # Maybe we have too look for dianogtic comments too. + else if (comments != 0) + { + comment = extract_tap_comment($0); + if (length(comment)) + report("#", comment); + } + } + +## -------- ## +## FINISH ## +## -------- ## +# In quiet mode, issue summary now: +if (quiet) { + printf ("%26s: %5s: %s\n", + test_script_name, + decorate_result(get_global_test_result()), + summarize_global_test_result()) +} + +# A "Bail out!" directive should cause us to ignore any following TAP +# error, as well as a non-zero exit status from the TAP producer. +if (!bailed_out) + { + if (!plan_seen) + { + testsuite_error("missing test plan") + } + else if (planned_tests != testno) + { + bad_amount = testno > planned_tests ? "many" : "few" + testsuite_error(sprintf("too %s tests run (expected %d, got %d)", + bad_amount, planned_tests, testno)) + } + if (!ignore_exit) + { + # Fetch exit status from the last line. + exit_message = get_test_exit_message(nextline) + if (exit_message) + testsuite_error(exit_message) + } + } + +write_test_results() + +exit 0 + +} # End of "BEGIN" block. +' + +# TODO: document that we consume the file descriptor 3 :-( +} 3>"$log_file" + +test $? -eq 0 || fatal "I/O or internal error" + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..535b409 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,22 @@ +AM_CFLAGS= -Wall -Werror -I$(top_srcdir)/src $(HWLOC_CFLAGS) +LDADD = ../src/libmpibind.la libtap.la $(HWLOC_LIBS) + +lib_LTLIBRARIES = libtap.la +libtap_la_SOURCES = tap.c tap.h + +TESTS = \ + error.t \ + coral_lassen.t \ + epyc_corona.t \ + coral_ea.t + +check_PROGRAMS = $(TESTS) + +TEST_EXTENSIONS = .t +T_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \ + $(top_srcdir)/config/tap-driver.sh + +coral_lassen_t_SOURCES = coral-lassen.c test_utils.c test_utils.h +epyc_corona_t_SOURCES = epyc-corona.c test_utils.c test_utils.h +coral_ea_t_SOURCES = coral-ea.c test_utils.c test_utils.h +error_t_SOURCES = error.c test_utils.c test_utils.h diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..7ce93ea --- /dev/null +++ b/tests/README.md @@ -0,0 +1,53 @@ +# Mpibind Tests + + +The current iteration of the test suite is designed to generate a set of tests based on a given topology, then compare the resultant mappings to a file that defines expected output. Generating the tests involving gathering basic information about a topology, and using that information to tweak each test to be suitable for the topology. + +An example of the answers file is below: + +``` + +# Line that start with a pound are comments! +# The first non-commented line should be the number of tests. +3 + +# 1: Map one task to every core +Map one task to every core +"1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1" +"6,54;6,54;7,55;7,55;8,56;8,56;9,57;9,57;10,58;10,58;11,59;11,59;12,60;12,60;13,61;13,61;14,62;14,62;15,63;15,63;16,64;16,64;17,65;17,65;30,78;30,78;31,79;31,79;32,80;32,80;33,81;33,81;34,82;34,82;35,83;35,83;42,90;42,90;43,91;43,91;44,92;44,92;45,93;45,93;46,94;46,94;47,95;47,95" +"0;0;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;1;1;2;2;2;2;2;2;2;2;2;2;2;2;3;3;3;3;3;3;3;3;3;3;3;3" + +# 2: Map 1 task greedily +Map 1 task greedily +"96" +"0-95" +"0-3" + +# 3: Map two tasks greedily +Map two tasks greedily +"48;48" +"0-23,48-71;24-47,72-95" +"0-1;2-3" + +``` + +The first non-blank, non-commented line in the answer file is the number of tests in the file. After that, each answer consists of four line: a description, the expected thread mapping, the expected cpu mapping, and the expected gpu_mapping for the tasks of a given mpibind run. Each of the 4 lines are wrapped in quotes. These strings are directly compared to the output of mpibind when given the corresponding input parameters. + +## Test Details + +1. Valid mpibind configurations + * Map one task to every core + * Map one task greedily + * Map two tasks greedily + * Mapping such that ntasks < #NUMA nodes but nworkers > #NUMA nodes (this makes sure mpibind accounts * for the number of threads as well + * Restrict x tasks a single core (x == machine's smt level) + * Map two tasks at smt 1 + * Map two tasks at smt (max_smt - 1) + * Map two tasks, but restrict them to a single NUMA domain + * Map number_numas tasks without GPU optimization + * Map number_numas tasks with GPU optimization +2. Error checking + * Passing NULL in place of the handle to all of the setter and getter functions. + * Trying to run mpibind with an invalid number of threads (e.g. -1) + * Trying to run mpibind with an invalid number of tasks (e.g. -1) + * Trying to run mpibind with an invalid SMT level (e.g. -1 or 8 on a machine with SMT-4 \ No newline at end of file diff --git a/tests/coral-ea.c b/tests/coral-ea.c new file mode 100644 index 0000000..e39beb5 --- /dev/null +++ b/tests/coral-ea.c @@ -0,0 +1,12 @@ +#include "test_utils.h" + +int main(int argc, char **argv) { + plan(NO_PLAN); + + char* topology_file = "../topo-xml/coral-ea-hwloc1.xml"; + char* answer_file = "./expected/expected.coral-ea"; + unit_test_topology(topology_file, answer_file); + + done_testing(); + return (0); +} diff --git a/tests/coral-lassen.c b/tests/coral-lassen.c new file mode 100644 index 0000000..b5059df --- /dev/null +++ b/tests/coral-lassen.c @@ -0,0 +1,12 @@ +#include "test_utils.h" + +int main(int argc, char **argv) { + plan(NO_PLAN); + + char* topology_file = "../topo-xml/coral-lassen.xml"; + char* answer_file = "./expected/expected.coral-lassen"; + unit_test_topology(topology_file, answer_file); + + done_testing(); + return (0); +} diff --git a/tests/epyc-corona.c b/tests/epyc-corona.c new file mode 100644 index 0000000..361325c --- /dev/null +++ b/tests/epyc-corona.c @@ -0,0 +1,12 @@ +#include "test_utils.h" + +int main(int argc, char **argv) { + plan(NO_PLAN); + + char* topology_file = "../topo-xml/epyc-corona.xml"; + char* answer_file = "./expected/expected.epyc-corona"; + unit_test_topology(topology_file, answer_file); + + done_testing(); + return (0); +} diff --git a/tests/error.c b/tests/error.c new file mode 100644 index 0000000..c24699b --- /dev/null +++ b/tests/error.c @@ -0,0 +1,97 @@ +#include "test_utils.h" +#define XML_PATH "../topo-xml/coral-lassen.xml" + +/**Test passing null to all setters and getter functions**/ +int test_null_handle() { + diag("Testing passing a null handle to setters and getters"); + mpibind_t *handle = NULL; + int count; //for mpibind_get_env_var_names + + ok(mpibind_set_ntasks(handle, 4) == 1, + "mpibind_set_ntasks fails when handle == NULL"); + ok(mpibind_set_nthreads(handle, 4) == 1, + "mpibind_set_nthreads fails when handle == NULL"); + ok(mpibind_set_greedy(handle, 1) == 1, + "mpibind_set_greedy fails when handle == NULL"); + ok(mpibind_set_gpu_optim(handle, 1) == 1, + "mpibind_set_gpu_optim fails when handle == NULL"); + ok(mpibind_set_smt(handle, 1) == 1, + "mpibind_set_smt fails when handle == NULL"); + ok(mpibind_set_restrict_ids(handle, NULL) == 1, + "mpibind_set_restrict_ids fails when handle == NULL"); + ok(mpibind_set_restrict_type(handle, 1) == 1, + "mpibind_set_restrict_type fails when handle == NULL"); + ok(mpibind_set_topology(handle, NULL) == 1, + "mpibind_set_topology fails when handle == NULL"); + ok(mpibind_set_env_vars(handle) == 1, + "mpibind_set_end_vars fails when handle == NULL"); + + ok(mpibind_get_nthreads(handle) == NULL, + "mpibind_get_nthreads returns NULL when handle == NULL"); + ok(mpibind_get_cpus(handle) == NULL, + "mpibind_get_cpus returns NULL when handle == NULL"); + ok(mpibind_get_gpus(handle) == NULL, + "mpibind_get_gpus returns NULL when handle == NULL"); + ok(mpibind_get_gpu_type(handle) == -1, + "mpibind_get_gpu_type returns NULL when handle == NULL"); + ok(mpibind_get_topology(handle) == NULL, + "mpibind_get_topology returns NULL when handle == NULL"); + ok(mpibind_get_env_var_values(handle, NULL) == NULL, + "mpibind_get_env_var_values returns NULL when handle == NULL"); + ok(mpibind_get_env_var_names(handle, &count) == NULL, + "mpibind_get_env_var_names returns NULL when handle == NULL"); + ok(mpibind_finalize(handle) == 1, + "mpibind_finalize fails when handle == NULL"); + + return 0; +} + +int test_mpibind_errors() { + mpibind_t *handle; + hwloc_topology_t topo; + + // setup topology + hwloc_topology_init(&topo); + hwloc_topology_set_xml(topo, XML_PATH); + hwloc_topology_set_all_types_filter(topo, HWLOC_TYPE_FILTER_KEEP_STRUCTURE); + hwloc_topology_set_type_filter(topo, HWLOC_OBJ_OS_DEVICE, + HWLOC_TYPE_FILTER_KEEP_IMPORTANT); + hwloc_topology_load(topo); + + mpibind_init(&handle); + + int ntasks = 5; + mpibind_set_ntasks(handle, ntasks); + mpibind_set_nthreads(handle, 4); + mpibind_set_greedy(handle, 0); + mpibind_set_gpu_optim(handle, 0); + mpibind_set_smt(handle, 2); + + diag("Testing error handling in mpibind()"); + + mpibind_set_nthreads(handle, -4); + ok(mpibind(handle) == 1, "Mapping fails if nthreads is invalid"); + + mpibind_set_nthreads(handle, 4); + mpibind_set_ntasks(handle, -1); + ok(mpibind(handle) == 1, "Mapping fails if ntasks is invalid"); + + mpibind_set_ntasks(handle, 4); + mpibind_set_smt(handle, -1); + ok(mpibind(handle) == 1, "Mapping fails if smt is invalid"); + + mpibind_set_smt(handle, 16); + ok(mpibind(handle) == 1, "Mapping fails if smt is valid but too high"); + + // TODO: ERROR CODES RELATED TO RESTRICT SETS + todo("Error codes related to restrict sets"); + return 0; +} + +int main(int argc, char **argv) { + plan(NO_PLAN); + test_null_handle(); + test_mpibind_errors(); + done_testing(); + return (0); +} diff --git a/tests/expected/expected.coral-ea b/tests/expected/expected.coral-ea new file mode 100644 index 0000000..1cab3fa --- /dev/null +++ b/tests/expected/expected.coral-ea @@ -0,0 +1,88 @@ +# Line that start with a pound are comments! +# The first non-commented line should be the number of tests. +# After the number of tests, each answer description consist of 4 lines: +# The test description, the thread mapping, the cpu mapping, and the +# gpu_mapping.The mapping for each task is separated by a defined character. +# This separator can be changed in test_utils.c::parse_answer() + +11 + + +# 1: Map one task to every core +Map one task to every core +"1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1" +"0;8;16;24;32;40;48;56;64;72;80;88;96;104;112;120;128;136;144;152" +";;;;;;;;;;;;;;;;;;;" + +# 2: Map 1 task greedily +Map 1 task greedily +"160" +"0-159" +"" + + +# 3: Map two tasks greedily +Map two tasks greedily +"10;10" +"0,8,16,24,32,40,48,56,64,72;80,88,96,104,112,120,128,136,144,152" +";" + +# 4: +Mapping such that ntasks < #NUMA nodes but nworkers > #NUMA nodes +"160" +"0-159" +"" + + +# 5: +Restrict x tasks a single core (x == machine's smt level) +"1;1;1;1;1;1;1;1" +"8;8;8;8;8;8;8;8" +";;;;;;;" + + +# 6: +Map two tasks at SMT 1 +"10;10" +"0,8,16,24,32,40,48,56,64,72;80,88,96,104,112,120,128,136,144,152" +";" + + +# 7: +Map 2 tasks at max smt (across all cores) +"80;80" +"0-79;80-159" +";" + + +# 8: +Map tasks at max smt-1" +"70;70" +"0-6,8-14,16-22,24-30,32-38,40-46,48-54,56-62,64-70,72-78;80-86,88-94,96-102,104-110,112-118,120-126,128-134,136-142,144-150,152-158" +";" + + +# 9: +Map two tasks, but restrict them to a single NUMA domain +"5;5" +"0,8,16,24,32;40,48,56,64,72" +";" + + +# 11: +Map num_numa tasks without GPU optimization +"10;10" +"0,8,16,24,32,40,48,56,64,72;80,88,96,104,112,120,128,136,144,152" +";" + + + +# 12: +Map num_numa tasks with GPU optimization +"10;10" +"0,8,16,24,32,40,48,56,64,72;80,88,96,104,112,120,128,136,144,152" +";" + + +# TODO: +# 13: Map using a complex configuration (exact details TBD) \ No newline at end of file diff --git a/tests/expected/expected.coral-lassen b/tests/expected/expected.coral-lassen new file mode 100644 index 0000000..50c3786 --- /dev/null +++ b/tests/expected/expected.coral-lassen @@ -0,0 +1,87 @@ +# Line that start with a pound are comments! +# The first non-commented line should be the number of tests. +# After the number of tests, each answer description consist of 4 lines: +# The test description, the thread mapping, the cpu mapping, and the +# gpu_mapping.The mapping for each task is separated by a defined character. +# This separator can be changed in test_utils.c::parse_answer() + +11 + + +# 1: Map one task to every core +Map one task to every core +"1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1" +"8;12;16;20;24;28;32;36;40;44;48;52;56;60;64;68;72;76;80;84;96;100;104;108;112;116;120;124;128;132;136;140;144;148;152;156;160;164;168;172" +"0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;2;2;2;2;2;2;2;2;2;2;3;3;3;3;3;3;3;3;3;3" + + +# 2: Map 1 task greedily +Map 1 task greedily +"160" +"8-87,96-175" +"0-3" + + +# 3: Map two tasks greedily +Map two tasks greedily +"20;20" +"8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84;96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172" +"0-1;2-3" + +# 4: +Mapping such that ntasks < #NUMA nodes but nworkers > #NUMA nodes +"160" +"8-87,96-175" +"0-3" + + +# 5: +Restrict x tasks a single core (x == machine's smt level) +"1;1;1;1" +"8;8;8;8" +"0;0;1;1" + + +# 6: +Map two tasks at SMT 1 +"20;20" +"8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84;96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172" +"0-1;2-3" + + +# 7: +Map 2 tasks at max smt (across all cores) +"80;80" +"8-87;96-175" +"0-1;2-3" + + +# 8: +Map tasks at max smt-1 +"60;60" +"8-10,12-14,16-18,20-22,24-26,28-30,32-34,36-38,40-42,44-46,48-50,52-54,56-58,60-62,64-66,68-70,72-74,76-78,80-82,84-86;96-98,100-102,104-106,108-110,112-114,116-118,120-122,124-126,128-130,132-134,136-138,140-142,144-146,148-150,152-154,156-158,160-162,164-166,168-170,172-174" +"0-1;2-3" + + +# 9: +Map two tasks, but restrict them to a single NUMA domain +"10;10" +"8,12,16,20,24,28,32,36,40,44;48,52,56,60,64,68,72,76,80,84" +"0;1" + + +# 11: +Map num_numa tasks without GPU optimization +"20;20" +"8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84;96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172" +"0-1;2-3" + + +# 12: +Map num_numa tasks with GPU optimization +"20;20" +"8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84;96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172" +"0-1;2-3" + +# TODO: +# 13: Map using a complex configuration (exact details TBD) \ No newline at end of file diff --git a/tests/expected/expected.coral-rzansel b/tests/expected/expected.coral-rzansel new file mode 100644 index 0000000..b8b126f --- /dev/null +++ b/tests/expected/expected.coral-rzansel @@ -0,0 +1,86 @@ +# Line that start with a pound are comments! +# The first non-commented line should be the number of tests. +# After the number of tests, each answer description consist of 4 lines: +# The test description, the thread mapping, the cpu mapping, and the +# gpu_mapping.The mapping for each task is separated by a defined character. +# This separator can be changed in test_utils.c::parse_answer() + +11 + +# 1: Map one task to every core +Map one task to every core +"1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1" +"8;12;16;20;24;28;32;36;40;44;48;52;56;60;64;68;72;76;80;84;96;100;104;108;112;116;120;124;128;132;136;140;144;148;152;156;160;164;168;172" +"0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;2;2;2;2;2;2;2;2;2;2;3;3;3;3;3;3;3;3;3;3" + + +# 2: Map 1 task greedily +Map 1 task greedily +"160" +"8-87,96-175" +"0-3" + + +# 3: Map two tasks greedily +Map two tasks greedily +"20;20" +"8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84;96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172" +"0-1;2-3" + +# 4: +Mapping such that ntasks < #NUMA nodes but nworkers > #NUMA nodes +"160" +"8-87,96-175" +"0-3" + + +# 5: +Restrict x tasks a single core (x == machine's smt level) +"1;1;1;1" +"8;8;8;8" +"0;0;1;1" + + +# 6: +Map two tasks at SMT 1 +"20;20" +"8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84;96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172" +"0-1;2-3" + + +# 7: +Map 2 tasks at max smt (across all cores) +"80;80" +"8-87;96-175" +"0-1;2-3" + + +# 8: +Map tasks at max smt-1 +"60;60" +"8-10,12-14,16-18,20-22,24-26,28-30,32-34,36-38,40-42,44-46,48-50,52-54,56-58,60-62,64-66,68-70,72-74,76-78,80-82,84-86;96-98,100-102,104-106,108-110,112-114,116-118,120-122,124-126,128-130,132-134,136-138,140-142,144-146,148-150,152-154,156-158,160-162,164-166,168-170,172-174" +"0-1;2-3" + + +# 9: +Map two tasks, but restrict them to a single NUMA domain +"10;10" +"96,100,104,108,112,116,120,124,128,132;136,140,144,148,152,156,160,164,168,172" +"2;3" + + +# 11: +Map num_numa tasks without GPU optimization +"20;20" +"8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84;96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172" +"0-1;2-3" + + +# 12: +Map num_numa tasks with GPU optimization +"20;20" +"8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84;96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172" +"0-1;2-3" + +# TODO: +# 13: Map using a complex configuration (exact details TBD) \ No newline at end of file diff --git a/tests/expected/expected.epyc-corona b/tests/expected/expected.epyc-corona new file mode 100644 index 0000000..7703313 --- /dev/null +++ b/tests/expected/expected.epyc-corona @@ -0,0 +1,84 @@ +# Line that start with a pound are comments! +# The first non-commented line should be the number of tests. +# After the number of tests, each answer description consist of 4 lines: +# The test description, the thread mapping, the cpu mapping, and the +# gpu_mapping.The mapping for each task is separated by a defined character. +# This separator can be changed in test_utils.c::parse_answer() + +11 + + +# 1: Map one task to every core +Map one task to every core +"1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1" +"6,54;6,54;7,55;7,55;8,56;8,56;9,57;9,57;10,58;10,58;11,59;11,59;12,60;12,60;13,61;13,61;14,62;14,62;15,63;15,63;16,64;16,64;17,65;17,65;30,78;30,78;31,79;31,79;32,80;32,80;33,81;33,81;34,82;34,82;35,83;35,83;42,90;42,90;43,91;43,91;44,92;44,92;45,93;45,93;46,94;46,94;47,95;47,95" +"0;0;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;1;1;2;2;2;2;2;2;2;2;2;2;2;2;3;3;3;3;3;3;3;3;3;3;3;3" + +# 2: Map 1 task greedily +Map 1 task greedily +"96" +"0-95" +"0-3" + + +# 3: Map two tasks greedily +Map two tasks greedily +"48;48" +"0-23,48-71;24-47,72-95" +"0-1;2-3" + +# 4: +Mapping such that ntasks < #NUMA nodes but nworkers > #NUMA nodes +"24;12;12;12;12;12;12" +"0-11,48-59;12-17,60-65;18-23,66-71;24-29,72-77;30-35,78-83;36-41,84-89;42-47,90-95" +"0;1;;;2;;3" + +# 5: +Restrict x tasks a single core (x == machine's smt level) +"1;1" +"0;0" +";" + +# 6: +Map two tasks at SMT 1 +"48;48" +"0-23,48-71;24-47,72-95" +"0-1;2-3" + + +# 7: +Map 2 tasks at max smt (across all cores) +"48;48" +"0-23,48-71;24-47,72-95" +"0-1;2-3" + + +# 8: +Map tasks at max smt-1 +"48;48" +"0-23,48-71;24-47,72-95" +"0-1;2-3" + + +# 9: +Map two tasks, but restrict them to a single NUMA domain +"3;3" +"0-2;3-5" +";" + + +# 11: +Map num_numa tasks without GPU optimization +"6;6;6;6;6;6;6;6" +"0-5;6-11;12-17;18-23;24-29;30-35;36-41;42-47" +";0;1;;;2;;3" + + +# 12: +Map num_numa tasks with GPU optimization +"3;3;3;3;3;3;3;3" +"6-8;9-11;12-14;15-17;30-32;33-35;42-44;45-47" +"0;0;1;1;2;2;3;3" + +# TODO: +# 13: Map using a complex configuration (exact details TBD) \ No newline at end of file diff --git a/tests/tap.c b/tests/tap.c new file mode 100644 index 0000000..788970a --- /dev/null +++ b/tests/tap.c @@ -0,0 +1,362 @@ +/* +libtap - Write tests in C +Copyright 2012 Jake Gelbman +This file is licensed under the LGPL +*/ + +#define _DEFAULT_SOURCE 1 + +#include +#include +#include +#include +#include "tap.h" + +static int expected_tests = NO_PLAN; +static int failed_tests; +static int current_test; +static char *todo_mesg; + +static char * +vstrdupf (const char *fmt, va_list args) { + char *str; + int size; + va_list args2; + va_copy(args2, args); + if (!fmt) + fmt = ""; + size = vsnprintf(NULL, 0, fmt, args2) + 2; + str = malloc(size); + if (!str) { + perror("malloc error"); + exit(1); + } + vsprintf(str, fmt, args); + va_end(args2); + return str; +} + +void +tap_plan (int tests, const char *fmt, ...) { + expected_tests = tests; + if (tests == SKIP_ALL) { + char *why; + va_list args; + va_start(args, fmt); + why = vstrdupf(fmt, args); + va_end(args); + printf("1..0 "); + diag("SKIP %s\n", why); + exit(0); + } + if (tests != NO_PLAN) { + printf("1..%d\n", tests); + } +} + +int +vok_at_loc (const char *file, int line, int test, const char *fmt, + va_list args) +{ + char *name = vstrdupf(fmt, args); + if (!test) { + printf("not "); + } + printf("ok %d", ++current_test); + if (*name) + printf(" - %s", name); + if (todo_mesg) { + printf(" # TODO"); + if (*todo_mesg) + printf(" %s", todo_mesg); + } + printf("\n"); + if (!test) { + printf("# Failed "); + if (todo_mesg) + printf("(TODO) "); + printf("test "); + if (*name) + printf("'%s'\n# ", name); + printf("at %s line %d.\n", file, line); + if (!todo_mesg) + failed_tests++; + } + free(name); + return test; +} + +int +ok_at_loc (const char *file, int line, int test, const char *fmt, ...) { + va_list args; + va_start(args, fmt); + vok_at_loc(file, line, test, fmt, args); + va_end(args); + return test; +} + +static int +mystrcmp (const char *a, const char *b) { + return a == b ? 0 : !a ? -1 : !b ? 1 : strcmp(a, b); +} + +#define eq(a, b) (!mystrcmp(a, b)) +#define ne(a, b) (mystrcmp(a, b)) + +int +is_at_loc (const char *file, int line, const char *got, const char *expected, + const char *fmt, ...) +{ + int test = eq(got, expected); + va_list args; + va_start(args, fmt); + vok_at_loc(file, line, test, fmt, args); + va_end(args); + if (!test) { + diag(" got: '%s'", got); + diag(" expected: '%s'", expected); + } + return test; +} + +int +isnt_at_loc (const char *file, int line, const char *got, const char *expected, + const char *fmt, ...) +{ + int test = ne(got, expected); + va_list args; + va_start(args, fmt); + vok_at_loc(file, line, test, fmt, args); + va_end(args); + if (!test) { + diag(" got: '%s'", got); + diag(" expected: anything else"); + } + return test; +} + +int +cmp_ok_at_loc (const char *file, int line, int a, const char *op, int b, + const char *fmt, ...) +{ + int test = eq(op, "||") ? a || b + : eq(op, "&&") ? a && b + : eq(op, "|") ? a | b + : eq(op, "^") ? a ^ b + : eq(op, "&") ? a & b + : eq(op, "==") ? a == b + : eq(op, "!=") ? a != b + : eq(op, "<") ? a < b + : eq(op, ">") ? a > b + : eq(op, "<=") ? a <= b + : eq(op, ">=") ? a >= b + : eq(op, "<<") ? a << b + : eq(op, ">>") ? a >> b + : eq(op, "+") ? a + b + : eq(op, "-") ? a - b + : eq(op, "*") ? a * b + : eq(op, "/") ? a / b + : eq(op, "%") ? a % b + : diag("unrecognized operator '%s'", op); + va_list args; + va_start(args, fmt); + vok_at_loc(file, line, test, fmt, args); + va_end(args); + if (!test) { + diag(" %d", a); + diag(" %s", op); + diag(" %d", b); + } + return test; +} + +static int +find_mem_diff (const char *a, const char *b, size_t n, size_t *offset) { + size_t i; + if (a == b) + return 0; + if (!a || !b) + return 2; + for (i = 0; i < n; i++) { + if (a[i] != b[i]) { + *offset = i; + return 1; + } + } + return 0; +} + +int +cmp_mem_at_loc (const char *file, int line, const void *got, + const void *expected, size_t n, const char *fmt, ...) +{ + size_t offset; + int diff = find_mem_diff(got, expected, n, &offset); + va_list args; + va_start(args, fmt); + vok_at_loc(file, line, !diff, fmt, args); + va_end(args); + if (diff == 1) { + diag(" Difference starts at offset %d", offset); + diag(" got: 0x%02x", ((unsigned char *)got)[offset]); + diag(" expected: 0x%02x", ((unsigned char *)expected)[offset]); + } + else if (diff == 2) { + diag(" got: %s", got ? "not NULL" : "NULL"); + diag(" expected: %s", expected ? "not NULL" : "NULL"); + } + return !diff; +} + +int +diag (const char *fmt, ...) { + va_list args; + char *mesg, *line; + int i; + va_start(args, fmt); + if (!fmt) { + va_end(args); + return 0; + } + mesg = vstrdupf(fmt, args); + line = mesg; + for (i = 0; *line; i++) { + char c = mesg[i]; + if (!c || c == '\n') { + mesg[i] = '\0'; + printf("# %s\n", line); + if (!c) + break; + mesg[i] = c; + line = mesg + i + 1; + } + } + free(mesg); + va_end(args); + return 0; +} + +int +exit_status () { + int retval = 0; + if (expected_tests == NO_PLAN) { + printf("1..%d\n", current_test); + } + else if (current_test != expected_tests) { + diag("Looks like you planned %d test%s but ran %d.", + expected_tests, expected_tests > 1 ? "s" : "", current_test); + retval = 2; + } + if (failed_tests) { + diag("Looks like you failed %d test%s of %d run.", + failed_tests, failed_tests > 1 ? "s" : "", current_test); + retval = 1; + } + return retval; +} + +int +bail_out (int ignore, const char *fmt, ...) { + va_list args; + (void) ignore; + va_start(args, fmt); + printf("Bail out! "); + vprintf(fmt, args); + printf("\n"); + va_end(args); + exit(255); + return 0; +} + +void +tap_skip (int n, const char *fmt, ...) { + char *why; + va_list args; + va_start(args, fmt); + why = vstrdupf(fmt, args); + va_end(args); + while (n --> 0) { + printf("ok %d ", ++current_test); + diag("skip %s\n", why); + } + free(why); +} + +void +tap_todo (int ignore, const char *fmt, ...) { + va_list args; + (void) ignore; + va_start(args, fmt); + todo_mesg = vstrdupf(fmt, args); + va_end(args); +} + +void +tap_end_todo () { + free(todo_mesg); + todo_mesg = NULL; +} + +#ifndef _WIN32 +#include +#include +#include + +#ifndef MAP_ANONYMOUS +#ifdef MAP_ANON +#define MAP_ANONYMOUS MAP_ANON +#else +#error "System does not support mapping anonymous pages" +#endif +#endif + +/* Create a shared memory int to keep track of whether a piece of code executed +dies. to be used in the dies_ok and lives_ok macros. */ +int +tap_test_died (int status) { + static int *test_died = NULL; + int prev; + if (!test_died) { + test_died = mmap(0, sizeof (int), PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, -1, 0); + *test_died = 0; + } + prev = *test_died; + *test_died = status; + return prev; +} + +int +like_at_loc (int for_match, const char *file, int line, const char *got, + const char *expected, const char *fmt, ...) +{ + int test; + regex_t re; + va_list args; + int err = regcomp(&re, expected, REG_EXTENDED); + if (err) { + char errbuf[256]; + regerror(err, &re, errbuf, sizeof errbuf); + fprintf(stderr, "Unable to compile regex '%s': %s at %s line %d\n", + expected, errbuf, file, line); + exit(255); + } + err = regexec(&re, got, 0, NULL, 0); + regfree(&re); + test = for_match ? !err : err; + va_start(args, fmt); + vok_at_loc(file, line, test, fmt, args); + va_end(args); + if (!test) { + if (for_match) { + diag(" '%s'", got); + diag(" doesn't match: '%s'", expected); + } + else { + diag(" '%s'", got); + diag(" matches: '%s'", expected); + } + } + return test; +} +#endif diff --git a/tests/tap.h b/tests/tap.h new file mode 100644 index 0000000..e366a6a --- /dev/null +++ b/tests/tap.h @@ -0,0 +1,115 @@ +/* +libtap - Write tests in C +Copyright 2012 Jake Gelbman +This file is licensed under the LGPL +*/ + +#ifndef __TAP_H__ +#define __TAP_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef va_copy +#ifdef __va_copy +#define va_copy __va_copy +#else +#define va_copy(d, s) ((d) = (s)) +#endif +#endif + +#include +#include +#include + +int vok_at_loc (const char *file, int line, int test, const char *fmt, + va_list args); +int ok_at_loc (const char *file, int line, int test, const char *fmt, + ...); +int is_at_loc (const char *file, int line, const char *got, + const char *expected, const char *fmt, ...); +int isnt_at_loc (const char *file, int line, const char *got, + const char *expected, const char *fmt, ...); +int cmp_ok_at_loc (const char *file, int line, int a, const char *op, + int b, const char *fmt, ...); +int cmp_mem_at_loc (const char *file, int line, const void *got, + const void *expected, size_t n, const char *fmt, ...); +int bail_out (int ignore, const char *fmt, ...); +void tap_plan (int tests, const char *fmt, ...); +int diag (const char *fmt, ...); +int exit_status (void); +void tap_skip (int n, const char *fmt, ...); +void tap_todo (int ignore, const char *fmt, ...); +void tap_end_todo (void); + +#define NO_PLAN -1 +#define SKIP_ALL -2 +#define ok(...) ok_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) +#define is(...) is_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) +#define isnt(...) isnt_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) +#define cmp_ok(...) cmp_ok_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) +#define cmp_mem(...) cmp_mem_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) +#define plan(...) tap_plan(__VA_ARGS__, NULL) +#define done_testing() return exit_status() +#define BAIL_OUT(...) bail_out(0, "" __VA_ARGS__, NULL) +#define pass(...) ok(1, "" __VA_ARGS__) +#define fail(...) ok(0, "" __VA_ARGS__) + +#define skip(test, ...) do {if (test) {tap_skip(__VA_ARGS__, NULL); break;} +#define end_skip } while (0) + +#define todo(...) tap_todo(0, "" __VA_ARGS__, NULL) +#define end_todo tap_end_todo() + +#define dies_ok(...) dies_ok_common(1, __VA_ARGS__) +#define lives_ok(...) dies_ok_common(0, __VA_ARGS__) + +#ifdef _WIN32 +#define like(...) tap_skip(1, "like is not implemented on Windows") +#define unlike(...) tap_skip(1, "unlike is not implemented on Windows") +#define dies_ok_common(...) \ + tap_skip(1, "Death detection is not supported on Windows") +#else +#define like(...) like_at_loc(1, __FILE__, __LINE__, __VA_ARGS__, NULL) +#define unlike(...) like_at_loc(0, __FILE__, __LINE__, __VA_ARGS__, NULL) +int like_at_loc (int for_match, const char *file, int line, + const char *got, const char *expected, + const char *fmt, ...); +#include +#include +#include +int tap_test_died (int status); +#define dies_ok_common(for_death, code, ...) \ + do { \ + int cpid; \ + int it_died; \ + tap_test_died(1); \ + cpid = fork(); \ + switch (cpid) { \ + case -1: \ + perror("fork error"); \ + exit(1); \ + case 0: \ + close(1); \ + close(2); \ + code \ + tap_test_died(0); \ + exit(0); \ + } \ + if (waitpid(cpid, NULL, 0) < 0) { \ + perror("waitpid error"); \ + exit(1); \ + } \ + it_died = tap_test_died(0); \ + if (!it_died) \ + {code} \ + ok(for_death ? it_died : !it_died, "" __VA_ARGS__); \ + } while (0) +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tests/test_utils.c b/tests/test_utils.c new file mode 100644 index 0000000..dd4652e --- /dev/null +++ b/tests/test_utils.c @@ -0,0 +1,449 @@ +#include "test_utils.h" +#define TEST_DEBUG 0 +#define BUF_SIZE 1024 + +#if 0 +/** + * Prints mpibind_t imput parameters + **/ +static void print_test_params(mpibind_t *handle) { + printf( + "tasks: %d\t threads: %d\n greedy: %d\n gpu_optim: %d\n smt: %d\n " + "restr_type: %d\t restrict_ids %s", + handle->ntasks, handle->in_nthreads, handle->greedy, handle->gpu_optim, + handle->smt, handle->restr_type, handle->restr_set); +} +#endif + +/** + * Initialize a test struct to default values. + * This mimics the behavior of mpibind_init + * **/ +int mpibind_test_t_init(mpibind_test_t *hdl) { + if (hdl == NULL) { + return 1; + } + + hdl->ntasks = 0; + hdl->in_nthreads = 0; + hdl->greedy = 1; + hdl->gpu_optim = 1; + hdl->smt = 0; + hdl->restr_set = NULL; + hdl->restr_type = MPIBIND_RESTRICT_CPU; + hdl->topo = NULL; + hdl->expected = NULL; + + return 0; +} + +/** + * Prints the current state of an mpibind_test_t object + * **/ +void mpibind_test_t_print(mpibind_test_t *params) { + printf("ntasks: %d\t in_nthreads: %d\n", params->ntasks, params->in_nthreads); + printf("greedy: %d\n", params->greedy); + printf("gpu_optim: %d\n", params->gpu_optim); + printf("smt: %d\n", params->smt); + printf("restr_set: %s\t restrict_type: %d\n", params->restr_set, + params->restr_type); + printf("\n"); +} + +/** + * Frees an answer + * **/ +void mpibind_test_ans_t_free(mpibind_test_ans_t *t) { + if (!t) { + perror("mpibind_test_ans_t == NULL"); + } + + free(t->description); + free(t->thread_mapping); + free(t->gpu_mapping); + free(t->cpu_mapping); + free(t); +} + +/** + * Frees a test object + * **/ +void mpibind_test_t_free(mpibind_test_t *t) { + if (!t) { + perror("mpibind_test_t == NULL"); + } + + if (t->restr_set) { + free(t->restr_set); + } + if (t->expected) { + mpibind_test_ans_t_free(t->expected); + free(t->expected); + } + free(t); +} + +/** + * Helper function to check the cpu, gpu, and thread mappings + * **/ +void check_mapping(mpibind_t *handle, mpibind_test_ans_t *expected) { + char *separator = ";"; + char thread_map_info[BUF_SIZE] = {'\0'}; + char cpu_map_info[BUF_SIZE] = {'\0'}; + char gpu_map_info[BUF_SIZE] = {'\0'}; + + // Concat string array into single string + int i = 0; + while (i < handle->ntasks) { + sprintf(thread_map_info + strlen(thread_map_info), "%d", + handle->nthreads[i]); + hwloc_bitmap_list_snprintf(cpu_map_info + strlen(cpu_map_info), + sizeof(cpu_map_info), handle->cpus[i]); + hwloc_bitmap_list_snprintf(gpu_map_info + strlen(gpu_map_info), + sizeof(gpu_map_info), handle->gpus[i]); + + // Separate entries with the specified separator + if (++i != handle->ntasks) { + strcat(thread_map_info, separator); + strcat(cpu_map_info, separator); + strcat(gpu_map_info, separator); + } + } + + // Check mappings against expected output + if (strcmp(expected->cpu_mapping, cpu_map_info) || + strcmp(expected->gpu_mapping, gpu_map_info) || + strcmp(expected->thread_mapping, thread_map_info)) { + fail("%s", expected->description); + diag( + "\tThreads: %s (expected %s)\n\tCPU: " + "%s (expected %s)\n\tGPU: %s (expected %s)", + thread_map_info, expected->thread_mapping, cpu_map_info, + expected->cpu_mapping, gpu_map_info, expected->gpu_mapping); + } else { + pass("%s", expected->description); + } +} + +/** + * Runs a set of tests and compares them to their answers. + * **/ +void run_test(hwloc_topology_t topo, mpibind_test_t *params, + mpibind_test_ans_t *expected) { + mpibind_t *handle; + hwloc_topology_t t; + + // dup the topology so the original doesn't accidentally get destroyed + mpibind_test_t_print(params); + hwloc_topology_dup(&t, topo); + mpibind_init(&handle); + mpibind_set_topology(handle, t); + mpibind_set_ntasks(handle, params->ntasks); + mpibind_set_nthreads(handle, params->in_nthreads); + mpibind_set_greedy(handle, params->greedy); + mpibind_set_gpu_optim(handle, params->gpu_optim); + mpibind_set_smt(handle, params->smt); + mpibind_set_restrict_type(handle, params->restr_type); + + mpibind_set_restrict_ids(handle, params->restr_set); + + if (mpibind(handle)) { + fail("%s\n\tEncountered error running mpibind", expected->description); + } else { + check_mapping(handle, expected); + mpibind_finalize(handle); + } + hwloc_topology_destroy(t); +} + +/** + * Generate unit test information from a topology + * TODO: EXPLAIN + * **/ +mpibind_test_t **generate_test_information(hwloc_topology_t topo, + int *num_test_ptr) { + int num_tests = 11; + mpibind_test_t **tests = calloc(num_tests, sizeof(mpibind_test_t *)); + *num_test_ptr = num_tests; + + // find the number of components at each level + int num_numas = hwloc_get_nbobjs_by_type(topo, HWLOC_OBJ_NUMANODE); + int num_cores = hwloc_get_nbobjs_by_type(topo, HWLOC_OBJ_CORE); + +#if TEST_DEBUG + int num_pus = hwloc_get_nbobjs_by_type(topo, HWLOC_OBJ_PU); + int num_gpus = hwloc_get_nbobjs_by_type(topo, HWLOC_OBJ_OS_DEVICE); +#endif + + int numa_id = + hwloc_get_next_obj_by_type(topo, HWLOC_OBJ_NUMANODE, NULL)->os_index; + int core_id = + hwloc_get_next_obj_by_type(topo, HWLOC_OBJ_CORE, NULL)->os_index; + + // find max arity btwn all the cores on the machine + hwloc_obj_t obj = NULL; + hwloc_obj_t prev = NULL; + int max_arity = 0; + + while ((obj = hwloc_get_next_obj_by_type(topo, HWLOC_OBJ_CORE, prev))) { + if (obj->arity > max_arity) { + max_arity = obj->arity; + } + prev = obj; + } + +#if TEST_DEBUG + printf("Num numas: %d \n", num_numas); + printf("Num gpus: %d \n", num_gpus); + printf("Num cores: %d \n", num_cores); + printf("Num PUs: %d \n", num_pus); +#endif + + mpibind_test_t **ptr = tests; + mpibind_test_t *handle; + + handle = calloc(1, sizeof(mpibind_test_t)); + // 1: Map one task to every core + mpibind_test_t_init(handle); + handle->ntasks = num_cores; + *ptr++ = handle; + + handle = calloc(1, sizeof(mpibind_test_t)); + // 2: Map one task greedily + mpibind_test_t_init(handle); + handle->ntasks = 1; + handle->greedy = 1; + *ptr++ = handle; + + handle = calloc(1, sizeof(mpibind_test_t)); + // 3: Map two tasks greedily + mpibind_test_t_init(handle); + handle->ntasks = 2; + handle->greedy = 1; + *ptr++ = handle; + + handle = calloc(1, sizeof(mpibind_test_t)); + mpibind_test_t_init(handle); + // 4: Mapping such that ntasks < #NUMA nodes but nworkers > #NUMA nodes + handle->in_nthreads = num_numas * 2; + handle->ntasks = (num_numas == 1) ? 1 : num_numas - 1; + *ptr++ = handle; + + handle = calloc(1, sizeof(mpibind_test_t)); + mpibind_test_t_init(handle); + // 5: Restrict x tasks a single core (x == machine's smt level) + handle->ntasks = max_arity; + handle->restr_type = MPIBIND_RESTRICT_CPU; + handle->restr_set = calloc(10, sizeof(char)); + sprintf(handle->restr_set, "%d", core_id); + *ptr++ = handle; + + handle = calloc(1, sizeof(mpibind_test_t)); + mpibind_test_t_init(handle); + // 6: Map two tasks at smt 1 + handle->ntasks = 2; + handle->smt = 1; + *ptr++ = handle; + + handle = calloc(1, sizeof(mpibind_test_t)); + mpibind_test_t_init(handle); + // 7: Map two tasks at max_smt + handle->ntasks = 2; + handle->smt = max_arity; + *ptr++ = handle; + + handle = calloc(1, sizeof(mpibind_test_t)); + mpibind_test_t_init(handle); + // 8: Map two tasks at (max_smt - 1) + handle->ntasks = 2; + handle->smt = (max_arity == 1) ? 1 : max_arity - 1; + *ptr++ = handle; + + handle = calloc(1, sizeof(mpibind_test_t)); + mpibind_test_t_init(handle); + // 9: Map two tasks, but restrict them to a single NUMA domain + handle->ntasks = 2; + handle->restr_type = MPIBIND_RESTRICT_MEM; + handle->restr_set = calloc(10, sizeof(char)); + sprintf(handle->restr_set, "%d", numa_id); + *ptr++ = handle; + + handle = calloc(1, sizeof(mpibind_test_t)); + mpibind_test_t_init(handle); + // 11: Map num_numa tasks without GPU optimization + handle->ntasks = num_numas; + handle->gpu_optim = 0; + *ptr++ = handle; + + handle = calloc(1, sizeof(mpibind_test_t)); + mpibind_test_t_init(handle); + // 12: Map num_numa tasks with GPU optimization + handle->ntasks = num_numas; + handle->gpu_optim = 1; + *ptr++ = handle; + + // Map using a complex configuration (exact details TBD) + return tests; +} + +/** load an xml file into a topology **/ +void load_topology(hwloc_topology_t *topo, char *xml_file) { + hwloc_topology_init(topo); + if (hwloc_topology_set_xml(*topo, xml_file) < 0) + perror("Failed to set topology"); + hwloc_topology_set_all_types_filter(*topo, HWLOC_TYPE_FILTER_KEEP_STRUCTURE); + hwloc_topology_set_type_filter(*topo, HWLOC_OBJ_OS_DEVICE, + HWLOC_TYPE_FILTER_KEEP_IMPORTANT); + hwloc_topology_load(*topo); +} + +/** + * Parse a single answer from an answer file + * An answer consists of three consectutive lines with each line containing + * the thread mapping, cpu mapping, and gpu mapping in that order + * */ +static int parse_answer(mpibind_test_ans_t *expected, FILE *fp) { + if (!expected) { + return 1; + } + + char buf[BUF_SIZE]; + char *tmp; + + // Skip newlines and comments + do { + if (!fgets(buf, sizeof(buf), fp)) { + perror("error reading from file"); + exit(1); + } + } while (!strcmp(buf, "\n") || buf[0] == '#'); + + // Since we were using fgets, we need to take out the newline if present + // else it would added to the description + if ((tmp = strchr(buf, '\n')) >= 0) { + *tmp = '\0'; + } + + // Copy description +#if TEST_DEBUG + printf("%s\n", buf); +#endif + expected->description = calloc(BUF_SIZE, sizeof(char)); + strcpy(expected->description, buf); + + if (!fgets(buf, sizeof(buf), fp)) { + perror("error reading from file"); + exit(1); + } + + // Copy thread mapping +#if TEST_DEBUG + printf("%s\n", buf); +#endif + + expected->thread_mapping = calloc(BUF_SIZE, sizeof(char)); + if (sscanf(buf, "\"%[^\"]\"", expected->thread_mapping) < 0) { + perror("error parsing answers"); + exit(1); + } + + if (!fgets(buf, sizeof(buf), fp)) { + perror("error reading from file"); + exit(1); + } + + // Copy cpu mapping +#if TEST_DEBUG + printf("%s\n", buf); +#endif + expected->cpu_mapping = calloc(BUF_SIZE, sizeof(char)); + if (sscanf(buf, "\"%[^\"]\"", expected->cpu_mapping) < 0) { + perror("error parsing answers"); + exit(1); + } + + if (!fgets(buf, sizeof(buf), fp)) { + perror("error reading from file"); + exit(1); + } + + // Copy gpu mapping +#if TEST_DEBUG + printf("%s\n", buf); +#endif + expected->gpu_mapping = calloc(BUF_SIZE, sizeof(char)); + if (sscanf(buf, "\"%[^\"]\"", expected->gpu_mapping) < 0) { + perror("error parsing answers"); + exit(1); + } + + return 0; +} + +mpibind_test_ans_t **load_answers(char *filename, int *num_tests_ptr) { + int num_tests; + char buf[BUF_SIZE]; + FILE *fp = fopen(filename, "r"); + + // Remove initial whitespace + do { + if (!fgets(buf, sizeof(buf), fp)) { + perror("error reading from file"); + exit(1); + } + } while (!strcmp(buf, "\n") || buf[0] == '#'); + + // Get number of tests + sscanf(buf, "%d\n", &num_tests); +#if TEST_DEBUG + printf("load_answers: num_tests = %d\n", num_tests); +#endif + *num_tests_ptr = num_tests; + + mpibind_test_ans_t **answers = + calloc(num_tests, sizeof(mpibind_test_ans_t *)); + + // Parse answers into return pointer + int i; + for (i = 0; i < num_tests; i++) { + answers[i] = calloc(1, sizeof(mpibind_test_ans_t)); + parse_answer(answers[i], fp); + } + + // Don't forget to close the file + fclose(fp); + return answers; +} + +/** Performs a unit test using a given topology xml and an answer file. + * Test drivers should call this method + * **/ +void unit_test_topology(char *topology_filename, char *answer_filename) { + int num_answers, num_tests; + hwloc_topology_t topo; + + load_topology(&topo, topology_filename); + diag("testing %s", topology_filename); + + mpibind_test_ans_t **answers = load_answers(answer_filename, &num_answers); + mpibind_test_t **tests = generate_test_information(topo, &num_tests); + + if (num_answers != num_tests) { + BAIL_OUT("ERROR: num. answers: %d, num. tests: %d\n", num_answers, + num_tests); + } + + int i; + for (i = 0; i < num_tests; i++) { + run_test(topo, tests[i], answers[i]); + } + + // cleanup everything + for (i = 0; i < num_tests; i++) { + mpibind_test_ans_t_free(answers[i]); + mpibind_test_t_free(tests[i]); + } + free(answers); + free(tests); + hwloc_topology_destroy(topo); +} \ No newline at end of file diff --git a/tests/test_utils.h b/tests/test_utils.h new file mode 100644 index 0000000..d502dba --- /dev/null +++ b/tests/test_utils.h @@ -0,0 +1,81 @@ +#ifndef MPIBIND_TEST_UTILS_H +#define MPIBIND_TEST_UTILS_H +#include +#include +#include + +#include "mpibind.h" +#include "mpibind-priv.h" +#include "tap.h" + +/** + * Representation of a test answer + * **/ +typedef struct { + char* description; + char* thread_mapping; + char* cpu_mapping; + char* gpu_mapping; +} mpibind_test_ans_t; +/** + * Input parameters for a test. This mimics + * the structure of mpibind_t, but is defined + * separately to make the tests independent of + * mpibind_t's definition. + * **/ +typedef struct { + /* Input parameters */ + hwloc_topology_t topo; + int ntasks; + int in_nthreads; + int greedy; + int gpu_optim; + int smt; + char* restr_set; + int restr_type; + + /* Optional place to hold an answer to a test */ + mpibind_test_ans_t* expected; +} mpibind_test_t; +/** + * Initialize a test struct to default values. + * This mimics the behavior of mpibind_init + * **/ +int mpibind_test_t_init(mpibind_test_t* hdl); +/** + * Frees an answer + * **/ +void mpibind_test_ans_t_free(mpibind_test_ans_t* t); +/** + * Frees a test object + * **/ +void mpibind_test_t_free(mpibind_test_t* t); +/** + * Prints the current state of an mpibind_test_t object + * **/ +void mpibind_test_t_print(mpibind_test_t* params); +/** Helper function to check the cpu, gpu, and thread mappings**/ +void check_mapping(mpibind_t* handle, mpibind_test_ans_t* expected); +/** + * Runs a set of tests and compares them to their answers. + * **/ +void run_test(hwloc_topology_t topo, mpibind_test_t *params, mpibind_test_ans_t *expected); +/** + * Generate unit test information from a topology + * TODO: EXPLAIN + * **/ +mpibind_test_t** generate_test_information(hwloc_topology_t topo, + int* num_test_ptr); +/** load an xml file into a topology **/ +void load_topology(hwloc_topology_t* topo, char* xml_file); +/** + * Loads a set of test answers from a file. + * num_test_ptr will be used to store the number of answers parsed + * **/ +mpibind_test_ans_t** load_answers(char* filename, int* num_tests_ptr); + +/** Performs a unit test using a given topology xml and an answer file. + * Test drivers should call this method + * **/ +void unit_test_topology(char* topology_filename, char* answer_filename); +#endif From 23e4c395d6041dd44132243138df796e0c1abe88 Mon Sep 17 00:00:00 2001 From: Samuel Furman Date: Mon, 27 Jul 2020 12:34:34 -0700 Subject: [PATCH 2/9] temp structure --- python_bindings/__init__.py | 0 python_bindings/cffi_build/__init__.py | 0 python_bindings/cffi_build/_mpibind.h | 184 ++ .../cffi_build/cffi_build/_mpibind_cffi.c | 1554 +++++++++++++++++ python_bindings/cffi_build/mpibind_build.py | 26 + python_bindings/cffi_build/test.c | 1554 +++++++++++++++++ python_bindings/mpibind/__init__.py | 0 python_bindings/mpibind/mpibind.py | 13 + python_bindings/setup.py | 13 + 9 files changed, 3344 insertions(+) create mode 100644 python_bindings/__init__.py create mode 100644 python_bindings/cffi_build/__init__.py create mode 100644 python_bindings/cffi_build/_mpibind.h create mode 100644 python_bindings/cffi_build/cffi_build/_mpibind_cffi.c create mode 100644 python_bindings/cffi_build/mpibind_build.py create mode 100644 python_bindings/cffi_build/test.c create mode 100644 python_bindings/mpibind/__init__.py create mode 100644 python_bindings/mpibind/mpibind.py create mode 100644 python_bindings/setup.py diff --git a/python_bindings/__init__.py b/python_bindings/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python_bindings/cffi_build/__init__.py b/python_bindings/cffi_build/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python_bindings/cffi_build/_mpibind.h b/python_bindings/cffi_build/_mpibind.h new file mode 100644 index 0000000..1d1c101 --- /dev/null +++ b/python_bindings/cffi_build/_mpibind.h @@ -0,0 +1,184 @@ +enum { + /* Caller can restrict the topology based on CPU or MEM */ + MPIBIND_RESTRICT_CPU, + MPIBIND_RESTRICT_MEM, + + /* The type of GPU by vendor */ + MPIBIND_GPU_AMD, + MPIBIND_GPU_NVIDIA, +}; + +/* Opaque mpibind handle */ +struct mpibind_t; +typedef struct mpibind_t mpibind_t; + +/* + * The mpibind API. + * Most calls return 0 on success and non-0 on failure. + */ + +/* + * Initialize an mpibind handle. All mpibind functions require + * this function to be called first. + */ +int mpibind_init(mpibind_t **handle); +/* + * Release resources associated with the input handle. + * After this call, no mpibind function should be called. + */ +int mpibind_finalize(mpibind_t *handle); + +/* + * Required input parameters + */ +/* + * The number of processes/tasks in the job. + */ +int mpibind_set_ntasks(mpibind_t *handle, + int ntasks); + +/* + * Optional input parameters + */ +/* + * The number of threads per process. + * If nthreads is not provided, mpibind calculates an + * appropriate number of threads for each task + * (see mpibind_get_nthreads). + */ +int mpibind_set_nthreads(mpibind_t *handle, + int nthreads); +/* + * Valid values are 0 and 1. Default is 1. + * If 1 and the number of tasks is less than the number of + * NUMA domains, mpibind assigns all of the available hardware + * resources to the input tasks. + * Otherwise, mpibind assigns no more than one NUMA domain + * (and associated resources) per task. + */ +int mpibind_set_greedy(mpibind_t *handle, + int greedy); +/* + * Valid values are 0 and 1. Default is 1. + * If 1, optimize task placement for GPUs. + * Otherwise, optimize placement for CPUs. + */ +int mpibind_set_gpu_optim(mpibind_t *handle, + int gpu_optim); +/* + * Map the application workers to this SMT-level. + * For an n-way SMT architecture, valid values are 1 to n. + * If not specified, mpibind determines the SMT level + * appropriately based on the number of input workers. + */ +int mpibind_set_smt(mpibind_t *handle, + int smt); +/* + * Restrict the hardware topology to resources + * associated with the specified hardware ids of type 'restr_type'. + */ +int mpibind_set_restrict_ids(mpibind_t *handle, + char *restr_set); +/* + * Specify the type of resource to use to restrict + * the hardware topology: MPIBIND_RESTRICT_CPU or + * MPIBIND_RESTRICT_MEM. + * The default value is MPIBIND_RESTRICT_CPU and it only + * applies if 'restr_set' is given. + */ +int mpibind_set_restrict_type(mpibind_t *handle, + int restr_type); +/* + * Pass a loaded topology to mpibind. + * mpibind will use this topology to perform the mappings + * instead of loading its own topology. + */ +int mpibind_set_topology(mpibind_t *handle, + hwloc_topology_t topo); + +/* + * Main mapping function. + * The resulting mapping can be retrieved with the + * mpibind_get* functions below. + */ +int mpibind(mpibind_t *handle); + +/* + * Output: The mapping policy. + * Asssign CPUs, GPUs, and number of threads to each + * task/process in the job. + * These output functions should only be called after + * a call to the main 'mpibind' function. + */ +/* + * Array with 'ntasks' elements. Each entry correspond + * to the number of threads to use for the process/task + * corresponding to this entry. + */ +int* mpibind_get_nthreads(mpibind_t *handle); +/* + * Array with 'ntasks' elements. The physical CPUs to + * use for a given process/task. + */ +hwloc_bitmap_t* mpibind_get_cpus(mpibind_t *handle); +/* + * Array with 'ntasks' elements. The GPUs to use for a + * given process/task. + */ +hwloc_bitmap_t* mpibind_get_gpus(mpibind_t *handle); +/* + * The GPU vendor associated with the GPUs on this + * node: MPIBIND_GPU_AMD or MPIBIND_GPU_NVIDIA. + */ +int mpibind_get_gpu_type(mpibind_t *handle); +/* + * Get the hwloc loaded topology used by mpibind so that + * callers can continue to use it even after mpibind has + * been finalized. This call, however, must be called + * before mpibind_finalize. This also means that the caller + * is responsible for unloading/freeing the topology. + */ +hwloc_topology_t mpibind_get_topology(mpibind_t *handle); + +/* + * Helper functions + */ +/* + * Print the mapping for each task. + */ +void mpibind_print_mapping(mpibind_t *handle); +/* + * Environment variables that need to be exported by the runtime. + * CUDA_VISIBLE_DEVICES --comma separated + * ROCR_VISIBLE_DEVICES + * OMP_NUM_THREADS + * OMP_PLACES --comma separated, each item in curly braces. + * OMP_PROC_BIND --spread + * It is the caller's responsibility to export the environment + * variables as desired. This function simply stores them and + * the appropriate values for the caller. + */ +int mpibind_set_env_vars(mpibind_t *handle); +/* + * Print the environment variables. + * mpibind_set_env_vars must be called before this function + * is executed. + */ +void mpibind_print_env_vars(mpibind_t *handle); +/* + * For each task, return the value of a given env + * variable (name). The output array has size 'ntasks'. + * mpibind_set_env_vars must be called before this function + * is executed. + */ +char** mpibind_get_env_var_values(mpibind_t *handle, + char *name); +/* + * Return an array with the names of the env variables. + * The size of the array is given in *count. + * mpibind_set_env_vars must be called before this function + * is executed. + */ +char** mpibind_get_env_var_names(mpibind_t *handle, int *count); + + diff --git a/python_bindings/cffi_build/cffi_build/_mpibind_cffi.c b/python_bindings/cffi_build/cffi_build/_mpibind_cffi.c new file mode 100644 index 0000000..9f2a1bf --- /dev/null +++ b/python_bindings/cffi_build/cffi_build/_mpibind_cffi.c @@ -0,0 +1,1554 @@ +#define _CFFI_ + +/* We try to define Py_LIMITED_API before including Python.h. + + Mess: we can only define it if Py_DEBUG, Py_TRACE_REFS and + Py_REF_DEBUG are not defined. This is a best-effort approximation: + we can learn about Py_DEBUG from pyconfig.h, but it is unclear if + the same works for the other two macros. Py_DEBUG implies them, + but not the other way around. + + Issue #350 is still open: on Windows, the code here causes it to link + with PYTHON36.DLL (for example) instead of PYTHON3.DLL. A fix was + attempted in 164e526a5515 and 14ce6985e1c3, but reverted: virtualenv + does not make PYTHON3.DLL available, and so the "correctly" compiled + version would not run inside a virtualenv. We will re-apply the fix + after virtualenv has been fixed for some time. For explanation, see + issue #355. For a workaround if you want PYTHON3.DLL and don't worry + about virtualenv, see issue #350. See also 'py_limited_api' in + setuptools_ext.py. +*/ +#if !defined(_CFFI_USE_EMBEDDING) && !defined(Py_LIMITED_API) +# include +# if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG) +# define Py_LIMITED_API +# endif +#endif + +#include +#ifdef __cplusplus +extern "C" { +#endif +#include + +/* This part is from file 'cffi/parse_c_type.h'. It is copied at the + beginning of C sources generated by CFFI's ffi.set_source(). */ + +typedef void *_cffi_opcode_t; + +#define _CFFI_OP(opcode, arg) (_cffi_opcode_t)(opcode | (((uintptr_t)(arg)) << 8)) +#define _CFFI_GETOP(cffi_opcode) ((unsigned char)(uintptr_t)cffi_opcode) +#define _CFFI_GETARG(cffi_opcode) (((intptr_t)cffi_opcode) >> 8) + +#define _CFFI_OP_PRIMITIVE 1 +#define _CFFI_OP_POINTER 3 +#define _CFFI_OP_ARRAY 5 +#define _CFFI_OP_OPEN_ARRAY 7 +#define _CFFI_OP_STRUCT_UNION 9 +#define _CFFI_OP_ENUM 11 +#define _CFFI_OP_FUNCTION 13 +#define _CFFI_OP_FUNCTION_END 15 +#define _CFFI_OP_NOOP 17 +#define _CFFI_OP_BITFIELD 19 +#define _CFFI_OP_TYPENAME 21 +#define _CFFI_OP_CPYTHON_BLTN_V 23 // varargs +#define _CFFI_OP_CPYTHON_BLTN_N 25 // noargs +#define _CFFI_OP_CPYTHON_BLTN_O 27 // O (i.e. a single arg) +#define _CFFI_OP_CONSTANT 29 +#define _CFFI_OP_CONSTANT_INT 31 +#define _CFFI_OP_GLOBAL_VAR 33 +#define _CFFI_OP_DLOPEN_FUNC 35 +#define _CFFI_OP_DLOPEN_CONST 37 +#define _CFFI_OP_GLOBAL_VAR_F 39 +#define _CFFI_OP_EXTERN_PYTHON 41 + +#define _CFFI_PRIM_VOID 0 +#define _CFFI_PRIM_BOOL 1 +#define _CFFI_PRIM_CHAR 2 +#define _CFFI_PRIM_SCHAR 3 +#define _CFFI_PRIM_UCHAR 4 +#define _CFFI_PRIM_SHORT 5 +#define _CFFI_PRIM_USHORT 6 +#define _CFFI_PRIM_INT 7 +#define _CFFI_PRIM_UINT 8 +#define _CFFI_PRIM_LONG 9 +#define _CFFI_PRIM_ULONG 10 +#define _CFFI_PRIM_LONGLONG 11 +#define _CFFI_PRIM_ULONGLONG 12 +#define _CFFI_PRIM_FLOAT 13 +#define _CFFI_PRIM_DOUBLE 14 +#define _CFFI_PRIM_LONGDOUBLE 15 + +#define _CFFI_PRIM_WCHAR 16 +#define _CFFI_PRIM_INT8 17 +#define _CFFI_PRIM_UINT8 18 +#define _CFFI_PRIM_INT16 19 +#define _CFFI_PRIM_UINT16 20 +#define _CFFI_PRIM_INT32 21 +#define _CFFI_PRIM_UINT32 22 +#define _CFFI_PRIM_INT64 23 +#define _CFFI_PRIM_UINT64 24 +#define _CFFI_PRIM_INTPTR 25 +#define _CFFI_PRIM_UINTPTR 26 +#define _CFFI_PRIM_PTRDIFF 27 +#define _CFFI_PRIM_SIZE 28 +#define _CFFI_PRIM_SSIZE 29 +#define _CFFI_PRIM_INT_LEAST8 30 +#define _CFFI_PRIM_UINT_LEAST8 31 +#define _CFFI_PRIM_INT_LEAST16 32 +#define _CFFI_PRIM_UINT_LEAST16 33 +#define _CFFI_PRIM_INT_LEAST32 34 +#define _CFFI_PRIM_UINT_LEAST32 35 +#define _CFFI_PRIM_INT_LEAST64 36 +#define _CFFI_PRIM_UINT_LEAST64 37 +#define _CFFI_PRIM_INT_FAST8 38 +#define _CFFI_PRIM_UINT_FAST8 39 +#define _CFFI_PRIM_INT_FAST16 40 +#define _CFFI_PRIM_UINT_FAST16 41 +#define _CFFI_PRIM_INT_FAST32 42 +#define _CFFI_PRIM_UINT_FAST32 43 +#define _CFFI_PRIM_INT_FAST64 44 +#define _CFFI_PRIM_UINT_FAST64 45 +#define _CFFI_PRIM_INTMAX 46 +#define _CFFI_PRIM_UINTMAX 47 +#define _CFFI_PRIM_FLOATCOMPLEX 48 +#define _CFFI_PRIM_DOUBLECOMPLEX 49 +#define _CFFI_PRIM_CHAR16 50 +#define _CFFI_PRIM_CHAR32 51 + +#define _CFFI__NUM_PRIM 52 +#define _CFFI__UNKNOWN_PRIM (-1) +#define _CFFI__UNKNOWN_FLOAT_PRIM (-2) +#define _CFFI__UNKNOWN_LONG_DOUBLE (-3) + +#define _CFFI__IO_FILE_STRUCT (-1) + + +struct _cffi_global_s { + const char *name; + void *address; + _cffi_opcode_t type_op; + void *size_or_direct_fn; // OP_GLOBAL_VAR: size, or 0 if unknown + // OP_CPYTHON_BLTN_*: addr of direct function +}; + +struct _cffi_getconst_s { + unsigned long long value; + const struct _cffi_type_context_s *ctx; + int gindex; +}; + +struct _cffi_struct_union_s { + const char *name; + int type_index; // -> _cffi_types, on a OP_STRUCT_UNION + int flags; // _CFFI_F_* flags below + size_t size; + int alignment; + int first_field_index; // -> _cffi_fields array + int num_fields; +}; +#define _CFFI_F_UNION 0x01 // is a union, not a struct +#define _CFFI_F_CHECK_FIELDS 0x02 // complain if fields are not in the + // "standard layout" or if some are missing +#define _CFFI_F_PACKED 0x04 // for CHECK_FIELDS, assume a packed struct +#define _CFFI_F_EXTERNAL 0x08 // in some other ffi.include() +#define _CFFI_F_OPAQUE 0x10 // opaque + +struct _cffi_field_s { + const char *name; + size_t field_offset; + size_t field_size; + _cffi_opcode_t field_type_op; +}; + +struct _cffi_enum_s { + const char *name; + int type_index; // -> _cffi_types, on a OP_ENUM + int type_prim; // _CFFI_PRIM_xxx + const char *enumerators; // comma-delimited string +}; + +struct _cffi_typename_s { + const char *name; + int type_index; /* if opaque, points to a possibly artificial + OP_STRUCT which is itself opaque */ +}; + +struct _cffi_type_context_s { + _cffi_opcode_t *types; + const struct _cffi_global_s *globals; + const struct _cffi_field_s *fields; + const struct _cffi_struct_union_s *struct_unions; + const struct _cffi_enum_s *enums; + const struct _cffi_typename_s *typenames; + int num_globals; + int num_struct_unions; + int num_enums; + int num_typenames; + const char *const *includes; + int num_types; + int flags; /* future extension */ +}; + +struct _cffi_parse_info_s { + const struct _cffi_type_context_s *ctx; + _cffi_opcode_t *output; + unsigned int output_size; + size_t error_location; + const char *error_message; +}; + +struct _cffi_externpy_s { + const char *name; + size_t size_of_result; + void *reserved1, *reserved2; +}; + +#ifdef _CFFI_INTERNAL +static int parse_c_type(struct _cffi_parse_info_s *info, const char *input); +static int search_in_globals(const struct _cffi_type_context_s *ctx, + const char *search, size_t search_len); +static int search_in_struct_unions(const struct _cffi_type_context_s *ctx, + const char *search, size_t search_len); +#endif + +/* this block of #ifs should be kept exactly identical between + c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py + and cffi/_cffi_include.h */ +#if defined(_MSC_VER) +# include /* for alloca() */ +# if _MSC_VER < 1600 /* MSVC < 2010 */ + typedef __int8 int8_t; + typedef __int16 int16_t; + typedef __int32 int32_t; + typedef __int64 int64_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; + typedef __int8 int_least8_t; + typedef __int16 int_least16_t; + typedef __int32 int_least32_t; + typedef __int64 int_least64_t; + typedef unsigned __int8 uint_least8_t; + typedef unsigned __int16 uint_least16_t; + typedef unsigned __int32 uint_least32_t; + typedef unsigned __int64 uint_least64_t; + typedef __int8 int_fast8_t; + typedef __int16 int_fast16_t; + typedef __int32 int_fast32_t; + typedef __int64 int_fast64_t; + typedef unsigned __int8 uint_fast8_t; + typedef unsigned __int16 uint_fast16_t; + typedef unsigned __int32 uint_fast32_t; + typedef unsigned __int64 uint_fast64_t; + typedef __int64 intmax_t; + typedef unsigned __int64 uintmax_t; +# else +# include +# endif +# if _MSC_VER < 1800 /* MSVC < 2013 */ +# ifndef __cplusplus + typedef unsigned char _Bool; +# endif +# endif +#else +# include +# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux) +# include +# endif +#endif + +#ifdef __GNUC__ +# define _CFFI_UNUSED_FN __attribute__((unused)) +#else +# define _CFFI_UNUSED_FN /* nothing */ +#endif + +#ifdef __cplusplus +# ifndef _Bool + typedef bool _Bool; /* semi-hackish: C++ has no _Bool; bool is builtin */ +# endif +#endif + +/********** CPython-specific section **********/ +#ifndef PYPY_VERSION + + +#if PY_MAJOR_VERSION >= 3 +# define PyInt_FromLong PyLong_FromLong +#endif + +#define _cffi_from_c_double PyFloat_FromDouble +#define _cffi_from_c_float PyFloat_FromDouble +#define _cffi_from_c_long PyInt_FromLong +#define _cffi_from_c_ulong PyLong_FromUnsignedLong +#define _cffi_from_c_longlong PyLong_FromLongLong +#define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong +#define _cffi_from_c__Bool PyBool_FromLong + +#define _cffi_to_c_double PyFloat_AsDouble +#define _cffi_to_c_float PyFloat_AsDouble + +#define _cffi_from_c_int(x, type) \ + (((type)-1) > 0 ? /* unsigned */ \ + (sizeof(type) < sizeof(long) ? \ + PyInt_FromLong((long)x) : \ + sizeof(type) == sizeof(long) ? \ + PyLong_FromUnsignedLong((unsigned long)x) : \ + PyLong_FromUnsignedLongLong((unsigned long long)x)) : \ + (sizeof(type) <= sizeof(long) ? \ + PyInt_FromLong((long)x) : \ + PyLong_FromLongLong((long long)x))) + +#define _cffi_to_c_int(o, type) \ + ((type)( \ + sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \ + : (type)_cffi_to_c_i8(o)) : \ + sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \ + : (type)_cffi_to_c_i16(o)) : \ + sizeof(type) == 4 ? (((type)-1) > 0 ? (type)_cffi_to_c_u32(o) \ + : (type)_cffi_to_c_i32(o)) : \ + sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \ + : (type)_cffi_to_c_i64(o)) : \ + (Py_FatalError("unsupported size for type " #type), (type)0))) + +#define _cffi_to_c_i8 \ + ((int(*)(PyObject *))_cffi_exports[1]) +#define _cffi_to_c_u8 \ + ((int(*)(PyObject *))_cffi_exports[2]) +#define _cffi_to_c_i16 \ + ((int(*)(PyObject *))_cffi_exports[3]) +#define _cffi_to_c_u16 \ + ((int(*)(PyObject *))_cffi_exports[4]) +#define _cffi_to_c_i32 \ + ((int(*)(PyObject *))_cffi_exports[5]) +#define _cffi_to_c_u32 \ + ((unsigned int(*)(PyObject *))_cffi_exports[6]) +#define _cffi_to_c_i64 \ + ((long long(*)(PyObject *))_cffi_exports[7]) +#define _cffi_to_c_u64 \ + ((unsigned long long(*)(PyObject *))_cffi_exports[8]) +#define _cffi_to_c_char \ + ((int(*)(PyObject *))_cffi_exports[9]) +#define _cffi_from_c_pointer \ + ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[10]) +#define _cffi_to_c_pointer \ + ((char *(*)(PyObject *, struct _cffi_ctypedescr *))_cffi_exports[11]) +#define _cffi_get_struct_layout \ + not used any more +#define _cffi_restore_errno \ + ((void(*)(void))_cffi_exports[13]) +#define _cffi_save_errno \ + ((void(*)(void))_cffi_exports[14]) +#define _cffi_from_c_char \ + ((PyObject *(*)(char))_cffi_exports[15]) +#define _cffi_from_c_deref \ + ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[16]) +#define _cffi_to_c \ + ((int(*)(char *, struct _cffi_ctypedescr *, PyObject *))_cffi_exports[17]) +#define _cffi_from_c_struct \ + ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[18]) +#define _cffi_to_c_wchar_t \ + ((_cffi_wchar_t(*)(PyObject *))_cffi_exports[19]) +#define _cffi_from_c_wchar_t \ + ((PyObject *(*)(_cffi_wchar_t))_cffi_exports[20]) +#define _cffi_to_c_long_double \ + ((long double(*)(PyObject *))_cffi_exports[21]) +#define _cffi_to_c__Bool \ + ((_Bool(*)(PyObject *))_cffi_exports[22]) +#define _cffi_prepare_pointer_call_argument \ + ((Py_ssize_t(*)(struct _cffi_ctypedescr *, \ + PyObject *, char **))_cffi_exports[23]) +#define _cffi_convert_array_from_object \ + ((int(*)(char *, struct _cffi_ctypedescr *, PyObject *))_cffi_exports[24]) +#define _CFFI_CPIDX 25 +#define _cffi_call_python \ + ((void(*)(struct _cffi_externpy_s *, char *))_cffi_exports[_CFFI_CPIDX]) +#define _cffi_to_c_wchar3216_t \ + ((int(*)(PyObject *))_cffi_exports[26]) +#define _cffi_from_c_wchar3216_t \ + ((PyObject *(*)(int))_cffi_exports[27]) +#define _CFFI_NUM_EXPORTS 28 + +struct _cffi_ctypedescr; + +static void *_cffi_exports[_CFFI_NUM_EXPORTS]; + +#define _cffi_type(index) ( \ + assert((((uintptr_t)_cffi_types[index]) & 1) == 0), \ + (struct _cffi_ctypedescr *)_cffi_types[index]) + +static PyObject *_cffi_init(const char *module_name, Py_ssize_t version, + const struct _cffi_type_context_s *ctx) +{ + PyObject *module, *o_arg, *new_module; + void *raw[] = { + (void *)module_name, + (void *)version, + (void *)_cffi_exports, + (void *)ctx, + }; + + module = PyImport_ImportModule("_cffi_backend"); + if (module == NULL) + goto failure; + + o_arg = PyLong_FromVoidPtr((void *)raw); + if (o_arg == NULL) + goto failure; + + new_module = PyObject_CallMethod( + module, (char *)"_init_cffi_1_0_external_module", (char *)"O", o_arg); + + Py_DECREF(o_arg); + Py_DECREF(module); + return new_module; + + failure: + Py_XDECREF(module); + return NULL; +} + + +#ifdef HAVE_WCHAR_H +typedef wchar_t _cffi_wchar_t; +#else +typedef uint16_t _cffi_wchar_t; /* same random pick as _cffi_backend.c */ +#endif + +_CFFI_UNUSED_FN static uint16_t _cffi_to_c_char16_t(PyObject *o) +{ + if (sizeof(_cffi_wchar_t) == 2) + return (uint16_t)_cffi_to_c_wchar_t(o); + else + return (uint16_t)_cffi_to_c_wchar3216_t(o); +} + +_CFFI_UNUSED_FN static PyObject *_cffi_from_c_char16_t(uint16_t x) +{ + if (sizeof(_cffi_wchar_t) == 2) + return _cffi_from_c_wchar_t((_cffi_wchar_t)x); + else + return _cffi_from_c_wchar3216_t((int)x); +} + +_CFFI_UNUSED_FN static int _cffi_to_c_char32_t(PyObject *o) +{ + if (sizeof(_cffi_wchar_t) == 4) + return (int)_cffi_to_c_wchar_t(o); + else + return (int)_cffi_to_c_wchar3216_t(o); +} + +_CFFI_UNUSED_FN static PyObject *_cffi_from_c_char32_t(int x) +{ + if (sizeof(_cffi_wchar_t) == 4) + return _cffi_from_c_wchar_t((_cffi_wchar_t)x); + else + return _cffi_from_c_wchar3216_t(x); +} + + +/********** end CPython-specific section **********/ +#else +_CFFI_UNUSED_FN +static void (*_cffi_call_python_org)(struct _cffi_externpy_s *, char *); +# define _cffi_call_python _cffi_call_python_org +#endif + + +#define _cffi_array_len(array) (sizeof(array) / sizeof((array)[0])) + +#define _cffi_prim_int(size, sign) \ + ((size) == 1 ? ((sign) ? _CFFI_PRIM_INT8 : _CFFI_PRIM_UINT8) : \ + (size) == 2 ? ((sign) ? _CFFI_PRIM_INT16 : _CFFI_PRIM_UINT16) : \ + (size) == 4 ? ((sign) ? _CFFI_PRIM_INT32 : _CFFI_PRIM_UINT32) : \ + (size) == 8 ? ((sign) ? _CFFI_PRIM_INT64 : _CFFI_PRIM_UINT64) : \ + _CFFI__UNKNOWN_PRIM) + +#define _cffi_prim_float(size) \ + ((size) == sizeof(float) ? _CFFI_PRIM_FLOAT : \ + (size) == sizeof(double) ? _CFFI_PRIM_DOUBLE : \ + (size) == sizeof(long double) ? _CFFI__UNKNOWN_LONG_DOUBLE : \ + _CFFI__UNKNOWN_FLOAT_PRIM) + +#define _cffi_check_int(got, got_nonpos, expected) \ + ((got_nonpos) == (expected <= 0) && \ + (got) == (unsigned long long)expected) + +#ifdef MS_WIN32 +# define _cffi_stdcall __stdcall +#else +# define _cffi_stdcall /* nothing */ +#endif + +#ifdef __cplusplus +} +#endif + +/************************************************************/ + + + #include "_mpibind.h" + #include + + +/************************************************************/ + +static void *_cffi_types[] = { +/* 0 */ _CFFI_OP(_CFFI_OP_FUNCTION, 38), // char * *()(mpibind_t *, char *) +/* 1 */ _CFFI_OP(_CFFI_OP_POINTER, 43), // mpibind_t * +/* 2 */ _CFFI_OP(_CFFI_OP_POINTER, 39), // char * +/* 3 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 4 */ _CFFI_OP(_CFFI_OP_FUNCTION, 38), // char * *()(mpibind_t *, int *) +/* 5 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 6 */ _CFFI_OP(_CFFI_OP_POINTER, 33), // int * +/* 7 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 8 */ _CFFI_OP(_CFFI_OP_FUNCTION, 41), // hwloc_bitmap_t *()(mpibind_t *) +/* 9 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 10 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 11 */ _CFFI_OP(_CFFI_OP_FUNCTION, 29), // hwloc_topology_t()(mpibind_t *) +/* 12 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 13 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 14 */ _CFFI_OP(_CFFI_OP_FUNCTION, 6), // int *()(mpibind_t *) +/* 15 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 16 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 17 */ _CFFI_OP(_CFFI_OP_FUNCTION, 33), // int()(mpibind_t * *) +/* 18 */ _CFFI_OP(_CFFI_OP_POINTER, 1), // mpibind_t * * +/* 19 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 20 */ _CFFI_OP(_CFFI_OP_FUNCTION, 33), // int()(mpibind_t *) +/* 21 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 22 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 23 */ _CFFI_OP(_CFFI_OP_FUNCTION, 33), // int()(mpibind_t *, char *) +/* 24 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 25 */ _CFFI_OP(_CFFI_OP_NOOP, 2), +/* 26 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 27 */ _CFFI_OP(_CFFI_OP_FUNCTION, 33), // int()(mpibind_t *, hwloc_topology_t) +/* 28 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 29 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, _cffi_prim_int(sizeof(hwloc_topology_t), ( + ((hwloc_topology_t)-1) | 0 /* check that hwloc_topology_t is an integer type */ + ) <= 0)), // hwloc_topology_t +/* 30 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 31 */ _CFFI_OP(_CFFI_OP_FUNCTION, 33), // int()(mpibind_t *, int) +/* 32 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 33 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 7), // int +/* 34 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 35 */ _CFFI_OP(_CFFI_OP_FUNCTION, 44), // void()(mpibind_t *) +/* 36 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 37 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 38 */ _CFFI_OP(_CFFI_OP_POINTER, 2), // char * * +/* 39 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 2), // char +/* 40 */ _CFFI_OP(_CFFI_OP_ENUM, 0), // enum $1 +/* 41 */ _CFFI_OP(_CFFI_OP_POINTER, 42), // hwloc_bitmap_t * +/* 42 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, _cffi_prim_int(sizeof(hwloc_bitmap_t), ( + ((hwloc_bitmap_t)-1) | 0 /* check that hwloc_bitmap_t is an integer type */ + ) <= 0)), // hwloc_bitmap_t +/* 43 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 0), // mpibind_t +/* 44 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 0), // void +}; + +static int _cffi_const_MPIBIND_RESTRICT_CPU(unsigned long long *o) +{ + int n = (MPIBIND_RESTRICT_CPU) <= 0; + *o = (unsigned long long)((MPIBIND_RESTRICT_CPU) | 0); /* check that MPIBIND_RESTRICT_CPU is an integer */ + return n; +} + +static int _cffi_const_MPIBIND_RESTRICT_MEM(unsigned long long *o) +{ + int n = (MPIBIND_RESTRICT_MEM) <= 0; + *o = (unsigned long long)((MPIBIND_RESTRICT_MEM) | 0); /* check that MPIBIND_RESTRICT_MEM is an integer */ + return n; +} + +static int _cffi_const_MPIBIND_GPU_AMD(unsigned long long *o) +{ + int n = (MPIBIND_GPU_AMD) <= 0; + *o = (unsigned long long)((MPIBIND_GPU_AMD) | 0); /* check that MPIBIND_GPU_AMD is an integer */ + return n; +} + +static int _cffi_const_MPIBIND_GPU_NVIDIA(unsigned long long *o) +{ + int n = (MPIBIND_GPU_NVIDIA) <= 0; + *o = (unsigned long long)((MPIBIND_GPU_NVIDIA) | 0); /* check that MPIBIND_GPU_NVIDIA is an integer */ + return n; +} + +static int _cffi_d_mpibind(mpibind_t * x0) +{ + return mpibind(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind(PyObject *self, PyObject *arg0) +{ + mpibind_t * x0; + Py_ssize_t datasize; + int result; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind _cffi_d_mpibind +#endif + +static int _cffi_d_mpibind_finalize(mpibind_t * x0) +{ + return mpibind_finalize(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_finalize(PyObject *self, PyObject *arg0) +{ + mpibind_t * x0; + Py_ssize_t datasize; + int result; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_finalize(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind_finalize _cffi_d_mpibind_finalize +#endif + +static hwloc_bitmap_t * _cffi_d_mpibind_get_cpus(mpibind_t * x0) +{ + return mpibind_get_cpus(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_get_cpus(PyObject *self, PyObject *arg0) +{ + mpibind_t * x0; + Py_ssize_t datasize; + hwloc_bitmap_t * result; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_get_cpus(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_pointer((char *)result, _cffi_type(41)); +} +#else +# define _cffi_f_mpibind_get_cpus _cffi_d_mpibind_get_cpus +#endif + +static char * * _cffi_d_mpibind_get_env_var_names(mpibind_t * x0, int * x1) +{ + return mpibind_get_env_var_names(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_get_env_var_names(PyObject *self, PyObject *args) +{ + mpibind_t * x0; + int * x1; + Py_ssize_t datasize; + char * * result; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "mpibind_get_env_var_names", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(6), arg1, (char **)&x1); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x1 = (int *)alloca((size_t)datasize); + memset((void *)x1, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x1, _cffi_type(6), arg1) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_get_env_var_names(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_pointer((char *)result, _cffi_type(38)); +} +#else +# define _cffi_f_mpibind_get_env_var_names _cffi_d_mpibind_get_env_var_names +#endif + +static char * * _cffi_d_mpibind_get_env_var_values(mpibind_t * x0, char * x1) +{ + return mpibind_get_env_var_values(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_get_env_var_values(PyObject *self, PyObject *args) +{ + mpibind_t * x0; + char * x1; + Py_ssize_t datasize; + char * * result; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "mpibind_get_env_var_values", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(2), arg1, (char **)&x1); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x1 = (char *)alloca((size_t)datasize); + memset((void *)x1, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x1, _cffi_type(2), arg1) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_get_env_var_values(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_pointer((char *)result, _cffi_type(38)); +} +#else +# define _cffi_f_mpibind_get_env_var_values _cffi_d_mpibind_get_env_var_values +#endif + +static int _cffi_d_mpibind_get_gpu_type(mpibind_t * x0) +{ + return mpibind_get_gpu_type(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_get_gpu_type(PyObject *self, PyObject *arg0) +{ + mpibind_t * x0; + Py_ssize_t datasize; + int result; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_get_gpu_type(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind_get_gpu_type _cffi_d_mpibind_get_gpu_type +#endif + +static hwloc_bitmap_t * _cffi_d_mpibind_get_gpus(mpibind_t * x0) +{ + return mpibind_get_gpus(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_get_gpus(PyObject *self, PyObject *arg0) +{ + mpibind_t * x0; + Py_ssize_t datasize; + hwloc_bitmap_t * result; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_get_gpus(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_pointer((char *)result, _cffi_type(41)); +} +#else +# define _cffi_f_mpibind_get_gpus _cffi_d_mpibind_get_gpus +#endif + +static int * _cffi_d_mpibind_get_nthreads(mpibind_t * x0) +{ + return mpibind_get_nthreads(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_get_nthreads(PyObject *self, PyObject *arg0) +{ + mpibind_t * x0; + Py_ssize_t datasize; + int * result; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_get_nthreads(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_pointer((char *)result, _cffi_type(6)); +} +#else +# define _cffi_f_mpibind_get_nthreads _cffi_d_mpibind_get_nthreads +#endif + +static hwloc_topology_t _cffi_d_mpibind_get_topology(mpibind_t * x0) +{ + return mpibind_get_topology(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_get_topology(PyObject *self, PyObject *arg0) +{ + mpibind_t * x0; + Py_ssize_t datasize; + hwloc_topology_t result; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_get_topology(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, hwloc_topology_t); +} +#else +# define _cffi_f_mpibind_get_topology _cffi_d_mpibind_get_topology +#endif + +static int _cffi_d_mpibind_init(mpibind_t * * x0) +{ + return mpibind_init(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_init(PyObject *self, PyObject *arg0) +{ + mpibind_t * * x0; + Py_ssize_t datasize; + int result; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(18), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t * *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(18), arg0) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_init(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind_init _cffi_d_mpibind_init +#endif + +static void _cffi_d_mpibind_print_env_vars(mpibind_t * x0) +{ + mpibind_print_env_vars(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_print_env_vars(PyObject *self, PyObject *arg0) +{ + mpibind_t * x0; + Py_ssize_t datasize; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { mpibind_print_env_vars(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + Py_INCREF(Py_None); + return Py_None; +} +#else +# define _cffi_f_mpibind_print_env_vars _cffi_d_mpibind_print_env_vars +#endif + +static void _cffi_d_mpibind_print_mapping(mpibind_t * x0) +{ + mpibind_print_mapping(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_print_mapping(PyObject *self, PyObject *arg0) +{ + mpibind_t * x0; + Py_ssize_t datasize; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { mpibind_print_mapping(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + Py_INCREF(Py_None); + return Py_None; +} +#else +# define _cffi_f_mpibind_print_mapping _cffi_d_mpibind_print_mapping +#endif + +static int _cffi_d_mpibind_set_env_vars(mpibind_t * x0) +{ + return mpibind_set_env_vars(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_set_env_vars(PyObject *self, PyObject *arg0) +{ + mpibind_t * x0; + Py_ssize_t datasize; + int result; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_set_env_vars(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind_set_env_vars _cffi_d_mpibind_set_env_vars +#endif + +static int _cffi_d_mpibind_set_gpu_optim(mpibind_t * x0, int x1) +{ + return mpibind_set_gpu_optim(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_set_gpu_optim(PyObject *self, PyObject *args) +{ + mpibind_t * x0; + int x1; + Py_ssize_t datasize; + int result; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "mpibind_set_gpu_optim", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + x1 = _cffi_to_c_int(arg1, int); + if (x1 == (int)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_set_gpu_optim(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind_set_gpu_optim _cffi_d_mpibind_set_gpu_optim +#endif + +static int _cffi_d_mpibind_set_greedy(mpibind_t * x0, int x1) +{ + return mpibind_set_greedy(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_set_greedy(PyObject *self, PyObject *args) +{ + mpibind_t * x0; + int x1; + Py_ssize_t datasize; + int result; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "mpibind_set_greedy", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + x1 = _cffi_to_c_int(arg1, int); + if (x1 == (int)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_set_greedy(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind_set_greedy _cffi_d_mpibind_set_greedy +#endif + +static int _cffi_d_mpibind_set_ntasks(mpibind_t * x0, int x1) +{ + return mpibind_set_ntasks(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_set_ntasks(PyObject *self, PyObject *args) +{ + mpibind_t * x0; + int x1; + Py_ssize_t datasize; + int result; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "mpibind_set_ntasks", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + x1 = _cffi_to_c_int(arg1, int); + if (x1 == (int)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_set_ntasks(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind_set_ntasks _cffi_d_mpibind_set_ntasks +#endif + +static int _cffi_d_mpibind_set_nthreads(mpibind_t * x0, int x1) +{ + return mpibind_set_nthreads(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_set_nthreads(PyObject *self, PyObject *args) +{ + mpibind_t * x0; + int x1; + Py_ssize_t datasize; + int result; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "mpibind_set_nthreads", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + x1 = _cffi_to_c_int(arg1, int); + if (x1 == (int)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_set_nthreads(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind_set_nthreads _cffi_d_mpibind_set_nthreads +#endif + +static int _cffi_d_mpibind_set_restrict_ids(mpibind_t * x0, char * x1) +{ + return mpibind_set_restrict_ids(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_set_restrict_ids(PyObject *self, PyObject *args) +{ + mpibind_t * x0; + char * x1; + Py_ssize_t datasize; + int result; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "mpibind_set_restrict_ids", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(2), arg1, (char **)&x1); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x1 = (char *)alloca((size_t)datasize); + memset((void *)x1, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x1, _cffi_type(2), arg1) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_set_restrict_ids(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind_set_restrict_ids _cffi_d_mpibind_set_restrict_ids +#endif + +static int _cffi_d_mpibind_set_restrict_type(mpibind_t * x0, int x1) +{ + return mpibind_set_restrict_type(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_set_restrict_type(PyObject *self, PyObject *args) +{ + mpibind_t * x0; + int x1; + Py_ssize_t datasize; + int result; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "mpibind_set_restrict_type", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + x1 = _cffi_to_c_int(arg1, int); + if (x1 == (int)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_set_restrict_type(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind_set_restrict_type _cffi_d_mpibind_set_restrict_type +#endif + +static int _cffi_d_mpibind_set_smt(mpibind_t * x0, int x1) +{ + return mpibind_set_smt(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_set_smt(PyObject *self, PyObject *args) +{ + mpibind_t * x0; + int x1; + Py_ssize_t datasize; + int result; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "mpibind_set_smt", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + x1 = _cffi_to_c_int(arg1, int); + if (x1 == (int)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_set_smt(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind_set_smt _cffi_d_mpibind_set_smt +#endif + +static int _cffi_d_mpibind_set_topology(mpibind_t * x0, hwloc_topology_t x1) +{ + return mpibind_set_topology(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_set_topology(PyObject *self, PyObject *args) +{ + mpibind_t * x0; + hwloc_topology_t x1; + Py_ssize_t datasize; + int result; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "mpibind_set_topology", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + x1 = _cffi_to_c_int(arg1, hwloc_topology_t); + if (x1 == (hwloc_topology_t)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_set_topology(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind_set_topology _cffi_d_mpibind_set_topology +#endif + +static const struct _cffi_global_s _cffi_globals[] = { + { "MPIBIND_GPU_AMD", (void *)_cffi_const_MPIBIND_GPU_AMD, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "MPIBIND_GPU_NVIDIA", (void *)_cffi_const_MPIBIND_GPU_NVIDIA, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "MPIBIND_RESTRICT_CPU", (void *)_cffi_const_MPIBIND_RESTRICT_CPU, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "MPIBIND_RESTRICT_MEM", (void *)_cffi_const_MPIBIND_RESTRICT_MEM, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "mpibind", (void *)_cffi_f_mpibind, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 20), (void *)_cffi_d_mpibind }, + { "mpibind_finalize", (void *)_cffi_f_mpibind_finalize, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 20), (void *)_cffi_d_mpibind_finalize }, + { "mpibind_get_cpus", (void *)_cffi_f_mpibind_get_cpus, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 8), (void *)_cffi_d_mpibind_get_cpus }, + { "mpibind_get_env_var_names", (void *)_cffi_f_mpibind_get_env_var_names, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 4), (void *)_cffi_d_mpibind_get_env_var_names }, + { "mpibind_get_env_var_values", (void *)_cffi_f_mpibind_get_env_var_values, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 0), (void *)_cffi_d_mpibind_get_env_var_values }, + { "mpibind_get_gpu_type", (void *)_cffi_f_mpibind_get_gpu_type, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 20), (void *)_cffi_d_mpibind_get_gpu_type }, + { "mpibind_get_gpus", (void *)_cffi_f_mpibind_get_gpus, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 8), (void *)_cffi_d_mpibind_get_gpus }, + { "mpibind_get_nthreads", (void *)_cffi_f_mpibind_get_nthreads, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 14), (void *)_cffi_d_mpibind_get_nthreads }, + { "mpibind_get_topology", (void *)_cffi_f_mpibind_get_topology, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 11), (void *)_cffi_d_mpibind_get_topology }, + { "mpibind_init", (void *)_cffi_f_mpibind_init, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 17), (void *)_cffi_d_mpibind_init }, + { "mpibind_print_env_vars", (void *)_cffi_f_mpibind_print_env_vars, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 35), (void *)_cffi_d_mpibind_print_env_vars }, + { "mpibind_print_mapping", (void *)_cffi_f_mpibind_print_mapping, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 35), (void *)_cffi_d_mpibind_print_mapping }, + { "mpibind_set_env_vars", (void *)_cffi_f_mpibind_set_env_vars, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 20), (void *)_cffi_d_mpibind_set_env_vars }, + { "mpibind_set_gpu_optim", (void *)_cffi_f_mpibind_set_gpu_optim, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 31), (void *)_cffi_d_mpibind_set_gpu_optim }, + { "mpibind_set_greedy", (void *)_cffi_f_mpibind_set_greedy, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 31), (void *)_cffi_d_mpibind_set_greedy }, + { "mpibind_set_ntasks", (void *)_cffi_f_mpibind_set_ntasks, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 31), (void *)_cffi_d_mpibind_set_ntasks }, + { "mpibind_set_nthreads", (void *)_cffi_f_mpibind_set_nthreads, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 31), (void *)_cffi_d_mpibind_set_nthreads }, + { "mpibind_set_restrict_ids", (void *)_cffi_f_mpibind_set_restrict_ids, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 23), (void *)_cffi_d_mpibind_set_restrict_ids }, + { "mpibind_set_restrict_type", (void *)_cffi_f_mpibind_set_restrict_type, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 31), (void *)_cffi_d_mpibind_set_restrict_type }, + { "mpibind_set_smt", (void *)_cffi_f_mpibind_set_smt, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 31), (void *)_cffi_d_mpibind_set_smt }, + { "mpibind_set_topology", (void *)_cffi_f_mpibind_set_topology, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 27), (void *)_cffi_d_mpibind_set_topology }, +}; + +static const struct _cffi_struct_union_s _cffi_struct_unions[] = { + { "mpibind_t", 43, _CFFI_F_OPAQUE, + (size_t)-1, -1, -1, 0 /* opaque */ }, +}; + +static const struct _cffi_enum_s _cffi_enums[] = { + { "$1", 40, _cffi_prim_int(4, 0), + "MPIBIND_RESTRICT_CPU,MPIBIND_RESTRICT_MEM,MPIBIND_GPU_AMD,MPIBIND_GPU_NVIDIA" }, +}; + +static const struct _cffi_typename_s _cffi_typenames[] = { + { "hwloc_bitmap_t", 42 }, + { "hwloc_topology_t", 29 }, + { "mpibind_t", 43 }, +}; + +static const struct _cffi_type_context_s _cffi_type_context = { + _cffi_types, + _cffi_globals, + NULL, /* no fields */ + _cffi_struct_unions, + _cffi_enums, + _cffi_typenames, + 25, /* num_globals */ + 1, /* num_struct_unions */ + 1, /* num_enums */ + 3, /* num_typenames */ + NULL, /* no includes */ + 45, /* num_types */ + 0, /* flags */ +}; + +#ifdef __GNUC__ +# pragma GCC visibility push(default) /* for -fvisibility= */ +#endif + +#ifdef PYPY_VERSION +PyMODINIT_FUNC +_cffi_pypyinit__mpibind_cffi(const void *p[]) +{ + p[0] = (const void *)0x2601; + p[1] = &_cffi_type_context; +#if PY_MAJOR_VERSION >= 3 + return NULL; +#endif +} +# ifdef _MSC_VER + PyMODINIT_FUNC +# if PY_MAJOR_VERSION >= 3 + PyInit__mpibind_cffi(void) { return NULL; } +# else + init_mpibind_cffi(void) { } +# endif +# endif +#elif PY_MAJOR_VERSION >= 3 +PyMODINIT_FUNC +PyInit__mpibind_cffi(void) +{ + return _cffi_init("cffi_build._mpibind_cffi", 0x2601, &_cffi_type_context); +} +#else +PyMODINIT_FUNC +init_mpibind_cffi(void) +{ + _cffi_init("cffi_build._mpibind_cffi", 0x2601, &_cffi_type_context); +} +#endif + +#ifdef __GNUC__ +# pragma GCC visibility pop +#endif diff --git a/python_bindings/cffi_build/mpibind_build.py b/python_bindings/cffi_build/mpibind_build.py new file mode 100644 index 0000000..f3553a4 --- /dev/null +++ b/python_bindings/cffi_build/mpibind_build.py @@ -0,0 +1,26 @@ +from cffi import FFI +ffibuilder = FFI() +source = """ +typedef int... hwloc_topology_t; +typedef int... hwloc_bitmap_t; +""" +with open("_mpibind.h") as h: + source += h.read() + +# set_source() gives the name of the python extension module to +# produce, and some C source code as a string. This C code needs +# to make the declarated functions, types and globals available, +# so it is often just the "#include". +ffibuilder.set_source("cffi_build._mpibind_cffi", + """ + #include \"_mpibind.h\" + #include + """, + libraries=['mpibind', 'hwloc']) + + +ffibuilder.cdef(source) + +if __name__ == "__main__": + #ffibuilder.emit_c_code('test.c') + ffibuilder.compile(verbose=True) \ No newline at end of file diff --git a/python_bindings/cffi_build/test.c b/python_bindings/cffi_build/test.c new file mode 100644 index 0000000..9f2a1bf --- /dev/null +++ b/python_bindings/cffi_build/test.c @@ -0,0 +1,1554 @@ +#define _CFFI_ + +/* We try to define Py_LIMITED_API before including Python.h. + + Mess: we can only define it if Py_DEBUG, Py_TRACE_REFS and + Py_REF_DEBUG are not defined. This is a best-effort approximation: + we can learn about Py_DEBUG from pyconfig.h, but it is unclear if + the same works for the other two macros. Py_DEBUG implies them, + but not the other way around. + + Issue #350 is still open: on Windows, the code here causes it to link + with PYTHON36.DLL (for example) instead of PYTHON3.DLL. A fix was + attempted in 164e526a5515 and 14ce6985e1c3, but reverted: virtualenv + does not make PYTHON3.DLL available, and so the "correctly" compiled + version would not run inside a virtualenv. We will re-apply the fix + after virtualenv has been fixed for some time. For explanation, see + issue #355. For a workaround if you want PYTHON3.DLL and don't worry + about virtualenv, see issue #350. See also 'py_limited_api' in + setuptools_ext.py. +*/ +#if !defined(_CFFI_USE_EMBEDDING) && !defined(Py_LIMITED_API) +# include +# if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG) +# define Py_LIMITED_API +# endif +#endif + +#include +#ifdef __cplusplus +extern "C" { +#endif +#include + +/* This part is from file 'cffi/parse_c_type.h'. It is copied at the + beginning of C sources generated by CFFI's ffi.set_source(). */ + +typedef void *_cffi_opcode_t; + +#define _CFFI_OP(opcode, arg) (_cffi_opcode_t)(opcode | (((uintptr_t)(arg)) << 8)) +#define _CFFI_GETOP(cffi_opcode) ((unsigned char)(uintptr_t)cffi_opcode) +#define _CFFI_GETARG(cffi_opcode) (((intptr_t)cffi_opcode) >> 8) + +#define _CFFI_OP_PRIMITIVE 1 +#define _CFFI_OP_POINTER 3 +#define _CFFI_OP_ARRAY 5 +#define _CFFI_OP_OPEN_ARRAY 7 +#define _CFFI_OP_STRUCT_UNION 9 +#define _CFFI_OP_ENUM 11 +#define _CFFI_OP_FUNCTION 13 +#define _CFFI_OP_FUNCTION_END 15 +#define _CFFI_OP_NOOP 17 +#define _CFFI_OP_BITFIELD 19 +#define _CFFI_OP_TYPENAME 21 +#define _CFFI_OP_CPYTHON_BLTN_V 23 // varargs +#define _CFFI_OP_CPYTHON_BLTN_N 25 // noargs +#define _CFFI_OP_CPYTHON_BLTN_O 27 // O (i.e. a single arg) +#define _CFFI_OP_CONSTANT 29 +#define _CFFI_OP_CONSTANT_INT 31 +#define _CFFI_OP_GLOBAL_VAR 33 +#define _CFFI_OP_DLOPEN_FUNC 35 +#define _CFFI_OP_DLOPEN_CONST 37 +#define _CFFI_OP_GLOBAL_VAR_F 39 +#define _CFFI_OP_EXTERN_PYTHON 41 + +#define _CFFI_PRIM_VOID 0 +#define _CFFI_PRIM_BOOL 1 +#define _CFFI_PRIM_CHAR 2 +#define _CFFI_PRIM_SCHAR 3 +#define _CFFI_PRIM_UCHAR 4 +#define _CFFI_PRIM_SHORT 5 +#define _CFFI_PRIM_USHORT 6 +#define _CFFI_PRIM_INT 7 +#define _CFFI_PRIM_UINT 8 +#define _CFFI_PRIM_LONG 9 +#define _CFFI_PRIM_ULONG 10 +#define _CFFI_PRIM_LONGLONG 11 +#define _CFFI_PRIM_ULONGLONG 12 +#define _CFFI_PRIM_FLOAT 13 +#define _CFFI_PRIM_DOUBLE 14 +#define _CFFI_PRIM_LONGDOUBLE 15 + +#define _CFFI_PRIM_WCHAR 16 +#define _CFFI_PRIM_INT8 17 +#define _CFFI_PRIM_UINT8 18 +#define _CFFI_PRIM_INT16 19 +#define _CFFI_PRIM_UINT16 20 +#define _CFFI_PRIM_INT32 21 +#define _CFFI_PRIM_UINT32 22 +#define _CFFI_PRIM_INT64 23 +#define _CFFI_PRIM_UINT64 24 +#define _CFFI_PRIM_INTPTR 25 +#define _CFFI_PRIM_UINTPTR 26 +#define _CFFI_PRIM_PTRDIFF 27 +#define _CFFI_PRIM_SIZE 28 +#define _CFFI_PRIM_SSIZE 29 +#define _CFFI_PRIM_INT_LEAST8 30 +#define _CFFI_PRIM_UINT_LEAST8 31 +#define _CFFI_PRIM_INT_LEAST16 32 +#define _CFFI_PRIM_UINT_LEAST16 33 +#define _CFFI_PRIM_INT_LEAST32 34 +#define _CFFI_PRIM_UINT_LEAST32 35 +#define _CFFI_PRIM_INT_LEAST64 36 +#define _CFFI_PRIM_UINT_LEAST64 37 +#define _CFFI_PRIM_INT_FAST8 38 +#define _CFFI_PRIM_UINT_FAST8 39 +#define _CFFI_PRIM_INT_FAST16 40 +#define _CFFI_PRIM_UINT_FAST16 41 +#define _CFFI_PRIM_INT_FAST32 42 +#define _CFFI_PRIM_UINT_FAST32 43 +#define _CFFI_PRIM_INT_FAST64 44 +#define _CFFI_PRIM_UINT_FAST64 45 +#define _CFFI_PRIM_INTMAX 46 +#define _CFFI_PRIM_UINTMAX 47 +#define _CFFI_PRIM_FLOATCOMPLEX 48 +#define _CFFI_PRIM_DOUBLECOMPLEX 49 +#define _CFFI_PRIM_CHAR16 50 +#define _CFFI_PRIM_CHAR32 51 + +#define _CFFI__NUM_PRIM 52 +#define _CFFI__UNKNOWN_PRIM (-1) +#define _CFFI__UNKNOWN_FLOAT_PRIM (-2) +#define _CFFI__UNKNOWN_LONG_DOUBLE (-3) + +#define _CFFI__IO_FILE_STRUCT (-1) + + +struct _cffi_global_s { + const char *name; + void *address; + _cffi_opcode_t type_op; + void *size_or_direct_fn; // OP_GLOBAL_VAR: size, or 0 if unknown + // OP_CPYTHON_BLTN_*: addr of direct function +}; + +struct _cffi_getconst_s { + unsigned long long value; + const struct _cffi_type_context_s *ctx; + int gindex; +}; + +struct _cffi_struct_union_s { + const char *name; + int type_index; // -> _cffi_types, on a OP_STRUCT_UNION + int flags; // _CFFI_F_* flags below + size_t size; + int alignment; + int first_field_index; // -> _cffi_fields array + int num_fields; +}; +#define _CFFI_F_UNION 0x01 // is a union, not a struct +#define _CFFI_F_CHECK_FIELDS 0x02 // complain if fields are not in the + // "standard layout" or if some are missing +#define _CFFI_F_PACKED 0x04 // for CHECK_FIELDS, assume a packed struct +#define _CFFI_F_EXTERNAL 0x08 // in some other ffi.include() +#define _CFFI_F_OPAQUE 0x10 // opaque + +struct _cffi_field_s { + const char *name; + size_t field_offset; + size_t field_size; + _cffi_opcode_t field_type_op; +}; + +struct _cffi_enum_s { + const char *name; + int type_index; // -> _cffi_types, on a OP_ENUM + int type_prim; // _CFFI_PRIM_xxx + const char *enumerators; // comma-delimited string +}; + +struct _cffi_typename_s { + const char *name; + int type_index; /* if opaque, points to a possibly artificial + OP_STRUCT which is itself opaque */ +}; + +struct _cffi_type_context_s { + _cffi_opcode_t *types; + const struct _cffi_global_s *globals; + const struct _cffi_field_s *fields; + const struct _cffi_struct_union_s *struct_unions; + const struct _cffi_enum_s *enums; + const struct _cffi_typename_s *typenames; + int num_globals; + int num_struct_unions; + int num_enums; + int num_typenames; + const char *const *includes; + int num_types; + int flags; /* future extension */ +}; + +struct _cffi_parse_info_s { + const struct _cffi_type_context_s *ctx; + _cffi_opcode_t *output; + unsigned int output_size; + size_t error_location; + const char *error_message; +}; + +struct _cffi_externpy_s { + const char *name; + size_t size_of_result; + void *reserved1, *reserved2; +}; + +#ifdef _CFFI_INTERNAL +static int parse_c_type(struct _cffi_parse_info_s *info, const char *input); +static int search_in_globals(const struct _cffi_type_context_s *ctx, + const char *search, size_t search_len); +static int search_in_struct_unions(const struct _cffi_type_context_s *ctx, + const char *search, size_t search_len); +#endif + +/* this block of #ifs should be kept exactly identical between + c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py + and cffi/_cffi_include.h */ +#if defined(_MSC_VER) +# include /* for alloca() */ +# if _MSC_VER < 1600 /* MSVC < 2010 */ + typedef __int8 int8_t; + typedef __int16 int16_t; + typedef __int32 int32_t; + typedef __int64 int64_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; + typedef __int8 int_least8_t; + typedef __int16 int_least16_t; + typedef __int32 int_least32_t; + typedef __int64 int_least64_t; + typedef unsigned __int8 uint_least8_t; + typedef unsigned __int16 uint_least16_t; + typedef unsigned __int32 uint_least32_t; + typedef unsigned __int64 uint_least64_t; + typedef __int8 int_fast8_t; + typedef __int16 int_fast16_t; + typedef __int32 int_fast32_t; + typedef __int64 int_fast64_t; + typedef unsigned __int8 uint_fast8_t; + typedef unsigned __int16 uint_fast16_t; + typedef unsigned __int32 uint_fast32_t; + typedef unsigned __int64 uint_fast64_t; + typedef __int64 intmax_t; + typedef unsigned __int64 uintmax_t; +# else +# include +# endif +# if _MSC_VER < 1800 /* MSVC < 2013 */ +# ifndef __cplusplus + typedef unsigned char _Bool; +# endif +# endif +#else +# include +# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux) +# include +# endif +#endif + +#ifdef __GNUC__ +# define _CFFI_UNUSED_FN __attribute__((unused)) +#else +# define _CFFI_UNUSED_FN /* nothing */ +#endif + +#ifdef __cplusplus +# ifndef _Bool + typedef bool _Bool; /* semi-hackish: C++ has no _Bool; bool is builtin */ +# endif +#endif + +/********** CPython-specific section **********/ +#ifndef PYPY_VERSION + + +#if PY_MAJOR_VERSION >= 3 +# define PyInt_FromLong PyLong_FromLong +#endif + +#define _cffi_from_c_double PyFloat_FromDouble +#define _cffi_from_c_float PyFloat_FromDouble +#define _cffi_from_c_long PyInt_FromLong +#define _cffi_from_c_ulong PyLong_FromUnsignedLong +#define _cffi_from_c_longlong PyLong_FromLongLong +#define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong +#define _cffi_from_c__Bool PyBool_FromLong + +#define _cffi_to_c_double PyFloat_AsDouble +#define _cffi_to_c_float PyFloat_AsDouble + +#define _cffi_from_c_int(x, type) \ + (((type)-1) > 0 ? /* unsigned */ \ + (sizeof(type) < sizeof(long) ? \ + PyInt_FromLong((long)x) : \ + sizeof(type) == sizeof(long) ? \ + PyLong_FromUnsignedLong((unsigned long)x) : \ + PyLong_FromUnsignedLongLong((unsigned long long)x)) : \ + (sizeof(type) <= sizeof(long) ? \ + PyInt_FromLong((long)x) : \ + PyLong_FromLongLong((long long)x))) + +#define _cffi_to_c_int(o, type) \ + ((type)( \ + sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \ + : (type)_cffi_to_c_i8(o)) : \ + sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \ + : (type)_cffi_to_c_i16(o)) : \ + sizeof(type) == 4 ? (((type)-1) > 0 ? (type)_cffi_to_c_u32(o) \ + : (type)_cffi_to_c_i32(o)) : \ + sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \ + : (type)_cffi_to_c_i64(o)) : \ + (Py_FatalError("unsupported size for type " #type), (type)0))) + +#define _cffi_to_c_i8 \ + ((int(*)(PyObject *))_cffi_exports[1]) +#define _cffi_to_c_u8 \ + ((int(*)(PyObject *))_cffi_exports[2]) +#define _cffi_to_c_i16 \ + ((int(*)(PyObject *))_cffi_exports[3]) +#define _cffi_to_c_u16 \ + ((int(*)(PyObject *))_cffi_exports[4]) +#define _cffi_to_c_i32 \ + ((int(*)(PyObject *))_cffi_exports[5]) +#define _cffi_to_c_u32 \ + ((unsigned int(*)(PyObject *))_cffi_exports[6]) +#define _cffi_to_c_i64 \ + ((long long(*)(PyObject *))_cffi_exports[7]) +#define _cffi_to_c_u64 \ + ((unsigned long long(*)(PyObject *))_cffi_exports[8]) +#define _cffi_to_c_char \ + ((int(*)(PyObject *))_cffi_exports[9]) +#define _cffi_from_c_pointer \ + ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[10]) +#define _cffi_to_c_pointer \ + ((char *(*)(PyObject *, struct _cffi_ctypedescr *))_cffi_exports[11]) +#define _cffi_get_struct_layout \ + not used any more +#define _cffi_restore_errno \ + ((void(*)(void))_cffi_exports[13]) +#define _cffi_save_errno \ + ((void(*)(void))_cffi_exports[14]) +#define _cffi_from_c_char \ + ((PyObject *(*)(char))_cffi_exports[15]) +#define _cffi_from_c_deref \ + ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[16]) +#define _cffi_to_c \ + ((int(*)(char *, struct _cffi_ctypedescr *, PyObject *))_cffi_exports[17]) +#define _cffi_from_c_struct \ + ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[18]) +#define _cffi_to_c_wchar_t \ + ((_cffi_wchar_t(*)(PyObject *))_cffi_exports[19]) +#define _cffi_from_c_wchar_t \ + ((PyObject *(*)(_cffi_wchar_t))_cffi_exports[20]) +#define _cffi_to_c_long_double \ + ((long double(*)(PyObject *))_cffi_exports[21]) +#define _cffi_to_c__Bool \ + ((_Bool(*)(PyObject *))_cffi_exports[22]) +#define _cffi_prepare_pointer_call_argument \ + ((Py_ssize_t(*)(struct _cffi_ctypedescr *, \ + PyObject *, char **))_cffi_exports[23]) +#define _cffi_convert_array_from_object \ + ((int(*)(char *, struct _cffi_ctypedescr *, PyObject *))_cffi_exports[24]) +#define _CFFI_CPIDX 25 +#define _cffi_call_python \ + ((void(*)(struct _cffi_externpy_s *, char *))_cffi_exports[_CFFI_CPIDX]) +#define _cffi_to_c_wchar3216_t \ + ((int(*)(PyObject *))_cffi_exports[26]) +#define _cffi_from_c_wchar3216_t \ + ((PyObject *(*)(int))_cffi_exports[27]) +#define _CFFI_NUM_EXPORTS 28 + +struct _cffi_ctypedescr; + +static void *_cffi_exports[_CFFI_NUM_EXPORTS]; + +#define _cffi_type(index) ( \ + assert((((uintptr_t)_cffi_types[index]) & 1) == 0), \ + (struct _cffi_ctypedescr *)_cffi_types[index]) + +static PyObject *_cffi_init(const char *module_name, Py_ssize_t version, + const struct _cffi_type_context_s *ctx) +{ + PyObject *module, *o_arg, *new_module; + void *raw[] = { + (void *)module_name, + (void *)version, + (void *)_cffi_exports, + (void *)ctx, + }; + + module = PyImport_ImportModule("_cffi_backend"); + if (module == NULL) + goto failure; + + o_arg = PyLong_FromVoidPtr((void *)raw); + if (o_arg == NULL) + goto failure; + + new_module = PyObject_CallMethod( + module, (char *)"_init_cffi_1_0_external_module", (char *)"O", o_arg); + + Py_DECREF(o_arg); + Py_DECREF(module); + return new_module; + + failure: + Py_XDECREF(module); + return NULL; +} + + +#ifdef HAVE_WCHAR_H +typedef wchar_t _cffi_wchar_t; +#else +typedef uint16_t _cffi_wchar_t; /* same random pick as _cffi_backend.c */ +#endif + +_CFFI_UNUSED_FN static uint16_t _cffi_to_c_char16_t(PyObject *o) +{ + if (sizeof(_cffi_wchar_t) == 2) + return (uint16_t)_cffi_to_c_wchar_t(o); + else + return (uint16_t)_cffi_to_c_wchar3216_t(o); +} + +_CFFI_UNUSED_FN static PyObject *_cffi_from_c_char16_t(uint16_t x) +{ + if (sizeof(_cffi_wchar_t) == 2) + return _cffi_from_c_wchar_t((_cffi_wchar_t)x); + else + return _cffi_from_c_wchar3216_t((int)x); +} + +_CFFI_UNUSED_FN static int _cffi_to_c_char32_t(PyObject *o) +{ + if (sizeof(_cffi_wchar_t) == 4) + return (int)_cffi_to_c_wchar_t(o); + else + return (int)_cffi_to_c_wchar3216_t(o); +} + +_CFFI_UNUSED_FN static PyObject *_cffi_from_c_char32_t(int x) +{ + if (sizeof(_cffi_wchar_t) == 4) + return _cffi_from_c_wchar_t((_cffi_wchar_t)x); + else + return _cffi_from_c_wchar3216_t(x); +} + + +/********** end CPython-specific section **********/ +#else +_CFFI_UNUSED_FN +static void (*_cffi_call_python_org)(struct _cffi_externpy_s *, char *); +# define _cffi_call_python _cffi_call_python_org +#endif + + +#define _cffi_array_len(array) (sizeof(array) / sizeof((array)[0])) + +#define _cffi_prim_int(size, sign) \ + ((size) == 1 ? ((sign) ? _CFFI_PRIM_INT8 : _CFFI_PRIM_UINT8) : \ + (size) == 2 ? ((sign) ? _CFFI_PRIM_INT16 : _CFFI_PRIM_UINT16) : \ + (size) == 4 ? ((sign) ? _CFFI_PRIM_INT32 : _CFFI_PRIM_UINT32) : \ + (size) == 8 ? ((sign) ? _CFFI_PRIM_INT64 : _CFFI_PRIM_UINT64) : \ + _CFFI__UNKNOWN_PRIM) + +#define _cffi_prim_float(size) \ + ((size) == sizeof(float) ? _CFFI_PRIM_FLOAT : \ + (size) == sizeof(double) ? _CFFI_PRIM_DOUBLE : \ + (size) == sizeof(long double) ? _CFFI__UNKNOWN_LONG_DOUBLE : \ + _CFFI__UNKNOWN_FLOAT_PRIM) + +#define _cffi_check_int(got, got_nonpos, expected) \ + ((got_nonpos) == (expected <= 0) && \ + (got) == (unsigned long long)expected) + +#ifdef MS_WIN32 +# define _cffi_stdcall __stdcall +#else +# define _cffi_stdcall /* nothing */ +#endif + +#ifdef __cplusplus +} +#endif + +/************************************************************/ + + + #include "_mpibind.h" + #include + + +/************************************************************/ + +static void *_cffi_types[] = { +/* 0 */ _CFFI_OP(_CFFI_OP_FUNCTION, 38), // char * *()(mpibind_t *, char *) +/* 1 */ _CFFI_OP(_CFFI_OP_POINTER, 43), // mpibind_t * +/* 2 */ _CFFI_OP(_CFFI_OP_POINTER, 39), // char * +/* 3 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 4 */ _CFFI_OP(_CFFI_OP_FUNCTION, 38), // char * *()(mpibind_t *, int *) +/* 5 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 6 */ _CFFI_OP(_CFFI_OP_POINTER, 33), // int * +/* 7 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 8 */ _CFFI_OP(_CFFI_OP_FUNCTION, 41), // hwloc_bitmap_t *()(mpibind_t *) +/* 9 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 10 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 11 */ _CFFI_OP(_CFFI_OP_FUNCTION, 29), // hwloc_topology_t()(mpibind_t *) +/* 12 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 13 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 14 */ _CFFI_OP(_CFFI_OP_FUNCTION, 6), // int *()(mpibind_t *) +/* 15 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 16 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 17 */ _CFFI_OP(_CFFI_OP_FUNCTION, 33), // int()(mpibind_t * *) +/* 18 */ _CFFI_OP(_CFFI_OP_POINTER, 1), // mpibind_t * * +/* 19 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 20 */ _CFFI_OP(_CFFI_OP_FUNCTION, 33), // int()(mpibind_t *) +/* 21 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 22 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 23 */ _CFFI_OP(_CFFI_OP_FUNCTION, 33), // int()(mpibind_t *, char *) +/* 24 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 25 */ _CFFI_OP(_CFFI_OP_NOOP, 2), +/* 26 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 27 */ _CFFI_OP(_CFFI_OP_FUNCTION, 33), // int()(mpibind_t *, hwloc_topology_t) +/* 28 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 29 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, _cffi_prim_int(sizeof(hwloc_topology_t), ( + ((hwloc_topology_t)-1) | 0 /* check that hwloc_topology_t is an integer type */ + ) <= 0)), // hwloc_topology_t +/* 30 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 31 */ _CFFI_OP(_CFFI_OP_FUNCTION, 33), // int()(mpibind_t *, int) +/* 32 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 33 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 7), // int +/* 34 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 35 */ _CFFI_OP(_CFFI_OP_FUNCTION, 44), // void()(mpibind_t *) +/* 36 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 37 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 38 */ _CFFI_OP(_CFFI_OP_POINTER, 2), // char * * +/* 39 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 2), // char +/* 40 */ _CFFI_OP(_CFFI_OP_ENUM, 0), // enum $1 +/* 41 */ _CFFI_OP(_CFFI_OP_POINTER, 42), // hwloc_bitmap_t * +/* 42 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, _cffi_prim_int(sizeof(hwloc_bitmap_t), ( + ((hwloc_bitmap_t)-1) | 0 /* check that hwloc_bitmap_t is an integer type */ + ) <= 0)), // hwloc_bitmap_t +/* 43 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 0), // mpibind_t +/* 44 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 0), // void +}; + +static int _cffi_const_MPIBIND_RESTRICT_CPU(unsigned long long *o) +{ + int n = (MPIBIND_RESTRICT_CPU) <= 0; + *o = (unsigned long long)((MPIBIND_RESTRICT_CPU) | 0); /* check that MPIBIND_RESTRICT_CPU is an integer */ + return n; +} + +static int _cffi_const_MPIBIND_RESTRICT_MEM(unsigned long long *o) +{ + int n = (MPIBIND_RESTRICT_MEM) <= 0; + *o = (unsigned long long)((MPIBIND_RESTRICT_MEM) | 0); /* check that MPIBIND_RESTRICT_MEM is an integer */ + return n; +} + +static int _cffi_const_MPIBIND_GPU_AMD(unsigned long long *o) +{ + int n = (MPIBIND_GPU_AMD) <= 0; + *o = (unsigned long long)((MPIBIND_GPU_AMD) | 0); /* check that MPIBIND_GPU_AMD is an integer */ + return n; +} + +static int _cffi_const_MPIBIND_GPU_NVIDIA(unsigned long long *o) +{ + int n = (MPIBIND_GPU_NVIDIA) <= 0; + *o = (unsigned long long)((MPIBIND_GPU_NVIDIA) | 0); /* check that MPIBIND_GPU_NVIDIA is an integer */ + return n; +} + +static int _cffi_d_mpibind(mpibind_t * x0) +{ + return mpibind(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind(PyObject *self, PyObject *arg0) +{ + mpibind_t * x0; + Py_ssize_t datasize; + int result; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind _cffi_d_mpibind +#endif + +static int _cffi_d_mpibind_finalize(mpibind_t * x0) +{ + return mpibind_finalize(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_finalize(PyObject *self, PyObject *arg0) +{ + mpibind_t * x0; + Py_ssize_t datasize; + int result; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_finalize(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind_finalize _cffi_d_mpibind_finalize +#endif + +static hwloc_bitmap_t * _cffi_d_mpibind_get_cpus(mpibind_t * x0) +{ + return mpibind_get_cpus(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_get_cpus(PyObject *self, PyObject *arg0) +{ + mpibind_t * x0; + Py_ssize_t datasize; + hwloc_bitmap_t * result; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_get_cpus(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_pointer((char *)result, _cffi_type(41)); +} +#else +# define _cffi_f_mpibind_get_cpus _cffi_d_mpibind_get_cpus +#endif + +static char * * _cffi_d_mpibind_get_env_var_names(mpibind_t * x0, int * x1) +{ + return mpibind_get_env_var_names(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_get_env_var_names(PyObject *self, PyObject *args) +{ + mpibind_t * x0; + int * x1; + Py_ssize_t datasize; + char * * result; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "mpibind_get_env_var_names", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(6), arg1, (char **)&x1); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x1 = (int *)alloca((size_t)datasize); + memset((void *)x1, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x1, _cffi_type(6), arg1) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_get_env_var_names(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_pointer((char *)result, _cffi_type(38)); +} +#else +# define _cffi_f_mpibind_get_env_var_names _cffi_d_mpibind_get_env_var_names +#endif + +static char * * _cffi_d_mpibind_get_env_var_values(mpibind_t * x0, char * x1) +{ + return mpibind_get_env_var_values(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_get_env_var_values(PyObject *self, PyObject *args) +{ + mpibind_t * x0; + char * x1; + Py_ssize_t datasize; + char * * result; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "mpibind_get_env_var_values", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(2), arg1, (char **)&x1); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x1 = (char *)alloca((size_t)datasize); + memset((void *)x1, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x1, _cffi_type(2), arg1) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_get_env_var_values(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_pointer((char *)result, _cffi_type(38)); +} +#else +# define _cffi_f_mpibind_get_env_var_values _cffi_d_mpibind_get_env_var_values +#endif + +static int _cffi_d_mpibind_get_gpu_type(mpibind_t * x0) +{ + return mpibind_get_gpu_type(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_get_gpu_type(PyObject *self, PyObject *arg0) +{ + mpibind_t * x0; + Py_ssize_t datasize; + int result; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_get_gpu_type(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind_get_gpu_type _cffi_d_mpibind_get_gpu_type +#endif + +static hwloc_bitmap_t * _cffi_d_mpibind_get_gpus(mpibind_t * x0) +{ + return mpibind_get_gpus(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_get_gpus(PyObject *self, PyObject *arg0) +{ + mpibind_t * x0; + Py_ssize_t datasize; + hwloc_bitmap_t * result; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_get_gpus(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_pointer((char *)result, _cffi_type(41)); +} +#else +# define _cffi_f_mpibind_get_gpus _cffi_d_mpibind_get_gpus +#endif + +static int * _cffi_d_mpibind_get_nthreads(mpibind_t * x0) +{ + return mpibind_get_nthreads(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_get_nthreads(PyObject *self, PyObject *arg0) +{ + mpibind_t * x0; + Py_ssize_t datasize; + int * result; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_get_nthreads(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_pointer((char *)result, _cffi_type(6)); +} +#else +# define _cffi_f_mpibind_get_nthreads _cffi_d_mpibind_get_nthreads +#endif + +static hwloc_topology_t _cffi_d_mpibind_get_topology(mpibind_t * x0) +{ + return mpibind_get_topology(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_get_topology(PyObject *self, PyObject *arg0) +{ + mpibind_t * x0; + Py_ssize_t datasize; + hwloc_topology_t result; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_get_topology(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, hwloc_topology_t); +} +#else +# define _cffi_f_mpibind_get_topology _cffi_d_mpibind_get_topology +#endif + +static int _cffi_d_mpibind_init(mpibind_t * * x0) +{ + return mpibind_init(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_init(PyObject *self, PyObject *arg0) +{ + mpibind_t * * x0; + Py_ssize_t datasize; + int result; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(18), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t * *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(18), arg0) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_init(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind_init _cffi_d_mpibind_init +#endif + +static void _cffi_d_mpibind_print_env_vars(mpibind_t * x0) +{ + mpibind_print_env_vars(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_print_env_vars(PyObject *self, PyObject *arg0) +{ + mpibind_t * x0; + Py_ssize_t datasize; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { mpibind_print_env_vars(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + Py_INCREF(Py_None); + return Py_None; +} +#else +# define _cffi_f_mpibind_print_env_vars _cffi_d_mpibind_print_env_vars +#endif + +static void _cffi_d_mpibind_print_mapping(mpibind_t * x0) +{ + mpibind_print_mapping(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_print_mapping(PyObject *self, PyObject *arg0) +{ + mpibind_t * x0; + Py_ssize_t datasize; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { mpibind_print_mapping(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + Py_INCREF(Py_None); + return Py_None; +} +#else +# define _cffi_f_mpibind_print_mapping _cffi_d_mpibind_print_mapping +#endif + +static int _cffi_d_mpibind_set_env_vars(mpibind_t * x0) +{ + return mpibind_set_env_vars(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_set_env_vars(PyObject *self, PyObject *arg0) +{ + mpibind_t * x0; + Py_ssize_t datasize; + int result; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_set_env_vars(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind_set_env_vars _cffi_d_mpibind_set_env_vars +#endif + +static int _cffi_d_mpibind_set_gpu_optim(mpibind_t * x0, int x1) +{ + return mpibind_set_gpu_optim(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_set_gpu_optim(PyObject *self, PyObject *args) +{ + mpibind_t * x0; + int x1; + Py_ssize_t datasize; + int result; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "mpibind_set_gpu_optim", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + x1 = _cffi_to_c_int(arg1, int); + if (x1 == (int)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_set_gpu_optim(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind_set_gpu_optim _cffi_d_mpibind_set_gpu_optim +#endif + +static int _cffi_d_mpibind_set_greedy(mpibind_t * x0, int x1) +{ + return mpibind_set_greedy(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_set_greedy(PyObject *self, PyObject *args) +{ + mpibind_t * x0; + int x1; + Py_ssize_t datasize; + int result; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "mpibind_set_greedy", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + x1 = _cffi_to_c_int(arg1, int); + if (x1 == (int)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_set_greedy(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind_set_greedy _cffi_d_mpibind_set_greedy +#endif + +static int _cffi_d_mpibind_set_ntasks(mpibind_t * x0, int x1) +{ + return mpibind_set_ntasks(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_set_ntasks(PyObject *self, PyObject *args) +{ + mpibind_t * x0; + int x1; + Py_ssize_t datasize; + int result; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "mpibind_set_ntasks", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + x1 = _cffi_to_c_int(arg1, int); + if (x1 == (int)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_set_ntasks(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind_set_ntasks _cffi_d_mpibind_set_ntasks +#endif + +static int _cffi_d_mpibind_set_nthreads(mpibind_t * x0, int x1) +{ + return mpibind_set_nthreads(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_set_nthreads(PyObject *self, PyObject *args) +{ + mpibind_t * x0; + int x1; + Py_ssize_t datasize; + int result; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "mpibind_set_nthreads", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + x1 = _cffi_to_c_int(arg1, int); + if (x1 == (int)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_set_nthreads(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind_set_nthreads _cffi_d_mpibind_set_nthreads +#endif + +static int _cffi_d_mpibind_set_restrict_ids(mpibind_t * x0, char * x1) +{ + return mpibind_set_restrict_ids(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_set_restrict_ids(PyObject *self, PyObject *args) +{ + mpibind_t * x0; + char * x1; + Py_ssize_t datasize; + int result; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "mpibind_set_restrict_ids", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(2), arg1, (char **)&x1); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x1 = (char *)alloca((size_t)datasize); + memset((void *)x1, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x1, _cffi_type(2), arg1) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_set_restrict_ids(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind_set_restrict_ids _cffi_d_mpibind_set_restrict_ids +#endif + +static int _cffi_d_mpibind_set_restrict_type(mpibind_t * x0, int x1) +{ + return mpibind_set_restrict_type(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_set_restrict_type(PyObject *self, PyObject *args) +{ + mpibind_t * x0; + int x1; + Py_ssize_t datasize; + int result; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "mpibind_set_restrict_type", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + x1 = _cffi_to_c_int(arg1, int); + if (x1 == (int)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_set_restrict_type(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind_set_restrict_type _cffi_d_mpibind_set_restrict_type +#endif + +static int _cffi_d_mpibind_set_smt(mpibind_t * x0, int x1) +{ + return mpibind_set_smt(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_set_smt(PyObject *self, PyObject *args) +{ + mpibind_t * x0; + int x1; + Py_ssize_t datasize; + int result; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "mpibind_set_smt", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + x1 = _cffi_to_c_int(arg1, int); + if (x1 == (int)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_set_smt(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind_set_smt _cffi_d_mpibind_set_smt +#endif + +static int _cffi_d_mpibind_set_topology(mpibind_t * x0, hwloc_topology_t x1) +{ + return mpibind_set_topology(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_mpibind_set_topology(PyObject *self, PyObject *args) +{ + mpibind_t * x0; + hwloc_topology_t x1; + Py_ssize_t datasize; + int result; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "mpibind_set_topology", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x0 = (mpibind_t *)alloca((size_t)datasize); + memset((void *)x0, 0, (size_t)datasize); + if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) + return NULL; + } + + x1 = _cffi_to_c_int(arg1, hwloc_topology_t); + if (x1 == (hwloc_topology_t)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = mpibind_set_topology(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + return _cffi_from_c_int(result, int); +} +#else +# define _cffi_f_mpibind_set_topology _cffi_d_mpibind_set_topology +#endif + +static const struct _cffi_global_s _cffi_globals[] = { + { "MPIBIND_GPU_AMD", (void *)_cffi_const_MPIBIND_GPU_AMD, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "MPIBIND_GPU_NVIDIA", (void *)_cffi_const_MPIBIND_GPU_NVIDIA, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "MPIBIND_RESTRICT_CPU", (void *)_cffi_const_MPIBIND_RESTRICT_CPU, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "MPIBIND_RESTRICT_MEM", (void *)_cffi_const_MPIBIND_RESTRICT_MEM, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "mpibind", (void *)_cffi_f_mpibind, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 20), (void *)_cffi_d_mpibind }, + { "mpibind_finalize", (void *)_cffi_f_mpibind_finalize, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 20), (void *)_cffi_d_mpibind_finalize }, + { "mpibind_get_cpus", (void *)_cffi_f_mpibind_get_cpus, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 8), (void *)_cffi_d_mpibind_get_cpus }, + { "mpibind_get_env_var_names", (void *)_cffi_f_mpibind_get_env_var_names, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 4), (void *)_cffi_d_mpibind_get_env_var_names }, + { "mpibind_get_env_var_values", (void *)_cffi_f_mpibind_get_env_var_values, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 0), (void *)_cffi_d_mpibind_get_env_var_values }, + { "mpibind_get_gpu_type", (void *)_cffi_f_mpibind_get_gpu_type, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 20), (void *)_cffi_d_mpibind_get_gpu_type }, + { "mpibind_get_gpus", (void *)_cffi_f_mpibind_get_gpus, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 8), (void *)_cffi_d_mpibind_get_gpus }, + { "mpibind_get_nthreads", (void *)_cffi_f_mpibind_get_nthreads, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 14), (void *)_cffi_d_mpibind_get_nthreads }, + { "mpibind_get_topology", (void *)_cffi_f_mpibind_get_topology, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 11), (void *)_cffi_d_mpibind_get_topology }, + { "mpibind_init", (void *)_cffi_f_mpibind_init, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 17), (void *)_cffi_d_mpibind_init }, + { "mpibind_print_env_vars", (void *)_cffi_f_mpibind_print_env_vars, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 35), (void *)_cffi_d_mpibind_print_env_vars }, + { "mpibind_print_mapping", (void *)_cffi_f_mpibind_print_mapping, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 35), (void *)_cffi_d_mpibind_print_mapping }, + { "mpibind_set_env_vars", (void *)_cffi_f_mpibind_set_env_vars, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 20), (void *)_cffi_d_mpibind_set_env_vars }, + { "mpibind_set_gpu_optim", (void *)_cffi_f_mpibind_set_gpu_optim, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 31), (void *)_cffi_d_mpibind_set_gpu_optim }, + { "mpibind_set_greedy", (void *)_cffi_f_mpibind_set_greedy, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 31), (void *)_cffi_d_mpibind_set_greedy }, + { "mpibind_set_ntasks", (void *)_cffi_f_mpibind_set_ntasks, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 31), (void *)_cffi_d_mpibind_set_ntasks }, + { "mpibind_set_nthreads", (void *)_cffi_f_mpibind_set_nthreads, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 31), (void *)_cffi_d_mpibind_set_nthreads }, + { "mpibind_set_restrict_ids", (void *)_cffi_f_mpibind_set_restrict_ids, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 23), (void *)_cffi_d_mpibind_set_restrict_ids }, + { "mpibind_set_restrict_type", (void *)_cffi_f_mpibind_set_restrict_type, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 31), (void *)_cffi_d_mpibind_set_restrict_type }, + { "mpibind_set_smt", (void *)_cffi_f_mpibind_set_smt, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 31), (void *)_cffi_d_mpibind_set_smt }, + { "mpibind_set_topology", (void *)_cffi_f_mpibind_set_topology, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 27), (void *)_cffi_d_mpibind_set_topology }, +}; + +static const struct _cffi_struct_union_s _cffi_struct_unions[] = { + { "mpibind_t", 43, _CFFI_F_OPAQUE, + (size_t)-1, -1, -1, 0 /* opaque */ }, +}; + +static const struct _cffi_enum_s _cffi_enums[] = { + { "$1", 40, _cffi_prim_int(4, 0), + "MPIBIND_RESTRICT_CPU,MPIBIND_RESTRICT_MEM,MPIBIND_GPU_AMD,MPIBIND_GPU_NVIDIA" }, +}; + +static const struct _cffi_typename_s _cffi_typenames[] = { + { "hwloc_bitmap_t", 42 }, + { "hwloc_topology_t", 29 }, + { "mpibind_t", 43 }, +}; + +static const struct _cffi_type_context_s _cffi_type_context = { + _cffi_types, + _cffi_globals, + NULL, /* no fields */ + _cffi_struct_unions, + _cffi_enums, + _cffi_typenames, + 25, /* num_globals */ + 1, /* num_struct_unions */ + 1, /* num_enums */ + 3, /* num_typenames */ + NULL, /* no includes */ + 45, /* num_types */ + 0, /* flags */ +}; + +#ifdef __GNUC__ +# pragma GCC visibility push(default) /* for -fvisibility= */ +#endif + +#ifdef PYPY_VERSION +PyMODINIT_FUNC +_cffi_pypyinit__mpibind_cffi(const void *p[]) +{ + p[0] = (const void *)0x2601; + p[1] = &_cffi_type_context; +#if PY_MAJOR_VERSION >= 3 + return NULL; +#endif +} +# ifdef _MSC_VER + PyMODINIT_FUNC +# if PY_MAJOR_VERSION >= 3 + PyInit__mpibind_cffi(void) { return NULL; } +# else + init_mpibind_cffi(void) { } +# endif +# endif +#elif PY_MAJOR_VERSION >= 3 +PyMODINIT_FUNC +PyInit__mpibind_cffi(void) +{ + return _cffi_init("cffi_build._mpibind_cffi", 0x2601, &_cffi_type_context); +} +#else +PyMODINIT_FUNC +init_mpibind_cffi(void) +{ + _cffi_init("cffi_build._mpibind_cffi", 0x2601, &_cffi_type_context); +} +#endif + +#ifdef __GNUC__ +# pragma GCC visibility pop +#endif diff --git a/python_bindings/mpibind/__init__.py b/python_bindings/mpibind/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python_bindings/mpibind/mpibind.py b/python_bindings/mpibind/mpibind.py new file mode 100644 index 0000000..0824e29 --- /dev/null +++ b/python_bindings/mpibind/mpibind.py @@ -0,0 +1,13 @@ +from cffi import FFI + +def abi_inline(): + ffi = FFI() + ffi.cdef(""" + struct mpibind_t; + typedef struct mpibind_t mpibind_t; + int mpibind_init(mpibind_t **handle); + """) + C = ffi.dlopen("mpibind") + +if __name__ == "__main__": + abi_inline() \ No newline at end of file diff --git a/python_bindings/setup.py b/python_bindings/setup.py new file mode 100644 index 0000000..5dd8dd7 --- /dev/null +++ b/python_bindings/setup.py @@ -0,0 +1,13 @@ +from setuptools import setup +import os + +here = os.path.abspath(os.path.dirname(__file__)) +cffi_dep = "cffi>=1.1" +setup( + name="mpibind", + version="0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1a1", + description="Python bindings for mpibind", + setup_requires=[cffi_dep], + cffi_modules=["cffi_build/mpibind_build.py:ffi"], + install_requires=[cffi_dep], +) From 5e51a14b168fb973c77fad7f6435b91ebc9d0c8b Mon Sep 17 00:00:00 2001 From: Samuel Furman Date: Thu, 30 Jul 2020 10:44:34 -0700 Subject: [PATCH 3/9] check_point, rebase later --- Makefile.am | 5 +- bindings/Makefile.am | 1 + bindings/python/Makefile.am | 1 + bindings/python/_mpibind/Makefile.am | 60 + .../python/_mpibind}/__init__.py | 0 bindings/python/_mpibind/build.py | 29 + bindings/python/_mpibind/make_clean_header.py | 108 ++ bindings/python/mpibind/Makefile.am | 21 + .../python/mpibind}/__init__.py | 0 bindings/python/mpibind/example.py | 50 + bindings/python/mpibind/jobspec.py | 145 ++ bindings/python/mpibind/mpibind_wrapper.py | 9 + bindings/python/mpibind/wrapper.py | 395 +++++ {python_bindings => bindings/python}/setup.py | 4 +- config/am_check_pymod.m4 | 40 + config/ax_python_devel.m4 | 324 ++++ config/py-compile | 170 ++ config/python.m4 | 245 +++ configure.ac | 140 ++ python_bindings/cffi_build/_mpibind.h | 184 -- .../cffi_build/cffi_build/_mpibind_cffi.c | 1554 ----------------- python_bindings/cffi_build/mpibind_build.py | 26 - python_bindings/cffi_build/test.c | 1554 ----------------- python_bindings/mpibind/__init__.py | 0 python_bindings/mpibind/mpibind.py | 13 - src/mpibind.c | 19 + src/mpibind.h | 4 + 27 files changed, 1766 insertions(+), 3335 deletions(-) create mode 100644 bindings/Makefile.am create mode 100644 bindings/python/Makefile.am create mode 100644 bindings/python/_mpibind/Makefile.am rename {python_bindings => bindings/python/_mpibind}/__init__.py (100%) create mode 100644 bindings/python/_mpibind/build.py create mode 100755 bindings/python/_mpibind/make_clean_header.py create mode 100644 bindings/python/mpibind/Makefile.am rename {python_bindings/cffi_build => bindings/python/mpibind}/__init__.py (100%) create mode 100644 bindings/python/mpibind/example.py create mode 100644 bindings/python/mpibind/jobspec.py create mode 100644 bindings/python/mpibind/mpibind_wrapper.py create mode 100644 bindings/python/mpibind/wrapper.py rename {python_bindings => bindings/python}/setup.py (78%) create mode 100644 config/am_check_pymod.m4 create mode 100644 config/ax_python_devel.m4 create mode 100755 config/py-compile create mode 100644 config/python.m4 delete mode 100644 python_bindings/cffi_build/_mpibind.h delete mode 100644 python_bindings/cffi_build/cffi_build/_mpibind_cffi.c delete mode 100644 python_bindings/cffi_build/mpibind_build.py delete mode 100644 python_bindings/cffi_build/test.c delete mode 100644 python_bindings/mpibind/__init__.py delete mode 100644 python_bindings/mpibind/mpibind.py diff --git a/Makefile.am b/Makefile.am index 1f8eb14..89b841e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,5 @@ +.NOTPARALLEL: -SUBDIRS = src test-suite etc +SUBDIRS = src test-suite etc bindings -ACLOCAL_AMFLAGS = -I config +ACLOCAL_AMFLAGS = -I config \ No newline at end of file diff --git a/bindings/Makefile.am b/bindings/Makefile.am new file mode 100644 index 0000000..e6e35a0 --- /dev/null +++ b/bindings/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = python \ No newline at end of file diff --git a/bindings/python/Makefile.am b/bindings/python/Makefile.am new file mode 100644 index 0000000..f931447 --- /dev/null +++ b/bindings/python/Makefile.am @@ -0,0 +1 @@ +SUBDIRS= _mpibind mpibind diff --git a/bindings/python/_mpibind/Makefile.am b/bindings/python/_mpibind/Makefile.am new file mode 100644 index 0000000..8855592 --- /dev/null +++ b/bindings/python/_mpibind/Makefile.am @@ -0,0 +1,60 @@ +AM_CPPFLAGS = \ + -Wall -Werror -Wno-missing-field-initializers \ + -I$(top_srcdir) -I$(top_srcdir)/src/ \ + $(PYTHON_CPPFLAGS) + +AM_LDFLAGS = \ + -avoid-version -module -Wl,-rpath,$(PYTHON_PREFIX)/lib + +PREPROC_FLAGS=-E '-D__attribute__(...)=' + +_mpibind.c: $(srcdir)/build.py _mpibind_preproc.h + $(PYTHON) $^ + +_mpibind_clean.h: Makefile + $(PYTHON) $(srcdir)/make_clean_header.py \ + --path $(top_srcdir) \ + --search $(top_builddir)/src/ \ + --search $(HWLOC_INCLUDEDIR) \ + --additional_headers \ + src/mpibind-priv.h \ + --output _mpibind_clean.h \ + src/mpibind.h + +#$(HWLOC_INCLUDEDIR)/hwloc.h + +_mpibind_preproc.h: _mpibind_clean.h + $(CC) $(PREPROC_FLAGS) _mpibind_clean.h\ + | sed -e '/^# [0-9]*.*/d' > $@ + +BUILT_SOURCES= _mpibind.c _mpibind_preproc.h +mpibindpyso_LTLIBRARIES = _mpibind.la +mpibindpyso_PYTHON = __init__.py + +nodist_mpibindbindinginclude_HEADERS = _mpibind_preproc.h +nodist__mpibind_la_SOURCES = _mpibind.c + + +common_libs = $(top_builddir)/src/libmpibind.la \ + $(PYTHON_LDFLAGS) \ + $(HWLOC_LIBS) + +_mpibind_la_LIBADD = $(common_libs) + +EXTRA_DIST=build.py make_clean_header.py + +.PHONY: lib-copy + +lib-copy-vpath: ${mpibindpyso_PYTHON} ${mpibindpyso_LTLIBRARIES} + -echo Copying libraries to where they can be used by python in-tree + [ "$(top_srcdir)" != "$(top_builddir)" ] && cp $(top_srcdir)/bindings/python/_mpibind/__init__.py ./; \ + for LIB in ${mpibindpyso_LTLIBRARIES:la=so} ; do \ + test -e .libs/$$LIB && \ + $(LN_S) .libs/$$LIB ./ || true; \ + done + +all-local: lib-copy-vpath + +clean-local: + -rm -f *.c *.so *.pyc *.pyo *_clean.h *_preproc.h + -rm -rf __pycache__ diff --git a/python_bindings/__init__.py b/bindings/python/_mpibind/__init__.py similarity index 100% rename from python_bindings/__init__.py rename to bindings/python/_mpibind/__init__.py diff --git a/bindings/python/_mpibind/build.py b/bindings/python/_mpibind/build.py new file mode 100644 index 0000000..575fdb2 --- /dev/null +++ b/bindings/python/_mpibind/build.py @@ -0,0 +1,29 @@ +from cffi import FFI + +ffi = FFI() + +cdefs = """ +struct hwloc_topology; +typedef struct hwloc_topology * hwloc_topology_t; +typedef struct { ...; } hwloc_bitmap_t; +""" + +with open("_mpibind_preproc.h") as h: + cdefs = cdefs + h.read() + +ffi.cdef(cdefs) + + +ffi.set_source( + "_mpibind._mpibind", + """ +#include +#include +#include + """, + libraries=["mpibind", "hwloc"], +) + + +if __name__ == "__main__": + ffi.emit_c_code("_mpibind.c") \ No newline at end of file diff --git a/bindings/python/_mpibind/make_clean_header.py b/bindings/python/_mpibind/make_clean_header.py new file mode 100755 index 0000000..1db79c1 --- /dev/null +++ b/bindings/python/_mpibind/make_clean_header.py @@ -0,0 +1,108 @@ +#TODO CREDIT FLUX TEAM + +############################################################### +# Copyright 2014 Lawrence Livermore National Security, LLC +# (c.f. AUTHORS, NOTICE.LLNS, COPYING) +# +# This file is part of the Flux resource manager framework. +# For details, see https://github.com/flux-framework. +# +# SPDX-License-Identifier: LGPL-3.0 +############################################################### + +from __future__ import print_function +import os +import re +import struct + +import argparse + +platform_c_maxint = 2 ** (struct.Struct('i').size * 8 - 1) - 1 + +def left_shift(base, shift): + return base << shift + + +parser = argparse.ArgumentParser() + +parser.add_argument("header", help="C header file to parse", type=str) +parser.add_argument("--include_header", help="Include base path", type=str, default="") +parser.add_argument( + "--additional_headers", help="Additional headers to parse", nargs="*", default=[] +) +parser.add_argument("--output", help="Output path", default=".") +parser.add_argument("--path", help="Include base path", default=".") +parser.add_argument( + "--search", help="append to header search path", action="append", default=[] +) +parser.add_argument( + "--ignore_header", + help="Pattern to ignore when searching header files", + default=[], + action="append", +) + +args = parser.parse_args() + +absolute_head = os.path.abspath(os.path.join(args.path, args.header)) + +# Prepend 'path' option to search list: +args.search.insert(0, args.path) +args.search = [os.path.abspath(f) for f in args.search] + +def find_first(path, name, extra=None): + for dirname in path: + filename = os.path.join(dirname, name) + if os.path.isfile(filename): + return filename + if extra is not None: + filename = os.path.join(extra, name) + if os.path.isfile(filename): + return filename + raise IOError(name) + + +mega_header="" +def process_header(f, including_path="."): + global mega_header + if not os.path.isfile(f): + f = os.path.join(including_path, f) + f = os.path.abspath(f) + if f not in checked_heads: + for p in args.ignore_header: + if re.search(p, f): + checked_heads[f] = 1 + return + with open(f, "r") as header: + for l in header.readlines(): + l = l.replace('__restrict', 'restrict') + l = l.replace('__inline__', 'inline') + l = l.replace('INT_MAX', str(platform_c_maxint)) + l = re.sub('(\d)(UL)?<<(\d)',lambda x: str(int(x.group(1))<= "./+-(),'"'"'%______p______%'` +AC_MSG_CHECKING(for ifelse([$2],[],,[$2 in ])python module $1) +AC_CACHE_VAL(py_cv_mod_$py_mod_var, [ +ifelse([$2],[], [prog=" +import sys +try: + import $1 +except ImportError: + sys.exit(1) +except: + sys.exit(0) +sys.exit(0)"], [prog=" +import sys +from distutils.version import LooseVersion, StrictVersion +import $1 +if not $2: + sys.exit(1) +"]) +if $PYTHON -c "$prog" 1>&AC_FD_CC 2>&AC_FD_CC + then + eval "py_cv_mod_$py_mod_var=yes" + else + eval "py_cv_mod_$py_mod_var=no" + fi +]) +py_val=`eval "echo \`echo '$py_cv_mod_'$py_mod_var\`"` +if test "x$py_val" != xno; then + AC_MSG_RESULT(yes) + ifelse([$3], [],, [$3 +])dnl +else + AC_MSG_RESULT(no) + ifelse([$4], [],, [$4 +])dnl +fi +]) diff --git a/config/ax_python_devel.m4 b/config/ax_python_devel.m4 new file mode 100644 index 0000000..59a2ff0 --- /dev/null +++ b/config/ax_python_devel.m4 @@ -0,0 +1,324 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_python_devel.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PYTHON_DEVEL([version]) +# +# DESCRIPTION +# +# Note: Defines as a precious variable "PYTHON_VERSION". Don't override it +# in your configure.ac. +# +# This macro checks for Python and tries to get the include path to +# 'Python.h'. It provides the $(PYTHON_CPPFLAGS) and $(PYTHON_LDFLAGS) +# output variables. It also exports $(PYTHON_EXTRA_LIBS) and +# $(PYTHON_EXTRA_LDFLAGS) for embedding Python in your code. +# +# You can search for some particular version of Python by passing a +# parameter to this macro, for example ">= '2.3.1'", or "== '2.4'". Please +# note that you *have* to pass also an operator along with the version to +# match, and pay special attention to the single quotes surrounding the +# version number. Don't use "PYTHON_VERSION" for this: that environment +# variable is declared as precious and thus reserved for the end-user. +# +# This macro should work for all versions of Python >= 2.1.0. As an end +# user, you can disable the check for the python version by setting the +# PYTHON_NOVERSIONCHECK environment variable to something else than the +# empty string. +# +# If you need to use this macro for an older Python version, please +# contact the authors. We're always open for feedback. +# +# LICENSE +# +# Copyright (c) 2009 Sebastian Huber +# Copyright (c) 2009 Alan W. Irwin +# Copyright (c) 2009 Rafael Laboissiere +# Copyright (c) 2009 Andrew Collier +# Copyright (c) 2009 Matteo Settenvini +# Copyright (c) 2009 Horst Knorr +# Copyright (c) 2013 Daniel Mullner +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 17 + +AU_ALIAS([AC_PYTHON_DEVEL], [AX_PYTHON_DEVEL]) +AC_DEFUN([AX_PYTHON_DEVEL],[ + # + # Allow the use of a (user set) custom python version + # + AC_ARG_VAR([PYTHON_VERSION],[The installed Python + version to use, for example '2.3'. This string + will be appended to the Python interpreter + canonical name.]) + + AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]]) + if test -z "$PYTHON"; then + AC_MSG_ERROR([Cannot find python$PYTHON_VERSION in your system path]) + PYTHON_VERSION="" + fi + + # + # Check for a version of Python >= 2.1.0 + # + AC_MSG_CHECKING([for a version of Python >= '2.1.0']) + ac_supports_python_ver=`$PYTHON -c "import sys; \ + ver = sys.version.split ()[[0]]; \ + print (ver >= '2.1.0')"` + if test "$ac_supports_python_ver" != "True"; then + if test -z "$PYTHON_NOVERSIONCHECK"; then + AC_MSG_RESULT([no]) + AC_MSG_FAILURE([ +This version of the AC@&t@_PYTHON_DEVEL macro +doesn't work properly with versions of Python before +2.1.0. You may need to re-run configure, setting the +variables PYTHON_CPPFLAGS, PYTHON_LDFLAGS, PYTHON_SITE_PKG, +PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand. +Moreover, to disable this check, set PYTHON_NOVERSIONCHECK +to something else than an empty string. +]) + else + AC_MSG_RESULT([skip at user request]) + fi + else + AC_MSG_RESULT([yes]) + fi + + # + # if the macro parameter ``version'' is set, honour it + # + if test -n "$1"; then + AC_MSG_CHECKING([for a version of Python $1]) + ac_supports_python_ver=`$PYTHON -c "import sys; \ + ver = sys.version.split ()[[0]]; \ + print (ver $1)"` + if test "$ac_supports_python_ver" = "True"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + AC_MSG_ERROR([this package requires Python $1. +If you have it installed, but it isn't the default Python +interpreter in your system path, please pass the PYTHON_VERSION +variable to configure. See ``configure --help'' for reference. +]) + PYTHON_VERSION="" + fi + fi + + # + # Check if you have distutils, else fail + # + AC_MSG_CHECKING([for the distutils Python package]) + ac_distutils_result=`$PYTHON -c "import distutils" 2>&1` + if test -z "$ac_distutils_result"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + AC_MSG_ERROR([cannot import Python module "distutils". +Please check your Python installation. The error was: +$ac_distutils_result]) + PYTHON_VERSION="" + fi + + # + # Check for Python include path + # + AC_MSG_CHECKING([for Python include path]) + if test -z "$PYTHON_CPPFLAGS"; then + python_path=`$PYTHON -c "import distutils.sysconfig; \ + print (distutils.sysconfig.get_python_inc ());"` + plat_python_path=`$PYTHON -c "import distutils.sysconfig; \ + print (distutils.sysconfig.get_python_inc (plat_specific=1));"` + if test -n "${python_path}"; then + if test "${plat_python_path}" != "${python_path}"; then + python_path="-I$python_path -I$plat_python_path" + else + python_path="-I$python_path" + fi + fi + PYTHON_CPPFLAGS=$python_path + fi + AC_MSG_RESULT([$PYTHON_CPPFLAGS]) + AC_SUBST([PYTHON_CPPFLAGS]) + + # + # Check for Python library path + # + AC_MSG_CHECKING([for Python library path]) + if test -z "$PYTHON_LDFLAGS"; then + # (makes two attempts to ensure we've got a version number + # from the interpreter) + ac_python_version=`cat<]], + [[Py_Initialize();]]) + ],[pythonexists=yes],[pythonexists=no]) + AC_LANG_POP([C]) + # turn back to default flags + CPPFLAGS="$ac_save_CPPFLAGS" + LIBS="$ac_save_LIBS" + + AC_MSG_RESULT([$pythonexists]) + + if test ! "x$pythonexists" = "xyes"; then + AC_MSG_FAILURE([ + Could not link test program to Python. Maybe the main Python library has been + installed in some non-standard library path. If so, pass it to configure, + via the LDFLAGS environment variable. + Example: ./configure LDFLAGS="-L/usr/non-standard-path/python/lib" + ============================================================================ + ERROR! + You probably have to install the development version of the Python package + for your distribution. The exact name of this package varies among them. + ============================================================================ + ]) + PYTHON_VERSION="" + fi + + # + # all done! + # +]) diff --git a/config/py-compile b/config/py-compile new file mode 100755 index 0000000..46ea866 --- /dev/null +++ b/config/py-compile @@ -0,0 +1,170 @@ +#!/bin/sh +# py-compile - Compile a Python program + +scriptversion=2011-06-08.12; # UTC + +# Copyright (C) 2000-2013 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +if [ -z "$PYTHON" ]; then + PYTHON=python +fi + +me=py-compile + +usage_error () +{ + echo "$me: $*" >&2 + echo "Try '$me --help' for more information." >&2 + exit 1 +} + +basedir= +destdir= +while test $# -ne 0; do + case "$1" in + --basedir) + if test $# -lt 2; then + usage_error "option '--basedir' requires an argument" + else + basedir=$2 + fi + shift + ;; + --destdir) + if test $# -lt 2; then + usage_error "option '--destdir' requires an argument" + else + destdir=$2 + fi + shift + ;; + -h|--help) + cat <<\EOF +Usage: py-compile [--help] [--version] [--basedir DIR] [--destdir DIR] FILES..." + +Byte compile some python scripts FILES. Use --destdir to specify any +leading directory path to the FILES that you don't want to include in the +byte compiled file. Specify --basedir for any additional path information you +do want to be shown in the byte compiled file. + +Example: + py-compile --destdir /tmp/pkg-root --basedir /usr/share/test test.py test2.py + +Report bugs to . +EOF + exit $? + ;; + -v|--version) + echo "$me $scriptversion" + exit $? + ;; + --) + shift + break + ;; + -*) + usage_error "unrecognized option '$1'" + ;; + *) + break + ;; + esac + shift +done + +files=$* +if test -z "$files"; then + usage_error "no files given" +fi + +# if basedir was given, then it should be prepended to filenames before +# byte compilation. +if [ -z "$basedir" ]; then + pathtrans="path = file" +else + pathtrans="path = os.path.join('$basedir', file)" +fi + +# if destdir was given, then it needs to be prepended to the filename to +# byte compile but not go into the compiled file. +if [ -z "$destdir" ]; then + filetrans="filepath = path" +else + filetrans="filepath = os.path.normpath('$destdir' + os.sep + path)" +fi + +$PYTHON -c " +import sys, os, py_compile, imp + +files = '''$files''' + +sys.stdout.write('Byte-compiling python modules...\n') +for file in files.split(): + $pathtrans + $filetrans + if not os.path.exists(filepath) or not (len(filepath) >= 3 + and filepath[-3:] == '.py'): + continue + sys.stdout.write(file) + sys.stdout.flush() + if hasattr(imp, 'get_tag'): + py_compile.compile(filepath, imp.cache_from_source(filepath), path) + else: + py_compile.compile(filepath, filepath + 'c', path) +sys.stdout.write('\n')" || exit $? + +# this will fail for python < 1.5, but that doesn't matter ... +$PYTHON -O -c " +import sys, os, py_compile, imp + +# pypy does not use .pyo optimization +if hasattr(sys, 'pypy_translation_info'): + sys.exit(0) + +files = '''$files''' +sys.stdout.write('Byte-compiling python modules (optimized versions) ...\n') +for file in files.split(): + $pathtrans + $filetrans + if not os.path.exists(filepath) or not (len(filepath) >= 3 + and filepath[-3:] == '.py'): + continue + sys.stdout.write(file) + sys.stdout.flush() + if hasattr(imp, 'get_tag'): + py_compile.compile(filepath, imp.cache_from_source(filepath, False), path) + else: + py_compile.compile(filepath, filepath + 'o', path) +sys.stdout.write('\n')" 2>/dev/null || : + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/config/python.m4 b/config/python.m4 new file mode 100644 index 0000000..b17f3de --- /dev/null +++ b/config/python.m4 @@ -0,0 +1,245 @@ + +## ------------------------ -*- Autoconf -*- +## Python file handling +## From Andrew Dalke +## Updated by James Henstridge +## ------------------------ +# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# AM_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# --------------------------------------------------------------------------- +# Adds support for distributing Python modules and packages. To +# install modules, copy them to $(pythondir), using the python_PYTHON +# automake variable. To install a package with the same name as the +# automake package, install to $(pkgpythondir), or use the +# pkgpython_PYTHON automake variable. +# +# The variables $(pyexecdir) and $(pkgpyexecdir) are provided as +# locations to install python extension modules (shared libraries). +# Another macro is required to find the appropriate flags to compile +# extension modules. +# +# If your package is configured with a different prefix to python, +# users will have to add the install directory to the PYTHONPATH +# environment variable, or create a .pth file (see the python +# documentation for details). +# +# If the MINIMUM-VERSION argument is passed, AM_PATH_PYTHON will +# cause an error if the version of python installed on the system +# doesn't meet the requirement. MINIMUM-VERSION should consist of +# numbers and dots only. +AC_DEFUN([AM_PATH_PYTHON], + [ + dnl Find a Python interpreter. Python versions prior to 2.0 are not + dnl supported. (2.0 was released on October 16, 2000). + dnl FIXME: Remove the need to hard-code Python versions here. + m4_define_default([_AM_PYTHON_INTERPRETER_LIST], +[python python2 python3 python3.5 python3.4 python3.3 python3.2 python3.1 python3.0 python2.7 dnl + python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0]) + + AC_ARG_VAR([PYTHON], [the Python interpreter]) + + m4_if([$1],[],[ + dnl No version check is needed. + # Find any Python interpreter. + if test -z "$PYTHON"; then + AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :) + fi + am_display_PYTHON=python + ], [ + dnl A version check is needed. + if test -n "$PYTHON"; then + # If the user set $PYTHON, use it and don't search something else. + AC_MSG_CHECKING([whether $PYTHON version is >= $1]) + AM_PYTHON_CHECK_VERSION([$PYTHON], [$1], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AC_MSG_ERROR([Python interpreter is too old])]) + am_display_PYTHON=$PYTHON + else + # Otherwise, try each interpreter until we find one that satisfies + # VERSION. + AC_CACHE_CHECK([for a Python interpreter with version >= $1], + [am_cv_pathless_PYTHON],[ + for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do + test "$am_cv_pathless_PYTHON" = none && break + AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break]) + done]) + # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. + if test "$am_cv_pathless_PYTHON" = none; then + PYTHON=: + else + AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON]) + fi + am_display_PYTHON=$am_cv_pathless_PYTHON + fi + ]) + + if test "$PYTHON" = :; then + dnl Run any user-specified action, or abort. + m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])]) + else + + dnl Query Python for its version number. Getting [:3] seems to be + dnl the best way to do this; it's what "site.py" does in the standard + dnl library. + + AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version], + [am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[[:3]])"`]) + AC_SUBST([PYTHON_VERSION], [$am_cv_python_version]) + + dnl Use the values of $prefix and $exec_prefix for the corresponding + dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX. These are made + dnl distinct variables so they can be overridden if need be. However, + dnl general consensus is that you shouldn't need this ability. + + AC_SUBST([PYTHON_PREFIX], ['${prefix}']) + AC_SUBST([PYTHON_EXEC_PREFIX], ['${exec_prefix}']) + + dnl At times (like when building shared libraries) you may want + dnl to know which OS platform Python thinks this is. + + AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform], + [am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`]) + AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform]) + + # Just factor out some code duplication. + am_python_setup_sysconfig="\ +import sys +# Prefer sysconfig over distutils.sysconfig, for better compatibility +# with python 3.x. See automake bug#10227. +try: + import sysconfig +except ImportError: + can_use_sysconfig = 0 +else: + can_use_sysconfig = 1 +# Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: +# +try: + from platform import python_implementation + if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7': + can_use_sysconfig = 0 +except ImportError: + pass" + + dnl Set up 4 directories: + + dnl pythondir -- where to install python scripts. This is the + dnl site-packages directory, not the python standard library + dnl directory like in previous automake betas. This behavior + dnl is more consistent with lispdir.m4 for example. + dnl Query distutils for this directory. + AC_CACHE_CHECK([for $am_display_PYTHON script directory], + [am_cv_python_pythondir], + [if test "x$prefix" = xNONE + then + am_py_prefix=$ac_default_prefix + else + am_py_prefix=$prefix + fi + am_cv_python_pythondir=`$PYTHON -c " +$am_python_setup_sysconfig +if can_use_sysconfig: + sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'}) +else: + from distutils import sysconfig + sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') +sys.stdout.write(sitedir)"` + case $am_cv_python_pythondir in + $am_py_prefix*) + am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` + am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"` + ;; + *) + case $am_py_prefix in + /usr|/System*) ;; + *) + am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages + ;; + esac + ;; + esac + ]) + AC_SUBST([pythondir], [$am_cv_python_pythondir]) + + dnl pkgpythondir -- $PACKAGE directory under pythondir. Was + dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is + dnl more consistent with the rest of automake. + + AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE]) + + dnl pyexecdir -- directory for installing python extension modules + dnl (shared libraries) + dnl Query distutils for this directory. + AC_CACHE_CHECK([for $am_display_PYTHON extension module directory], + [am_cv_python_pyexecdir], + [if test "x$exec_prefix" = xNONE + then + am_py_exec_prefix=$am_py_prefix + else + am_py_exec_prefix=$exec_prefix + fi + if test "x$PYTHON_SITE_PKG" = x ; then + am_cv_python_pyexecdir=`$PYTHON -c " +$am_python_setup_sysconfig +if can_use_sysconfig: + sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'}) +else: + from distutils import sysconfig + sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix') +sys.stdout.write(sitedir)"` + else + am_cv_python_pyexecdir=$PYTHON_SITE_PKG + fi + case $am_cv_python_pyexecdir in + $am_py_exec_prefix*) + am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` + am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"` + ;; + *) + case $am_py_exec_prefix in + /usr|/System*) ;; + *) + am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages + ;; + esac + ;; + esac + ]) + AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir]) + + dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE) + + AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE]) + + dnl Run any user-specified action. + $2 + fi + +]) + + +# AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) +# --------------------------------------------------------------------------- +# Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION. +# Run ACTION-IF-FALSE otherwise. +# This test uses sys.hexversion instead of the string equivalent (first +# word of sys.version), in order to cope with versions such as 2.2c1. +# This supports Python 2.0 or higher. (2.0 was released on October 16, 2000). +AC_DEFUN([AM_PYTHON_CHECK_VERSION], + [prog="import sys +# split strings by '.' and convert to numeric. Append some zeros +# because we need at least 4 digits for the hex conversion. +# map returns an iterator in Python 3.0 and a list in 2.x +minver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]] +minverhex = 0 +# xrange is not present in Python 3.0 and range returns an iterator +for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]] +sys.exit(sys.hexversion < minverhex)" + AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])]) diff --git a/configure.ac b/configure.ac index 7533309..012b6b9 100644 --- a/configure.ac +++ b/configure.ac @@ -28,6 +28,142 @@ LT_INIT AC_PROG_CC_C99 AC_PROG_LN_S +AC_PROG_MAKE_SET +AC_PROG_AWK + +# Constants to substitute +HWLOC_LIBS=$(pkg-config --libs hwloc) +HWLOC_CFLAGS=$(pkg-config --cflags hwloc) +HWLOC_INCLUDEDIR=$(pkg-config --variable=includedir hwloc) +AC_SUBST([HWLOC_LIBS]) +AC_SUBST([HWLOC_CFLAGS]) +AC_SUBST([HWLOC_INCLUDEDIR]) + +TOPOLOGY_DIR = ./topo-xml +AC_SUBST([TOPOLOGY_DIR]) + +# Checks for header files. +AC_CHECK_HEADERS([stdlib.h string.h sys/param.h unistd.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_RESTRICT +AC_TYPE_SIZE_T + +# Checks for library functions. +AC_FUNC_FORK +AC_FUNC_MALLOC +AC_FUNC_MMAP +AC_CHECK_FUNCS([regcomp strchr strerror]) + +################ Python Configuration ################ + +# Edit PATH to remove $PWD/src/cmd so that AM_PATH_PYTHON doesn't find +# mpibind python script (thus creating a link to itself.) This needs to be +# done *before* AX_PYTHON_DEVEL. +# +saved_PATH=$PATH +export PATH=$(echo $PATH | sed "s|$(pwd)/src/cmd:*||") + +if test "X$PYTHON_VERSION" = "X" ; then + if test "X$PYTHON" = "X" ; then + # if the user hasn't specified, try for python 3 + PYTHON_VERSION=3 + fi +fi + +# Do not let AX_PYTHON_DEVEL set PYTHON_SITE_PKG +saved_PYTHON_SITE_PKG=$PYTHON_SITE_PKG +AX_PYTHON_DEVEL([>='3.6']) +PYTHON_SITE_PKG=$saved_PYTHON_SITE_PKG + +AM_PATH_PYTHON([$ac_python_version]) +if test "X$PYTHON" = "X"; then + AC_MSG_ERROR([could not find python]) +fi +if test "X$PYTHON" = "X"; then + AC_MSG_ERROR([could not find python]) +fi +# Restore original PATH: +export PATH=${saved_PATH} + +# Flag for PYTHON_LDFLAGS workaround below. +if test -n "$PYTHON_LDFLAGS"; then + ac_python_ldflags_set_by_user=true +fi + +AM_CHECK_PYMOD(cffi, + [cffi.__version_info__ >= (1,10)], + , + [AC_MSG_ERROR([could not find python module cffi, version 1.1+ required])] + ) +AM_CHECK_PYMOD(six, + [StrictVersion(six.__version__) >= StrictVersion('1.9.0')], + , + [AC_MSG_ERROR([could not find python module six, version 1.9.0+ required])] + ) +AM_CHECK_PYMOD(yaml, + [StrictVersion(yaml.__version__) >= StrictVersion ('3.10.0')], + , + [AC_MSG_ERROR([could not find python module yaml, version 3.10+ required])] + ) +AM_CHECK_PYMOD(jsonschema, + [StrictVersion(jsonschema.__version__) >= StrictVersion ('2.3.0')], + , + [AC_MSG_ERROR([could not find python module jsonschema, version 2.3.0+ required])] + ) + +# Remove -L from PYTHON_LDFLAGS if it is in a standard path +# (e.g. /usr/lib64). Placing a standard path earlier in the linker +# search can lead to linking problems. +# +# Logic below assumes only newer Python versions, protected by +# above check for atleast Python 3.6. +if test "$ac_python_ldflags_set_by_user" != "true"; then + AC_CHECK_LIB([$ac_python_library], [PyArg_ParseTuple], + [ac_python_in_ld_path=true]) + if test "$ac_python_in_ld_path" = "true"; then + AC_MSG_NOTICE([Removing -L$ac_python_libdir from PYTHON_LDFLAGS]) + PYTHON_LDFLAGS="-l$ac_python_library" + fi +fi +AS_VAR_SET(mpibindpydir, $pyexecdir/mpibind) +AC_SUBST(mpibindpydir) +AS_VAR_SET(mpibindpysodir, $pyexecdir/_mpibind) +AC_SUBST(mpibindpysodir) +AC_SUBST(PYTHON_LIBRARY, lib${ac_python_library}.so) + +AS_VAR_SET(mpibindlibdir, $libdir/mpibind) +AC_SUBST(mpibindlibdir) +AS_VAR_SET(mpibindpylinkdir, $mpibindlibdir/python$PYTHON_VERSION) +AC_SUBST(mpibindpylinkdir) + +AS_VAR_SET(mpibindbindingincludedir, $includedir/mpibind/_binding) +AC_SUBST(mpibindbindingincludedir) + +AC_DEFINE_UNQUOTED([PYTHON_INTERPRETER], ["$PYTHON"], [The python interpreter mpibind is configured with]) +AC_SUBST(PYTHON) + +AC_ARG_ENABLE([pylint], + [AS_HELP_STRING([--enable-pylint], + [Enable pylint checks of python bindings])],, + [enable_pylint="no"] +) +AS_IF([test "x$enable_pylint" = "xyes"], [ + AC_CHECK_PROG(PYLINT,[pylint],[pylint]) + AS_IF([test "x$PYLINT" != "xpylint"], [AC_MSG_ERROR([No pylint found in PATH])]) + AM_CHECK_PYMOD(pylint, + [StrictVersion(pylint.__version__) >= StrictVersion('1.8.4')], + , + [AC_MSG_ERROR([could not find python module pylint, version 1.8.4+ required])] + ) +]) +AM_CONDITIONAL([ENABLE_PYLINT], [test "x$PYLINT" = "xpylint"]) + + + +# checks for Modules + +PKG_CHECK_MODULES([HWLOC], [hwloc >= 2.0.1], [], []) # hwloc PKG_CHECK_MODULES([HWLOC], [hwloc >= 2.1]) @@ -81,6 +217,10 @@ AC_CONFIG_FILES([ test-suite/Makefile etc/Makefile etc/mpibind.pc + bindings/Makefile + bindings/python/Makefile + bindings/python/_mpibind/Makefile + bindings/python/mpibind/Makefile ]) AC_OUTPUT diff --git a/python_bindings/cffi_build/_mpibind.h b/python_bindings/cffi_build/_mpibind.h deleted file mode 100644 index 1d1c101..0000000 --- a/python_bindings/cffi_build/_mpibind.h +++ /dev/null @@ -1,184 +0,0 @@ -enum { - /* Caller can restrict the topology based on CPU or MEM */ - MPIBIND_RESTRICT_CPU, - MPIBIND_RESTRICT_MEM, - - /* The type of GPU by vendor */ - MPIBIND_GPU_AMD, - MPIBIND_GPU_NVIDIA, -}; - -/* Opaque mpibind handle */ -struct mpibind_t; -typedef struct mpibind_t mpibind_t; - -/* - * The mpibind API. - * Most calls return 0 on success and non-0 on failure. - */ - -/* - * Initialize an mpibind handle. All mpibind functions require - * this function to be called first. - */ -int mpibind_init(mpibind_t **handle); -/* - * Release resources associated with the input handle. - * After this call, no mpibind function should be called. - */ -int mpibind_finalize(mpibind_t *handle); - -/* - * Required input parameters - */ -/* - * The number of processes/tasks in the job. - */ -int mpibind_set_ntasks(mpibind_t *handle, - int ntasks); - -/* - * Optional input parameters - */ -/* - * The number of threads per process. - * If nthreads is not provided, mpibind calculates an - * appropriate number of threads for each task - * (see mpibind_get_nthreads). - */ -int mpibind_set_nthreads(mpibind_t *handle, - int nthreads); -/* - * Valid values are 0 and 1. Default is 1. - * If 1 and the number of tasks is less than the number of - * NUMA domains, mpibind assigns all of the available hardware - * resources to the input tasks. - * Otherwise, mpibind assigns no more than one NUMA domain - * (and associated resources) per task. - */ -int mpibind_set_greedy(mpibind_t *handle, - int greedy); -/* - * Valid values are 0 and 1. Default is 1. - * If 1, optimize task placement for GPUs. - * Otherwise, optimize placement for CPUs. - */ -int mpibind_set_gpu_optim(mpibind_t *handle, - int gpu_optim); -/* - * Map the application workers to this SMT-level. - * For an n-way SMT architecture, valid values are 1 to n. - * If not specified, mpibind determines the SMT level - * appropriately based on the number of input workers. - */ -int mpibind_set_smt(mpibind_t *handle, - int smt); -/* - * Restrict the hardware topology to resources - * associated with the specified hardware ids of type 'restr_type'. - */ -int mpibind_set_restrict_ids(mpibind_t *handle, - char *restr_set); -/* - * Specify the type of resource to use to restrict - * the hardware topology: MPIBIND_RESTRICT_CPU or - * MPIBIND_RESTRICT_MEM. - * The default value is MPIBIND_RESTRICT_CPU and it only - * applies if 'restr_set' is given. - */ -int mpibind_set_restrict_type(mpibind_t *handle, - int restr_type); -/* - * Pass a loaded topology to mpibind. - * mpibind will use this topology to perform the mappings - * instead of loading its own topology. - */ -int mpibind_set_topology(mpibind_t *handle, - hwloc_topology_t topo); - -/* - * Main mapping function. - * The resulting mapping can be retrieved with the - * mpibind_get* functions below. - */ -int mpibind(mpibind_t *handle); - -/* - * Output: The mapping policy. - * Asssign CPUs, GPUs, and number of threads to each - * task/process in the job. - * These output functions should only be called after - * a call to the main 'mpibind' function. - */ -/* - * Array with 'ntasks' elements. Each entry correspond - * to the number of threads to use for the process/task - * corresponding to this entry. - */ -int* mpibind_get_nthreads(mpibind_t *handle); -/* - * Array with 'ntasks' elements. The physical CPUs to - * use for a given process/task. - */ -hwloc_bitmap_t* mpibind_get_cpus(mpibind_t *handle); -/* - * Array with 'ntasks' elements. The GPUs to use for a - * given process/task. - */ -hwloc_bitmap_t* mpibind_get_gpus(mpibind_t *handle); -/* - * The GPU vendor associated with the GPUs on this - * node: MPIBIND_GPU_AMD or MPIBIND_GPU_NVIDIA. - */ -int mpibind_get_gpu_type(mpibind_t *handle); -/* - * Get the hwloc loaded topology used by mpibind so that - * callers can continue to use it even after mpibind has - * been finalized. This call, however, must be called - * before mpibind_finalize. This also means that the caller - * is responsible for unloading/freeing the topology. - */ -hwloc_topology_t mpibind_get_topology(mpibind_t *handle); - -/* - * Helper functions - */ -/* - * Print the mapping for each task. - */ -void mpibind_print_mapping(mpibind_t *handle); -/* - * Environment variables that need to be exported by the runtime. - * CUDA_VISIBLE_DEVICES --comma separated - * ROCR_VISIBLE_DEVICES - * OMP_NUM_THREADS - * OMP_PLACES --comma separated, each item in curly braces. - * OMP_PROC_BIND --spread - * It is the caller's responsibility to export the environment - * variables as desired. This function simply stores them and - * the appropriate values for the caller. - */ -int mpibind_set_env_vars(mpibind_t *handle); -/* - * Print the environment variables. - * mpibind_set_env_vars must be called before this function - * is executed. - */ -void mpibind_print_env_vars(mpibind_t *handle); -/* - * For each task, return the value of a given env - * variable (name). The output array has size 'ntasks'. - * mpibind_set_env_vars must be called before this function - * is executed. - */ -char** mpibind_get_env_var_values(mpibind_t *handle, - char *name); -/* - * Return an array with the names of the env variables. - * The size of the array is given in *count. - * mpibind_set_env_vars must be called before this function - * is executed. - */ -char** mpibind_get_env_var_names(mpibind_t *handle, int *count); - - diff --git a/python_bindings/cffi_build/cffi_build/_mpibind_cffi.c b/python_bindings/cffi_build/cffi_build/_mpibind_cffi.c deleted file mode 100644 index 9f2a1bf..0000000 --- a/python_bindings/cffi_build/cffi_build/_mpibind_cffi.c +++ /dev/null @@ -1,1554 +0,0 @@ -#define _CFFI_ - -/* We try to define Py_LIMITED_API before including Python.h. - - Mess: we can only define it if Py_DEBUG, Py_TRACE_REFS and - Py_REF_DEBUG are not defined. This is a best-effort approximation: - we can learn about Py_DEBUG from pyconfig.h, but it is unclear if - the same works for the other two macros. Py_DEBUG implies them, - but not the other way around. - - Issue #350 is still open: on Windows, the code here causes it to link - with PYTHON36.DLL (for example) instead of PYTHON3.DLL. A fix was - attempted in 164e526a5515 and 14ce6985e1c3, but reverted: virtualenv - does not make PYTHON3.DLL available, and so the "correctly" compiled - version would not run inside a virtualenv. We will re-apply the fix - after virtualenv has been fixed for some time. For explanation, see - issue #355. For a workaround if you want PYTHON3.DLL and don't worry - about virtualenv, see issue #350. See also 'py_limited_api' in - setuptools_ext.py. -*/ -#if !defined(_CFFI_USE_EMBEDDING) && !defined(Py_LIMITED_API) -# include -# if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG) -# define Py_LIMITED_API -# endif -#endif - -#include -#ifdef __cplusplus -extern "C" { -#endif -#include - -/* This part is from file 'cffi/parse_c_type.h'. It is copied at the - beginning of C sources generated by CFFI's ffi.set_source(). */ - -typedef void *_cffi_opcode_t; - -#define _CFFI_OP(opcode, arg) (_cffi_opcode_t)(opcode | (((uintptr_t)(arg)) << 8)) -#define _CFFI_GETOP(cffi_opcode) ((unsigned char)(uintptr_t)cffi_opcode) -#define _CFFI_GETARG(cffi_opcode) (((intptr_t)cffi_opcode) >> 8) - -#define _CFFI_OP_PRIMITIVE 1 -#define _CFFI_OP_POINTER 3 -#define _CFFI_OP_ARRAY 5 -#define _CFFI_OP_OPEN_ARRAY 7 -#define _CFFI_OP_STRUCT_UNION 9 -#define _CFFI_OP_ENUM 11 -#define _CFFI_OP_FUNCTION 13 -#define _CFFI_OP_FUNCTION_END 15 -#define _CFFI_OP_NOOP 17 -#define _CFFI_OP_BITFIELD 19 -#define _CFFI_OP_TYPENAME 21 -#define _CFFI_OP_CPYTHON_BLTN_V 23 // varargs -#define _CFFI_OP_CPYTHON_BLTN_N 25 // noargs -#define _CFFI_OP_CPYTHON_BLTN_O 27 // O (i.e. a single arg) -#define _CFFI_OP_CONSTANT 29 -#define _CFFI_OP_CONSTANT_INT 31 -#define _CFFI_OP_GLOBAL_VAR 33 -#define _CFFI_OP_DLOPEN_FUNC 35 -#define _CFFI_OP_DLOPEN_CONST 37 -#define _CFFI_OP_GLOBAL_VAR_F 39 -#define _CFFI_OP_EXTERN_PYTHON 41 - -#define _CFFI_PRIM_VOID 0 -#define _CFFI_PRIM_BOOL 1 -#define _CFFI_PRIM_CHAR 2 -#define _CFFI_PRIM_SCHAR 3 -#define _CFFI_PRIM_UCHAR 4 -#define _CFFI_PRIM_SHORT 5 -#define _CFFI_PRIM_USHORT 6 -#define _CFFI_PRIM_INT 7 -#define _CFFI_PRIM_UINT 8 -#define _CFFI_PRIM_LONG 9 -#define _CFFI_PRIM_ULONG 10 -#define _CFFI_PRIM_LONGLONG 11 -#define _CFFI_PRIM_ULONGLONG 12 -#define _CFFI_PRIM_FLOAT 13 -#define _CFFI_PRIM_DOUBLE 14 -#define _CFFI_PRIM_LONGDOUBLE 15 - -#define _CFFI_PRIM_WCHAR 16 -#define _CFFI_PRIM_INT8 17 -#define _CFFI_PRIM_UINT8 18 -#define _CFFI_PRIM_INT16 19 -#define _CFFI_PRIM_UINT16 20 -#define _CFFI_PRIM_INT32 21 -#define _CFFI_PRIM_UINT32 22 -#define _CFFI_PRIM_INT64 23 -#define _CFFI_PRIM_UINT64 24 -#define _CFFI_PRIM_INTPTR 25 -#define _CFFI_PRIM_UINTPTR 26 -#define _CFFI_PRIM_PTRDIFF 27 -#define _CFFI_PRIM_SIZE 28 -#define _CFFI_PRIM_SSIZE 29 -#define _CFFI_PRIM_INT_LEAST8 30 -#define _CFFI_PRIM_UINT_LEAST8 31 -#define _CFFI_PRIM_INT_LEAST16 32 -#define _CFFI_PRIM_UINT_LEAST16 33 -#define _CFFI_PRIM_INT_LEAST32 34 -#define _CFFI_PRIM_UINT_LEAST32 35 -#define _CFFI_PRIM_INT_LEAST64 36 -#define _CFFI_PRIM_UINT_LEAST64 37 -#define _CFFI_PRIM_INT_FAST8 38 -#define _CFFI_PRIM_UINT_FAST8 39 -#define _CFFI_PRIM_INT_FAST16 40 -#define _CFFI_PRIM_UINT_FAST16 41 -#define _CFFI_PRIM_INT_FAST32 42 -#define _CFFI_PRIM_UINT_FAST32 43 -#define _CFFI_PRIM_INT_FAST64 44 -#define _CFFI_PRIM_UINT_FAST64 45 -#define _CFFI_PRIM_INTMAX 46 -#define _CFFI_PRIM_UINTMAX 47 -#define _CFFI_PRIM_FLOATCOMPLEX 48 -#define _CFFI_PRIM_DOUBLECOMPLEX 49 -#define _CFFI_PRIM_CHAR16 50 -#define _CFFI_PRIM_CHAR32 51 - -#define _CFFI__NUM_PRIM 52 -#define _CFFI__UNKNOWN_PRIM (-1) -#define _CFFI__UNKNOWN_FLOAT_PRIM (-2) -#define _CFFI__UNKNOWN_LONG_DOUBLE (-3) - -#define _CFFI__IO_FILE_STRUCT (-1) - - -struct _cffi_global_s { - const char *name; - void *address; - _cffi_opcode_t type_op; - void *size_or_direct_fn; // OP_GLOBAL_VAR: size, or 0 if unknown - // OP_CPYTHON_BLTN_*: addr of direct function -}; - -struct _cffi_getconst_s { - unsigned long long value; - const struct _cffi_type_context_s *ctx; - int gindex; -}; - -struct _cffi_struct_union_s { - const char *name; - int type_index; // -> _cffi_types, on a OP_STRUCT_UNION - int flags; // _CFFI_F_* flags below - size_t size; - int alignment; - int first_field_index; // -> _cffi_fields array - int num_fields; -}; -#define _CFFI_F_UNION 0x01 // is a union, not a struct -#define _CFFI_F_CHECK_FIELDS 0x02 // complain if fields are not in the - // "standard layout" or if some are missing -#define _CFFI_F_PACKED 0x04 // for CHECK_FIELDS, assume a packed struct -#define _CFFI_F_EXTERNAL 0x08 // in some other ffi.include() -#define _CFFI_F_OPAQUE 0x10 // opaque - -struct _cffi_field_s { - const char *name; - size_t field_offset; - size_t field_size; - _cffi_opcode_t field_type_op; -}; - -struct _cffi_enum_s { - const char *name; - int type_index; // -> _cffi_types, on a OP_ENUM - int type_prim; // _CFFI_PRIM_xxx - const char *enumerators; // comma-delimited string -}; - -struct _cffi_typename_s { - const char *name; - int type_index; /* if opaque, points to a possibly artificial - OP_STRUCT which is itself opaque */ -}; - -struct _cffi_type_context_s { - _cffi_opcode_t *types; - const struct _cffi_global_s *globals; - const struct _cffi_field_s *fields; - const struct _cffi_struct_union_s *struct_unions; - const struct _cffi_enum_s *enums; - const struct _cffi_typename_s *typenames; - int num_globals; - int num_struct_unions; - int num_enums; - int num_typenames; - const char *const *includes; - int num_types; - int flags; /* future extension */ -}; - -struct _cffi_parse_info_s { - const struct _cffi_type_context_s *ctx; - _cffi_opcode_t *output; - unsigned int output_size; - size_t error_location; - const char *error_message; -}; - -struct _cffi_externpy_s { - const char *name; - size_t size_of_result; - void *reserved1, *reserved2; -}; - -#ifdef _CFFI_INTERNAL -static int parse_c_type(struct _cffi_parse_info_s *info, const char *input); -static int search_in_globals(const struct _cffi_type_context_s *ctx, - const char *search, size_t search_len); -static int search_in_struct_unions(const struct _cffi_type_context_s *ctx, - const char *search, size_t search_len); -#endif - -/* this block of #ifs should be kept exactly identical between - c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py - and cffi/_cffi_include.h */ -#if defined(_MSC_VER) -# include /* for alloca() */ -# if _MSC_VER < 1600 /* MSVC < 2010 */ - typedef __int8 int8_t; - typedef __int16 int16_t; - typedef __int32 int32_t; - typedef __int64 int64_t; - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; - typedef unsigned __int64 uint64_t; - typedef __int8 int_least8_t; - typedef __int16 int_least16_t; - typedef __int32 int_least32_t; - typedef __int64 int_least64_t; - typedef unsigned __int8 uint_least8_t; - typedef unsigned __int16 uint_least16_t; - typedef unsigned __int32 uint_least32_t; - typedef unsigned __int64 uint_least64_t; - typedef __int8 int_fast8_t; - typedef __int16 int_fast16_t; - typedef __int32 int_fast32_t; - typedef __int64 int_fast64_t; - typedef unsigned __int8 uint_fast8_t; - typedef unsigned __int16 uint_fast16_t; - typedef unsigned __int32 uint_fast32_t; - typedef unsigned __int64 uint_fast64_t; - typedef __int64 intmax_t; - typedef unsigned __int64 uintmax_t; -# else -# include -# endif -# if _MSC_VER < 1800 /* MSVC < 2013 */ -# ifndef __cplusplus - typedef unsigned char _Bool; -# endif -# endif -#else -# include -# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux) -# include -# endif -#endif - -#ifdef __GNUC__ -# define _CFFI_UNUSED_FN __attribute__((unused)) -#else -# define _CFFI_UNUSED_FN /* nothing */ -#endif - -#ifdef __cplusplus -# ifndef _Bool - typedef bool _Bool; /* semi-hackish: C++ has no _Bool; bool is builtin */ -# endif -#endif - -/********** CPython-specific section **********/ -#ifndef PYPY_VERSION - - -#if PY_MAJOR_VERSION >= 3 -# define PyInt_FromLong PyLong_FromLong -#endif - -#define _cffi_from_c_double PyFloat_FromDouble -#define _cffi_from_c_float PyFloat_FromDouble -#define _cffi_from_c_long PyInt_FromLong -#define _cffi_from_c_ulong PyLong_FromUnsignedLong -#define _cffi_from_c_longlong PyLong_FromLongLong -#define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong -#define _cffi_from_c__Bool PyBool_FromLong - -#define _cffi_to_c_double PyFloat_AsDouble -#define _cffi_to_c_float PyFloat_AsDouble - -#define _cffi_from_c_int(x, type) \ - (((type)-1) > 0 ? /* unsigned */ \ - (sizeof(type) < sizeof(long) ? \ - PyInt_FromLong((long)x) : \ - sizeof(type) == sizeof(long) ? \ - PyLong_FromUnsignedLong((unsigned long)x) : \ - PyLong_FromUnsignedLongLong((unsigned long long)x)) : \ - (sizeof(type) <= sizeof(long) ? \ - PyInt_FromLong((long)x) : \ - PyLong_FromLongLong((long long)x))) - -#define _cffi_to_c_int(o, type) \ - ((type)( \ - sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \ - : (type)_cffi_to_c_i8(o)) : \ - sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \ - : (type)_cffi_to_c_i16(o)) : \ - sizeof(type) == 4 ? (((type)-1) > 0 ? (type)_cffi_to_c_u32(o) \ - : (type)_cffi_to_c_i32(o)) : \ - sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \ - : (type)_cffi_to_c_i64(o)) : \ - (Py_FatalError("unsupported size for type " #type), (type)0))) - -#define _cffi_to_c_i8 \ - ((int(*)(PyObject *))_cffi_exports[1]) -#define _cffi_to_c_u8 \ - ((int(*)(PyObject *))_cffi_exports[2]) -#define _cffi_to_c_i16 \ - ((int(*)(PyObject *))_cffi_exports[3]) -#define _cffi_to_c_u16 \ - ((int(*)(PyObject *))_cffi_exports[4]) -#define _cffi_to_c_i32 \ - ((int(*)(PyObject *))_cffi_exports[5]) -#define _cffi_to_c_u32 \ - ((unsigned int(*)(PyObject *))_cffi_exports[6]) -#define _cffi_to_c_i64 \ - ((long long(*)(PyObject *))_cffi_exports[7]) -#define _cffi_to_c_u64 \ - ((unsigned long long(*)(PyObject *))_cffi_exports[8]) -#define _cffi_to_c_char \ - ((int(*)(PyObject *))_cffi_exports[9]) -#define _cffi_from_c_pointer \ - ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[10]) -#define _cffi_to_c_pointer \ - ((char *(*)(PyObject *, struct _cffi_ctypedescr *))_cffi_exports[11]) -#define _cffi_get_struct_layout \ - not used any more -#define _cffi_restore_errno \ - ((void(*)(void))_cffi_exports[13]) -#define _cffi_save_errno \ - ((void(*)(void))_cffi_exports[14]) -#define _cffi_from_c_char \ - ((PyObject *(*)(char))_cffi_exports[15]) -#define _cffi_from_c_deref \ - ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[16]) -#define _cffi_to_c \ - ((int(*)(char *, struct _cffi_ctypedescr *, PyObject *))_cffi_exports[17]) -#define _cffi_from_c_struct \ - ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[18]) -#define _cffi_to_c_wchar_t \ - ((_cffi_wchar_t(*)(PyObject *))_cffi_exports[19]) -#define _cffi_from_c_wchar_t \ - ((PyObject *(*)(_cffi_wchar_t))_cffi_exports[20]) -#define _cffi_to_c_long_double \ - ((long double(*)(PyObject *))_cffi_exports[21]) -#define _cffi_to_c__Bool \ - ((_Bool(*)(PyObject *))_cffi_exports[22]) -#define _cffi_prepare_pointer_call_argument \ - ((Py_ssize_t(*)(struct _cffi_ctypedescr *, \ - PyObject *, char **))_cffi_exports[23]) -#define _cffi_convert_array_from_object \ - ((int(*)(char *, struct _cffi_ctypedescr *, PyObject *))_cffi_exports[24]) -#define _CFFI_CPIDX 25 -#define _cffi_call_python \ - ((void(*)(struct _cffi_externpy_s *, char *))_cffi_exports[_CFFI_CPIDX]) -#define _cffi_to_c_wchar3216_t \ - ((int(*)(PyObject *))_cffi_exports[26]) -#define _cffi_from_c_wchar3216_t \ - ((PyObject *(*)(int))_cffi_exports[27]) -#define _CFFI_NUM_EXPORTS 28 - -struct _cffi_ctypedescr; - -static void *_cffi_exports[_CFFI_NUM_EXPORTS]; - -#define _cffi_type(index) ( \ - assert((((uintptr_t)_cffi_types[index]) & 1) == 0), \ - (struct _cffi_ctypedescr *)_cffi_types[index]) - -static PyObject *_cffi_init(const char *module_name, Py_ssize_t version, - const struct _cffi_type_context_s *ctx) -{ - PyObject *module, *o_arg, *new_module; - void *raw[] = { - (void *)module_name, - (void *)version, - (void *)_cffi_exports, - (void *)ctx, - }; - - module = PyImport_ImportModule("_cffi_backend"); - if (module == NULL) - goto failure; - - o_arg = PyLong_FromVoidPtr((void *)raw); - if (o_arg == NULL) - goto failure; - - new_module = PyObject_CallMethod( - module, (char *)"_init_cffi_1_0_external_module", (char *)"O", o_arg); - - Py_DECREF(o_arg); - Py_DECREF(module); - return new_module; - - failure: - Py_XDECREF(module); - return NULL; -} - - -#ifdef HAVE_WCHAR_H -typedef wchar_t _cffi_wchar_t; -#else -typedef uint16_t _cffi_wchar_t; /* same random pick as _cffi_backend.c */ -#endif - -_CFFI_UNUSED_FN static uint16_t _cffi_to_c_char16_t(PyObject *o) -{ - if (sizeof(_cffi_wchar_t) == 2) - return (uint16_t)_cffi_to_c_wchar_t(o); - else - return (uint16_t)_cffi_to_c_wchar3216_t(o); -} - -_CFFI_UNUSED_FN static PyObject *_cffi_from_c_char16_t(uint16_t x) -{ - if (sizeof(_cffi_wchar_t) == 2) - return _cffi_from_c_wchar_t((_cffi_wchar_t)x); - else - return _cffi_from_c_wchar3216_t((int)x); -} - -_CFFI_UNUSED_FN static int _cffi_to_c_char32_t(PyObject *o) -{ - if (sizeof(_cffi_wchar_t) == 4) - return (int)_cffi_to_c_wchar_t(o); - else - return (int)_cffi_to_c_wchar3216_t(o); -} - -_CFFI_UNUSED_FN static PyObject *_cffi_from_c_char32_t(int x) -{ - if (sizeof(_cffi_wchar_t) == 4) - return _cffi_from_c_wchar_t((_cffi_wchar_t)x); - else - return _cffi_from_c_wchar3216_t(x); -} - - -/********** end CPython-specific section **********/ -#else -_CFFI_UNUSED_FN -static void (*_cffi_call_python_org)(struct _cffi_externpy_s *, char *); -# define _cffi_call_python _cffi_call_python_org -#endif - - -#define _cffi_array_len(array) (sizeof(array) / sizeof((array)[0])) - -#define _cffi_prim_int(size, sign) \ - ((size) == 1 ? ((sign) ? _CFFI_PRIM_INT8 : _CFFI_PRIM_UINT8) : \ - (size) == 2 ? ((sign) ? _CFFI_PRIM_INT16 : _CFFI_PRIM_UINT16) : \ - (size) == 4 ? ((sign) ? _CFFI_PRIM_INT32 : _CFFI_PRIM_UINT32) : \ - (size) == 8 ? ((sign) ? _CFFI_PRIM_INT64 : _CFFI_PRIM_UINT64) : \ - _CFFI__UNKNOWN_PRIM) - -#define _cffi_prim_float(size) \ - ((size) == sizeof(float) ? _CFFI_PRIM_FLOAT : \ - (size) == sizeof(double) ? _CFFI_PRIM_DOUBLE : \ - (size) == sizeof(long double) ? _CFFI__UNKNOWN_LONG_DOUBLE : \ - _CFFI__UNKNOWN_FLOAT_PRIM) - -#define _cffi_check_int(got, got_nonpos, expected) \ - ((got_nonpos) == (expected <= 0) && \ - (got) == (unsigned long long)expected) - -#ifdef MS_WIN32 -# define _cffi_stdcall __stdcall -#else -# define _cffi_stdcall /* nothing */ -#endif - -#ifdef __cplusplus -} -#endif - -/************************************************************/ - - - #include "_mpibind.h" - #include - - -/************************************************************/ - -static void *_cffi_types[] = { -/* 0 */ _CFFI_OP(_CFFI_OP_FUNCTION, 38), // char * *()(mpibind_t *, char *) -/* 1 */ _CFFI_OP(_CFFI_OP_POINTER, 43), // mpibind_t * -/* 2 */ _CFFI_OP(_CFFI_OP_POINTER, 39), // char * -/* 3 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), -/* 4 */ _CFFI_OP(_CFFI_OP_FUNCTION, 38), // char * *()(mpibind_t *, int *) -/* 5 */ _CFFI_OP(_CFFI_OP_NOOP, 1), -/* 6 */ _CFFI_OP(_CFFI_OP_POINTER, 33), // int * -/* 7 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), -/* 8 */ _CFFI_OP(_CFFI_OP_FUNCTION, 41), // hwloc_bitmap_t *()(mpibind_t *) -/* 9 */ _CFFI_OP(_CFFI_OP_NOOP, 1), -/* 10 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), -/* 11 */ _CFFI_OP(_CFFI_OP_FUNCTION, 29), // hwloc_topology_t()(mpibind_t *) -/* 12 */ _CFFI_OP(_CFFI_OP_NOOP, 1), -/* 13 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), -/* 14 */ _CFFI_OP(_CFFI_OP_FUNCTION, 6), // int *()(mpibind_t *) -/* 15 */ _CFFI_OP(_CFFI_OP_NOOP, 1), -/* 16 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), -/* 17 */ _CFFI_OP(_CFFI_OP_FUNCTION, 33), // int()(mpibind_t * *) -/* 18 */ _CFFI_OP(_CFFI_OP_POINTER, 1), // mpibind_t * * -/* 19 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), -/* 20 */ _CFFI_OP(_CFFI_OP_FUNCTION, 33), // int()(mpibind_t *) -/* 21 */ _CFFI_OP(_CFFI_OP_NOOP, 1), -/* 22 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), -/* 23 */ _CFFI_OP(_CFFI_OP_FUNCTION, 33), // int()(mpibind_t *, char *) -/* 24 */ _CFFI_OP(_CFFI_OP_NOOP, 1), -/* 25 */ _CFFI_OP(_CFFI_OP_NOOP, 2), -/* 26 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), -/* 27 */ _CFFI_OP(_CFFI_OP_FUNCTION, 33), // int()(mpibind_t *, hwloc_topology_t) -/* 28 */ _CFFI_OP(_CFFI_OP_NOOP, 1), -/* 29 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, _cffi_prim_int(sizeof(hwloc_topology_t), ( - ((hwloc_topology_t)-1) | 0 /* check that hwloc_topology_t is an integer type */ - ) <= 0)), // hwloc_topology_t -/* 30 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), -/* 31 */ _CFFI_OP(_CFFI_OP_FUNCTION, 33), // int()(mpibind_t *, int) -/* 32 */ _CFFI_OP(_CFFI_OP_NOOP, 1), -/* 33 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 7), // int -/* 34 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), -/* 35 */ _CFFI_OP(_CFFI_OP_FUNCTION, 44), // void()(mpibind_t *) -/* 36 */ _CFFI_OP(_CFFI_OP_NOOP, 1), -/* 37 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), -/* 38 */ _CFFI_OP(_CFFI_OP_POINTER, 2), // char * * -/* 39 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 2), // char -/* 40 */ _CFFI_OP(_CFFI_OP_ENUM, 0), // enum $1 -/* 41 */ _CFFI_OP(_CFFI_OP_POINTER, 42), // hwloc_bitmap_t * -/* 42 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, _cffi_prim_int(sizeof(hwloc_bitmap_t), ( - ((hwloc_bitmap_t)-1) | 0 /* check that hwloc_bitmap_t is an integer type */ - ) <= 0)), // hwloc_bitmap_t -/* 43 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 0), // mpibind_t -/* 44 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 0), // void -}; - -static int _cffi_const_MPIBIND_RESTRICT_CPU(unsigned long long *o) -{ - int n = (MPIBIND_RESTRICT_CPU) <= 0; - *o = (unsigned long long)((MPIBIND_RESTRICT_CPU) | 0); /* check that MPIBIND_RESTRICT_CPU is an integer */ - return n; -} - -static int _cffi_const_MPIBIND_RESTRICT_MEM(unsigned long long *o) -{ - int n = (MPIBIND_RESTRICT_MEM) <= 0; - *o = (unsigned long long)((MPIBIND_RESTRICT_MEM) | 0); /* check that MPIBIND_RESTRICT_MEM is an integer */ - return n; -} - -static int _cffi_const_MPIBIND_GPU_AMD(unsigned long long *o) -{ - int n = (MPIBIND_GPU_AMD) <= 0; - *o = (unsigned long long)((MPIBIND_GPU_AMD) | 0); /* check that MPIBIND_GPU_AMD is an integer */ - return n; -} - -static int _cffi_const_MPIBIND_GPU_NVIDIA(unsigned long long *o) -{ - int n = (MPIBIND_GPU_NVIDIA) <= 0; - *o = (unsigned long long)((MPIBIND_GPU_NVIDIA) | 0); /* check that MPIBIND_GPU_NVIDIA is an integer */ - return n; -} - -static int _cffi_d_mpibind(mpibind_t * x0) -{ - return mpibind(x0); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind(PyObject *self, PyObject *arg0) -{ - mpibind_t * x0; - Py_ssize_t datasize; - int result; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind(x0); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind _cffi_d_mpibind -#endif - -static int _cffi_d_mpibind_finalize(mpibind_t * x0) -{ - return mpibind_finalize(x0); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_finalize(PyObject *self, PyObject *arg0) -{ - mpibind_t * x0; - Py_ssize_t datasize; - int result; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_finalize(x0); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind_finalize _cffi_d_mpibind_finalize -#endif - -static hwloc_bitmap_t * _cffi_d_mpibind_get_cpus(mpibind_t * x0) -{ - return mpibind_get_cpus(x0); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_get_cpus(PyObject *self, PyObject *arg0) -{ - mpibind_t * x0; - Py_ssize_t datasize; - hwloc_bitmap_t * result; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_get_cpus(x0); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_pointer((char *)result, _cffi_type(41)); -} -#else -# define _cffi_f_mpibind_get_cpus _cffi_d_mpibind_get_cpus -#endif - -static char * * _cffi_d_mpibind_get_env_var_names(mpibind_t * x0, int * x1) -{ - return mpibind_get_env_var_names(x0, x1); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_get_env_var_names(PyObject *self, PyObject *args) -{ - mpibind_t * x0; - int * x1; - Py_ssize_t datasize; - char * * result; - PyObject *arg0; - PyObject *arg1; - - if (!PyArg_UnpackTuple(args, "mpibind_get_env_var_names", 2, 2, &arg0, &arg1)) - return NULL; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(6), arg1, (char **)&x1); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x1 = (int *)alloca((size_t)datasize); - memset((void *)x1, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x1, _cffi_type(6), arg1) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_get_env_var_names(x0, x1); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_pointer((char *)result, _cffi_type(38)); -} -#else -# define _cffi_f_mpibind_get_env_var_names _cffi_d_mpibind_get_env_var_names -#endif - -static char * * _cffi_d_mpibind_get_env_var_values(mpibind_t * x0, char * x1) -{ - return mpibind_get_env_var_values(x0, x1); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_get_env_var_values(PyObject *self, PyObject *args) -{ - mpibind_t * x0; - char * x1; - Py_ssize_t datasize; - char * * result; - PyObject *arg0; - PyObject *arg1; - - if (!PyArg_UnpackTuple(args, "mpibind_get_env_var_values", 2, 2, &arg0, &arg1)) - return NULL; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(2), arg1, (char **)&x1); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x1 = (char *)alloca((size_t)datasize); - memset((void *)x1, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x1, _cffi_type(2), arg1) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_get_env_var_values(x0, x1); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_pointer((char *)result, _cffi_type(38)); -} -#else -# define _cffi_f_mpibind_get_env_var_values _cffi_d_mpibind_get_env_var_values -#endif - -static int _cffi_d_mpibind_get_gpu_type(mpibind_t * x0) -{ - return mpibind_get_gpu_type(x0); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_get_gpu_type(PyObject *self, PyObject *arg0) -{ - mpibind_t * x0; - Py_ssize_t datasize; - int result; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_get_gpu_type(x0); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind_get_gpu_type _cffi_d_mpibind_get_gpu_type -#endif - -static hwloc_bitmap_t * _cffi_d_mpibind_get_gpus(mpibind_t * x0) -{ - return mpibind_get_gpus(x0); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_get_gpus(PyObject *self, PyObject *arg0) -{ - mpibind_t * x0; - Py_ssize_t datasize; - hwloc_bitmap_t * result; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_get_gpus(x0); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_pointer((char *)result, _cffi_type(41)); -} -#else -# define _cffi_f_mpibind_get_gpus _cffi_d_mpibind_get_gpus -#endif - -static int * _cffi_d_mpibind_get_nthreads(mpibind_t * x0) -{ - return mpibind_get_nthreads(x0); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_get_nthreads(PyObject *self, PyObject *arg0) -{ - mpibind_t * x0; - Py_ssize_t datasize; - int * result; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_get_nthreads(x0); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_pointer((char *)result, _cffi_type(6)); -} -#else -# define _cffi_f_mpibind_get_nthreads _cffi_d_mpibind_get_nthreads -#endif - -static hwloc_topology_t _cffi_d_mpibind_get_topology(mpibind_t * x0) -{ - return mpibind_get_topology(x0); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_get_topology(PyObject *self, PyObject *arg0) -{ - mpibind_t * x0; - Py_ssize_t datasize; - hwloc_topology_t result; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_get_topology(x0); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, hwloc_topology_t); -} -#else -# define _cffi_f_mpibind_get_topology _cffi_d_mpibind_get_topology -#endif - -static int _cffi_d_mpibind_init(mpibind_t * * x0) -{ - return mpibind_init(x0); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_init(PyObject *self, PyObject *arg0) -{ - mpibind_t * * x0; - Py_ssize_t datasize; - int result; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(18), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t * *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(18), arg0) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_init(x0); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind_init _cffi_d_mpibind_init -#endif - -static void _cffi_d_mpibind_print_env_vars(mpibind_t * x0) -{ - mpibind_print_env_vars(x0); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_print_env_vars(PyObject *self, PyObject *arg0) -{ - mpibind_t * x0; - Py_ssize_t datasize; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { mpibind_print_env_vars(x0); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - Py_INCREF(Py_None); - return Py_None; -} -#else -# define _cffi_f_mpibind_print_env_vars _cffi_d_mpibind_print_env_vars -#endif - -static void _cffi_d_mpibind_print_mapping(mpibind_t * x0) -{ - mpibind_print_mapping(x0); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_print_mapping(PyObject *self, PyObject *arg0) -{ - mpibind_t * x0; - Py_ssize_t datasize; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { mpibind_print_mapping(x0); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - Py_INCREF(Py_None); - return Py_None; -} -#else -# define _cffi_f_mpibind_print_mapping _cffi_d_mpibind_print_mapping -#endif - -static int _cffi_d_mpibind_set_env_vars(mpibind_t * x0) -{ - return mpibind_set_env_vars(x0); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_set_env_vars(PyObject *self, PyObject *arg0) -{ - mpibind_t * x0; - Py_ssize_t datasize; - int result; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_set_env_vars(x0); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind_set_env_vars _cffi_d_mpibind_set_env_vars -#endif - -static int _cffi_d_mpibind_set_gpu_optim(mpibind_t * x0, int x1) -{ - return mpibind_set_gpu_optim(x0, x1); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_set_gpu_optim(PyObject *self, PyObject *args) -{ - mpibind_t * x0; - int x1; - Py_ssize_t datasize; - int result; - PyObject *arg0; - PyObject *arg1; - - if (!PyArg_UnpackTuple(args, "mpibind_set_gpu_optim", 2, 2, &arg0, &arg1)) - return NULL; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - x1 = _cffi_to_c_int(arg1, int); - if (x1 == (int)-1 && PyErr_Occurred()) - return NULL; - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_set_gpu_optim(x0, x1); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind_set_gpu_optim _cffi_d_mpibind_set_gpu_optim -#endif - -static int _cffi_d_mpibind_set_greedy(mpibind_t * x0, int x1) -{ - return mpibind_set_greedy(x0, x1); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_set_greedy(PyObject *self, PyObject *args) -{ - mpibind_t * x0; - int x1; - Py_ssize_t datasize; - int result; - PyObject *arg0; - PyObject *arg1; - - if (!PyArg_UnpackTuple(args, "mpibind_set_greedy", 2, 2, &arg0, &arg1)) - return NULL; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - x1 = _cffi_to_c_int(arg1, int); - if (x1 == (int)-1 && PyErr_Occurred()) - return NULL; - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_set_greedy(x0, x1); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind_set_greedy _cffi_d_mpibind_set_greedy -#endif - -static int _cffi_d_mpibind_set_ntasks(mpibind_t * x0, int x1) -{ - return mpibind_set_ntasks(x0, x1); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_set_ntasks(PyObject *self, PyObject *args) -{ - mpibind_t * x0; - int x1; - Py_ssize_t datasize; - int result; - PyObject *arg0; - PyObject *arg1; - - if (!PyArg_UnpackTuple(args, "mpibind_set_ntasks", 2, 2, &arg0, &arg1)) - return NULL; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - x1 = _cffi_to_c_int(arg1, int); - if (x1 == (int)-1 && PyErr_Occurred()) - return NULL; - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_set_ntasks(x0, x1); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind_set_ntasks _cffi_d_mpibind_set_ntasks -#endif - -static int _cffi_d_mpibind_set_nthreads(mpibind_t * x0, int x1) -{ - return mpibind_set_nthreads(x0, x1); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_set_nthreads(PyObject *self, PyObject *args) -{ - mpibind_t * x0; - int x1; - Py_ssize_t datasize; - int result; - PyObject *arg0; - PyObject *arg1; - - if (!PyArg_UnpackTuple(args, "mpibind_set_nthreads", 2, 2, &arg0, &arg1)) - return NULL; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - x1 = _cffi_to_c_int(arg1, int); - if (x1 == (int)-1 && PyErr_Occurred()) - return NULL; - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_set_nthreads(x0, x1); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind_set_nthreads _cffi_d_mpibind_set_nthreads -#endif - -static int _cffi_d_mpibind_set_restrict_ids(mpibind_t * x0, char * x1) -{ - return mpibind_set_restrict_ids(x0, x1); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_set_restrict_ids(PyObject *self, PyObject *args) -{ - mpibind_t * x0; - char * x1; - Py_ssize_t datasize; - int result; - PyObject *arg0; - PyObject *arg1; - - if (!PyArg_UnpackTuple(args, "mpibind_set_restrict_ids", 2, 2, &arg0, &arg1)) - return NULL; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(2), arg1, (char **)&x1); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x1 = (char *)alloca((size_t)datasize); - memset((void *)x1, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x1, _cffi_type(2), arg1) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_set_restrict_ids(x0, x1); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind_set_restrict_ids _cffi_d_mpibind_set_restrict_ids -#endif - -static int _cffi_d_mpibind_set_restrict_type(mpibind_t * x0, int x1) -{ - return mpibind_set_restrict_type(x0, x1); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_set_restrict_type(PyObject *self, PyObject *args) -{ - mpibind_t * x0; - int x1; - Py_ssize_t datasize; - int result; - PyObject *arg0; - PyObject *arg1; - - if (!PyArg_UnpackTuple(args, "mpibind_set_restrict_type", 2, 2, &arg0, &arg1)) - return NULL; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - x1 = _cffi_to_c_int(arg1, int); - if (x1 == (int)-1 && PyErr_Occurred()) - return NULL; - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_set_restrict_type(x0, x1); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind_set_restrict_type _cffi_d_mpibind_set_restrict_type -#endif - -static int _cffi_d_mpibind_set_smt(mpibind_t * x0, int x1) -{ - return mpibind_set_smt(x0, x1); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_set_smt(PyObject *self, PyObject *args) -{ - mpibind_t * x0; - int x1; - Py_ssize_t datasize; - int result; - PyObject *arg0; - PyObject *arg1; - - if (!PyArg_UnpackTuple(args, "mpibind_set_smt", 2, 2, &arg0, &arg1)) - return NULL; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - x1 = _cffi_to_c_int(arg1, int); - if (x1 == (int)-1 && PyErr_Occurred()) - return NULL; - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_set_smt(x0, x1); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind_set_smt _cffi_d_mpibind_set_smt -#endif - -static int _cffi_d_mpibind_set_topology(mpibind_t * x0, hwloc_topology_t x1) -{ - return mpibind_set_topology(x0, x1); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_set_topology(PyObject *self, PyObject *args) -{ - mpibind_t * x0; - hwloc_topology_t x1; - Py_ssize_t datasize; - int result; - PyObject *arg0; - PyObject *arg1; - - if (!PyArg_UnpackTuple(args, "mpibind_set_topology", 2, 2, &arg0, &arg1)) - return NULL; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - x1 = _cffi_to_c_int(arg1, hwloc_topology_t); - if (x1 == (hwloc_topology_t)-1 && PyErr_Occurred()) - return NULL; - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_set_topology(x0, x1); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind_set_topology _cffi_d_mpibind_set_topology -#endif - -static const struct _cffi_global_s _cffi_globals[] = { - { "MPIBIND_GPU_AMD", (void *)_cffi_const_MPIBIND_GPU_AMD, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, - { "MPIBIND_GPU_NVIDIA", (void *)_cffi_const_MPIBIND_GPU_NVIDIA, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, - { "MPIBIND_RESTRICT_CPU", (void *)_cffi_const_MPIBIND_RESTRICT_CPU, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, - { "MPIBIND_RESTRICT_MEM", (void *)_cffi_const_MPIBIND_RESTRICT_MEM, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, - { "mpibind", (void *)_cffi_f_mpibind, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 20), (void *)_cffi_d_mpibind }, - { "mpibind_finalize", (void *)_cffi_f_mpibind_finalize, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 20), (void *)_cffi_d_mpibind_finalize }, - { "mpibind_get_cpus", (void *)_cffi_f_mpibind_get_cpus, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 8), (void *)_cffi_d_mpibind_get_cpus }, - { "mpibind_get_env_var_names", (void *)_cffi_f_mpibind_get_env_var_names, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 4), (void *)_cffi_d_mpibind_get_env_var_names }, - { "mpibind_get_env_var_values", (void *)_cffi_f_mpibind_get_env_var_values, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 0), (void *)_cffi_d_mpibind_get_env_var_values }, - { "mpibind_get_gpu_type", (void *)_cffi_f_mpibind_get_gpu_type, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 20), (void *)_cffi_d_mpibind_get_gpu_type }, - { "mpibind_get_gpus", (void *)_cffi_f_mpibind_get_gpus, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 8), (void *)_cffi_d_mpibind_get_gpus }, - { "mpibind_get_nthreads", (void *)_cffi_f_mpibind_get_nthreads, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 14), (void *)_cffi_d_mpibind_get_nthreads }, - { "mpibind_get_topology", (void *)_cffi_f_mpibind_get_topology, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 11), (void *)_cffi_d_mpibind_get_topology }, - { "mpibind_init", (void *)_cffi_f_mpibind_init, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 17), (void *)_cffi_d_mpibind_init }, - { "mpibind_print_env_vars", (void *)_cffi_f_mpibind_print_env_vars, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 35), (void *)_cffi_d_mpibind_print_env_vars }, - { "mpibind_print_mapping", (void *)_cffi_f_mpibind_print_mapping, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 35), (void *)_cffi_d_mpibind_print_mapping }, - { "mpibind_set_env_vars", (void *)_cffi_f_mpibind_set_env_vars, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 20), (void *)_cffi_d_mpibind_set_env_vars }, - { "mpibind_set_gpu_optim", (void *)_cffi_f_mpibind_set_gpu_optim, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 31), (void *)_cffi_d_mpibind_set_gpu_optim }, - { "mpibind_set_greedy", (void *)_cffi_f_mpibind_set_greedy, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 31), (void *)_cffi_d_mpibind_set_greedy }, - { "mpibind_set_ntasks", (void *)_cffi_f_mpibind_set_ntasks, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 31), (void *)_cffi_d_mpibind_set_ntasks }, - { "mpibind_set_nthreads", (void *)_cffi_f_mpibind_set_nthreads, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 31), (void *)_cffi_d_mpibind_set_nthreads }, - { "mpibind_set_restrict_ids", (void *)_cffi_f_mpibind_set_restrict_ids, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 23), (void *)_cffi_d_mpibind_set_restrict_ids }, - { "mpibind_set_restrict_type", (void *)_cffi_f_mpibind_set_restrict_type, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 31), (void *)_cffi_d_mpibind_set_restrict_type }, - { "mpibind_set_smt", (void *)_cffi_f_mpibind_set_smt, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 31), (void *)_cffi_d_mpibind_set_smt }, - { "mpibind_set_topology", (void *)_cffi_f_mpibind_set_topology, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 27), (void *)_cffi_d_mpibind_set_topology }, -}; - -static const struct _cffi_struct_union_s _cffi_struct_unions[] = { - { "mpibind_t", 43, _CFFI_F_OPAQUE, - (size_t)-1, -1, -1, 0 /* opaque */ }, -}; - -static const struct _cffi_enum_s _cffi_enums[] = { - { "$1", 40, _cffi_prim_int(4, 0), - "MPIBIND_RESTRICT_CPU,MPIBIND_RESTRICT_MEM,MPIBIND_GPU_AMD,MPIBIND_GPU_NVIDIA" }, -}; - -static const struct _cffi_typename_s _cffi_typenames[] = { - { "hwloc_bitmap_t", 42 }, - { "hwloc_topology_t", 29 }, - { "mpibind_t", 43 }, -}; - -static const struct _cffi_type_context_s _cffi_type_context = { - _cffi_types, - _cffi_globals, - NULL, /* no fields */ - _cffi_struct_unions, - _cffi_enums, - _cffi_typenames, - 25, /* num_globals */ - 1, /* num_struct_unions */ - 1, /* num_enums */ - 3, /* num_typenames */ - NULL, /* no includes */ - 45, /* num_types */ - 0, /* flags */ -}; - -#ifdef __GNUC__ -# pragma GCC visibility push(default) /* for -fvisibility= */ -#endif - -#ifdef PYPY_VERSION -PyMODINIT_FUNC -_cffi_pypyinit__mpibind_cffi(const void *p[]) -{ - p[0] = (const void *)0x2601; - p[1] = &_cffi_type_context; -#if PY_MAJOR_VERSION >= 3 - return NULL; -#endif -} -# ifdef _MSC_VER - PyMODINIT_FUNC -# if PY_MAJOR_VERSION >= 3 - PyInit__mpibind_cffi(void) { return NULL; } -# else - init_mpibind_cffi(void) { } -# endif -# endif -#elif PY_MAJOR_VERSION >= 3 -PyMODINIT_FUNC -PyInit__mpibind_cffi(void) -{ - return _cffi_init("cffi_build._mpibind_cffi", 0x2601, &_cffi_type_context); -} -#else -PyMODINIT_FUNC -init_mpibind_cffi(void) -{ - _cffi_init("cffi_build._mpibind_cffi", 0x2601, &_cffi_type_context); -} -#endif - -#ifdef __GNUC__ -# pragma GCC visibility pop -#endif diff --git a/python_bindings/cffi_build/mpibind_build.py b/python_bindings/cffi_build/mpibind_build.py deleted file mode 100644 index f3553a4..0000000 --- a/python_bindings/cffi_build/mpibind_build.py +++ /dev/null @@ -1,26 +0,0 @@ -from cffi import FFI -ffibuilder = FFI() -source = """ -typedef int... hwloc_topology_t; -typedef int... hwloc_bitmap_t; -""" -with open("_mpibind.h") as h: - source += h.read() - -# set_source() gives the name of the python extension module to -# produce, and some C source code as a string. This C code needs -# to make the declarated functions, types and globals available, -# so it is often just the "#include". -ffibuilder.set_source("cffi_build._mpibind_cffi", - """ - #include \"_mpibind.h\" - #include - """, - libraries=['mpibind', 'hwloc']) - - -ffibuilder.cdef(source) - -if __name__ == "__main__": - #ffibuilder.emit_c_code('test.c') - ffibuilder.compile(verbose=True) \ No newline at end of file diff --git a/python_bindings/cffi_build/test.c b/python_bindings/cffi_build/test.c deleted file mode 100644 index 9f2a1bf..0000000 --- a/python_bindings/cffi_build/test.c +++ /dev/null @@ -1,1554 +0,0 @@ -#define _CFFI_ - -/* We try to define Py_LIMITED_API before including Python.h. - - Mess: we can only define it if Py_DEBUG, Py_TRACE_REFS and - Py_REF_DEBUG are not defined. This is a best-effort approximation: - we can learn about Py_DEBUG from pyconfig.h, but it is unclear if - the same works for the other two macros. Py_DEBUG implies them, - but not the other way around. - - Issue #350 is still open: on Windows, the code here causes it to link - with PYTHON36.DLL (for example) instead of PYTHON3.DLL. A fix was - attempted in 164e526a5515 and 14ce6985e1c3, but reverted: virtualenv - does not make PYTHON3.DLL available, and so the "correctly" compiled - version would not run inside a virtualenv. We will re-apply the fix - after virtualenv has been fixed for some time. For explanation, see - issue #355. For a workaround if you want PYTHON3.DLL and don't worry - about virtualenv, see issue #350. See also 'py_limited_api' in - setuptools_ext.py. -*/ -#if !defined(_CFFI_USE_EMBEDDING) && !defined(Py_LIMITED_API) -# include -# if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG) -# define Py_LIMITED_API -# endif -#endif - -#include -#ifdef __cplusplus -extern "C" { -#endif -#include - -/* This part is from file 'cffi/parse_c_type.h'. It is copied at the - beginning of C sources generated by CFFI's ffi.set_source(). */ - -typedef void *_cffi_opcode_t; - -#define _CFFI_OP(opcode, arg) (_cffi_opcode_t)(opcode | (((uintptr_t)(arg)) << 8)) -#define _CFFI_GETOP(cffi_opcode) ((unsigned char)(uintptr_t)cffi_opcode) -#define _CFFI_GETARG(cffi_opcode) (((intptr_t)cffi_opcode) >> 8) - -#define _CFFI_OP_PRIMITIVE 1 -#define _CFFI_OP_POINTER 3 -#define _CFFI_OP_ARRAY 5 -#define _CFFI_OP_OPEN_ARRAY 7 -#define _CFFI_OP_STRUCT_UNION 9 -#define _CFFI_OP_ENUM 11 -#define _CFFI_OP_FUNCTION 13 -#define _CFFI_OP_FUNCTION_END 15 -#define _CFFI_OP_NOOP 17 -#define _CFFI_OP_BITFIELD 19 -#define _CFFI_OP_TYPENAME 21 -#define _CFFI_OP_CPYTHON_BLTN_V 23 // varargs -#define _CFFI_OP_CPYTHON_BLTN_N 25 // noargs -#define _CFFI_OP_CPYTHON_BLTN_O 27 // O (i.e. a single arg) -#define _CFFI_OP_CONSTANT 29 -#define _CFFI_OP_CONSTANT_INT 31 -#define _CFFI_OP_GLOBAL_VAR 33 -#define _CFFI_OP_DLOPEN_FUNC 35 -#define _CFFI_OP_DLOPEN_CONST 37 -#define _CFFI_OP_GLOBAL_VAR_F 39 -#define _CFFI_OP_EXTERN_PYTHON 41 - -#define _CFFI_PRIM_VOID 0 -#define _CFFI_PRIM_BOOL 1 -#define _CFFI_PRIM_CHAR 2 -#define _CFFI_PRIM_SCHAR 3 -#define _CFFI_PRIM_UCHAR 4 -#define _CFFI_PRIM_SHORT 5 -#define _CFFI_PRIM_USHORT 6 -#define _CFFI_PRIM_INT 7 -#define _CFFI_PRIM_UINT 8 -#define _CFFI_PRIM_LONG 9 -#define _CFFI_PRIM_ULONG 10 -#define _CFFI_PRIM_LONGLONG 11 -#define _CFFI_PRIM_ULONGLONG 12 -#define _CFFI_PRIM_FLOAT 13 -#define _CFFI_PRIM_DOUBLE 14 -#define _CFFI_PRIM_LONGDOUBLE 15 - -#define _CFFI_PRIM_WCHAR 16 -#define _CFFI_PRIM_INT8 17 -#define _CFFI_PRIM_UINT8 18 -#define _CFFI_PRIM_INT16 19 -#define _CFFI_PRIM_UINT16 20 -#define _CFFI_PRIM_INT32 21 -#define _CFFI_PRIM_UINT32 22 -#define _CFFI_PRIM_INT64 23 -#define _CFFI_PRIM_UINT64 24 -#define _CFFI_PRIM_INTPTR 25 -#define _CFFI_PRIM_UINTPTR 26 -#define _CFFI_PRIM_PTRDIFF 27 -#define _CFFI_PRIM_SIZE 28 -#define _CFFI_PRIM_SSIZE 29 -#define _CFFI_PRIM_INT_LEAST8 30 -#define _CFFI_PRIM_UINT_LEAST8 31 -#define _CFFI_PRIM_INT_LEAST16 32 -#define _CFFI_PRIM_UINT_LEAST16 33 -#define _CFFI_PRIM_INT_LEAST32 34 -#define _CFFI_PRIM_UINT_LEAST32 35 -#define _CFFI_PRIM_INT_LEAST64 36 -#define _CFFI_PRIM_UINT_LEAST64 37 -#define _CFFI_PRIM_INT_FAST8 38 -#define _CFFI_PRIM_UINT_FAST8 39 -#define _CFFI_PRIM_INT_FAST16 40 -#define _CFFI_PRIM_UINT_FAST16 41 -#define _CFFI_PRIM_INT_FAST32 42 -#define _CFFI_PRIM_UINT_FAST32 43 -#define _CFFI_PRIM_INT_FAST64 44 -#define _CFFI_PRIM_UINT_FAST64 45 -#define _CFFI_PRIM_INTMAX 46 -#define _CFFI_PRIM_UINTMAX 47 -#define _CFFI_PRIM_FLOATCOMPLEX 48 -#define _CFFI_PRIM_DOUBLECOMPLEX 49 -#define _CFFI_PRIM_CHAR16 50 -#define _CFFI_PRIM_CHAR32 51 - -#define _CFFI__NUM_PRIM 52 -#define _CFFI__UNKNOWN_PRIM (-1) -#define _CFFI__UNKNOWN_FLOAT_PRIM (-2) -#define _CFFI__UNKNOWN_LONG_DOUBLE (-3) - -#define _CFFI__IO_FILE_STRUCT (-1) - - -struct _cffi_global_s { - const char *name; - void *address; - _cffi_opcode_t type_op; - void *size_or_direct_fn; // OP_GLOBAL_VAR: size, or 0 if unknown - // OP_CPYTHON_BLTN_*: addr of direct function -}; - -struct _cffi_getconst_s { - unsigned long long value; - const struct _cffi_type_context_s *ctx; - int gindex; -}; - -struct _cffi_struct_union_s { - const char *name; - int type_index; // -> _cffi_types, on a OP_STRUCT_UNION - int flags; // _CFFI_F_* flags below - size_t size; - int alignment; - int first_field_index; // -> _cffi_fields array - int num_fields; -}; -#define _CFFI_F_UNION 0x01 // is a union, not a struct -#define _CFFI_F_CHECK_FIELDS 0x02 // complain if fields are not in the - // "standard layout" or if some are missing -#define _CFFI_F_PACKED 0x04 // for CHECK_FIELDS, assume a packed struct -#define _CFFI_F_EXTERNAL 0x08 // in some other ffi.include() -#define _CFFI_F_OPAQUE 0x10 // opaque - -struct _cffi_field_s { - const char *name; - size_t field_offset; - size_t field_size; - _cffi_opcode_t field_type_op; -}; - -struct _cffi_enum_s { - const char *name; - int type_index; // -> _cffi_types, on a OP_ENUM - int type_prim; // _CFFI_PRIM_xxx - const char *enumerators; // comma-delimited string -}; - -struct _cffi_typename_s { - const char *name; - int type_index; /* if opaque, points to a possibly artificial - OP_STRUCT which is itself opaque */ -}; - -struct _cffi_type_context_s { - _cffi_opcode_t *types; - const struct _cffi_global_s *globals; - const struct _cffi_field_s *fields; - const struct _cffi_struct_union_s *struct_unions; - const struct _cffi_enum_s *enums; - const struct _cffi_typename_s *typenames; - int num_globals; - int num_struct_unions; - int num_enums; - int num_typenames; - const char *const *includes; - int num_types; - int flags; /* future extension */ -}; - -struct _cffi_parse_info_s { - const struct _cffi_type_context_s *ctx; - _cffi_opcode_t *output; - unsigned int output_size; - size_t error_location; - const char *error_message; -}; - -struct _cffi_externpy_s { - const char *name; - size_t size_of_result; - void *reserved1, *reserved2; -}; - -#ifdef _CFFI_INTERNAL -static int parse_c_type(struct _cffi_parse_info_s *info, const char *input); -static int search_in_globals(const struct _cffi_type_context_s *ctx, - const char *search, size_t search_len); -static int search_in_struct_unions(const struct _cffi_type_context_s *ctx, - const char *search, size_t search_len); -#endif - -/* this block of #ifs should be kept exactly identical between - c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py - and cffi/_cffi_include.h */ -#if defined(_MSC_VER) -# include /* for alloca() */ -# if _MSC_VER < 1600 /* MSVC < 2010 */ - typedef __int8 int8_t; - typedef __int16 int16_t; - typedef __int32 int32_t; - typedef __int64 int64_t; - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; - typedef unsigned __int64 uint64_t; - typedef __int8 int_least8_t; - typedef __int16 int_least16_t; - typedef __int32 int_least32_t; - typedef __int64 int_least64_t; - typedef unsigned __int8 uint_least8_t; - typedef unsigned __int16 uint_least16_t; - typedef unsigned __int32 uint_least32_t; - typedef unsigned __int64 uint_least64_t; - typedef __int8 int_fast8_t; - typedef __int16 int_fast16_t; - typedef __int32 int_fast32_t; - typedef __int64 int_fast64_t; - typedef unsigned __int8 uint_fast8_t; - typedef unsigned __int16 uint_fast16_t; - typedef unsigned __int32 uint_fast32_t; - typedef unsigned __int64 uint_fast64_t; - typedef __int64 intmax_t; - typedef unsigned __int64 uintmax_t; -# else -# include -# endif -# if _MSC_VER < 1800 /* MSVC < 2013 */ -# ifndef __cplusplus - typedef unsigned char _Bool; -# endif -# endif -#else -# include -# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux) -# include -# endif -#endif - -#ifdef __GNUC__ -# define _CFFI_UNUSED_FN __attribute__((unused)) -#else -# define _CFFI_UNUSED_FN /* nothing */ -#endif - -#ifdef __cplusplus -# ifndef _Bool - typedef bool _Bool; /* semi-hackish: C++ has no _Bool; bool is builtin */ -# endif -#endif - -/********** CPython-specific section **********/ -#ifndef PYPY_VERSION - - -#if PY_MAJOR_VERSION >= 3 -# define PyInt_FromLong PyLong_FromLong -#endif - -#define _cffi_from_c_double PyFloat_FromDouble -#define _cffi_from_c_float PyFloat_FromDouble -#define _cffi_from_c_long PyInt_FromLong -#define _cffi_from_c_ulong PyLong_FromUnsignedLong -#define _cffi_from_c_longlong PyLong_FromLongLong -#define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong -#define _cffi_from_c__Bool PyBool_FromLong - -#define _cffi_to_c_double PyFloat_AsDouble -#define _cffi_to_c_float PyFloat_AsDouble - -#define _cffi_from_c_int(x, type) \ - (((type)-1) > 0 ? /* unsigned */ \ - (sizeof(type) < sizeof(long) ? \ - PyInt_FromLong((long)x) : \ - sizeof(type) == sizeof(long) ? \ - PyLong_FromUnsignedLong((unsigned long)x) : \ - PyLong_FromUnsignedLongLong((unsigned long long)x)) : \ - (sizeof(type) <= sizeof(long) ? \ - PyInt_FromLong((long)x) : \ - PyLong_FromLongLong((long long)x))) - -#define _cffi_to_c_int(o, type) \ - ((type)( \ - sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \ - : (type)_cffi_to_c_i8(o)) : \ - sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \ - : (type)_cffi_to_c_i16(o)) : \ - sizeof(type) == 4 ? (((type)-1) > 0 ? (type)_cffi_to_c_u32(o) \ - : (type)_cffi_to_c_i32(o)) : \ - sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \ - : (type)_cffi_to_c_i64(o)) : \ - (Py_FatalError("unsupported size for type " #type), (type)0))) - -#define _cffi_to_c_i8 \ - ((int(*)(PyObject *))_cffi_exports[1]) -#define _cffi_to_c_u8 \ - ((int(*)(PyObject *))_cffi_exports[2]) -#define _cffi_to_c_i16 \ - ((int(*)(PyObject *))_cffi_exports[3]) -#define _cffi_to_c_u16 \ - ((int(*)(PyObject *))_cffi_exports[4]) -#define _cffi_to_c_i32 \ - ((int(*)(PyObject *))_cffi_exports[5]) -#define _cffi_to_c_u32 \ - ((unsigned int(*)(PyObject *))_cffi_exports[6]) -#define _cffi_to_c_i64 \ - ((long long(*)(PyObject *))_cffi_exports[7]) -#define _cffi_to_c_u64 \ - ((unsigned long long(*)(PyObject *))_cffi_exports[8]) -#define _cffi_to_c_char \ - ((int(*)(PyObject *))_cffi_exports[9]) -#define _cffi_from_c_pointer \ - ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[10]) -#define _cffi_to_c_pointer \ - ((char *(*)(PyObject *, struct _cffi_ctypedescr *))_cffi_exports[11]) -#define _cffi_get_struct_layout \ - not used any more -#define _cffi_restore_errno \ - ((void(*)(void))_cffi_exports[13]) -#define _cffi_save_errno \ - ((void(*)(void))_cffi_exports[14]) -#define _cffi_from_c_char \ - ((PyObject *(*)(char))_cffi_exports[15]) -#define _cffi_from_c_deref \ - ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[16]) -#define _cffi_to_c \ - ((int(*)(char *, struct _cffi_ctypedescr *, PyObject *))_cffi_exports[17]) -#define _cffi_from_c_struct \ - ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[18]) -#define _cffi_to_c_wchar_t \ - ((_cffi_wchar_t(*)(PyObject *))_cffi_exports[19]) -#define _cffi_from_c_wchar_t \ - ((PyObject *(*)(_cffi_wchar_t))_cffi_exports[20]) -#define _cffi_to_c_long_double \ - ((long double(*)(PyObject *))_cffi_exports[21]) -#define _cffi_to_c__Bool \ - ((_Bool(*)(PyObject *))_cffi_exports[22]) -#define _cffi_prepare_pointer_call_argument \ - ((Py_ssize_t(*)(struct _cffi_ctypedescr *, \ - PyObject *, char **))_cffi_exports[23]) -#define _cffi_convert_array_from_object \ - ((int(*)(char *, struct _cffi_ctypedescr *, PyObject *))_cffi_exports[24]) -#define _CFFI_CPIDX 25 -#define _cffi_call_python \ - ((void(*)(struct _cffi_externpy_s *, char *))_cffi_exports[_CFFI_CPIDX]) -#define _cffi_to_c_wchar3216_t \ - ((int(*)(PyObject *))_cffi_exports[26]) -#define _cffi_from_c_wchar3216_t \ - ((PyObject *(*)(int))_cffi_exports[27]) -#define _CFFI_NUM_EXPORTS 28 - -struct _cffi_ctypedescr; - -static void *_cffi_exports[_CFFI_NUM_EXPORTS]; - -#define _cffi_type(index) ( \ - assert((((uintptr_t)_cffi_types[index]) & 1) == 0), \ - (struct _cffi_ctypedescr *)_cffi_types[index]) - -static PyObject *_cffi_init(const char *module_name, Py_ssize_t version, - const struct _cffi_type_context_s *ctx) -{ - PyObject *module, *o_arg, *new_module; - void *raw[] = { - (void *)module_name, - (void *)version, - (void *)_cffi_exports, - (void *)ctx, - }; - - module = PyImport_ImportModule("_cffi_backend"); - if (module == NULL) - goto failure; - - o_arg = PyLong_FromVoidPtr((void *)raw); - if (o_arg == NULL) - goto failure; - - new_module = PyObject_CallMethod( - module, (char *)"_init_cffi_1_0_external_module", (char *)"O", o_arg); - - Py_DECREF(o_arg); - Py_DECREF(module); - return new_module; - - failure: - Py_XDECREF(module); - return NULL; -} - - -#ifdef HAVE_WCHAR_H -typedef wchar_t _cffi_wchar_t; -#else -typedef uint16_t _cffi_wchar_t; /* same random pick as _cffi_backend.c */ -#endif - -_CFFI_UNUSED_FN static uint16_t _cffi_to_c_char16_t(PyObject *o) -{ - if (sizeof(_cffi_wchar_t) == 2) - return (uint16_t)_cffi_to_c_wchar_t(o); - else - return (uint16_t)_cffi_to_c_wchar3216_t(o); -} - -_CFFI_UNUSED_FN static PyObject *_cffi_from_c_char16_t(uint16_t x) -{ - if (sizeof(_cffi_wchar_t) == 2) - return _cffi_from_c_wchar_t((_cffi_wchar_t)x); - else - return _cffi_from_c_wchar3216_t((int)x); -} - -_CFFI_UNUSED_FN static int _cffi_to_c_char32_t(PyObject *o) -{ - if (sizeof(_cffi_wchar_t) == 4) - return (int)_cffi_to_c_wchar_t(o); - else - return (int)_cffi_to_c_wchar3216_t(o); -} - -_CFFI_UNUSED_FN static PyObject *_cffi_from_c_char32_t(int x) -{ - if (sizeof(_cffi_wchar_t) == 4) - return _cffi_from_c_wchar_t((_cffi_wchar_t)x); - else - return _cffi_from_c_wchar3216_t(x); -} - - -/********** end CPython-specific section **********/ -#else -_CFFI_UNUSED_FN -static void (*_cffi_call_python_org)(struct _cffi_externpy_s *, char *); -# define _cffi_call_python _cffi_call_python_org -#endif - - -#define _cffi_array_len(array) (sizeof(array) / sizeof((array)[0])) - -#define _cffi_prim_int(size, sign) \ - ((size) == 1 ? ((sign) ? _CFFI_PRIM_INT8 : _CFFI_PRIM_UINT8) : \ - (size) == 2 ? ((sign) ? _CFFI_PRIM_INT16 : _CFFI_PRIM_UINT16) : \ - (size) == 4 ? ((sign) ? _CFFI_PRIM_INT32 : _CFFI_PRIM_UINT32) : \ - (size) == 8 ? ((sign) ? _CFFI_PRIM_INT64 : _CFFI_PRIM_UINT64) : \ - _CFFI__UNKNOWN_PRIM) - -#define _cffi_prim_float(size) \ - ((size) == sizeof(float) ? _CFFI_PRIM_FLOAT : \ - (size) == sizeof(double) ? _CFFI_PRIM_DOUBLE : \ - (size) == sizeof(long double) ? _CFFI__UNKNOWN_LONG_DOUBLE : \ - _CFFI__UNKNOWN_FLOAT_PRIM) - -#define _cffi_check_int(got, got_nonpos, expected) \ - ((got_nonpos) == (expected <= 0) && \ - (got) == (unsigned long long)expected) - -#ifdef MS_WIN32 -# define _cffi_stdcall __stdcall -#else -# define _cffi_stdcall /* nothing */ -#endif - -#ifdef __cplusplus -} -#endif - -/************************************************************/ - - - #include "_mpibind.h" - #include - - -/************************************************************/ - -static void *_cffi_types[] = { -/* 0 */ _CFFI_OP(_CFFI_OP_FUNCTION, 38), // char * *()(mpibind_t *, char *) -/* 1 */ _CFFI_OP(_CFFI_OP_POINTER, 43), // mpibind_t * -/* 2 */ _CFFI_OP(_CFFI_OP_POINTER, 39), // char * -/* 3 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), -/* 4 */ _CFFI_OP(_CFFI_OP_FUNCTION, 38), // char * *()(mpibind_t *, int *) -/* 5 */ _CFFI_OP(_CFFI_OP_NOOP, 1), -/* 6 */ _CFFI_OP(_CFFI_OP_POINTER, 33), // int * -/* 7 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), -/* 8 */ _CFFI_OP(_CFFI_OP_FUNCTION, 41), // hwloc_bitmap_t *()(mpibind_t *) -/* 9 */ _CFFI_OP(_CFFI_OP_NOOP, 1), -/* 10 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), -/* 11 */ _CFFI_OP(_CFFI_OP_FUNCTION, 29), // hwloc_topology_t()(mpibind_t *) -/* 12 */ _CFFI_OP(_CFFI_OP_NOOP, 1), -/* 13 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), -/* 14 */ _CFFI_OP(_CFFI_OP_FUNCTION, 6), // int *()(mpibind_t *) -/* 15 */ _CFFI_OP(_CFFI_OP_NOOP, 1), -/* 16 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), -/* 17 */ _CFFI_OP(_CFFI_OP_FUNCTION, 33), // int()(mpibind_t * *) -/* 18 */ _CFFI_OP(_CFFI_OP_POINTER, 1), // mpibind_t * * -/* 19 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), -/* 20 */ _CFFI_OP(_CFFI_OP_FUNCTION, 33), // int()(mpibind_t *) -/* 21 */ _CFFI_OP(_CFFI_OP_NOOP, 1), -/* 22 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), -/* 23 */ _CFFI_OP(_CFFI_OP_FUNCTION, 33), // int()(mpibind_t *, char *) -/* 24 */ _CFFI_OP(_CFFI_OP_NOOP, 1), -/* 25 */ _CFFI_OP(_CFFI_OP_NOOP, 2), -/* 26 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), -/* 27 */ _CFFI_OP(_CFFI_OP_FUNCTION, 33), // int()(mpibind_t *, hwloc_topology_t) -/* 28 */ _CFFI_OP(_CFFI_OP_NOOP, 1), -/* 29 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, _cffi_prim_int(sizeof(hwloc_topology_t), ( - ((hwloc_topology_t)-1) | 0 /* check that hwloc_topology_t is an integer type */ - ) <= 0)), // hwloc_topology_t -/* 30 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), -/* 31 */ _CFFI_OP(_CFFI_OP_FUNCTION, 33), // int()(mpibind_t *, int) -/* 32 */ _CFFI_OP(_CFFI_OP_NOOP, 1), -/* 33 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 7), // int -/* 34 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), -/* 35 */ _CFFI_OP(_CFFI_OP_FUNCTION, 44), // void()(mpibind_t *) -/* 36 */ _CFFI_OP(_CFFI_OP_NOOP, 1), -/* 37 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), -/* 38 */ _CFFI_OP(_CFFI_OP_POINTER, 2), // char * * -/* 39 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 2), // char -/* 40 */ _CFFI_OP(_CFFI_OP_ENUM, 0), // enum $1 -/* 41 */ _CFFI_OP(_CFFI_OP_POINTER, 42), // hwloc_bitmap_t * -/* 42 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, _cffi_prim_int(sizeof(hwloc_bitmap_t), ( - ((hwloc_bitmap_t)-1) | 0 /* check that hwloc_bitmap_t is an integer type */ - ) <= 0)), // hwloc_bitmap_t -/* 43 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 0), // mpibind_t -/* 44 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 0), // void -}; - -static int _cffi_const_MPIBIND_RESTRICT_CPU(unsigned long long *o) -{ - int n = (MPIBIND_RESTRICT_CPU) <= 0; - *o = (unsigned long long)((MPIBIND_RESTRICT_CPU) | 0); /* check that MPIBIND_RESTRICT_CPU is an integer */ - return n; -} - -static int _cffi_const_MPIBIND_RESTRICT_MEM(unsigned long long *o) -{ - int n = (MPIBIND_RESTRICT_MEM) <= 0; - *o = (unsigned long long)((MPIBIND_RESTRICT_MEM) | 0); /* check that MPIBIND_RESTRICT_MEM is an integer */ - return n; -} - -static int _cffi_const_MPIBIND_GPU_AMD(unsigned long long *o) -{ - int n = (MPIBIND_GPU_AMD) <= 0; - *o = (unsigned long long)((MPIBIND_GPU_AMD) | 0); /* check that MPIBIND_GPU_AMD is an integer */ - return n; -} - -static int _cffi_const_MPIBIND_GPU_NVIDIA(unsigned long long *o) -{ - int n = (MPIBIND_GPU_NVIDIA) <= 0; - *o = (unsigned long long)((MPIBIND_GPU_NVIDIA) | 0); /* check that MPIBIND_GPU_NVIDIA is an integer */ - return n; -} - -static int _cffi_d_mpibind(mpibind_t * x0) -{ - return mpibind(x0); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind(PyObject *self, PyObject *arg0) -{ - mpibind_t * x0; - Py_ssize_t datasize; - int result; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind(x0); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind _cffi_d_mpibind -#endif - -static int _cffi_d_mpibind_finalize(mpibind_t * x0) -{ - return mpibind_finalize(x0); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_finalize(PyObject *self, PyObject *arg0) -{ - mpibind_t * x0; - Py_ssize_t datasize; - int result; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_finalize(x0); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind_finalize _cffi_d_mpibind_finalize -#endif - -static hwloc_bitmap_t * _cffi_d_mpibind_get_cpus(mpibind_t * x0) -{ - return mpibind_get_cpus(x0); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_get_cpus(PyObject *self, PyObject *arg0) -{ - mpibind_t * x0; - Py_ssize_t datasize; - hwloc_bitmap_t * result; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_get_cpus(x0); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_pointer((char *)result, _cffi_type(41)); -} -#else -# define _cffi_f_mpibind_get_cpus _cffi_d_mpibind_get_cpus -#endif - -static char * * _cffi_d_mpibind_get_env_var_names(mpibind_t * x0, int * x1) -{ - return mpibind_get_env_var_names(x0, x1); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_get_env_var_names(PyObject *self, PyObject *args) -{ - mpibind_t * x0; - int * x1; - Py_ssize_t datasize; - char * * result; - PyObject *arg0; - PyObject *arg1; - - if (!PyArg_UnpackTuple(args, "mpibind_get_env_var_names", 2, 2, &arg0, &arg1)) - return NULL; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(6), arg1, (char **)&x1); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x1 = (int *)alloca((size_t)datasize); - memset((void *)x1, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x1, _cffi_type(6), arg1) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_get_env_var_names(x0, x1); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_pointer((char *)result, _cffi_type(38)); -} -#else -# define _cffi_f_mpibind_get_env_var_names _cffi_d_mpibind_get_env_var_names -#endif - -static char * * _cffi_d_mpibind_get_env_var_values(mpibind_t * x0, char * x1) -{ - return mpibind_get_env_var_values(x0, x1); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_get_env_var_values(PyObject *self, PyObject *args) -{ - mpibind_t * x0; - char * x1; - Py_ssize_t datasize; - char * * result; - PyObject *arg0; - PyObject *arg1; - - if (!PyArg_UnpackTuple(args, "mpibind_get_env_var_values", 2, 2, &arg0, &arg1)) - return NULL; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(2), arg1, (char **)&x1); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x1 = (char *)alloca((size_t)datasize); - memset((void *)x1, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x1, _cffi_type(2), arg1) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_get_env_var_values(x0, x1); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_pointer((char *)result, _cffi_type(38)); -} -#else -# define _cffi_f_mpibind_get_env_var_values _cffi_d_mpibind_get_env_var_values -#endif - -static int _cffi_d_mpibind_get_gpu_type(mpibind_t * x0) -{ - return mpibind_get_gpu_type(x0); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_get_gpu_type(PyObject *self, PyObject *arg0) -{ - mpibind_t * x0; - Py_ssize_t datasize; - int result; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_get_gpu_type(x0); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind_get_gpu_type _cffi_d_mpibind_get_gpu_type -#endif - -static hwloc_bitmap_t * _cffi_d_mpibind_get_gpus(mpibind_t * x0) -{ - return mpibind_get_gpus(x0); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_get_gpus(PyObject *self, PyObject *arg0) -{ - mpibind_t * x0; - Py_ssize_t datasize; - hwloc_bitmap_t * result; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_get_gpus(x0); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_pointer((char *)result, _cffi_type(41)); -} -#else -# define _cffi_f_mpibind_get_gpus _cffi_d_mpibind_get_gpus -#endif - -static int * _cffi_d_mpibind_get_nthreads(mpibind_t * x0) -{ - return mpibind_get_nthreads(x0); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_get_nthreads(PyObject *self, PyObject *arg0) -{ - mpibind_t * x0; - Py_ssize_t datasize; - int * result; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_get_nthreads(x0); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_pointer((char *)result, _cffi_type(6)); -} -#else -# define _cffi_f_mpibind_get_nthreads _cffi_d_mpibind_get_nthreads -#endif - -static hwloc_topology_t _cffi_d_mpibind_get_topology(mpibind_t * x0) -{ - return mpibind_get_topology(x0); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_get_topology(PyObject *self, PyObject *arg0) -{ - mpibind_t * x0; - Py_ssize_t datasize; - hwloc_topology_t result; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_get_topology(x0); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, hwloc_topology_t); -} -#else -# define _cffi_f_mpibind_get_topology _cffi_d_mpibind_get_topology -#endif - -static int _cffi_d_mpibind_init(mpibind_t * * x0) -{ - return mpibind_init(x0); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_init(PyObject *self, PyObject *arg0) -{ - mpibind_t * * x0; - Py_ssize_t datasize; - int result; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(18), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t * *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(18), arg0) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_init(x0); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind_init _cffi_d_mpibind_init -#endif - -static void _cffi_d_mpibind_print_env_vars(mpibind_t * x0) -{ - mpibind_print_env_vars(x0); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_print_env_vars(PyObject *self, PyObject *arg0) -{ - mpibind_t * x0; - Py_ssize_t datasize; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { mpibind_print_env_vars(x0); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - Py_INCREF(Py_None); - return Py_None; -} -#else -# define _cffi_f_mpibind_print_env_vars _cffi_d_mpibind_print_env_vars -#endif - -static void _cffi_d_mpibind_print_mapping(mpibind_t * x0) -{ - mpibind_print_mapping(x0); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_print_mapping(PyObject *self, PyObject *arg0) -{ - mpibind_t * x0; - Py_ssize_t datasize; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { mpibind_print_mapping(x0); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - Py_INCREF(Py_None); - return Py_None; -} -#else -# define _cffi_f_mpibind_print_mapping _cffi_d_mpibind_print_mapping -#endif - -static int _cffi_d_mpibind_set_env_vars(mpibind_t * x0) -{ - return mpibind_set_env_vars(x0); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_set_env_vars(PyObject *self, PyObject *arg0) -{ - mpibind_t * x0; - Py_ssize_t datasize; - int result; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_set_env_vars(x0); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind_set_env_vars _cffi_d_mpibind_set_env_vars -#endif - -static int _cffi_d_mpibind_set_gpu_optim(mpibind_t * x0, int x1) -{ - return mpibind_set_gpu_optim(x0, x1); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_set_gpu_optim(PyObject *self, PyObject *args) -{ - mpibind_t * x0; - int x1; - Py_ssize_t datasize; - int result; - PyObject *arg0; - PyObject *arg1; - - if (!PyArg_UnpackTuple(args, "mpibind_set_gpu_optim", 2, 2, &arg0, &arg1)) - return NULL; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - x1 = _cffi_to_c_int(arg1, int); - if (x1 == (int)-1 && PyErr_Occurred()) - return NULL; - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_set_gpu_optim(x0, x1); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind_set_gpu_optim _cffi_d_mpibind_set_gpu_optim -#endif - -static int _cffi_d_mpibind_set_greedy(mpibind_t * x0, int x1) -{ - return mpibind_set_greedy(x0, x1); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_set_greedy(PyObject *self, PyObject *args) -{ - mpibind_t * x0; - int x1; - Py_ssize_t datasize; - int result; - PyObject *arg0; - PyObject *arg1; - - if (!PyArg_UnpackTuple(args, "mpibind_set_greedy", 2, 2, &arg0, &arg1)) - return NULL; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - x1 = _cffi_to_c_int(arg1, int); - if (x1 == (int)-1 && PyErr_Occurred()) - return NULL; - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_set_greedy(x0, x1); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind_set_greedy _cffi_d_mpibind_set_greedy -#endif - -static int _cffi_d_mpibind_set_ntasks(mpibind_t * x0, int x1) -{ - return mpibind_set_ntasks(x0, x1); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_set_ntasks(PyObject *self, PyObject *args) -{ - mpibind_t * x0; - int x1; - Py_ssize_t datasize; - int result; - PyObject *arg0; - PyObject *arg1; - - if (!PyArg_UnpackTuple(args, "mpibind_set_ntasks", 2, 2, &arg0, &arg1)) - return NULL; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - x1 = _cffi_to_c_int(arg1, int); - if (x1 == (int)-1 && PyErr_Occurred()) - return NULL; - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_set_ntasks(x0, x1); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind_set_ntasks _cffi_d_mpibind_set_ntasks -#endif - -static int _cffi_d_mpibind_set_nthreads(mpibind_t * x0, int x1) -{ - return mpibind_set_nthreads(x0, x1); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_set_nthreads(PyObject *self, PyObject *args) -{ - mpibind_t * x0; - int x1; - Py_ssize_t datasize; - int result; - PyObject *arg0; - PyObject *arg1; - - if (!PyArg_UnpackTuple(args, "mpibind_set_nthreads", 2, 2, &arg0, &arg1)) - return NULL; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - x1 = _cffi_to_c_int(arg1, int); - if (x1 == (int)-1 && PyErr_Occurred()) - return NULL; - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_set_nthreads(x0, x1); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind_set_nthreads _cffi_d_mpibind_set_nthreads -#endif - -static int _cffi_d_mpibind_set_restrict_ids(mpibind_t * x0, char * x1) -{ - return mpibind_set_restrict_ids(x0, x1); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_set_restrict_ids(PyObject *self, PyObject *args) -{ - mpibind_t * x0; - char * x1; - Py_ssize_t datasize; - int result; - PyObject *arg0; - PyObject *arg1; - - if (!PyArg_UnpackTuple(args, "mpibind_set_restrict_ids", 2, 2, &arg0, &arg1)) - return NULL; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(2), arg1, (char **)&x1); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x1 = (char *)alloca((size_t)datasize); - memset((void *)x1, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x1, _cffi_type(2), arg1) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_set_restrict_ids(x0, x1); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind_set_restrict_ids _cffi_d_mpibind_set_restrict_ids -#endif - -static int _cffi_d_mpibind_set_restrict_type(mpibind_t * x0, int x1) -{ - return mpibind_set_restrict_type(x0, x1); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_set_restrict_type(PyObject *self, PyObject *args) -{ - mpibind_t * x0; - int x1; - Py_ssize_t datasize; - int result; - PyObject *arg0; - PyObject *arg1; - - if (!PyArg_UnpackTuple(args, "mpibind_set_restrict_type", 2, 2, &arg0, &arg1)) - return NULL; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - x1 = _cffi_to_c_int(arg1, int); - if (x1 == (int)-1 && PyErr_Occurred()) - return NULL; - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_set_restrict_type(x0, x1); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind_set_restrict_type _cffi_d_mpibind_set_restrict_type -#endif - -static int _cffi_d_mpibind_set_smt(mpibind_t * x0, int x1) -{ - return mpibind_set_smt(x0, x1); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_set_smt(PyObject *self, PyObject *args) -{ - mpibind_t * x0; - int x1; - Py_ssize_t datasize; - int result; - PyObject *arg0; - PyObject *arg1; - - if (!PyArg_UnpackTuple(args, "mpibind_set_smt", 2, 2, &arg0, &arg1)) - return NULL; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - x1 = _cffi_to_c_int(arg1, int); - if (x1 == (int)-1 && PyErr_Occurred()) - return NULL; - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_set_smt(x0, x1); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind_set_smt _cffi_d_mpibind_set_smt -#endif - -static int _cffi_d_mpibind_set_topology(mpibind_t * x0, hwloc_topology_t x1) -{ - return mpibind_set_topology(x0, x1); -} -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_mpibind_set_topology(PyObject *self, PyObject *args) -{ - mpibind_t * x0; - hwloc_topology_t x1; - Py_ssize_t datasize; - int result; - PyObject *arg0; - PyObject *arg1; - - if (!PyArg_UnpackTuple(args, "mpibind_set_topology", 2, 2, &arg0, &arg1)) - return NULL; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_type(1), arg0, (char **)&x0); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x0 = (mpibind_t *)alloca((size_t)datasize); - memset((void *)x0, 0, (size_t)datasize); - if (_cffi_convert_array_from_object((char *)x0, _cffi_type(1), arg0) < 0) - return NULL; - } - - x1 = _cffi_to_c_int(arg1, hwloc_topology_t); - if (x1 == (hwloc_topology_t)-1 && PyErr_Occurred()) - return NULL; - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = mpibind_set_topology(x0, x1); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - (void)self; /* unused */ - return _cffi_from_c_int(result, int); -} -#else -# define _cffi_f_mpibind_set_topology _cffi_d_mpibind_set_topology -#endif - -static const struct _cffi_global_s _cffi_globals[] = { - { "MPIBIND_GPU_AMD", (void *)_cffi_const_MPIBIND_GPU_AMD, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, - { "MPIBIND_GPU_NVIDIA", (void *)_cffi_const_MPIBIND_GPU_NVIDIA, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, - { "MPIBIND_RESTRICT_CPU", (void *)_cffi_const_MPIBIND_RESTRICT_CPU, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, - { "MPIBIND_RESTRICT_MEM", (void *)_cffi_const_MPIBIND_RESTRICT_MEM, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, - { "mpibind", (void *)_cffi_f_mpibind, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 20), (void *)_cffi_d_mpibind }, - { "mpibind_finalize", (void *)_cffi_f_mpibind_finalize, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 20), (void *)_cffi_d_mpibind_finalize }, - { "mpibind_get_cpus", (void *)_cffi_f_mpibind_get_cpus, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 8), (void *)_cffi_d_mpibind_get_cpus }, - { "mpibind_get_env_var_names", (void *)_cffi_f_mpibind_get_env_var_names, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 4), (void *)_cffi_d_mpibind_get_env_var_names }, - { "mpibind_get_env_var_values", (void *)_cffi_f_mpibind_get_env_var_values, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 0), (void *)_cffi_d_mpibind_get_env_var_values }, - { "mpibind_get_gpu_type", (void *)_cffi_f_mpibind_get_gpu_type, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 20), (void *)_cffi_d_mpibind_get_gpu_type }, - { "mpibind_get_gpus", (void *)_cffi_f_mpibind_get_gpus, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 8), (void *)_cffi_d_mpibind_get_gpus }, - { "mpibind_get_nthreads", (void *)_cffi_f_mpibind_get_nthreads, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 14), (void *)_cffi_d_mpibind_get_nthreads }, - { "mpibind_get_topology", (void *)_cffi_f_mpibind_get_topology, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 11), (void *)_cffi_d_mpibind_get_topology }, - { "mpibind_init", (void *)_cffi_f_mpibind_init, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 17), (void *)_cffi_d_mpibind_init }, - { "mpibind_print_env_vars", (void *)_cffi_f_mpibind_print_env_vars, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 35), (void *)_cffi_d_mpibind_print_env_vars }, - { "mpibind_print_mapping", (void *)_cffi_f_mpibind_print_mapping, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 35), (void *)_cffi_d_mpibind_print_mapping }, - { "mpibind_set_env_vars", (void *)_cffi_f_mpibind_set_env_vars, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 20), (void *)_cffi_d_mpibind_set_env_vars }, - { "mpibind_set_gpu_optim", (void *)_cffi_f_mpibind_set_gpu_optim, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 31), (void *)_cffi_d_mpibind_set_gpu_optim }, - { "mpibind_set_greedy", (void *)_cffi_f_mpibind_set_greedy, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 31), (void *)_cffi_d_mpibind_set_greedy }, - { "mpibind_set_ntasks", (void *)_cffi_f_mpibind_set_ntasks, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 31), (void *)_cffi_d_mpibind_set_ntasks }, - { "mpibind_set_nthreads", (void *)_cffi_f_mpibind_set_nthreads, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 31), (void *)_cffi_d_mpibind_set_nthreads }, - { "mpibind_set_restrict_ids", (void *)_cffi_f_mpibind_set_restrict_ids, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 23), (void *)_cffi_d_mpibind_set_restrict_ids }, - { "mpibind_set_restrict_type", (void *)_cffi_f_mpibind_set_restrict_type, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 31), (void *)_cffi_d_mpibind_set_restrict_type }, - { "mpibind_set_smt", (void *)_cffi_f_mpibind_set_smt, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 31), (void *)_cffi_d_mpibind_set_smt }, - { "mpibind_set_topology", (void *)_cffi_f_mpibind_set_topology, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 27), (void *)_cffi_d_mpibind_set_topology }, -}; - -static const struct _cffi_struct_union_s _cffi_struct_unions[] = { - { "mpibind_t", 43, _CFFI_F_OPAQUE, - (size_t)-1, -1, -1, 0 /* opaque */ }, -}; - -static const struct _cffi_enum_s _cffi_enums[] = { - { "$1", 40, _cffi_prim_int(4, 0), - "MPIBIND_RESTRICT_CPU,MPIBIND_RESTRICT_MEM,MPIBIND_GPU_AMD,MPIBIND_GPU_NVIDIA" }, -}; - -static const struct _cffi_typename_s _cffi_typenames[] = { - { "hwloc_bitmap_t", 42 }, - { "hwloc_topology_t", 29 }, - { "mpibind_t", 43 }, -}; - -static const struct _cffi_type_context_s _cffi_type_context = { - _cffi_types, - _cffi_globals, - NULL, /* no fields */ - _cffi_struct_unions, - _cffi_enums, - _cffi_typenames, - 25, /* num_globals */ - 1, /* num_struct_unions */ - 1, /* num_enums */ - 3, /* num_typenames */ - NULL, /* no includes */ - 45, /* num_types */ - 0, /* flags */ -}; - -#ifdef __GNUC__ -# pragma GCC visibility push(default) /* for -fvisibility= */ -#endif - -#ifdef PYPY_VERSION -PyMODINIT_FUNC -_cffi_pypyinit__mpibind_cffi(const void *p[]) -{ - p[0] = (const void *)0x2601; - p[1] = &_cffi_type_context; -#if PY_MAJOR_VERSION >= 3 - return NULL; -#endif -} -# ifdef _MSC_VER - PyMODINIT_FUNC -# if PY_MAJOR_VERSION >= 3 - PyInit__mpibind_cffi(void) { return NULL; } -# else - init_mpibind_cffi(void) { } -# endif -# endif -#elif PY_MAJOR_VERSION >= 3 -PyMODINIT_FUNC -PyInit__mpibind_cffi(void) -{ - return _cffi_init("cffi_build._mpibind_cffi", 0x2601, &_cffi_type_context); -} -#else -PyMODINIT_FUNC -init_mpibind_cffi(void) -{ - _cffi_init("cffi_build._mpibind_cffi", 0x2601, &_cffi_type_context); -} -#endif - -#ifdef __GNUC__ -# pragma GCC visibility pop -#endif diff --git a/python_bindings/mpibind/__init__.py b/python_bindings/mpibind/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/python_bindings/mpibind/mpibind.py b/python_bindings/mpibind/mpibind.py deleted file mode 100644 index 0824e29..0000000 --- a/python_bindings/mpibind/mpibind.py +++ /dev/null @@ -1,13 +0,0 @@ -from cffi import FFI - -def abi_inline(): - ffi = FFI() - ffi.cdef(""" - struct mpibind_t; - typedef struct mpibind_t mpibind_t; - int mpibind_init(mpibind_t **handle); - """) - C = ffi.dlopen("mpibind") - -if __name__ == "__main__": - abi_inline() \ No newline at end of file diff --git a/src/mpibind.c b/src/mpibind.c index 881adec..3c2fd5a 100644 --- a/src/mpibind.c +++ b/src/mpibind.c @@ -1502,6 +1502,25 @@ void mpibind_print_mapping(mpibind_t *handle) } } +/* + * Print the mapping for each task. + */ +char ** mpibind_get_mapping(mpibind_t *handle) +{ + REALLY_LONG_STR_SIZE = 2 * LONG_STR_SIZE + 1 + char assignment_strings[handle->ntasks][REALLY_LONG_STR_SIZE]; + char str1[LONG_STR_SIZE], str2[LONG_STR_SIZE]; + + int i; + for (i=0; intasks; i++) { + hwloc_bitmap_list_snprintf(str1, sizeof(str1), handle->cpus[i]); + hwloc_bitmap_list_snprintf(str2, sizeof(str2), handle->gpus[i]); + snprintf(assignment_strings[i], REALLY_LONG_STR_SIZE, + "mpibind: task %2d thds %2d gpus %3s cpus %s\n", + i, handle->nthreads[i], str2, str1); + } + return assignment_strings +} /* * Environment variables that need to be exported by the runtime. diff --git a/src/mpibind.h b/src/mpibind.h index 85ede8c..6cdf62e 100644 --- a/src/mpibind.h +++ b/src/mpibind.h @@ -160,6 +160,10 @@ extern "C" { * Print the mapping for each task. */ void mpibind_print_mapping(mpibind_t *handle); + /* + * Get the mapping for each task + */ + char ** mpibind_get_mapping(mpibind_t *handle); /* * Environment variables that need to be exported by the runtime. * CUDA_VISIBLE_DEVICES --comma separated From 54d49735d139fba8e62ec5aa648753a84ff5cd73 Mon Sep 17 00:00:00 2001 From: Samuel Furman Date: Tue, 11 Aug 2020 07:12:25 -0700 Subject: [PATCH 4/9] rebase check point --- bindings/python/Makefile.am | 16 + bindings/python/_mpibind/build.py | 10 +- bindings/python/_mpibind/make_clean_header.py | 2 - bindings/python/mpibind/Makefile.am | 2 +- bindings/python/mpibind/jobspec.py | 145 ----- bindings/python/mpibind/mpibind_wrapper.py | 9 - bindings/python/mpibind/wrapper.py | 533 +++++------------- bindings/python/setup.py | 9 +- {bindings/python/mpibind => cmd}/example.py | 23 +- cmd/flux-mpibind.py | 324 +++++++++++ config/am_check_pymod.m4 | 2 + src/mpibind.c | 20 +- src/mpibind.h | 2 +- 13 files changed, 535 insertions(+), 562 deletions(-) delete mode 100644 bindings/python/mpibind/jobspec.py delete mode 100644 bindings/python/mpibind/mpibind_wrapper.py rename {bindings/python/mpibind => cmd}/example.py (74%) create mode 100644 cmd/flux-mpibind.py diff --git a/bindings/python/Makefile.am b/bindings/python/Makefile.am index f931447..68b3ad3 100644 --- a/bindings/python/Makefile.am +++ b/bindings/python/Makefile.am @@ -1 +1,17 @@ +.NOTPARALLEL: + SUBDIRS= _mpibind mpibind + +installable: + $(PYTHON) $(srcdir)/setup.py \ + sdist \ + bdist_wheel + +install-exec-local: + (cd $(srcdir); $(PYTHON) setup.py sdist bdist_wheel --verbose) + +clean-local: + -rm -f *.pyc *.pyo + -rm -rf __pycache__ + -rm -rf mpibind.egg-info + -rm -rf build \ No newline at end of file diff --git a/bindings/python/_mpibind/build.py b/bindings/python/_mpibind/build.py index 575fdb2..9a94ac1 100644 --- a/bindings/python/_mpibind/build.py +++ b/bindings/python/_mpibind/build.py @@ -1,4 +1,5 @@ from cffi import FFI +from os import path ffi = FFI() @@ -8,7 +9,11 @@ typedef struct { ...; } hwloc_bitmap_t; """ -with open("_mpibind_preproc.h") as h: +prepared_headers = "_mpibind_preproc.h" +if not path.exists(prepared_headers): + prepared_headers = "_mpibind/_mpibind_preproc.h" + +with open(prepared_headers) as h: cdefs = cdefs + h.read() ffi.cdef(cdefs) @@ -19,9 +24,8 @@ """ #include #include -#include """, - libraries=["mpibind", "hwloc"], + libraries=["mpibind"], ) diff --git a/bindings/python/_mpibind/make_clean_header.py b/bindings/python/_mpibind/make_clean_header.py index 1db79c1..153b831 100755 --- a/bindings/python/_mpibind/make_clean_header.py +++ b/bindings/python/_mpibind/make_clean_header.py @@ -79,8 +79,6 @@ def process_header(f, including_path="."): l = l.replace('__inline__', 'inline') l = l.replace('INT_MAX', str(platform_c_maxint)) l = re.sub('(\d)(UL)?<<(\d)',lambda x: str(int(x.group(1))<ntasks][REALLY_LONG_STR_SIZE]; char str1[LONG_STR_SIZE], str2[LONG_STR_SIZE]; int i; + int written; for (i=0; intasks; i++) { + int to_write = buffer_size - strlen(mapping_buffer); hwloc_bitmap_list_snprintf(str1, sizeof(str1), handle->cpus[i]); hwloc_bitmap_list_snprintf(str2, sizeof(str2), handle->gpus[i]); - snprintf(assignment_strings[i], REALLY_LONG_STR_SIZE, - "mpibind: task %2d thds %2d gpus %3s cpus %s\n", - i, handle->nthreads[i], str2, str1); + written = snprintf(mapping_buffer + strlen(mapping_buffer), + to_write, + "mpibind: task %2d thds %2d gpus %3s cpus %s\n", + i, handle->nthreads[i], str2, str1); + + if (written < 0 || written > to_write){ + return -1; + } } - return assignment_strings + + return 0; } /* diff --git a/src/mpibind.h b/src/mpibind.h index 6cdf62e..92016c3 100644 --- a/src/mpibind.h +++ b/src/mpibind.h @@ -163,7 +163,7 @@ extern "C" { /* * Get the mapping for each task */ - char ** mpibind_get_mapping(mpibind_t *handle); + int mpibind_get_mapping_string(mpibind_t *handle, char *mapping_buffer, size_t buffer_size); /* * Environment variables that need to be exported by the runtime. * CUDA_VISIBLE_DEVICES --comma separated From 8ac737239a130c6f783a3604bcb9e948e4a0b840 Mon Sep 17 00:00:00 2001 From: Samuel Furman Date: Tue, 11 Aug 2020 07:46:53 -0700 Subject: [PATCH 5/9] remove autogen now that we have bootstrap --- autogen.sh | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100755 autogen.sh diff --git a/autogen.sh b/autogen.sh deleted file mode 100755 index 15729eb..0000000 --- a/autogen.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh -# -# Run an extra libtoolize before autoreconf to ensure that -# libtool macros can be found if libtool is in PATH, but its -# macros are not in default aclocal search path. -# -echo "Running libtoolize --automake --copy ... " -libtoolize --automake --copy || exit -echo "Running autoreconf --verbose --install" -autoreconf --verbose --install || exit -echo "Now run ./configure." From 0aae1080b83c8cfc36d87181d2f858f6670d1124 Mon Sep 17 00:00:00 2001 From: Samuel Furman Date: Wed, 12 Aug 2020 20:50:34 -0700 Subject: [PATCH 6/9] distribution and header script checkpoint --- bindings/README.md | 17 ++ bindings/python/Makefile.am | 16 +- bindings/python/README.md | 25 +++ bindings/python/_mpibind/Makefile.am | 35 ++-- bindings/python/_mpibind/build.py | 25 +-- bindings/python/_mpibind/clean_header.py | 56 ++++++ bindings/python/_mpibind/make_clean_header.py | 106 ------------ bindings/python/mpibind/wrapper.py | 131 +++++++------- bindings/python/setup.py | 11 +- config/am_check_pymod.m4 | 2 +- config/ax_python_devel.m4 | 1 + config/tap-driver.py | 26 +++ config/test-driver | 127 ++++++++++++++ configure.ac | 50 +----- test-suite/Makefile.am | 21 ++- test-suite/python/.gitignore | 4 + test-suite/python/COPYING | 18 ++ test-suite/python/pycotap/__init__.py | 161 ++++++++++++++++++ test-suite/python/wrapper.py | 13 ++ 19 files changed, 585 insertions(+), 260 deletions(-) create mode 100644 bindings/README.md create mode 100644 bindings/python/README.md create mode 100644 bindings/python/_mpibind/clean_header.py delete mode 100755 bindings/python/_mpibind/make_clean_header.py create mode 100644 config/tap-driver.py create mode 100755 config/test-driver create mode 100644 test-suite/python/.gitignore create mode 100644 test-suite/python/COPYING create mode 100644 test-suite/python/pycotap/__init__.py create mode 100644 test-suite/python/wrapper.py diff --git a/bindings/README.md b/bindings/README.md new file mode 100644 index 0000000..af0ac19 --- /dev/null +++ b/bindings/README.md @@ -0,0 +1,17 @@ +## Bindings for mpibind + +### Overview + +In order to improve its usability, we offer bindings for the mpibind library in +languagues beyond C. Currently the only other language supported is Python. + +### License + +*mpibind* is distributed under the terms of the MIT license. All new +contributions must be made under this license. + +See [LICENSE](LICENSE) and [NOTICE](NOTICE) for details. + +SPDX-License-Identifier: MIT. + +LLNL-CODE-812647. diff --git a/bindings/python/Makefile.am b/bindings/python/Makefile.am index 68b3ad3..0214539 100644 --- a/bindings/python/Makefile.am +++ b/bindings/python/Makefile.am @@ -2,16 +2,18 @@ SUBDIRS= _mpibind mpibind -installable: - $(PYTHON) $(srcdir)/setup.py \ - sdist \ - bdist_wheel +AM_CPPFLAGS = \ + -Wall -Werror -Wno-missing-field-initializers \ + -I$(top_srcdir) -I$(top_srcdir)/src/ -L$(top_srcdir)/src/.libs \ + $(PYTHON_CPPFLAGS) -install-exec-local: - (cd $(srcdir); $(PYTHON) setup.py sdist bdist_wheel --verbose) +all-local: + (cd $(srcdir); CFLAGS="$(AM_CPPFLAGS)" \ + $(PYTHON) setup.py bdist_wheel) clean-local: -rm -f *.pyc *.pyo -rm -rf __pycache__ -rm -rf mpibind.egg-info - -rm -rf build \ No newline at end of file + -rm -rf build + -rm -rf dist \ No newline at end of file diff --git a/bindings/python/README.md b/bindings/python/README.md new file mode 100644 index 0000000..afd9b45 --- /dev/null +++ b/bindings/python/README.md @@ -0,0 +1,25 @@ +## Python Bindings for mpibind + +### Overview + +You can interact with mpibind through your python scripts: + +```python +# running on syrah login node +from mpibind import MpibindWrapper +wrapper = MpibindWrapper() +mapping = wrapper.get_mapping(ntasks=4) +``` + +### Installing + +### License + +*mpibind* is distributed under the terms of the MIT license. All new +contributions must be made under this license. + +See [LICENSE](LICENSE) and [NOTICE](NOTICE) for details. + +SPDX-License-Identifier: MIT. + +LLNL-CODE-812647. diff --git a/bindings/python/_mpibind/Makefile.am b/bindings/python/_mpibind/Makefile.am index 8855592..e5aa898 100644 --- a/bindings/python/_mpibind/Makefile.am +++ b/bindings/python/_mpibind/Makefile.am @@ -1,3 +1,5 @@ + + AM_CPPFLAGS = \ -Wall -Werror -Wno-missing-field-initializers \ -I$(top_srcdir) -I$(top_srcdir)/src/ \ @@ -8,38 +10,38 @@ AM_LDFLAGS = \ PREPROC_FLAGS=-E '-D__attribute__(...)=' -_mpibind.c: $(srcdir)/build.py _mpibind_preproc.h +_pympibind.c: $(srcdir)/build.py _mpibind_preproc.h $(PYTHON) $^ _mpibind_clean.h: Makefile - $(PYTHON) $(srcdir)/make_clean_header.py \ - --path $(top_srcdir) \ - --search $(top_builddir)/src/ \ - --search $(HWLOC_INCLUDEDIR) \ - --additional_headers \ - src/mpibind-priv.h \ - --output _mpibind_clean.h \ - src/mpibind.h + $(PYTHON) $(srcdir)/clean_header.py \ + $(top_builddir)/src/mpibind.h \ + _mpibind_clean.h + +# _mpibind_clean.h: Makefile +# $(PYTHON) $(srcdir)/make_clean_header.py \ +# --path $(top_srcdir) \ +# --search $(top_builddir)/src/ \ +# --output _mpibind_clean.h \ +# src/mpibind.h -#$(HWLOC_INCLUDEDIR)/hwloc.h - _mpibind_preproc.h: _mpibind_clean.h $(CC) $(PREPROC_FLAGS) _mpibind_clean.h\ | sed -e '/^# [0-9]*.*/d' > $@ -BUILT_SOURCES= _mpibind.c _mpibind_preproc.h -mpibindpyso_LTLIBRARIES = _mpibind.la +BUILT_SOURCES= _pympibind.c _mpibind_preproc.h +mpibindpyso_LTLIBRARIES = _pympibind.la mpibindpyso_PYTHON = __init__.py nodist_mpibindbindinginclude_HEADERS = _mpibind_preproc.h -nodist__mpibind_la_SOURCES = _mpibind.c +nodist__pympibind_la_SOURCES = _pympibind.c common_libs = $(top_builddir)/src/libmpibind.la \ - $(PYTHON_LDFLAGS) \ + $(PYTHON_LDFLAGS) \ $(HWLOC_LIBS) -_mpibind_la_LIBADD = $(common_libs) +_pympibind_la_LIBADD = $(common_libs) EXTRA_DIST=build.py make_clean_header.py @@ -58,3 +60,4 @@ all-local: lib-copy-vpath clean-local: -rm -f *.c *.so *.pyc *.pyo *_clean.h *_preproc.h -rm -rf __pycache__ + -rm -rf .libs \ No newline at end of file diff --git a/bindings/python/_mpibind/build.py b/bindings/python/_mpibind/build.py index 9a94ac1..173d3ac 100644 --- a/bindings/python/_mpibind/build.py +++ b/bindings/python/_mpibind/build.py @@ -1,33 +1,36 @@ from cffi import FFI from os import path -ffi = FFI() +ffibuilder = FFI() +# add some of the opaque hwloc objects cdefs = """ -struct hwloc_topology; -typedef struct hwloc_topology * hwloc_topology_t; +typedef struct { ...; } hwloc_topology_t; typedef struct { ...; } hwloc_bitmap_t; """ +# this file is used from two different places during build +# and then during distribution prepared_headers = "_mpibind_preproc.h" if not path.exists(prepared_headers): prepared_headers = "_mpibind/_mpibind_preproc.h" +# add cleaned header file to the definitions we expose to python with open(prepared_headers) as h: cdefs = cdefs + h.read() -ffi.cdef(cdefs) +# set the defintions we expose to python +ffibuilder.cdef(cdefs) - -ffi.set_source( - "_mpibind._mpibind", +# indicate that the library makes the definitions we set +ffibuilder.set_source( + "_mpibind._pympibind", """ -#include -#include + #include """, libraries=["mpibind"], ) - +#emit c code and let autotools build _pympibind.so extension module if __name__ == "__main__": - ffi.emit_c_code("_mpibind.c") \ No newline at end of file + ffibuilder.emit_c_code("_pympibind.c") \ No newline at end of file diff --git a/bindings/python/_mpibind/clean_header.py b/bindings/python/_mpibind/clean_header.py new file mode 100644 index 0000000..7194b76 --- /dev/null +++ b/bindings/python/_mpibind/clean_header.py @@ -0,0 +1,56 @@ +import os +import re +import struct + +import argparse + +platform_c_maxint = 2 ** (struct.Struct('i').size * 8 - 1) - 1 + +def parse_arguments(): + parser = argparse.ArgumentParser() + + parser.add_argument("header", help="header file to parse", type=str) + parser.add_argument("output", help="destination of clean header", type=str) + + return parser.parse_args() + +def apply_replacement_rules(line): + rules = { + "__restrict": "restrict", + "__inline__": "inline", + "INT_MAX": str(platform_c_maxint), + } + + for k,v in rules.items(): + line = line.replace(k, v) + + if ("inline" in line): + print(line) + return line + +def make_enum_literal(line): + return re.sub(r'(\d)(UL)?<<(\d)',lambda x: str(int(x.group(1))<', '', line) + +def clean_header(header): + cleaned = "" + with open(header, "r") as f: + for line in f.readlines(): + line = apply_replacement_rules(line) + line = make_enum_literal(line) + line = remove_external_headers(line) + cleaned += line + + return cleaned + +def output_header(output_file, cleaned): + with open(output_file, "w") as f: + f.write(cleaned) + +if __name__ == "__main__": + args = parse_arguments() + abs_header = os.path.abspath(args.header) + abs_output = os.path.abspath(args.output) + output_header(abs_output, clean_header(abs_header)) \ No newline at end of file diff --git a/bindings/python/_mpibind/make_clean_header.py b/bindings/python/_mpibind/make_clean_header.py deleted file mode 100755 index 153b831..0000000 --- a/bindings/python/_mpibind/make_clean_header.py +++ /dev/null @@ -1,106 +0,0 @@ -#TODO CREDIT FLUX TEAM - -############################################################### -# Copyright 2014 Lawrence Livermore National Security, LLC -# (c.f. AUTHORS, NOTICE.LLNS, COPYING) -# -# This file is part of the Flux resource manager framework. -# For details, see https://github.com/flux-framework. -# -# SPDX-License-Identifier: LGPL-3.0 -############################################################### - -from __future__ import print_function -import os -import re -import struct - -import argparse - -platform_c_maxint = 2 ** (struct.Struct('i').size * 8 - 1) - 1 - -def left_shift(base, shift): - return base << shift - - -parser = argparse.ArgumentParser() - -parser.add_argument("header", help="C header file to parse", type=str) -parser.add_argument("--include_header", help="Include base path", type=str, default="") -parser.add_argument( - "--additional_headers", help="Additional headers to parse", nargs="*", default=[] -) -parser.add_argument("--output", help="Output path", default=".") -parser.add_argument("--path", help="Include base path", default=".") -parser.add_argument( - "--search", help="append to header search path", action="append", default=[] -) -parser.add_argument( - "--ignore_header", - help="Pattern to ignore when searching header files", - default=[], - action="append", -) - -args = parser.parse_args() - -absolute_head = os.path.abspath(os.path.join(args.path, args.header)) - -# Prepend 'path' option to search list: -args.search.insert(0, args.path) -args.search = [os.path.abspath(f) for f in args.search] - -def find_first(path, name, extra=None): - for dirname in path: - filename = os.path.join(dirname, name) - if os.path.isfile(filename): - return filename - if extra is not None: - filename = os.path.join(extra, name) - if os.path.isfile(filename): - return filename - raise IOError(name) - - -mega_header="" -def process_header(f, including_path="."): - global mega_header - if not os.path.isfile(f): - f = os.path.join(including_path, f) - f = os.path.abspath(f) - if f not in checked_heads: - for p in args.ignore_header: - if re.search(p, f): - checked_heads[f] = 1 - return - with open(f, "r") as header: - for l in header.readlines(): - l = l.replace('__restrict', 'restrict') - l = l.replace('__inline__', 'inline') - l = l.replace('INT_MAX', str(platform_c_maxint)) - l = re.sub('(\d)(UL)?<<(\d)',lambda x: str(int(x.group(1))<. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +# Make unconditional expansion of undefined variables an error. This +# helps a lot in preventing typo-related bugs. +set -u + +usage_error () +{ + echo "$0: $*" >&2 + print_usage >&2 + exit 2 +} + +print_usage () +{ + cat <$log_file 2>&1 +estatus=$? +if test $enable_hard_errors = no && test $estatus -eq 99; then + estatus=1 +fi + +case $estatus:$expect_failure in + 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; + 0:*) col=$grn res=PASS recheck=no gcopy=no;; + 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; + 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; + *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; + *:*) col=$red res=FAIL recheck=yes gcopy=yes;; +esac + +# Report outcome to console. +echo "${col}${res}${std}: $test_name" + +# Register the test result, and other relevant metadata. +echo ":test-result: $res" > $trs_file +echo ":global-test-result: $res" >> $trs_file +echo ":recheck: $recheck" >> $trs_file +echo ":copy-in-global-log: $gcopy" >> $trs_file + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/configure.ac b/configure.ac index 012b6b9..954066c 100644 --- a/configure.ac +++ b/configure.ac @@ -92,40 +92,11 @@ if test -n "$PYTHON_LDFLAGS"; then fi AM_CHECK_PYMOD(cffi, - [cffi.__version_info__ >= (1,10)], + [StrictVersion(cffi.__version__) >= StrictVersion('1.1.0')], , [AC_MSG_ERROR([could not find python module cffi, version 1.1+ required])] ) -AM_CHECK_PYMOD(six, - [StrictVersion(six.__version__) >= StrictVersion('1.9.0')], - , - [AC_MSG_ERROR([could not find python module six, version 1.9.0+ required])] - ) -AM_CHECK_PYMOD(yaml, - [StrictVersion(yaml.__version__) >= StrictVersion ('3.10.0')], - , - [AC_MSG_ERROR([could not find python module yaml, version 3.10+ required])] - ) -AM_CHECK_PYMOD(jsonschema, - [StrictVersion(jsonschema.__version__) >= StrictVersion ('2.3.0')], - , - [AC_MSG_ERROR([could not find python module jsonschema, version 2.3.0+ required])] - ) -# Remove -L from PYTHON_LDFLAGS if it is in a standard path -# (e.g. /usr/lib64). Placing a standard path earlier in the linker -# search can lead to linking problems. -# -# Logic below assumes only newer Python versions, protected by -# above check for atleast Python 3.6. -if test "$ac_python_ldflags_set_by_user" != "true"; then - AC_CHECK_LIB([$ac_python_library], [PyArg_ParseTuple], - [ac_python_in_ld_path=true]) - if test "$ac_python_in_ld_path" = "true"; then - AC_MSG_NOTICE([Removing -L$ac_python_libdir from PYTHON_LDFLAGS]) - PYTHON_LDFLAGS="-l$ac_python_library" - fi -fi AS_VAR_SET(mpibindpydir, $pyexecdir/mpibind) AC_SUBST(mpibindpydir) AS_VAR_SET(mpibindpysodir, $pyexecdir/_mpibind) @@ -140,26 +111,9 @@ AC_SUBST(mpibindpylinkdir) AS_VAR_SET(mpibindbindingincludedir, $includedir/mpibind/_binding) AC_SUBST(mpibindbindingincludedir) -AC_DEFINE_UNQUOTED([PYTHON_INTERPRETER], ["$PYTHON"], [The python interpreter mpibind is configured with]) AC_SUBST(PYTHON) -AC_ARG_ENABLE([pylint], - [AS_HELP_STRING([--enable-pylint], - [Enable pylint checks of python bindings])],, - [enable_pylint="no"] -) -AS_IF([test "x$enable_pylint" = "xyes"], [ - AC_CHECK_PROG(PYLINT,[pylint],[pylint]) - AS_IF([test "x$PYLINT" != "xpylint"], [AC_MSG_ERROR([No pylint found in PATH])]) - AM_CHECK_PYMOD(pylint, - [StrictVersion(pylint.__version__) >= StrictVersion('1.8.4')], - , - [AC_MSG_ERROR([could not find python module pylint, version 1.8.4+ required])] - ) -]) -AM_CONDITIONAL([ENABLE_PYLINT], [test "x$PYLINT" = "xpylint"]) - - +################ end Python Configuration ################ # checks for Modules diff --git a/test-suite/Makefile.am b/test-suite/Makefile.am index 9f39f97..029e2b1 100644 --- a/test-suite/Makefile.am +++ b/test-suite/Makefile.am @@ -24,4 +24,23 @@ environment_t_SOURCES = environment.c test_utils.c test_utils.h if HAVE_LIBTAP check_PROGRAMS = $(TESTS) -endif \ No newline at end of file +endif +TEST_EXTENSIONS = .t .py +PY_LOG_DRIVER = $(PYTHON) $(top_srcdir)/config/tap-driver.py + +PYSCRIPTS = \ + python/wrapper.py + +TESTS = \ + $(PYSCRIPTS) + +#if HAVE_LIBTAP +#check_PROGRAMS = $(TESTS) +#endif + +AM_TESTS_ENVIRONMENT = \ + export PYTHONPATH="$(abs_top_builddir)/bindings/python:$(abs_top_builddir)/test-suite/python::$$PYTHONPATH";\ + export PYTHON="${PYTHON}"; + +clean-local: + rm -rf trash-directory.* test-results .prove *.broker.log */*.broker.log *.output python/__pycache__ diff --git a/test-suite/python/.gitignore b/test-suite/python/.gitignore new file mode 100644 index 0000000..0e4cbba --- /dev/null +++ b/test-suite/python/.gitignore @@ -0,0 +1,4 @@ +*.pyc +/build +/dist +/*.egg-info diff --git a/test-suite/python/COPYING b/test-suite/python/COPYING new file mode 100644 index 0000000..1b24840 --- /dev/null +++ b/test-suite/python/COPYING @@ -0,0 +1,18 @@ +Copyright (c) 2015 Remko Tronçon (https://el-tramo.be) + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/test-suite/python/pycotap/__init__.py b/test-suite/python/pycotap/__init__.py new file mode 100644 index 0000000..ca41dba --- /dev/null +++ b/test-suite/python/pycotap/__init__.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python +# coding=utf-8 + +# Copyright (c) 2015 Remko Tronçon (https://el-tramo.be) +# Released under the MIT license +# See COPYING for details + + +import unittest +import sys +import base64 + +if sys.hexversion >= 0x03000000: + from io import StringIO +else: + from StringIO import StringIO + +# Log modes +class LogMode(object): + LogToError, LogToDiagnostics, LogToYAML, LogToAttachment = range(4) + + +class TAPTestResult(unittest.TestResult): + def __init__(self, output_stream, error_stream, message_log, test_output_log): + super(TAPTestResult, self).__init__(self, output_stream) + self.output_stream = output_stream + self.error_stream = error_stream + self.orig_stdout = None + self.orig_stderr = None + self.message = error_stream + self.test_output = None + self.message_log = message_log + self.test_output_log = test_output_log + self.output_stream.write("TAP version 13\n") + + def print_raw(self, text): + self.output_stream.write(text) + self.output_stream.flush() + + def print_result(self, result, test, directive=None): + self.output_stream.write("%s %d %s" % (result, self.testsRun, test.id())) + if directive: + self.output_stream.write(" # " + directive) + self.output_stream.write("\n") + self.output_stream.flush() + + def ok(self, test, directive=None): + self.print_result("ok", test, directive) + + def not_ok(self, test): + self.print_result("not ok", test) + + def startTest(self, test): + self.orig_stdout = sys.stdout + self.orig_stderr = sys.stderr + if self.message_log == LogMode.LogToError: + self.message = self.error_stream + else: + self.message = StringIO() + if self.test_output_log == LogMode.LogToError: + self.test_output = self.error_stream + else: + self.test_output = StringIO() + + if self.message_log == self.test_output_log: + self.test_output = self.message + + sys.stdout = sys.stderr = self.test_output + super(TAPTestResult, self).startTest(test) + + def stopTest(self, test): + super(TAPTestResult, self).stopTest(test) + sys.stdout = self.orig_stdout + sys.stderr = self.orig_stderr + if self.message_log == self.test_output_log: + logs = [(self.message_log, self.message, "output")] + else: + logs = [ + (self.test_output_log, self.test_output, "test_output"), + (self.message_log, self.message, "message"), + ] + for log_mode, log, log_name in logs: + if log_mode != LogMode.LogToError: + output = log.getvalue() + if len(output): + if log_mode == LogMode.LogToYAML: + self.print_raw(" ---\n") + self.print_raw(" " + log_name + ": |\n") + self.print_raw( + " " + output.rstrip().replace("\n", "\n ") + "\n" + ) + self.print_raw(" ...\n") + elif log_mode == LogMode.LogToAttachment: + self.print_raw(" ---\n") + self.print_raw(" " + log_name + ":\n") + self.print_raw(" File-Name: " + log_name + ".txt\n") + self.print_raw(" File-Type: text/plain\n") + self.print_raw( + " File-Content: " + base64.b64encode(output) + "\n" + ) + self.print_raw(" ...\n") + else: + self.print_raw( + "# " + output.rstrip().replace("\n", "\n# ") + "\n" + ) + + def addSuccess(self, test): + super(TAPTestResult, self).addSuccess(test) + self.ok(test) + + def addError(self, test, err): + super(TAPTestResult, self).addError(test, err) + self.message.write(self.errors[-1][1] + "\n") + self.not_ok(test) + + def addFailure(self, test, err): + super(TAPTestResult, self).addFailure(test, err) + self.message.write(self.failures[-1][1] + "\n") + self.not_ok(test) + + def addSkip(self, test, reason): + super(TAPTestResult, self).addSkip(test, reason) + self.ok(test, "SKIP " + reason) + + def addExpectedFailure(self, test, err): + super(TAPTestResult, self).addExpectedFailure(test, err) + self.message.write(self.expectedFailures[-1][1] + "\n") + self.ok(test) + + def addUnexpectedSuccess(self, test): + super(TAPTestResult, self).addUnexpectedSuccess(self, test) + self.not_ok(test) + + def printErrors(self): + self.print_raw("1..%d\n" % self.testsRun) + + +class TAPTestRunner(unittest.TextTestRunner): + def __init__( + self, + message_log=LogMode.LogToYAML, + test_output_log=LogMode.LogToDiagnostics, + output_stream=sys.stdout, + error_stream=sys.stderr, + ): + self.output_stream = output_stream + self.error_stream = error_stream + self.message_log = message_log + self.test_output_log = test_output_log + + def run(self, test): + result = TAPTestResult( + self.output_stream, + self.error_stream, + self.message_log, + self.test_output_log, + ) + test(result) + result.printErrors() + + return result diff --git a/test-suite/python/wrapper.py b/test-suite/python/wrapper.py new file mode 100644 index 0000000..83caaba --- /dev/null +++ b/test-suite/python/wrapper.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python + +import unittest + +from mpibind import wrapper + +class WrapperTests(unittest.TestCase): + def test_placeholder(self): + self.assertTrue(True) + +if __name__ == "__main__": + from pycotap import TAPTestRunner + unittest.main(testRunner=TAPTestRunner) \ No newline at end of file From cb8030bd82aae7e879ef0d3905e1084105bb079c Mon Sep 17 00:00:00 2001 From: Samuel Furman Date: Thu, 13 Aug 2020 06:43:05 -0700 Subject: [PATCH 7/9] pre test rebase checkpoint --- bindings/python/_mpibind/Makefile.am | 45 +- bindings/python/mpibind/Makefile.am | 16 +- config/am_check_pymod.m4 | 2 +- config/ar-lib | 270 ----------- config/ax_code_coverage.m4 | 264 ----------- config/ax_python_devel.m4 | 325 ------------- config/py-compile | 170 ------- config/python.m4 | 245 ---------- config/tap-driver.py | 26 - config/tap-driver.sh | 678 --------------------------- config/test-driver | 127 ----- configure.ac | 27 +- test-suite/Makefile.am | 5 +- test-suite/tap-driver.py | 26 + 14 files changed, 61 insertions(+), 2165 deletions(-) delete mode 100755 config/ar-lib delete mode 100644 config/ax_code_coverage.m4 delete mode 100644 config/ax_python_devel.m4 delete mode 100755 config/py-compile delete mode 100644 config/python.m4 delete mode 100644 config/tap-driver.py delete mode 100755 config/tap-driver.sh delete mode 100755 config/test-driver create mode 100644 test-suite/tap-driver.py diff --git a/bindings/python/_mpibind/Makefile.am b/bindings/python/_mpibind/Makefile.am index e5aa898..20a3a55 100644 --- a/bindings/python/_mpibind/Makefile.am +++ b/bindings/python/_mpibind/Makefile.am @@ -1,5 +1,3 @@ - - AM_CPPFLAGS = \ -Wall -Werror -Wno-missing-field-initializers \ -I$(top_srcdir) -I$(top_srcdir)/src/ \ @@ -8,27 +6,19 @@ AM_CPPFLAGS = \ AM_LDFLAGS = \ -avoid-version -module -Wl,-rpath,$(PYTHON_PREFIX)/lib -PREPROC_FLAGS=-E '-D__attribute__(...)=' - _pympibind.c: $(srcdir)/build.py _mpibind_preproc.h - $(PYTHON) $^ + $(PYTHON) $< +# Flux LICENSE +_mpibind_preproc.h: _mpibind_clean.h + $(CC) -E '-D__attribute__(...)=' _mpibind_clean.h\ + | sed -e '/^# [0-9]*.*/d' > $@ + _mpibind_clean.h: Makefile $(PYTHON) $(srcdir)/clean_header.py \ $(top_builddir)/src/mpibind.h \ _mpibind_clean.h -# _mpibind_clean.h: Makefile -# $(PYTHON) $(srcdir)/make_clean_header.py \ -# --path $(top_srcdir) \ -# --search $(top_builddir)/src/ \ -# --output _mpibind_clean.h \ -# src/mpibind.h - -_mpibind_preproc.h: _mpibind_clean.h - $(CC) $(PREPROC_FLAGS) _mpibind_clean.h\ - | sed -e '/^# [0-9]*.*/d' > $@ - BUILT_SOURCES= _pympibind.c _mpibind_preproc.h mpibindpyso_LTLIBRARIES = _pympibind.la mpibindpyso_PYTHON = __init__.py @@ -36,28 +26,29 @@ mpibindpyso_PYTHON = __init__.py nodist_mpibindbindinginclude_HEADERS = _mpibind_preproc.h nodist__pympibind_la_SOURCES = _pympibind.c - common_libs = $(top_builddir)/src/libmpibind.la \ - $(PYTHON_LDFLAGS) \ - $(HWLOC_LIBS) + $(PYTHON_LDFLAGS) _pympibind_la_LIBADD = $(common_libs) EXTRA_DIST=build.py make_clean_header.py +clean-local: + -rm -f *.c *.so *.pyc *.pyo *_clean.h *_preproc.h + -rm -rf __pycache__ + -rm -rf .libs + +# creates a symbolic link _pympibind.so to +# _pympibind.so in _mpibind/.libs so that it can be imported in mpibind/wrapper +# Flux LICENSE + .PHONY: lib-copy -lib-copy-vpath: ${mpibindpyso_PYTHON} ${mpibindpyso_LTLIBRARIES} +lib-copy: ${mpibindpyso_PYTHON} ${mpibindpyso_LTLIBRARIES} -echo Copying libraries to where they can be used by python in-tree - [ "$(top_srcdir)" != "$(top_builddir)" ] && cp $(top_srcdir)/bindings/python/_mpibind/__init__.py ./; \ for LIB in ${mpibindpyso_LTLIBRARIES:la=so} ; do \ test -e .libs/$$LIB && \ $(LN_S) .libs/$$LIB ./ || true; \ done -all-local: lib-copy-vpath - -clean-local: - -rm -f *.c *.so *.pyc *.pyo *_clean.h *_preproc.h - -rm -rf __pycache__ - -rm -rf .libs \ No newline at end of file +all-local: lib-copy \ No newline at end of file diff --git a/bindings/python/mpibind/Makefile.am b/bindings/python/mpibind/Makefile.am index 1cdb1bc..68081b4 100644 --- a/bindings/python/mpibind/Makefile.am +++ b/bindings/python/mpibind/Makefile.am @@ -4,18 +4,4 @@ mpibindpy_PYTHON=\ clean-local: -rm -f *.pyc *.pyo - -rm -rf __pycache__ - -install-data-hook: - $(AM_V_at)echo Linking python modules in non-standard location... && \ - $(INSTALL) -d -m 0755 "$(DESTDIR)$(mpibindpylinkdir)" && \ - target=$(mpibindpydir) && \ - f=$${target##*/} && \ - cd "$(DESTDIR)$(mpibindpylinkdir)" && \ - rm -f $$f && \ - $(LN_S) $$target . - -uninstall-local: - $(AM_V_at)target=$(mpibindpydir) && f=$${target##*/} && \ - echo "Removing $(mpibindpylinkdir)/$$f" && \ - rm -rf $(mpibindpylinkdir)/$$f + -rm -rf __pycache__ \ No newline at end of file diff --git a/config/am_check_pymod.m4 b/config/am_check_pymod.m4 index 3688c13..dd9944e 100644 --- a/config/am_check_pymod.m4 +++ b/config/am_check_pymod.m4 @@ -1,4 +1,4 @@ -# TODO: LICENSE FROM FLUX +# TODO: LICENSE FROM FLUX, note this is also alvailable in GNOME dnl AM_CHECK_PYMOD(MODNAME [,SYMBOL [,ACTION-IF-FOUND [,ACTION-IF-NOT-FOUND]]]) dnl Check if a module containing a given symbol is visible to python. diff --git a/config/ar-lib b/config/ar-lib deleted file mode 100755 index 0baa4f6..0000000 --- a/config/ar-lib +++ /dev/null @@ -1,270 +0,0 @@ -#! /bin/sh -# Wrapper for Microsoft lib.exe - -me=ar-lib -scriptversion=2012-03-01.08; # UTC - -# Copyright (C) 2010-2018 Free Software Foundation, Inc. -# Written by Peter Rosin . -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# This file is maintained in Automake, please report -# bugs to or send patches to -# . - - -# func_error message -func_error () -{ - echo "$me: $1" 1>&2 - exit 1 -} - -file_conv= - -# func_file_conv build_file -# Convert a $build file to $host form and store it in $file -# Currently only supports Windows hosts. -func_file_conv () -{ - file=$1 - case $file in - / | /[!/]*) # absolute file, and not a UNC file - if test -z "$file_conv"; then - # lazily determine how to convert abs files - case `uname -s` in - MINGW*) - file_conv=mingw - ;; - CYGWIN*) - file_conv=cygwin - ;; - *) - file_conv=wine - ;; - esac - fi - case $file_conv in - mingw) - file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` - ;; - cygwin) - file=`cygpath -m "$file" || echo "$file"` - ;; - wine) - file=`winepath -w "$file" || echo "$file"` - ;; - esac - ;; - esac -} - -# func_at_file at_file operation archive -# Iterate over all members in AT_FILE performing OPERATION on ARCHIVE -# for each of them. -# When interpreting the content of the @FILE, do NOT use func_file_conv, -# since the user would need to supply preconverted file names to -# binutils ar, at least for MinGW. -func_at_file () -{ - operation=$2 - archive=$3 - at_file_contents=`cat "$1"` - eval set x "$at_file_contents" - shift - - for member - do - $AR -NOLOGO $operation:"$member" "$archive" || exit $? - done -} - -case $1 in - '') - func_error "no command. Try '$0 --help' for more information." - ;; - -h | --h*) - cat <. - -#serial 25 - -AC_DEFUN([AX_CODE_COVERAGE],[ - dnl Check for --enable-code-coverage - AC_REQUIRE([AC_PROG_SED]) - - # allow to override gcov location - AC_ARG_WITH([gcov], - [AS_HELP_STRING([--with-gcov[=GCOV]], [use given GCOV for coverage (GCOV=gcov).])], - [_AX_CODE_COVERAGE_GCOV_PROG_WITH=$with_gcov], - [_AX_CODE_COVERAGE_GCOV_PROG_WITH=gcov]) - - AC_MSG_CHECKING([whether to build with code coverage support]) - AC_ARG_ENABLE([code-coverage], - AS_HELP_STRING([--enable-code-coverage], - [Whether to enable code coverage support]),, - enable_code_coverage=no) - - AM_CONDITIONAL([CODE_COVERAGE_ENABLED], [test x$enable_code_coverage = xyes]) - AC_SUBST([CODE_COVERAGE_ENABLED], [$enable_code_coverage]) - AC_MSG_RESULT($enable_code_coverage) - - AS_IF([ test "$enable_code_coverage" = "yes" ], [ - # check for gcov - AC_CHECK_TOOL([GCOV], - [$_AX_CODE_COVERAGE_GCOV_PROG_WITH], - [:]) - AS_IF([test "X$GCOV" = "X:"], - [AC_MSG_ERROR([gcov is needed to do coverage])]) - AC_SUBST([GCOV]) - - dnl Check if gcc is being used - AS_IF([ test "$GCC" = "no" ], [ - AC_MSG_ERROR([not compiling with gcc, which is required for gcov code coverage]) - ]) - - AC_CHECK_PROG([LCOV], [lcov], [lcov]) - AC_CHECK_PROG([GENHTML], [genhtml], [genhtml]) - - AS_IF([ test -z "$LCOV" ], [ - AC_MSG_ERROR([To enable code coverage reporting you must have lcov installed]) - ]) - - AS_IF([ test -z "$GENHTML" ], [ - AC_MSG_ERROR([Could not find genhtml from the lcov package]) - ]) - - dnl Build the code coverage flags - dnl Define CODE_COVERAGE_LDFLAGS for backwards compatibility - CODE_COVERAGE_CPPFLAGS="-DNDEBUG" - CODE_COVERAGE_CFLAGS="-O0 -g -fprofile-arcs -ftest-coverage" - CODE_COVERAGE_CXXFLAGS="-O0 -g -fprofile-arcs -ftest-coverage" - CODE_COVERAGE_LIBS="-lgcov" - CODE_COVERAGE_LDFLAGS="$CODE_COVERAGE_LIBS" - - AC_SUBST([CODE_COVERAGE_CPPFLAGS]) - AC_SUBST([CODE_COVERAGE_CFLAGS]) - AC_SUBST([CODE_COVERAGE_CXXFLAGS]) - AC_SUBST([CODE_COVERAGE_LIBS]) - AC_SUBST([CODE_COVERAGE_LDFLAGS]) - - [CODE_COVERAGE_RULES_CHECK=' - -$(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) -k check - $(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) code-coverage-capture -'] - [CODE_COVERAGE_RULES_CAPTURE=' - $(code_coverage_v_lcov_cap)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --capture --output-file "$(CODE_COVERAGE_OUTPUT_FILE).tmp" --test-name "$(call code_coverage_sanitize,$(PACKAGE_NAME)-$(PACKAGE_VERSION))" --no-checksum --compat-libtool $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_OPTIONS) - $(code_coverage_v_lcov_ign)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --remove "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "/tmp/*" $(CODE_COVERAGE_IGNORE_PATTERN) --output-file "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_RMOPTS) - -@rm -f $(CODE_COVERAGE_OUTPUT_FILE).tmp - $(code_coverage_v_genhtml)LANG=C $(GENHTML) $(code_coverage_quiet) $(addprefix --prefix ,$(CODE_COVERAGE_DIRECTORY)) --output-directory "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" --title "$(PACKAGE_NAME)-$(PACKAGE_VERSION) Code Coverage" --legend --show-details "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_GENHTML_OPTIONS) - @echo "file://$(abs_builddir)/$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html" -'] - [CODE_COVERAGE_RULES_CLEAN=' -clean: code-coverage-clean -distclean: code-coverage-clean -code-coverage-clean: - -$(LCOV) --directory $(top_builddir) -z - -rm -rf $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_FILE).tmp $(CODE_COVERAGE_OUTPUT_DIRECTORY) - -find . \( -name "*.gcda" -o -name "*.gcno" -o -name "*.gcov" \) -delete -'] - ], [ - [CODE_COVERAGE_RULES_CHECK=' - @echo "Need to reconfigure with --enable-code-coverage" -'] - CODE_COVERAGE_RULES_CAPTURE="$CODE_COVERAGE_RULES_CHECK" - CODE_COVERAGE_RULES_CLEAN='' - ]) - -[CODE_COVERAGE_RULES=' -# Code coverage -# -# Optional: -# - CODE_COVERAGE_DIRECTORY: Top-level directory for code coverage reporting. -# Multiple directories may be specified, separated by whitespace. -# (Default: $(top_builddir)) -# - CODE_COVERAGE_OUTPUT_FILE: Filename and path for the .info file generated -# by lcov for code coverage. (Default: -# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info) -# - CODE_COVERAGE_OUTPUT_DIRECTORY: Directory for generated code coverage -# reports to be created. (Default: -# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage) -# - CODE_COVERAGE_BRANCH_COVERAGE: Set to 1 to enforce branch coverage, -# set to 0 to disable it and leave empty to stay with the default. -# (Default: empty) -# - CODE_COVERAGE_LCOV_SHOPTS_DEFAULT: Extra options shared between both lcov -# instances. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE) -# - CODE_COVERAGE_LCOV_SHOPTS: Extra options to shared between both lcov -# instances. (Default: $CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) -# - CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH: --gcov-tool pathtogcov -# - CODE_COVERAGE_LCOV_OPTIONS_DEFAULT: Extra options to pass to the -# collecting lcov instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) -# - CODE_COVERAGE_LCOV_OPTIONS: Extra options to pass to the collecting lcov -# instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) -# - CODE_COVERAGE_LCOV_RMOPTS_DEFAULT: Extra options to pass to the filtering -# lcov instance. (Default: empty) -# - CODE_COVERAGE_LCOV_RMOPTS: Extra options to pass to the filtering lcov -# instance. (Default: $CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) -# - CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT: Extra options to pass to the -# genhtml instance. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE) -# - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml -# instance. (Default: $CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) -# - CODE_COVERAGE_IGNORE_PATTERN: Extra glob pattern of files to ignore -# -# The generated report will be titled using the $(PACKAGE_NAME) and -# $(PACKAGE_VERSION). In order to add the current git hash to the title, -# use the git-version-gen script, available online. - -# Optional variables -CODE_COVERAGE_DIRECTORY ?= $(top_builddir) -CODE_COVERAGE_OUTPUT_FILE ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info -CODE_COVERAGE_OUTPUT_DIRECTORY ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage -CODE_COVERAGE_BRANCH_COVERAGE ?= -CODE_COVERAGE_LCOV_SHOPTS_DEFAULT ?= $(if $(CODE_COVERAGE_BRANCH_COVERAGE),\ ---rc lcov_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE)) -CODE_COVERAGE_LCOV_SHOPTS ?= $(CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) -CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH ?= --gcov-tool "$(GCOV)" -CODE_COVERAGE_LCOV_OPTIONS_DEFAULT ?= $(CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) -CODE_COVERAGE_LCOV_OPTIONS ?= $(CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) -CODE_COVERAGE_LCOV_RMOPTS_DEFAULT ?= -CODE_COVERAGE_LCOV_RMOPTS ?= $(CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) -CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT ?=\ -$(if $(CODE_COVERAGE_BRANCH_COVERAGE),\ ---rc genhtml_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE)) -CODE_COVERAGE_GENHTML_OPTIONS ?= $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) -CODE_COVERAGE_IGNORE_PATTERN ?= - -GITIGNOREFILES ?= -GITIGNOREFILES += $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_DIRECTORY) - -code_coverage_v_lcov_cap = $(code_coverage_v_lcov_cap_$(V)) -code_coverage_v_lcov_cap_ = $(code_coverage_v_lcov_cap_$(AM_DEFAULT_VERBOSITY)) -code_coverage_v_lcov_cap_0 = @echo " LCOV --capture"\ - $(CODE_COVERAGE_OUTPUT_FILE); -code_coverage_v_lcov_ign = $(code_coverage_v_lcov_ign_$(V)) -code_coverage_v_lcov_ign_ = $(code_coverage_v_lcov_ign_$(AM_DEFAULT_VERBOSITY)) -code_coverage_v_lcov_ign_0 = @echo " LCOV --remove /tmp/*"\ - $(CODE_COVERAGE_IGNORE_PATTERN); -code_coverage_v_genhtml = $(code_coverage_v_genhtml_$(V)) -code_coverage_v_genhtml_ = $(code_coverage_v_genhtml_$(AM_DEFAULT_VERBOSITY)) -code_coverage_v_genhtml_0 = @echo " GEN " $(CODE_COVERAGE_OUTPUT_DIRECTORY); -code_coverage_quiet = $(code_coverage_quiet_$(V)) -code_coverage_quiet_ = $(code_coverage_quiet_$(AM_DEFAULT_VERBOSITY)) -code_coverage_quiet_0 = --quiet - -# sanitizes the test-name: replaces with underscores: dashes and dots -code_coverage_sanitize = $(subst -,_,$(subst .,_,$(1))) - -# Use recursive makes in order to ignore errors during check -check-code-coverage:'"$CODE_COVERAGE_RULES_CHECK"' - -# Capture code coverage data -code-coverage-capture: code-coverage-capture-hook'"$CODE_COVERAGE_RULES_CAPTURE"' - -# Hook rule executed before code-coverage-capture, overridable by the user -code-coverage-capture-hook: - -'"$CODE_COVERAGE_RULES_CLEAN"' - -A''M_DISTCHECK_CONFIGURE_FLAGS ?= -A''M_DISTCHECK_CONFIGURE_FLAGS += --disable-code-coverage - -.PHONY: check-code-coverage code-coverage-capture code-coverage-capture-hook code-coverage-clean -'] - - AC_SUBST([CODE_COVERAGE_RULES]) - m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([CODE_COVERAGE_RULES])]) -]) diff --git a/config/ax_python_devel.m4 b/config/ax_python_devel.m4 deleted file mode 100644 index 7314656..0000000 --- a/config/ax_python_devel.m4 +++ /dev/null @@ -1,325 +0,0 @@ -# TODO: LICENSE FROM FLUX -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_python_devel.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_PYTHON_DEVEL([version]) -# -# DESCRIPTION -# -# Note: Defines as a precious variable "PYTHON_VERSION". Don't override it -# in your configure.ac. -# -# This macro checks for Python and tries to get the include path to -# 'Python.h'. It provides the $(PYTHON_CPPFLAGS) and $(PYTHON_LDFLAGS) -# output variables. It also exports $(PYTHON_EXTRA_LIBS) and -# $(PYTHON_EXTRA_LDFLAGS) for embedding Python in your code. -# -# You can search for some particular version of Python by passing a -# parameter to this macro, for example ">= '2.3.1'", or "== '2.4'". Please -# note that you *have* to pass also an operator along with the version to -# match, and pay special attention to the single quotes surrounding the -# version number. Don't use "PYTHON_VERSION" for this: that environment -# variable is declared as precious and thus reserved for the end-user. -# -# This macro should work for all versions of Python >= 2.1.0. As an end -# user, you can disable the check for the python version by setting the -# PYTHON_NOVERSIONCHECK environment variable to something else than the -# empty string. -# -# If you need to use this macro for an older Python version, please -# contact the authors. We're always open for feedback. -# -# LICENSE -# -# Copyright (c) 2009 Sebastian Huber -# Copyright (c) 2009 Alan W. Irwin -# Copyright (c) 2009 Rafael Laboissiere -# Copyright (c) 2009 Andrew Collier -# Copyright (c) 2009 Matteo Settenvini -# Copyright (c) 2009 Horst Knorr -# Copyright (c) 2013 Daniel Mullner -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 17 - -AU_ALIAS([AC_PYTHON_DEVEL], [AX_PYTHON_DEVEL]) -AC_DEFUN([AX_PYTHON_DEVEL],[ - # - # Allow the use of a (user set) custom python version - # - AC_ARG_VAR([PYTHON_VERSION],[The installed Python - version to use, for example '2.3'. This string - will be appended to the Python interpreter - canonical name.]) - - AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]]) - if test -z "$PYTHON"; then - AC_MSG_ERROR([Cannot find python$PYTHON_VERSION in your system path]) - PYTHON_VERSION="" - fi - - # - # Check for a version of Python >= 2.1.0 - # - AC_MSG_CHECKING([for a version of Python >= '2.1.0']) - ac_supports_python_ver=`$PYTHON -c "import sys; \ - ver = sys.version.split ()[[0]]; \ - print (ver >= '2.1.0')"` - if test "$ac_supports_python_ver" != "True"; then - if test -z "$PYTHON_NOVERSIONCHECK"; then - AC_MSG_RESULT([no]) - AC_MSG_FAILURE([ -This version of the AC@&t@_PYTHON_DEVEL macro -doesn't work properly with versions of Python before -2.1.0. You may need to re-run configure, setting the -variables PYTHON_CPPFLAGS, PYTHON_LDFLAGS, PYTHON_SITE_PKG, -PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand. -Moreover, to disable this check, set PYTHON_NOVERSIONCHECK -to something else than an empty string. -]) - else - AC_MSG_RESULT([skip at user request]) - fi - else - AC_MSG_RESULT([yes]) - fi - - # - # if the macro parameter ``version'' is set, honour it - # - if test -n "$1"; then - AC_MSG_CHECKING([for a version of Python $1]) - ac_supports_python_ver=`$PYTHON -c "import sys; \ - ver = sys.version.split ()[[0]]; \ - print (ver $1)"` - if test "$ac_supports_python_ver" = "True"; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - AC_MSG_ERROR([this package requires Python $1. -If you have it installed, but it isn't the default Python -interpreter in your system path, please pass the PYTHON_VERSION -variable to configure. See ``configure --help'' for reference. -]) - PYTHON_VERSION="" - fi - fi - - # - # Check if you have distutils, else fail - # - AC_MSG_CHECKING([for the distutils Python package]) - ac_distutils_result=`$PYTHON -c "import distutils" 2>&1` - if test -z "$ac_distutils_result"; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - AC_MSG_ERROR([cannot import Python module "distutils". -Please check your Python installation. The error was: -$ac_distutils_result]) - PYTHON_VERSION="" - fi - - # - # Check for Python include path - # - AC_MSG_CHECKING([for Python include path]) - if test -z "$PYTHON_CPPFLAGS"; then - python_path=`$PYTHON -c "import distutils.sysconfig; \ - print (distutils.sysconfig.get_python_inc ());"` - plat_python_path=`$PYTHON -c "import distutils.sysconfig; \ - print (distutils.sysconfig.get_python_inc (plat_specific=1));"` - if test -n "${python_path}"; then - if test "${plat_python_path}" != "${python_path}"; then - python_path="-I$python_path -I$plat_python_path" - else - python_path="-I$python_path" - fi - fi - PYTHON_CPPFLAGS=$python_path - fi - AC_MSG_RESULT([$PYTHON_CPPFLAGS]) - AC_SUBST([PYTHON_CPPFLAGS]) - - # - # Check for Python library path - # - AC_MSG_CHECKING([for Python library path]) - if test -z "$PYTHON_LDFLAGS"; then - # (makes two attempts to ensure we've got a version number - # from the interpreter) - ac_python_version=`cat<]], - [[Py_Initialize();]]) - ],[pythonexists=yes],[pythonexists=no]) - AC_LANG_POP([C]) - # turn back to default flags - CPPFLAGS="$ac_save_CPPFLAGS" - LIBS="$ac_save_LIBS" - - AC_MSG_RESULT([$pythonexists]) - - if test ! "x$pythonexists" = "xyes"; then - AC_MSG_FAILURE([ - Could not link test program to Python. Maybe the main Python library has been - installed in some non-standard library path. If so, pass it to configure, - via the LDFLAGS environment variable. - Example: ./configure LDFLAGS="-L/usr/non-standard-path/python/lib" - ============================================================================ - ERROR! - You probably have to install the development version of the Python package - for your distribution. The exact name of this package varies among them. - ============================================================================ - ]) - PYTHON_VERSION="" - fi - - # - # all done! - # -]) diff --git a/config/py-compile b/config/py-compile deleted file mode 100755 index 46ea866..0000000 --- a/config/py-compile +++ /dev/null @@ -1,170 +0,0 @@ -#!/bin/sh -# py-compile - Compile a Python program - -scriptversion=2011-06-08.12; # UTC - -# Copyright (C) 2000-2013 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# This file is maintained in Automake, please report -# bugs to or send patches to -# . - -if [ -z "$PYTHON" ]; then - PYTHON=python -fi - -me=py-compile - -usage_error () -{ - echo "$me: $*" >&2 - echo "Try '$me --help' for more information." >&2 - exit 1 -} - -basedir= -destdir= -while test $# -ne 0; do - case "$1" in - --basedir) - if test $# -lt 2; then - usage_error "option '--basedir' requires an argument" - else - basedir=$2 - fi - shift - ;; - --destdir) - if test $# -lt 2; then - usage_error "option '--destdir' requires an argument" - else - destdir=$2 - fi - shift - ;; - -h|--help) - cat <<\EOF -Usage: py-compile [--help] [--version] [--basedir DIR] [--destdir DIR] FILES..." - -Byte compile some python scripts FILES. Use --destdir to specify any -leading directory path to the FILES that you don't want to include in the -byte compiled file. Specify --basedir for any additional path information you -do want to be shown in the byte compiled file. - -Example: - py-compile --destdir /tmp/pkg-root --basedir /usr/share/test test.py test2.py - -Report bugs to . -EOF - exit $? - ;; - -v|--version) - echo "$me $scriptversion" - exit $? - ;; - --) - shift - break - ;; - -*) - usage_error "unrecognized option '$1'" - ;; - *) - break - ;; - esac - shift -done - -files=$* -if test -z "$files"; then - usage_error "no files given" -fi - -# if basedir was given, then it should be prepended to filenames before -# byte compilation. -if [ -z "$basedir" ]; then - pathtrans="path = file" -else - pathtrans="path = os.path.join('$basedir', file)" -fi - -# if destdir was given, then it needs to be prepended to the filename to -# byte compile but not go into the compiled file. -if [ -z "$destdir" ]; then - filetrans="filepath = path" -else - filetrans="filepath = os.path.normpath('$destdir' + os.sep + path)" -fi - -$PYTHON -c " -import sys, os, py_compile, imp - -files = '''$files''' - -sys.stdout.write('Byte-compiling python modules...\n') -for file in files.split(): - $pathtrans - $filetrans - if not os.path.exists(filepath) or not (len(filepath) >= 3 - and filepath[-3:] == '.py'): - continue - sys.stdout.write(file) - sys.stdout.flush() - if hasattr(imp, 'get_tag'): - py_compile.compile(filepath, imp.cache_from_source(filepath), path) - else: - py_compile.compile(filepath, filepath + 'c', path) -sys.stdout.write('\n')" || exit $? - -# this will fail for python < 1.5, but that doesn't matter ... -$PYTHON -O -c " -import sys, os, py_compile, imp - -# pypy does not use .pyo optimization -if hasattr(sys, 'pypy_translation_info'): - sys.exit(0) - -files = '''$files''' -sys.stdout.write('Byte-compiling python modules (optimized versions) ...\n') -for file in files.split(): - $pathtrans - $filetrans - if not os.path.exists(filepath) or not (len(filepath) >= 3 - and filepath[-3:] == '.py'): - continue - sys.stdout.write(file) - sys.stdout.flush() - if hasattr(imp, 'get_tag'): - py_compile.compile(filepath, imp.cache_from_source(filepath, False), path) - else: - py_compile.compile(filepath, filepath + 'o', path) -sys.stdout.write('\n')" 2>/dev/null || : - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/config/python.m4 b/config/python.m4 deleted file mode 100644 index b17f3de..0000000 --- a/config/python.m4 +++ /dev/null @@ -1,245 +0,0 @@ - -## ------------------------ -*- Autoconf -*- -## Python file handling -## From Andrew Dalke -## Updated by James Henstridge -## ------------------------ -# Copyright (C) 1999-2017 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - - -# AM_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -# --------------------------------------------------------------------------- -# Adds support for distributing Python modules and packages. To -# install modules, copy them to $(pythondir), using the python_PYTHON -# automake variable. To install a package with the same name as the -# automake package, install to $(pkgpythondir), or use the -# pkgpython_PYTHON automake variable. -# -# The variables $(pyexecdir) and $(pkgpyexecdir) are provided as -# locations to install python extension modules (shared libraries). -# Another macro is required to find the appropriate flags to compile -# extension modules. -# -# If your package is configured with a different prefix to python, -# users will have to add the install directory to the PYTHONPATH -# environment variable, or create a .pth file (see the python -# documentation for details). -# -# If the MINIMUM-VERSION argument is passed, AM_PATH_PYTHON will -# cause an error if the version of python installed on the system -# doesn't meet the requirement. MINIMUM-VERSION should consist of -# numbers and dots only. -AC_DEFUN([AM_PATH_PYTHON], - [ - dnl Find a Python interpreter. Python versions prior to 2.0 are not - dnl supported. (2.0 was released on October 16, 2000). - dnl FIXME: Remove the need to hard-code Python versions here. - m4_define_default([_AM_PYTHON_INTERPRETER_LIST], -[python python2 python3 python3.5 python3.4 python3.3 python3.2 python3.1 python3.0 python2.7 dnl - python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0]) - - AC_ARG_VAR([PYTHON], [the Python interpreter]) - - m4_if([$1],[],[ - dnl No version check is needed. - # Find any Python interpreter. - if test -z "$PYTHON"; then - AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :) - fi - am_display_PYTHON=python - ], [ - dnl A version check is needed. - if test -n "$PYTHON"; then - # If the user set $PYTHON, use it and don't search something else. - AC_MSG_CHECKING([whether $PYTHON version is >= $1]) - AM_PYTHON_CHECK_VERSION([$PYTHON], [$1], - [AC_MSG_RESULT([yes])], - [AC_MSG_RESULT([no]) - AC_MSG_ERROR([Python interpreter is too old])]) - am_display_PYTHON=$PYTHON - else - # Otherwise, try each interpreter until we find one that satisfies - # VERSION. - AC_CACHE_CHECK([for a Python interpreter with version >= $1], - [am_cv_pathless_PYTHON],[ - for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do - test "$am_cv_pathless_PYTHON" = none && break - AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break]) - done]) - # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. - if test "$am_cv_pathless_PYTHON" = none; then - PYTHON=: - else - AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON]) - fi - am_display_PYTHON=$am_cv_pathless_PYTHON - fi - ]) - - if test "$PYTHON" = :; then - dnl Run any user-specified action, or abort. - m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])]) - else - - dnl Query Python for its version number. Getting [:3] seems to be - dnl the best way to do this; it's what "site.py" does in the standard - dnl library. - - AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version], - [am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[[:3]])"`]) - AC_SUBST([PYTHON_VERSION], [$am_cv_python_version]) - - dnl Use the values of $prefix and $exec_prefix for the corresponding - dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX. These are made - dnl distinct variables so they can be overridden if need be. However, - dnl general consensus is that you shouldn't need this ability. - - AC_SUBST([PYTHON_PREFIX], ['${prefix}']) - AC_SUBST([PYTHON_EXEC_PREFIX], ['${exec_prefix}']) - - dnl At times (like when building shared libraries) you may want - dnl to know which OS platform Python thinks this is. - - AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform], - [am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`]) - AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform]) - - # Just factor out some code duplication. - am_python_setup_sysconfig="\ -import sys -# Prefer sysconfig over distutils.sysconfig, for better compatibility -# with python 3.x. See automake bug#10227. -try: - import sysconfig -except ImportError: - can_use_sysconfig = 0 -else: - can_use_sysconfig = 1 -# Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: -# -try: - from platform import python_implementation - if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7': - can_use_sysconfig = 0 -except ImportError: - pass" - - dnl Set up 4 directories: - - dnl pythondir -- where to install python scripts. This is the - dnl site-packages directory, not the python standard library - dnl directory like in previous automake betas. This behavior - dnl is more consistent with lispdir.m4 for example. - dnl Query distutils for this directory. - AC_CACHE_CHECK([for $am_display_PYTHON script directory], - [am_cv_python_pythondir], - [if test "x$prefix" = xNONE - then - am_py_prefix=$ac_default_prefix - else - am_py_prefix=$prefix - fi - am_cv_python_pythondir=`$PYTHON -c " -$am_python_setup_sysconfig -if can_use_sysconfig: - sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'}) -else: - from distutils import sysconfig - sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') -sys.stdout.write(sitedir)"` - case $am_cv_python_pythondir in - $am_py_prefix*) - am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` - am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"` - ;; - *) - case $am_py_prefix in - /usr|/System*) ;; - *) - am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages - ;; - esac - ;; - esac - ]) - AC_SUBST([pythondir], [$am_cv_python_pythondir]) - - dnl pkgpythondir -- $PACKAGE directory under pythondir. Was - dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is - dnl more consistent with the rest of automake. - - AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE]) - - dnl pyexecdir -- directory for installing python extension modules - dnl (shared libraries) - dnl Query distutils for this directory. - AC_CACHE_CHECK([for $am_display_PYTHON extension module directory], - [am_cv_python_pyexecdir], - [if test "x$exec_prefix" = xNONE - then - am_py_exec_prefix=$am_py_prefix - else - am_py_exec_prefix=$exec_prefix - fi - if test "x$PYTHON_SITE_PKG" = x ; then - am_cv_python_pyexecdir=`$PYTHON -c " -$am_python_setup_sysconfig -if can_use_sysconfig: - sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'}) -else: - from distutils import sysconfig - sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix') -sys.stdout.write(sitedir)"` - else - am_cv_python_pyexecdir=$PYTHON_SITE_PKG - fi - case $am_cv_python_pyexecdir in - $am_py_exec_prefix*) - am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` - am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"` - ;; - *) - case $am_py_exec_prefix in - /usr|/System*) ;; - *) - am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages - ;; - esac - ;; - esac - ]) - AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir]) - - dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE) - - AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE]) - - dnl Run any user-specified action. - $2 - fi - -]) - - -# AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) -# --------------------------------------------------------------------------- -# Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION. -# Run ACTION-IF-FALSE otherwise. -# This test uses sys.hexversion instead of the string equivalent (first -# word of sys.version), in order to cope with versions such as 2.2c1. -# This supports Python 2.0 or higher. (2.0 was released on October 16, 2000). -AC_DEFUN([AM_PYTHON_CHECK_VERSION], - [prog="import sys -# split strings by '.' and convert to numeric. Append some zeros -# because we need at least 4 digits for the hex conversion. -# map returns an iterator in Python 3.0 and a list in 2.x -minver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]] -minverhex = 0 -# xrange is not present in Python 3.0 and range returns an iterator -for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]] -sys.exit(sys.hexversion < minverhex)" - AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])]) diff --git a/config/tap-driver.py b/config/tap-driver.py deleted file mode 100644 index a4864fa..0000000 --- a/config/tap-driver.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python - -#TODO LICENSE FROM FLUX - -import sys -import os - -def main(): - arguments = sys.argv[1:] # 0 is me - try: - args_split_point = arguments.index('--') - driver_args = arguments[:args_split_point] - test_command = arguments[args_split_point+1:] - except ValueError: - for idx, value in enumerate(arguments): - if not value.startswith('--'): - driver_args = arguments[:idx] - test_command = arguments[idx:] - break - - driver = os.path.join(os.path.dirname(os.path.realpath(__file__)), "tap-driver.sh") - full_command = [driver] + driver_args + ["--", sys.executable] + test_command - os.execv(driver, full_command) - -if __name__ == "__main__": - main() diff --git a/config/tap-driver.sh b/config/tap-driver.sh deleted file mode 100755 index 4a687e2..0000000 --- a/config/tap-driver.sh +++ /dev/null @@ -1,678 +0,0 @@ -#! /bin/sh -# Copyright (C) 2011-2013 Free Software Foundation, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# This file is maintained in Automake, please report -# bugs to or send patches to -# . - -scriptversion=2013-12-23.17; # UTC - -# Make unconditional expansion of undefined variables an error. This -# helps a lot in preventing typo-related bugs. -set -u - -me=tap-driver.sh - -fatal () -{ - echo "$me: fatal: $*" >&2 - exit 1 -} - -usage_error () -{ - echo "$me: $*" >&2 - print_usage >&2 - exit 2 -} - -print_usage () -{ - cat < - # - trap : 1 3 2 13 15 - if test $merge -gt 0; then - exec 2>&1 - else - exec 2>&3 - fi - "$@" - echo $? - ) | LC_ALL=C ${AM_TAP_AWK-awk} \ - -v me="$me" \ - -v test_script_name="$test_name" \ - -v log_file="$log_file" \ - -v trs_file="$trs_file" \ - -v expect_failure="$expect_failure" \ - -v merge="$merge" \ - -v ignore_exit="$ignore_exit" \ - -v comments="$comments" \ - -v diag_string="$diag_string" \ - -v quiet="$TAP_DRIVER_QUIET" \ -' -# TODO: the usages of "cat >&3" below could be optimized when using -# GNU awk, and/on on systems that supports /dev/fd/. - -# Implementation note: in what follows, `result_obj` will be an -# associative array that (partly) simulates a TAP result object -# from the `TAP::Parser` perl module. - -## ----------- ## -## FUNCTIONS ## -## ----------- ## - -function fatal(msg) -{ - print me ": " msg | "cat >&2" - exit 1 -} - -function abort(where) -{ - fatal("internal error " where) -} - -# Convert a boolean to a "yes"/"no" string. -function yn(bool) -{ - return bool ? "yes" : "no"; -} - -function add_test_result(result) -{ - if (!test_results_index) - test_results_index = 0 - test_results_list[test_results_index] = result - test_results_index += 1 - test_results_seen[result] = 1; -} - -# Whether the test script should be re-run by "make recheck". -function must_recheck() -{ - for (k in test_results_seen) - if (k != "XFAIL" && k != "PASS" && k != "SKIP") - return 1 - return 0 -} - -# Whether the content of the log file associated to this test should -# be copied into the "global" test-suite.log. -function copy_in_global_log() -{ - for (k in test_results_seen) - if (k != "PASS") - return 1 - return 0 -} - -function get_global_test_result() -{ - if ("ERROR" in test_results_seen) - return "ERROR" - if ("FAIL" in test_results_seen || "XPASS" in test_results_seen) - return "FAIL" - all_skipped = 1 - for (k in test_results_seen) - if (k != "SKIP") - all_skipped = 0 - if (all_skipped) - return "SKIP" - return "PASS"; -} - -function summarize_global_test_result() -{ - i = 0 - for (k in test_results_list) { - i += 1 - totals[ test_results_list[k] ] += 1 - } - res = sprintf ("N=%-3d PASS=%-3d FAIL=%d SKIP=%d XPASS=%d XFAIL=%d", - i, totals["PASS"], totals["FAIL"], - totals["SKIP"], totals["XPASS"], - totals["XFAIL"]) - return res -} - -function stringify_result_obj(result_obj) -{ - if (result_obj["is_unplanned"] || result_obj["number"] != testno) - return "ERROR" - - if (plan_seen == LATE_PLAN) - return "ERROR" - - if (result_obj["directive"] == "TODO") - return result_obj["is_ok"] ? "XPASS" : "XFAIL" - - if (result_obj["directive"] == "SKIP") - return result_obj["is_ok"] ? "SKIP" : COOKED_FAIL; - - if (length(result_obj["directive"])) - abort("in function stringify_result_obj()") - - return result_obj["is_ok"] ? COOKED_PASS : COOKED_FAIL -} - -function decorate_result(result) -{ - color_name = color_for_result[result] - if (color_name) - return color_map[color_name] "" result "" color_map["std"] - # If we are not using colorized output, or if we do not know how - # to colorize the given result, we should return it unchanged. - return result -} - -function report(result, details) -{ - if (result ~ /^(X?(PASS|FAIL)|SKIP|ERROR)/) - { - msg = ": " test_script_name - add_test_result(result) - } - else if (result == "#") - { - msg = " " test_script_name ":" - } - else - { - abort("in function report()") - } - if (length(details)) - msg = msg " " details - # Output on console might be colorized. - if (!quiet || result ~ /^(FAIL|ERROR)/) - print decorate_result(result) msg - # Log the result in the log file too, to help debugging (this is - # especially true when said result is a TAP error or "Bail out!"). - print result msg | "cat >&3"; -} - -function testsuite_error(error_message) -{ - report("ERROR", "- " error_message) -} - -function handle_tap_result() -{ - details = result_obj["number"]; - if (length(result_obj["description"])) - details = details " " result_obj["description"] - - if (plan_seen == LATE_PLAN) - { - details = details " # AFTER LATE PLAN"; - } - else if (result_obj["is_unplanned"]) - { - details = details " # UNPLANNED"; - } - else if (result_obj["number"] != testno) - { - details = sprintf("%s # OUT-OF-ORDER (expecting %d)", - details, testno); - } - else if (result_obj["directive"]) - { - details = details " # " result_obj["directive"]; - if (length(result_obj["explanation"])) - details = details " " result_obj["explanation"] - } - - report(stringify_result_obj(result_obj), details) -} - -# `skip_reason` should be empty whenever planned > 0. -function handle_tap_plan(planned, skip_reason) -{ - planned += 0 # Avoid getting confused if, say, `planned` is "00" - if (length(skip_reason) && planned > 0) - abort("in function handle_tap_plan()") - if (plan_seen) - { - # Error, only one plan per stream is acceptable. - testsuite_error("multiple test plans") - return; - } - planned_tests = planned - # The TAP plan can come before or after *all* the TAP results; we speak - # respectively of an "early" or a "late" plan. If we see the plan line - # after at least one TAP result has been seen, assume we have a late - # plan; in this case, any further test result seen after the plan will - # be flagged as an error. - plan_seen = (testno >= 1 ? LATE_PLAN : EARLY_PLAN) - # If testno > 0, we have an error ("too many tests run") that will be - # automatically dealt with later, so do not worry about it here. If - # $plan_seen is true, we have an error due to a repeated plan, and that - # has already been dealt with above. Otherwise, we have a valid "plan - # with SKIP" specification, and should report it as a particular kind - # of SKIP result. - if (planned == 0 && testno == 0) - { - if (length(skip_reason)) - skip_reason = "- " skip_reason; - report("SKIP", skip_reason); - } -} - -function extract_tap_comment(line) -{ - if (index(line, diag_string) == 1) - { - # Strip leading `diag_string` from `line`. - line = substr(line, length(diag_string) + 1) - # And strip any leading and trailing whitespace left. - sub("^[ \t]*", "", line) - sub("[ \t]*$", "", line) - # Return what is left (if any). - return line; - } - return ""; -} - -# When this function is called, we know that line is a TAP result line, -# so that it matches the (perl) RE "^(not )?ok\b". -function setup_result_obj(line) -{ - # Get the result, and remove it from the line. - result_obj["is_ok"] = (substr(line, 1, 2) == "ok" ? 1 : 0) - sub("^(not )?ok[ \t]*", "", line) - - # If the result has an explicit number, get it and strip it; otherwise, - # automatically assing the next progresive number to it. - if (line ~ /^[0-9]+$/ || line ~ /^[0-9]+[^a-zA-Z0-9_]/) - { - match(line, "^[0-9]+") - # The final `+ 0` is to normalize numbers with leading zeros. - result_obj["number"] = substr(line, 1, RLENGTH) + 0 - line = substr(line, RLENGTH + 1) - } - else - { - result_obj["number"] = testno - } - - if (plan_seen == LATE_PLAN) - # No further test results are acceptable after a "late" TAP plan - # has been seen. - result_obj["is_unplanned"] = 1 - else if (plan_seen && testno > planned_tests) - result_obj["is_unplanned"] = 1 - else - result_obj["is_unplanned"] = 0 - - # Strip trailing and leading whitespace. - sub("^[ \t]*", "", line) - sub("[ \t]*$", "", line) - - # This will have to be corrected if we have a "TODO"/"SKIP" directive. - result_obj["description"] = line - result_obj["directive"] = "" - result_obj["explanation"] = "" - - if (index(line, "#") == 0) - return # No possible directive, nothing more to do. - - # Directives are case-insensitive. - rx = "[ \t]*#[ \t]*([tT][oO][dD][oO]|[sS][kK][iI][pP])[ \t]*" - - # See whether we have the directive, and if yes, where. - pos = match(line, rx "$") - if (!pos) - pos = match(line, rx "[^a-zA-Z0-9_]") - - # If there was no TAP directive, we have nothing more to do. - if (!pos) - return - - # Let`s now see if the TAP directive has been escaped. For example: - # escaped: ok \# SKIP - # not escaped: ok \\# SKIP - # escaped: ok \\\\\# SKIP - # not escaped: ok \ # SKIP - if (substr(line, pos, 1) == "#") - { - bslash_count = 0 - for (i = pos; i > 1 && substr(line, i - 1, 1) == "\\"; i--) - bslash_count += 1 - if (bslash_count % 2) - return # Directive was escaped. - } - - # Strip the directive and its explanation (if any) from the test - # description. - result_obj["description"] = substr(line, 1, pos - 1) - # Now remove the test description from the line, that has been dealt - # with already. - line = substr(line, pos) - # Strip the directive, and save its value (normalized to upper case). - sub("^[ \t]*#[ \t]*", "", line) - result_obj["directive"] = toupper(substr(line, 1, 4)) - line = substr(line, 5) - # Now get the explanation for the directive (if any), with leading - # and trailing whitespace removed. - sub("^[ \t]*", "", line) - sub("[ \t]*$", "", line) - result_obj["explanation"] = line -} - -function get_test_exit_message(status) -{ - if (status == 0) - return "" - if (status !~ /^[1-9][0-9]*$/) - abort("getting exit status") - if (status < 127) - exit_details = "" - else if (status == 127) - exit_details = " (command not found?)" - else if (status >= 128 && status <= 255) - exit_details = sprintf(" (terminated by signal %d?)", status - 128) - else if (status > 256 && status <= 384) - # We used to report an "abnormal termination" here, but some Korn - # shells, when a child process die due to signal number n, can leave - # in $? an exit status of 256+n instead of the more standard 128+n. - # Apparently, both behaviours are allowed by POSIX (2008), so be - # prepared to handle them both. See also Austing Group report ID - # 0000051 - exit_details = sprintf(" (terminated by signal %d?)", status - 256) - else - # Never seen in practice. - exit_details = " (abnormal termination)" - return sprintf("exited with status %d%s", status, exit_details) -} - -function write_test_results() -{ - print ":global-test-result: " get_global_test_result() > trs_file - print ":recheck: " yn(must_recheck()) > trs_file - print ":copy-in-global-log: " yn(copy_in_global_log()) > trs_file - for (i = 0; i < test_results_index; i += 1) - print ":test-result: " test_results_list[i] > trs_file - close(trs_file); -} - -BEGIN { - -## ------- ## -## SETUP ## -## ------- ## - -'"$init_colors"' - -# Properly initialized once the TAP plan is seen. -planned_tests = 0 - -COOKED_PASS = expect_failure ? "XPASS": "PASS"; -COOKED_FAIL = expect_failure ? "XFAIL": "FAIL"; - -# Enumeration-like constants to remember which kind of plan (if any) -# has been seen. It is important that NO_PLAN evaluates "false" as -# a boolean. -NO_PLAN = 0 -EARLY_PLAN = 1 -LATE_PLAN = 2 - -testno = 0 # Number of test results seen so far. -bailed_out = 0 # Whether a "Bail out!" directive has been seen. - -# Whether the TAP plan has been seen or not, and if yes, which kind -# it is ("early" is seen before any test result, "late" otherwise). -plan_seen = NO_PLAN - -## --------- ## -## PARSING ## -## --------- ## - -is_first_read = 1 - -while (1) - { - # Involutions required so that we are able to read the exit status - # from the last input line. - st = getline - if (st < 0) # I/O error. - fatal("I/O error while reading from input stream") - else if (st == 0) # End-of-input - { - if (is_first_read) - abort("in input loop: only one input line") - break - } - if (is_first_read) - { - is_first_read = 0 - nextline = $0 - continue - } - else - { - curline = nextline - nextline = $0 - $0 = curline - } - # Copy any input line verbatim into the log file. - print | "cat >&3" - # Parsing of TAP input should stop after a "Bail out!" directive. - if (bailed_out) - continue - - # TAP test result. - if ($0 ~ /^(not )?ok$/ || $0 ~ /^(not )?ok[^a-zA-Z0-9_]/) - { - testno += 1 - setup_result_obj($0) - handle_tap_result() - } - # TAP plan (normal or "SKIP" without explanation). - else if ($0 ~ /^1\.\.[0-9]+[ \t]*$/) - { - # The next two lines will put the number of planned tests in $0. - sub("^1\\.\\.", "") - sub("[^0-9]*$", "") - handle_tap_plan($0, "") - continue - } - # TAP "SKIP" plan, with an explanation. - else if ($0 ~ /^1\.\.0+[ \t]*#/) - { - # The next lines will put the skip explanation in $0, stripping - # any leading and trailing whitespace. This is a little more - # tricky in truth, since we want to also strip a potential leading - # "SKIP" string from the message. - sub("^[^#]*#[ \t]*(SKIP[: \t][ \t]*)?", "") - sub("[ \t]*$", ""); - handle_tap_plan(0, $0) - } - # "Bail out!" magic. - # Older versions of prove and TAP::Harness (e.g., 3.17) did not - # recognize a "Bail out!" directive when preceded by leading - # whitespace, but more modern versions (e.g., 3.23) do. So we - # emulate the latter, "more modern" behaviour. - else if ($0 ~ /^[ \t]*Bail out!/) - { - bailed_out = 1 - # Get the bailout message (if any), with leading and trailing - # whitespace stripped. The message remains stored in `$0`. - sub("^[ \t]*Bail out![ \t]*", ""); - sub("[ \t]*$", ""); - # Format the error message for the - bailout_message = "Bail out!" - if (length($0)) - bailout_message = bailout_message " " $0 - testsuite_error(bailout_message) - } - # Maybe we have too look for dianogtic comments too. - else if (comments != 0) - { - comment = extract_tap_comment($0); - if (length(comment)) - report("#", comment); - } - } - -## -------- ## -## FINISH ## -## -------- ## -# In quiet mode, issue summary now: -if (quiet) { - printf ("%26s: %5s: %s\n", - test_script_name, - decorate_result(get_global_test_result()), - summarize_global_test_result()) -} - -# A "Bail out!" directive should cause us to ignore any following TAP -# error, as well as a non-zero exit status from the TAP producer. -if (!bailed_out) - { - if (!plan_seen) - { - testsuite_error("missing test plan") - } - else if (planned_tests != testno) - { - bad_amount = testno > planned_tests ? "many" : "few" - testsuite_error(sprintf("too %s tests run (expected %d, got %d)", - bad_amount, planned_tests, testno)) - } - if (!ignore_exit) - { - # Fetch exit status from the last line. - exit_message = get_test_exit_message(nextline) - if (exit_message) - testsuite_error(exit_message) - } - } - -write_test_results() - -exit 0 - -} # End of "BEGIN" block. -' - -# TODO: document that we consume the file descriptor 3 :-( -} 3>"$log_file" - -test $? -eq 0 || fatal "I/O or internal error" - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/config/test-driver b/config/test-driver deleted file mode 100755 index 32bf39e..0000000 --- a/config/test-driver +++ /dev/null @@ -1,127 +0,0 @@ -#! /bin/sh -# test-driver - basic testsuite driver script. - -scriptversion=2012-06-27.10; # UTC - -# Copyright (C) 2011-2013 Free Software Foundation, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# This file is maintained in Automake, please report -# bugs to or send patches to -# . - -# Make unconditional expansion of undefined variables an error. This -# helps a lot in preventing typo-related bugs. -set -u - -usage_error () -{ - echo "$0: $*" >&2 - print_usage >&2 - exit 2 -} - -print_usage () -{ - cat <$log_file 2>&1 -estatus=$? -if test $enable_hard_errors = no && test $estatus -eq 99; then - estatus=1 -fi - -case $estatus:$expect_failure in - 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; - 0:*) col=$grn res=PASS recheck=no gcopy=no;; - 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; - 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; - *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; - *:*) col=$red res=FAIL recheck=yes gcopy=yes;; -esac - -# Report outcome to console. -echo "${col}${res}${std}: $test_name" - -# Register the test result, and other relevant metadata. -echo ":test-result: $res" > $trs_file -echo ":global-test-result: $res" >> $trs_file -echo ":recheck: $recheck" >> $trs_file -echo ":copy-in-global-log: $gcopy" >> $trs_file - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/configure.ac b/configure.ac index 954066c..66f7d44 100644 --- a/configure.ac +++ b/configure.ac @@ -57,25 +57,21 @@ AC_CHECK_FUNCS([regcomp strchr strerror]) ################ Python Configuration ################ -# Edit PATH to remove $PWD/src/cmd so that AM_PATH_PYTHON doesn't find -# mpibind python script (thus creating a link to itself.) This needs to be -# done *before* AX_PYTHON_DEVEL. -# -saved_PATH=$PATH -export PATH=$(echo $PATH | sed "s|$(pwd)/src/cmd:*||") - +# Set python_version to 3 if no user requested version if test "X$PYTHON_VERSION" = "X" ; then if test "X$PYTHON" = "X" ; then - # if the user hasn't specified, try for python 3 PYTHON_VERSION=3 fi fi # Do not let AX_PYTHON_DEVEL set PYTHON_SITE_PKG +# AX_PYTHON_DEVEL supplies the PYTHON_VERSION variable +# https://www.gnu.org/software/autoconf-archive/ax_python_devel.html saved_PYTHON_SITE_PKG=$PYTHON_SITE_PKG AX_PYTHON_DEVEL([>='3.6']) PYTHON_SITE_PKG=$saved_PYTHON_SITE_PKG +# Verify that some version of python was discovered AM_PATH_PYTHON([$ac_python_version]) if test "X$PYTHON" = "X"; then AC_MSG_ERROR([could not find python]) @@ -83,20 +79,21 @@ fi if test "X$PYTHON" = "X"; then AC_MSG_ERROR([could not find python]) fi -# Restore original PATH: -export PATH=${saved_PATH} - -# Flag for PYTHON_LDFLAGS workaround below. -if test -n "$PYTHON_LDFLAGS"; then - ac_python_ldflags_set_by_user=true -fi +# Verify that the discovered python has the required modules AM_CHECK_PYMOD(cffi, [StrictVersion(cffi.__version__) >= StrictVersion('1.1.0')], , [AC_MSG_ERROR([could not find python module cffi, version 1.1+ required])] ) +AM_CHECK_PYMOD(wheel, + [StrictVersion(wheel.__version__) >= StrictVersion('0.0.0')], + , + [AC_MSG_ERROR([could not find python module wheel, any version should do])] + ) + +# Set up locations for python bindings AS_VAR_SET(mpibindpydir, $pyexecdir/mpibind) AC_SUBST(mpibindpydir) AS_VAR_SET(mpibindpysodir, $pyexecdir/_mpibind) diff --git a/test-suite/Makefile.am b/test-suite/Makefile.am index 029e2b1..414b83e 100644 --- a/test-suite/Makefile.am +++ b/test-suite/Makefile.am @@ -40,7 +40,8 @@ TESTS = \ AM_TESTS_ENVIRONMENT = \ export PYTHONPATH="$(abs_top_builddir)/bindings/python:$(abs_top_builddir)/test-suite/python::$$PYTHONPATH";\ - export PYTHON="${PYTHON}"; + export PYTHON="${PYTHON}";\ + cp $(top_srcdir)/config/tap-driver.py; clean-local: - rm -rf trash-directory.* test-results .prove *.broker.log */*.broker.log *.output python/__pycache__ + rm -rf trash-directory.* test-results .prove *.broker.log */*.broker.log *.output python/__pycache__ \ No newline at end of file diff --git a/test-suite/tap-driver.py b/test-suite/tap-driver.py new file mode 100644 index 0000000..40c1300 --- /dev/null +++ b/test-suite/tap-driver.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python +import sys +import os +import argparse + +def get_tap_driver(driver_path): + return os.path.join(os.path.dirname(os.path.realpath(__file__)), "tap-driver.sh") + +def get_python_executable(): + return sys.executable + +def split_arguments(args): + args_split_point = args.index('--') + return args[:args_split_point], args[args_split_point+1:] + +def build_command(driver_path, python_executable, args): + driver_args, test_path = split_arguments(args) + return [driver_path] + driver_args + ['--', python_executable] + test_path + +if __name__ == "__main__": + driver_path = get_tap_driver(sys.argv[1]) + args = sys.argv[2:] + + full_command = build_command(driver_path, get_python_executable(), args) + print(full_command) + #os.execv(driver_path, full_command) \ No newline at end of file From d68116496a9ec3c1ff6c24b3cb93c7213a5035a6 Mon Sep 17 00:00:00 2001 From: Samuel Furman Date: Thu, 13 Aug 2020 06:52:49 -0700 Subject: [PATCH 8/9] removing tests dir because we have test-suite --- tests/Makefile.am | 22 -- tests/README.md | 53 --- tests/coral-ea.c | 12 - tests/coral-lassen.c | 12 - tests/epyc-corona.c | 12 - tests/error.c | 97 ------ tests/expected/expected.coral-ea | 88 ----- tests/expected/expected.coral-lassen | 87 ----- tests/expected/expected.coral-rzansel | 86 ----- tests/expected/expected.epyc-corona | 84 ----- tests/tap.c | 362 --------------------- tests/tap.h | 115 ------- tests/test_utils.c | 449 -------------------------- tests/test_utils.h | 81 ----- 14 files changed, 1560 deletions(-) delete mode 100644 tests/Makefile.am delete mode 100644 tests/README.md delete mode 100644 tests/coral-ea.c delete mode 100644 tests/coral-lassen.c delete mode 100644 tests/epyc-corona.c delete mode 100644 tests/error.c delete mode 100644 tests/expected/expected.coral-ea delete mode 100644 tests/expected/expected.coral-lassen delete mode 100644 tests/expected/expected.coral-rzansel delete mode 100644 tests/expected/expected.epyc-corona delete mode 100644 tests/tap.c delete mode 100644 tests/tap.h delete mode 100644 tests/test_utils.c delete mode 100644 tests/test_utils.h diff --git a/tests/Makefile.am b/tests/Makefile.am deleted file mode 100644 index 535b409..0000000 --- a/tests/Makefile.am +++ /dev/null @@ -1,22 +0,0 @@ -AM_CFLAGS= -Wall -Werror -I$(top_srcdir)/src $(HWLOC_CFLAGS) -LDADD = ../src/libmpibind.la libtap.la $(HWLOC_LIBS) - -lib_LTLIBRARIES = libtap.la -libtap_la_SOURCES = tap.c tap.h - -TESTS = \ - error.t \ - coral_lassen.t \ - epyc_corona.t \ - coral_ea.t - -check_PROGRAMS = $(TESTS) - -TEST_EXTENSIONS = .t -T_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \ - $(top_srcdir)/config/tap-driver.sh - -coral_lassen_t_SOURCES = coral-lassen.c test_utils.c test_utils.h -epyc_corona_t_SOURCES = epyc-corona.c test_utils.c test_utils.h -coral_ea_t_SOURCES = coral-ea.c test_utils.c test_utils.h -error_t_SOURCES = error.c test_utils.c test_utils.h diff --git a/tests/README.md b/tests/README.md deleted file mode 100644 index 7ce93ea..0000000 --- a/tests/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# Mpibind Tests - - -The current iteration of the test suite is designed to generate a set of tests based on a given topology, then compare the resultant mappings to a file that defines expected output. Generating the tests involving gathering basic information about a topology, and using that information to tweak each test to be suitable for the topology. - -An example of the answers file is below: - -``` - -# Line that start with a pound are comments! -# The first non-commented line should be the number of tests. -3 - -# 1: Map one task to every core -Map one task to every core -"1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1" -"6,54;6,54;7,55;7,55;8,56;8,56;9,57;9,57;10,58;10,58;11,59;11,59;12,60;12,60;13,61;13,61;14,62;14,62;15,63;15,63;16,64;16,64;17,65;17,65;30,78;30,78;31,79;31,79;32,80;32,80;33,81;33,81;34,82;34,82;35,83;35,83;42,90;42,90;43,91;43,91;44,92;44,92;45,93;45,93;46,94;46,94;47,95;47,95" -"0;0;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;1;1;2;2;2;2;2;2;2;2;2;2;2;2;3;3;3;3;3;3;3;3;3;3;3;3" - -# 2: Map 1 task greedily -Map 1 task greedily -"96" -"0-95" -"0-3" - -# 3: Map two tasks greedily -Map two tasks greedily -"48;48" -"0-23,48-71;24-47,72-95" -"0-1;2-3" - -``` - -The first non-blank, non-commented line in the answer file is the number of tests in the file. After that, each answer consists of four line: a description, the expected thread mapping, the expected cpu mapping, and the expected gpu_mapping for the tasks of a given mpibind run. Each of the 4 lines are wrapped in quotes. These strings are directly compared to the output of mpibind when given the corresponding input parameters. - -## Test Details - -1. Valid mpibind configurations - * Map one task to every core - * Map one task greedily - * Map two tasks greedily - * Mapping such that ntasks < #NUMA nodes but nworkers > #NUMA nodes (this makes sure mpibind accounts * for the number of threads as well - * Restrict x tasks a single core (x == machine's smt level) - * Map two tasks at smt 1 - * Map two tasks at smt (max_smt - 1) - * Map two tasks, but restrict them to a single NUMA domain - * Map number_numas tasks without GPU optimization - * Map number_numas tasks with GPU optimization -2. Error checking - * Passing NULL in place of the handle to all of the setter and getter functions. - * Trying to run mpibind with an invalid number of threads (e.g. -1) - * Trying to run mpibind with an invalid number of tasks (e.g. -1) - * Trying to run mpibind with an invalid SMT level (e.g. -1 or 8 on a machine with SMT-4 \ No newline at end of file diff --git a/tests/coral-ea.c b/tests/coral-ea.c deleted file mode 100644 index e39beb5..0000000 --- a/tests/coral-ea.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "test_utils.h" - -int main(int argc, char **argv) { - plan(NO_PLAN); - - char* topology_file = "../topo-xml/coral-ea-hwloc1.xml"; - char* answer_file = "./expected/expected.coral-ea"; - unit_test_topology(topology_file, answer_file); - - done_testing(); - return (0); -} diff --git a/tests/coral-lassen.c b/tests/coral-lassen.c deleted file mode 100644 index b5059df..0000000 --- a/tests/coral-lassen.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "test_utils.h" - -int main(int argc, char **argv) { - plan(NO_PLAN); - - char* topology_file = "../topo-xml/coral-lassen.xml"; - char* answer_file = "./expected/expected.coral-lassen"; - unit_test_topology(topology_file, answer_file); - - done_testing(); - return (0); -} diff --git a/tests/epyc-corona.c b/tests/epyc-corona.c deleted file mode 100644 index 361325c..0000000 --- a/tests/epyc-corona.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "test_utils.h" - -int main(int argc, char **argv) { - plan(NO_PLAN); - - char* topology_file = "../topo-xml/epyc-corona.xml"; - char* answer_file = "./expected/expected.epyc-corona"; - unit_test_topology(topology_file, answer_file); - - done_testing(); - return (0); -} diff --git a/tests/error.c b/tests/error.c deleted file mode 100644 index c24699b..0000000 --- a/tests/error.c +++ /dev/null @@ -1,97 +0,0 @@ -#include "test_utils.h" -#define XML_PATH "../topo-xml/coral-lassen.xml" - -/**Test passing null to all setters and getter functions**/ -int test_null_handle() { - diag("Testing passing a null handle to setters and getters"); - mpibind_t *handle = NULL; - int count; //for mpibind_get_env_var_names - - ok(mpibind_set_ntasks(handle, 4) == 1, - "mpibind_set_ntasks fails when handle == NULL"); - ok(mpibind_set_nthreads(handle, 4) == 1, - "mpibind_set_nthreads fails when handle == NULL"); - ok(mpibind_set_greedy(handle, 1) == 1, - "mpibind_set_greedy fails when handle == NULL"); - ok(mpibind_set_gpu_optim(handle, 1) == 1, - "mpibind_set_gpu_optim fails when handle == NULL"); - ok(mpibind_set_smt(handle, 1) == 1, - "mpibind_set_smt fails when handle == NULL"); - ok(mpibind_set_restrict_ids(handle, NULL) == 1, - "mpibind_set_restrict_ids fails when handle == NULL"); - ok(mpibind_set_restrict_type(handle, 1) == 1, - "mpibind_set_restrict_type fails when handle == NULL"); - ok(mpibind_set_topology(handle, NULL) == 1, - "mpibind_set_topology fails when handle == NULL"); - ok(mpibind_set_env_vars(handle) == 1, - "mpibind_set_end_vars fails when handle == NULL"); - - ok(mpibind_get_nthreads(handle) == NULL, - "mpibind_get_nthreads returns NULL when handle == NULL"); - ok(mpibind_get_cpus(handle) == NULL, - "mpibind_get_cpus returns NULL when handle == NULL"); - ok(mpibind_get_gpus(handle) == NULL, - "mpibind_get_gpus returns NULL when handle == NULL"); - ok(mpibind_get_gpu_type(handle) == -1, - "mpibind_get_gpu_type returns NULL when handle == NULL"); - ok(mpibind_get_topology(handle) == NULL, - "mpibind_get_topology returns NULL when handle == NULL"); - ok(mpibind_get_env_var_values(handle, NULL) == NULL, - "mpibind_get_env_var_values returns NULL when handle == NULL"); - ok(mpibind_get_env_var_names(handle, &count) == NULL, - "mpibind_get_env_var_names returns NULL when handle == NULL"); - ok(mpibind_finalize(handle) == 1, - "mpibind_finalize fails when handle == NULL"); - - return 0; -} - -int test_mpibind_errors() { - mpibind_t *handle; - hwloc_topology_t topo; - - // setup topology - hwloc_topology_init(&topo); - hwloc_topology_set_xml(topo, XML_PATH); - hwloc_topology_set_all_types_filter(topo, HWLOC_TYPE_FILTER_KEEP_STRUCTURE); - hwloc_topology_set_type_filter(topo, HWLOC_OBJ_OS_DEVICE, - HWLOC_TYPE_FILTER_KEEP_IMPORTANT); - hwloc_topology_load(topo); - - mpibind_init(&handle); - - int ntasks = 5; - mpibind_set_ntasks(handle, ntasks); - mpibind_set_nthreads(handle, 4); - mpibind_set_greedy(handle, 0); - mpibind_set_gpu_optim(handle, 0); - mpibind_set_smt(handle, 2); - - diag("Testing error handling in mpibind()"); - - mpibind_set_nthreads(handle, -4); - ok(mpibind(handle) == 1, "Mapping fails if nthreads is invalid"); - - mpibind_set_nthreads(handle, 4); - mpibind_set_ntasks(handle, -1); - ok(mpibind(handle) == 1, "Mapping fails if ntasks is invalid"); - - mpibind_set_ntasks(handle, 4); - mpibind_set_smt(handle, -1); - ok(mpibind(handle) == 1, "Mapping fails if smt is invalid"); - - mpibind_set_smt(handle, 16); - ok(mpibind(handle) == 1, "Mapping fails if smt is valid but too high"); - - // TODO: ERROR CODES RELATED TO RESTRICT SETS - todo("Error codes related to restrict sets"); - return 0; -} - -int main(int argc, char **argv) { - plan(NO_PLAN); - test_null_handle(); - test_mpibind_errors(); - done_testing(); - return (0); -} diff --git a/tests/expected/expected.coral-ea b/tests/expected/expected.coral-ea deleted file mode 100644 index 1cab3fa..0000000 --- a/tests/expected/expected.coral-ea +++ /dev/null @@ -1,88 +0,0 @@ -# Line that start with a pound are comments! -# The first non-commented line should be the number of tests. -# After the number of tests, each answer description consist of 4 lines: -# The test description, the thread mapping, the cpu mapping, and the -# gpu_mapping.The mapping for each task is separated by a defined character. -# This separator can be changed in test_utils.c::parse_answer() - -11 - - -# 1: Map one task to every core -Map one task to every core -"1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1" -"0;8;16;24;32;40;48;56;64;72;80;88;96;104;112;120;128;136;144;152" -";;;;;;;;;;;;;;;;;;;" - -# 2: Map 1 task greedily -Map 1 task greedily -"160" -"0-159" -"" - - -# 3: Map two tasks greedily -Map two tasks greedily -"10;10" -"0,8,16,24,32,40,48,56,64,72;80,88,96,104,112,120,128,136,144,152" -";" - -# 4: -Mapping such that ntasks < #NUMA nodes but nworkers > #NUMA nodes -"160" -"0-159" -"" - - -# 5: -Restrict x tasks a single core (x == machine's smt level) -"1;1;1;1;1;1;1;1" -"8;8;8;8;8;8;8;8" -";;;;;;;" - - -# 6: -Map two tasks at SMT 1 -"10;10" -"0,8,16,24,32,40,48,56,64,72;80,88,96,104,112,120,128,136,144,152" -";" - - -# 7: -Map 2 tasks at max smt (across all cores) -"80;80" -"0-79;80-159" -";" - - -# 8: -Map tasks at max smt-1" -"70;70" -"0-6,8-14,16-22,24-30,32-38,40-46,48-54,56-62,64-70,72-78;80-86,88-94,96-102,104-110,112-118,120-126,128-134,136-142,144-150,152-158" -";" - - -# 9: -Map two tasks, but restrict them to a single NUMA domain -"5;5" -"0,8,16,24,32;40,48,56,64,72" -";" - - -# 11: -Map num_numa tasks without GPU optimization -"10;10" -"0,8,16,24,32,40,48,56,64,72;80,88,96,104,112,120,128,136,144,152" -";" - - - -# 12: -Map num_numa tasks with GPU optimization -"10;10" -"0,8,16,24,32,40,48,56,64,72;80,88,96,104,112,120,128,136,144,152" -";" - - -# TODO: -# 13: Map using a complex configuration (exact details TBD) \ No newline at end of file diff --git a/tests/expected/expected.coral-lassen b/tests/expected/expected.coral-lassen deleted file mode 100644 index 50c3786..0000000 --- a/tests/expected/expected.coral-lassen +++ /dev/null @@ -1,87 +0,0 @@ -# Line that start with a pound are comments! -# The first non-commented line should be the number of tests. -# After the number of tests, each answer description consist of 4 lines: -# The test description, the thread mapping, the cpu mapping, and the -# gpu_mapping.The mapping for each task is separated by a defined character. -# This separator can be changed in test_utils.c::parse_answer() - -11 - - -# 1: Map one task to every core -Map one task to every core -"1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1" -"8;12;16;20;24;28;32;36;40;44;48;52;56;60;64;68;72;76;80;84;96;100;104;108;112;116;120;124;128;132;136;140;144;148;152;156;160;164;168;172" -"0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;2;2;2;2;2;2;2;2;2;2;3;3;3;3;3;3;3;3;3;3" - - -# 2: Map 1 task greedily -Map 1 task greedily -"160" -"8-87,96-175" -"0-3" - - -# 3: Map two tasks greedily -Map two tasks greedily -"20;20" -"8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84;96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172" -"0-1;2-3" - -# 4: -Mapping such that ntasks < #NUMA nodes but nworkers > #NUMA nodes -"160" -"8-87,96-175" -"0-3" - - -# 5: -Restrict x tasks a single core (x == machine's smt level) -"1;1;1;1" -"8;8;8;8" -"0;0;1;1" - - -# 6: -Map two tasks at SMT 1 -"20;20" -"8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84;96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172" -"0-1;2-3" - - -# 7: -Map 2 tasks at max smt (across all cores) -"80;80" -"8-87;96-175" -"0-1;2-3" - - -# 8: -Map tasks at max smt-1 -"60;60" -"8-10,12-14,16-18,20-22,24-26,28-30,32-34,36-38,40-42,44-46,48-50,52-54,56-58,60-62,64-66,68-70,72-74,76-78,80-82,84-86;96-98,100-102,104-106,108-110,112-114,116-118,120-122,124-126,128-130,132-134,136-138,140-142,144-146,148-150,152-154,156-158,160-162,164-166,168-170,172-174" -"0-1;2-3" - - -# 9: -Map two tasks, but restrict them to a single NUMA domain -"10;10" -"8,12,16,20,24,28,32,36,40,44;48,52,56,60,64,68,72,76,80,84" -"0;1" - - -# 11: -Map num_numa tasks without GPU optimization -"20;20" -"8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84;96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172" -"0-1;2-3" - - -# 12: -Map num_numa tasks with GPU optimization -"20;20" -"8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84;96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172" -"0-1;2-3" - -# TODO: -# 13: Map using a complex configuration (exact details TBD) \ No newline at end of file diff --git a/tests/expected/expected.coral-rzansel b/tests/expected/expected.coral-rzansel deleted file mode 100644 index b8b126f..0000000 --- a/tests/expected/expected.coral-rzansel +++ /dev/null @@ -1,86 +0,0 @@ -# Line that start with a pound are comments! -# The first non-commented line should be the number of tests. -# After the number of tests, each answer description consist of 4 lines: -# The test description, the thread mapping, the cpu mapping, and the -# gpu_mapping.The mapping for each task is separated by a defined character. -# This separator can be changed in test_utils.c::parse_answer() - -11 - -# 1: Map one task to every core -Map one task to every core -"1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1" -"8;12;16;20;24;28;32;36;40;44;48;52;56;60;64;68;72;76;80;84;96;100;104;108;112;116;120;124;128;132;136;140;144;148;152;156;160;164;168;172" -"0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;2;2;2;2;2;2;2;2;2;2;3;3;3;3;3;3;3;3;3;3" - - -# 2: Map 1 task greedily -Map 1 task greedily -"160" -"8-87,96-175" -"0-3" - - -# 3: Map two tasks greedily -Map two tasks greedily -"20;20" -"8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84;96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172" -"0-1;2-3" - -# 4: -Mapping such that ntasks < #NUMA nodes but nworkers > #NUMA nodes -"160" -"8-87,96-175" -"0-3" - - -# 5: -Restrict x tasks a single core (x == machine's smt level) -"1;1;1;1" -"8;8;8;8" -"0;0;1;1" - - -# 6: -Map two tasks at SMT 1 -"20;20" -"8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84;96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172" -"0-1;2-3" - - -# 7: -Map 2 tasks at max smt (across all cores) -"80;80" -"8-87;96-175" -"0-1;2-3" - - -# 8: -Map tasks at max smt-1 -"60;60" -"8-10,12-14,16-18,20-22,24-26,28-30,32-34,36-38,40-42,44-46,48-50,52-54,56-58,60-62,64-66,68-70,72-74,76-78,80-82,84-86;96-98,100-102,104-106,108-110,112-114,116-118,120-122,124-126,128-130,132-134,136-138,140-142,144-146,148-150,152-154,156-158,160-162,164-166,168-170,172-174" -"0-1;2-3" - - -# 9: -Map two tasks, but restrict them to a single NUMA domain -"10;10" -"96,100,104,108,112,116,120,124,128,132;136,140,144,148,152,156,160,164,168,172" -"2;3" - - -# 11: -Map num_numa tasks without GPU optimization -"20;20" -"8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84;96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172" -"0-1;2-3" - - -# 12: -Map num_numa tasks with GPU optimization -"20;20" -"8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84;96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172" -"0-1;2-3" - -# TODO: -# 13: Map using a complex configuration (exact details TBD) \ No newline at end of file diff --git a/tests/expected/expected.epyc-corona b/tests/expected/expected.epyc-corona deleted file mode 100644 index 7703313..0000000 --- a/tests/expected/expected.epyc-corona +++ /dev/null @@ -1,84 +0,0 @@ -# Line that start with a pound are comments! -# The first non-commented line should be the number of tests. -# After the number of tests, each answer description consist of 4 lines: -# The test description, the thread mapping, the cpu mapping, and the -# gpu_mapping.The mapping for each task is separated by a defined character. -# This separator can be changed in test_utils.c::parse_answer() - -11 - - -# 1: Map one task to every core -Map one task to every core -"1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1" -"6,54;6,54;7,55;7,55;8,56;8,56;9,57;9,57;10,58;10,58;11,59;11,59;12,60;12,60;13,61;13,61;14,62;14,62;15,63;15,63;16,64;16,64;17,65;17,65;30,78;30,78;31,79;31,79;32,80;32,80;33,81;33,81;34,82;34,82;35,83;35,83;42,90;42,90;43,91;43,91;44,92;44,92;45,93;45,93;46,94;46,94;47,95;47,95" -"0;0;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;1;1;2;2;2;2;2;2;2;2;2;2;2;2;3;3;3;3;3;3;3;3;3;3;3;3" - -# 2: Map 1 task greedily -Map 1 task greedily -"96" -"0-95" -"0-3" - - -# 3: Map two tasks greedily -Map two tasks greedily -"48;48" -"0-23,48-71;24-47,72-95" -"0-1;2-3" - -# 4: -Mapping such that ntasks < #NUMA nodes but nworkers > #NUMA nodes -"24;12;12;12;12;12;12" -"0-11,48-59;12-17,60-65;18-23,66-71;24-29,72-77;30-35,78-83;36-41,84-89;42-47,90-95" -"0;1;;;2;;3" - -# 5: -Restrict x tasks a single core (x == machine's smt level) -"1;1" -"0;0" -";" - -# 6: -Map two tasks at SMT 1 -"48;48" -"0-23,48-71;24-47,72-95" -"0-1;2-3" - - -# 7: -Map 2 tasks at max smt (across all cores) -"48;48" -"0-23,48-71;24-47,72-95" -"0-1;2-3" - - -# 8: -Map tasks at max smt-1 -"48;48" -"0-23,48-71;24-47,72-95" -"0-1;2-3" - - -# 9: -Map two tasks, but restrict them to a single NUMA domain -"3;3" -"0-2;3-5" -";" - - -# 11: -Map num_numa tasks without GPU optimization -"6;6;6;6;6;6;6;6" -"0-5;6-11;12-17;18-23;24-29;30-35;36-41;42-47" -";0;1;;;2;;3" - - -# 12: -Map num_numa tasks with GPU optimization -"3;3;3;3;3;3;3;3" -"6-8;9-11;12-14;15-17;30-32;33-35;42-44;45-47" -"0;0;1;1;2;2;3;3" - -# TODO: -# 13: Map using a complex configuration (exact details TBD) \ No newline at end of file diff --git a/tests/tap.c b/tests/tap.c deleted file mode 100644 index 788970a..0000000 --- a/tests/tap.c +++ /dev/null @@ -1,362 +0,0 @@ -/* -libtap - Write tests in C -Copyright 2012 Jake Gelbman -This file is licensed under the LGPL -*/ - -#define _DEFAULT_SOURCE 1 - -#include -#include -#include -#include -#include "tap.h" - -static int expected_tests = NO_PLAN; -static int failed_tests; -static int current_test; -static char *todo_mesg; - -static char * -vstrdupf (const char *fmt, va_list args) { - char *str; - int size; - va_list args2; - va_copy(args2, args); - if (!fmt) - fmt = ""; - size = vsnprintf(NULL, 0, fmt, args2) + 2; - str = malloc(size); - if (!str) { - perror("malloc error"); - exit(1); - } - vsprintf(str, fmt, args); - va_end(args2); - return str; -} - -void -tap_plan (int tests, const char *fmt, ...) { - expected_tests = tests; - if (tests == SKIP_ALL) { - char *why; - va_list args; - va_start(args, fmt); - why = vstrdupf(fmt, args); - va_end(args); - printf("1..0 "); - diag("SKIP %s\n", why); - exit(0); - } - if (tests != NO_PLAN) { - printf("1..%d\n", tests); - } -} - -int -vok_at_loc (const char *file, int line, int test, const char *fmt, - va_list args) -{ - char *name = vstrdupf(fmt, args); - if (!test) { - printf("not "); - } - printf("ok %d", ++current_test); - if (*name) - printf(" - %s", name); - if (todo_mesg) { - printf(" # TODO"); - if (*todo_mesg) - printf(" %s", todo_mesg); - } - printf("\n"); - if (!test) { - printf("# Failed "); - if (todo_mesg) - printf("(TODO) "); - printf("test "); - if (*name) - printf("'%s'\n# ", name); - printf("at %s line %d.\n", file, line); - if (!todo_mesg) - failed_tests++; - } - free(name); - return test; -} - -int -ok_at_loc (const char *file, int line, int test, const char *fmt, ...) { - va_list args; - va_start(args, fmt); - vok_at_loc(file, line, test, fmt, args); - va_end(args); - return test; -} - -static int -mystrcmp (const char *a, const char *b) { - return a == b ? 0 : !a ? -1 : !b ? 1 : strcmp(a, b); -} - -#define eq(a, b) (!mystrcmp(a, b)) -#define ne(a, b) (mystrcmp(a, b)) - -int -is_at_loc (const char *file, int line, const char *got, const char *expected, - const char *fmt, ...) -{ - int test = eq(got, expected); - va_list args; - va_start(args, fmt); - vok_at_loc(file, line, test, fmt, args); - va_end(args); - if (!test) { - diag(" got: '%s'", got); - diag(" expected: '%s'", expected); - } - return test; -} - -int -isnt_at_loc (const char *file, int line, const char *got, const char *expected, - const char *fmt, ...) -{ - int test = ne(got, expected); - va_list args; - va_start(args, fmt); - vok_at_loc(file, line, test, fmt, args); - va_end(args); - if (!test) { - diag(" got: '%s'", got); - diag(" expected: anything else"); - } - return test; -} - -int -cmp_ok_at_loc (const char *file, int line, int a, const char *op, int b, - const char *fmt, ...) -{ - int test = eq(op, "||") ? a || b - : eq(op, "&&") ? a && b - : eq(op, "|") ? a | b - : eq(op, "^") ? a ^ b - : eq(op, "&") ? a & b - : eq(op, "==") ? a == b - : eq(op, "!=") ? a != b - : eq(op, "<") ? a < b - : eq(op, ">") ? a > b - : eq(op, "<=") ? a <= b - : eq(op, ">=") ? a >= b - : eq(op, "<<") ? a << b - : eq(op, ">>") ? a >> b - : eq(op, "+") ? a + b - : eq(op, "-") ? a - b - : eq(op, "*") ? a * b - : eq(op, "/") ? a / b - : eq(op, "%") ? a % b - : diag("unrecognized operator '%s'", op); - va_list args; - va_start(args, fmt); - vok_at_loc(file, line, test, fmt, args); - va_end(args); - if (!test) { - diag(" %d", a); - diag(" %s", op); - diag(" %d", b); - } - return test; -} - -static int -find_mem_diff (const char *a, const char *b, size_t n, size_t *offset) { - size_t i; - if (a == b) - return 0; - if (!a || !b) - return 2; - for (i = 0; i < n; i++) { - if (a[i] != b[i]) { - *offset = i; - return 1; - } - } - return 0; -} - -int -cmp_mem_at_loc (const char *file, int line, const void *got, - const void *expected, size_t n, const char *fmt, ...) -{ - size_t offset; - int diff = find_mem_diff(got, expected, n, &offset); - va_list args; - va_start(args, fmt); - vok_at_loc(file, line, !diff, fmt, args); - va_end(args); - if (diff == 1) { - diag(" Difference starts at offset %d", offset); - diag(" got: 0x%02x", ((unsigned char *)got)[offset]); - diag(" expected: 0x%02x", ((unsigned char *)expected)[offset]); - } - else if (diff == 2) { - diag(" got: %s", got ? "not NULL" : "NULL"); - diag(" expected: %s", expected ? "not NULL" : "NULL"); - } - return !diff; -} - -int -diag (const char *fmt, ...) { - va_list args; - char *mesg, *line; - int i; - va_start(args, fmt); - if (!fmt) { - va_end(args); - return 0; - } - mesg = vstrdupf(fmt, args); - line = mesg; - for (i = 0; *line; i++) { - char c = mesg[i]; - if (!c || c == '\n') { - mesg[i] = '\0'; - printf("# %s\n", line); - if (!c) - break; - mesg[i] = c; - line = mesg + i + 1; - } - } - free(mesg); - va_end(args); - return 0; -} - -int -exit_status () { - int retval = 0; - if (expected_tests == NO_PLAN) { - printf("1..%d\n", current_test); - } - else if (current_test != expected_tests) { - diag("Looks like you planned %d test%s but ran %d.", - expected_tests, expected_tests > 1 ? "s" : "", current_test); - retval = 2; - } - if (failed_tests) { - diag("Looks like you failed %d test%s of %d run.", - failed_tests, failed_tests > 1 ? "s" : "", current_test); - retval = 1; - } - return retval; -} - -int -bail_out (int ignore, const char *fmt, ...) { - va_list args; - (void) ignore; - va_start(args, fmt); - printf("Bail out! "); - vprintf(fmt, args); - printf("\n"); - va_end(args); - exit(255); - return 0; -} - -void -tap_skip (int n, const char *fmt, ...) { - char *why; - va_list args; - va_start(args, fmt); - why = vstrdupf(fmt, args); - va_end(args); - while (n --> 0) { - printf("ok %d ", ++current_test); - diag("skip %s\n", why); - } - free(why); -} - -void -tap_todo (int ignore, const char *fmt, ...) { - va_list args; - (void) ignore; - va_start(args, fmt); - todo_mesg = vstrdupf(fmt, args); - va_end(args); -} - -void -tap_end_todo () { - free(todo_mesg); - todo_mesg = NULL; -} - -#ifndef _WIN32 -#include -#include -#include - -#ifndef MAP_ANONYMOUS -#ifdef MAP_ANON -#define MAP_ANONYMOUS MAP_ANON -#else -#error "System does not support mapping anonymous pages" -#endif -#endif - -/* Create a shared memory int to keep track of whether a piece of code executed -dies. to be used in the dies_ok and lives_ok macros. */ -int -tap_test_died (int status) { - static int *test_died = NULL; - int prev; - if (!test_died) { - test_died = mmap(0, sizeof (int), PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_ANONYMOUS, -1, 0); - *test_died = 0; - } - prev = *test_died; - *test_died = status; - return prev; -} - -int -like_at_loc (int for_match, const char *file, int line, const char *got, - const char *expected, const char *fmt, ...) -{ - int test; - regex_t re; - va_list args; - int err = regcomp(&re, expected, REG_EXTENDED); - if (err) { - char errbuf[256]; - regerror(err, &re, errbuf, sizeof errbuf); - fprintf(stderr, "Unable to compile regex '%s': %s at %s line %d\n", - expected, errbuf, file, line); - exit(255); - } - err = regexec(&re, got, 0, NULL, 0); - regfree(&re); - test = for_match ? !err : err; - va_start(args, fmt); - vok_at_loc(file, line, test, fmt, args); - va_end(args); - if (!test) { - if (for_match) { - diag(" '%s'", got); - diag(" doesn't match: '%s'", expected); - } - else { - diag(" '%s'", got); - diag(" matches: '%s'", expected); - } - } - return test; -} -#endif diff --git a/tests/tap.h b/tests/tap.h deleted file mode 100644 index e366a6a..0000000 --- a/tests/tap.h +++ /dev/null @@ -1,115 +0,0 @@ -/* -libtap - Write tests in C -Copyright 2012 Jake Gelbman -This file is licensed under the LGPL -*/ - -#ifndef __TAP_H__ -#define __TAP_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef va_copy -#ifdef __va_copy -#define va_copy __va_copy -#else -#define va_copy(d, s) ((d) = (s)) -#endif -#endif - -#include -#include -#include - -int vok_at_loc (const char *file, int line, int test, const char *fmt, - va_list args); -int ok_at_loc (const char *file, int line, int test, const char *fmt, - ...); -int is_at_loc (const char *file, int line, const char *got, - const char *expected, const char *fmt, ...); -int isnt_at_loc (const char *file, int line, const char *got, - const char *expected, const char *fmt, ...); -int cmp_ok_at_loc (const char *file, int line, int a, const char *op, - int b, const char *fmt, ...); -int cmp_mem_at_loc (const char *file, int line, const void *got, - const void *expected, size_t n, const char *fmt, ...); -int bail_out (int ignore, const char *fmt, ...); -void tap_plan (int tests, const char *fmt, ...); -int diag (const char *fmt, ...); -int exit_status (void); -void tap_skip (int n, const char *fmt, ...); -void tap_todo (int ignore, const char *fmt, ...); -void tap_end_todo (void); - -#define NO_PLAN -1 -#define SKIP_ALL -2 -#define ok(...) ok_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) -#define is(...) is_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) -#define isnt(...) isnt_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) -#define cmp_ok(...) cmp_ok_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) -#define cmp_mem(...) cmp_mem_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) -#define plan(...) tap_plan(__VA_ARGS__, NULL) -#define done_testing() return exit_status() -#define BAIL_OUT(...) bail_out(0, "" __VA_ARGS__, NULL) -#define pass(...) ok(1, "" __VA_ARGS__) -#define fail(...) ok(0, "" __VA_ARGS__) - -#define skip(test, ...) do {if (test) {tap_skip(__VA_ARGS__, NULL); break;} -#define end_skip } while (0) - -#define todo(...) tap_todo(0, "" __VA_ARGS__, NULL) -#define end_todo tap_end_todo() - -#define dies_ok(...) dies_ok_common(1, __VA_ARGS__) -#define lives_ok(...) dies_ok_common(0, __VA_ARGS__) - -#ifdef _WIN32 -#define like(...) tap_skip(1, "like is not implemented on Windows") -#define unlike(...) tap_skip(1, "unlike is not implemented on Windows") -#define dies_ok_common(...) \ - tap_skip(1, "Death detection is not supported on Windows") -#else -#define like(...) like_at_loc(1, __FILE__, __LINE__, __VA_ARGS__, NULL) -#define unlike(...) like_at_loc(0, __FILE__, __LINE__, __VA_ARGS__, NULL) -int like_at_loc (int for_match, const char *file, int line, - const char *got, const char *expected, - const char *fmt, ...); -#include -#include -#include -int tap_test_died (int status); -#define dies_ok_common(for_death, code, ...) \ - do { \ - int cpid; \ - int it_died; \ - tap_test_died(1); \ - cpid = fork(); \ - switch (cpid) { \ - case -1: \ - perror("fork error"); \ - exit(1); \ - case 0: \ - close(1); \ - close(2); \ - code \ - tap_test_died(0); \ - exit(0); \ - } \ - if (waitpid(cpid, NULL, 0) < 0) { \ - perror("waitpid error"); \ - exit(1); \ - } \ - it_died = tap_test_died(0); \ - if (!it_died) \ - {code} \ - ok(for_death ? it_died : !it_died, "" __VA_ARGS__); \ - } while (0) -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/tests/test_utils.c b/tests/test_utils.c deleted file mode 100644 index dd4652e..0000000 --- a/tests/test_utils.c +++ /dev/null @@ -1,449 +0,0 @@ -#include "test_utils.h" -#define TEST_DEBUG 0 -#define BUF_SIZE 1024 - -#if 0 -/** - * Prints mpibind_t imput parameters - **/ -static void print_test_params(mpibind_t *handle) { - printf( - "tasks: %d\t threads: %d\n greedy: %d\n gpu_optim: %d\n smt: %d\n " - "restr_type: %d\t restrict_ids %s", - handle->ntasks, handle->in_nthreads, handle->greedy, handle->gpu_optim, - handle->smt, handle->restr_type, handle->restr_set); -} -#endif - -/** - * Initialize a test struct to default values. - * This mimics the behavior of mpibind_init - * **/ -int mpibind_test_t_init(mpibind_test_t *hdl) { - if (hdl == NULL) { - return 1; - } - - hdl->ntasks = 0; - hdl->in_nthreads = 0; - hdl->greedy = 1; - hdl->gpu_optim = 1; - hdl->smt = 0; - hdl->restr_set = NULL; - hdl->restr_type = MPIBIND_RESTRICT_CPU; - hdl->topo = NULL; - hdl->expected = NULL; - - return 0; -} - -/** - * Prints the current state of an mpibind_test_t object - * **/ -void mpibind_test_t_print(mpibind_test_t *params) { - printf("ntasks: %d\t in_nthreads: %d\n", params->ntasks, params->in_nthreads); - printf("greedy: %d\n", params->greedy); - printf("gpu_optim: %d\n", params->gpu_optim); - printf("smt: %d\n", params->smt); - printf("restr_set: %s\t restrict_type: %d\n", params->restr_set, - params->restr_type); - printf("\n"); -} - -/** - * Frees an answer - * **/ -void mpibind_test_ans_t_free(mpibind_test_ans_t *t) { - if (!t) { - perror("mpibind_test_ans_t == NULL"); - } - - free(t->description); - free(t->thread_mapping); - free(t->gpu_mapping); - free(t->cpu_mapping); - free(t); -} - -/** - * Frees a test object - * **/ -void mpibind_test_t_free(mpibind_test_t *t) { - if (!t) { - perror("mpibind_test_t == NULL"); - } - - if (t->restr_set) { - free(t->restr_set); - } - if (t->expected) { - mpibind_test_ans_t_free(t->expected); - free(t->expected); - } - free(t); -} - -/** - * Helper function to check the cpu, gpu, and thread mappings - * **/ -void check_mapping(mpibind_t *handle, mpibind_test_ans_t *expected) { - char *separator = ";"; - char thread_map_info[BUF_SIZE] = {'\0'}; - char cpu_map_info[BUF_SIZE] = {'\0'}; - char gpu_map_info[BUF_SIZE] = {'\0'}; - - // Concat string array into single string - int i = 0; - while (i < handle->ntasks) { - sprintf(thread_map_info + strlen(thread_map_info), "%d", - handle->nthreads[i]); - hwloc_bitmap_list_snprintf(cpu_map_info + strlen(cpu_map_info), - sizeof(cpu_map_info), handle->cpus[i]); - hwloc_bitmap_list_snprintf(gpu_map_info + strlen(gpu_map_info), - sizeof(gpu_map_info), handle->gpus[i]); - - // Separate entries with the specified separator - if (++i != handle->ntasks) { - strcat(thread_map_info, separator); - strcat(cpu_map_info, separator); - strcat(gpu_map_info, separator); - } - } - - // Check mappings against expected output - if (strcmp(expected->cpu_mapping, cpu_map_info) || - strcmp(expected->gpu_mapping, gpu_map_info) || - strcmp(expected->thread_mapping, thread_map_info)) { - fail("%s", expected->description); - diag( - "\tThreads: %s (expected %s)\n\tCPU: " - "%s (expected %s)\n\tGPU: %s (expected %s)", - thread_map_info, expected->thread_mapping, cpu_map_info, - expected->cpu_mapping, gpu_map_info, expected->gpu_mapping); - } else { - pass("%s", expected->description); - } -} - -/** - * Runs a set of tests and compares them to their answers. - * **/ -void run_test(hwloc_topology_t topo, mpibind_test_t *params, - mpibind_test_ans_t *expected) { - mpibind_t *handle; - hwloc_topology_t t; - - // dup the topology so the original doesn't accidentally get destroyed - mpibind_test_t_print(params); - hwloc_topology_dup(&t, topo); - mpibind_init(&handle); - mpibind_set_topology(handle, t); - mpibind_set_ntasks(handle, params->ntasks); - mpibind_set_nthreads(handle, params->in_nthreads); - mpibind_set_greedy(handle, params->greedy); - mpibind_set_gpu_optim(handle, params->gpu_optim); - mpibind_set_smt(handle, params->smt); - mpibind_set_restrict_type(handle, params->restr_type); - - mpibind_set_restrict_ids(handle, params->restr_set); - - if (mpibind(handle)) { - fail("%s\n\tEncountered error running mpibind", expected->description); - } else { - check_mapping(handle, expected); - mpibind_finalize(handle); - } - hwloc_topology_destroy(t); -} - -/** - * Generate unit test information from a topology - * TODO: EXPLAIN - * **/ -mpibind_test_t **generate_test_information(hwloc_topology_t topo, - int *num_test_ptr) { - int num_tests = 11; - mpibind_test_t **tests = calloc(num_tests, sizeof(mpibind_test_t *)); - *num_test_ptr = num_tests; - - // find the number of components at each level - int num_numas = hwloc_get_nbobjs_by_type(topo, HWLOC_OBJ_NUMANODE); - int num_cores = hwloc_get_nbobjs_by_type(topo, HWLOC_OBJ_CORE); - -#if TEST_DEBUG - int num_pus = hwloc_get_nbobjs_by_type(topo, HWLOC_OBJ_PU); - int num_gpus = hwloc_get_nbobjs_by_type(topo, HWLOC_OBJ_OS_DEVICE); -#endif - - int numa_id = - hwloc_get_next_obj_by_type(topo, HWLOC_OBJ_NUMANODE, NULL)->os_index; - int core_id = - hwloc_get_next_obj_by_type(topo, HWLOC_OBJ_CORE, NULL)->os_index; - - // find max arity btwn all the cores on the machine - hwloc_obj_t obj = NULL; - hwloc_obj_t prev = NULL; - int max_arity = 0; - - while ((obj = hwloc_get_next_obj_by_type(topo, HWLOC_OBJ_CORE, prev))) { - if (obj->arity > max_arity) { - max_arity = obj->arity; - } - prev = obj; - } - -#if TEST_DEBUG - printf("Num numas: %d \n", num_numas); - printf("Num gpus: %d \n", num_gpus); - printf("Num cores: %d \n", num_cores); - printf("Num PUs: %d \n", num_pus); -#endif - - mpibind_test_t **ptr = tests; - mpibind_test_t *handle; - - handle = calloc(1, sizeof(mpibind_test_t)); - // 1: Map one task to every core - mpibind_test_t_init(handle); - handle->ntasks = num_cores; - *ptr++ = handle; - - handle = calloc(1, sizeof(mpibind_test_t)); - // 2: Map one task greedily - mpibind_test_t_init(handle); - handle->ntasks = 1; - handle->greedy = 1; - *ptr++ = handle; - - handle = calloc(1, sizeof(mpibind_test_t)); - // 3: Map two tasks greedily - mpibind_test_t_init(handle); - handle->ntasks = 2; - handle->greedy = 1; - *ptr++ = handle; - - handle = calloc(1, sizeof(mpibind_test_t)); - mpibind_test_t_init(handle); - // 4: Mapping such that ntasks < #NUMA nodes but nworkers > #NUMA nodes - handle->in_nthreads = num_numas * 2; - handle->ntasks = (num_numas == 1) ? 1 : num_numas - 1; - *ptr++ = handle; - - handle = calloc(1, sizeof(mpibind_test_t)); - mpibind_test_t_init(handle); - // 5: Restrict x tasks a single core (x == machine's smt level) - handle->ntasks = max_arity; - handle->restr_type = MPIBIND_RESTRICT_CPU; - handle->restr_set = calloc(10, sizeof(char)); - sprintf(handle->restr_set, "%d", core_id); - *ptr++ = handle; - - handle = calloc(1, sizeof(mpibind_test_t)); - mpibind_test_t_init(handle); - // 6: Map two tasks at smt 1 - handle->ntasks = 2; - handle->smt = 1; - *ptr++ = handle; - - handle = calloc(1, sizeof(mpibind_test_t)); - mpibind_test_t_init(handle); - // 7: Map two tasks at max_smt - handle->ntasks = 2; - handle->smt = max_arity; - *ptr++ = handle; - - handle = calloc(1, sizeof(mpibind_test_t)); - mpibind_test_t_init(handle); - // 8: Map two tasks at (max_smt - 1) - handle->ntasks = 2; - handle->smt = (max_arity == 1) ? 1 : max_arity - 1; - *ptr++ = handle; - - handle = calloc(1, sizeof(mpibind_test_t)); - mpibind_test_t_init(handle); - // 9: Map two tasks, but restrict them to a single NUMA domain - handle->ntasks = 2; - handle->restr_type = MPIBIND_RESTRICT_MEM; - handle->restr_set = calloc(10, sizeof(char)); - sprintf(handle->restr_set, "%d", numa_id); - *ptr++ = handle; - - handle = calloc(1, sizeof(mpibind_test_t)); - mpibind_test_t_init(handle); - // 11: Map num_numa tasks without GPU optimization - handle->ntasks = num_numas; - handle->gpu_optim = 0; - *ptr++ = handle; - - handle = calloc(1, sizeof(mpibind_test_t)); - mpibind_test_t_init(handle); - // 12: Map num_numa tasks with GPU optimization - handle->ntasks = num_numas; - handle->gpu_optim = 1; - *ptr++ = handle; - - // Map using a complex configuration (exact details TBD) - return tests; -} - -/** load an xml file into a topology **/ -void load_topology(hwloc_topology_t *topo, char *xml_file) { - hwloc_topology_init(topo); - if (hwloc_topology_set_xml(*topo, xml_file) < 0) - perror("Failed to set topology"); - hwloc_topology_set_all_types_filter(*topo, HWLOC_TYPE_FILTER_KEEP_STRUCTURE); - hwloc_topology_set_type_filter(*topo, HWLOC_OBJ_OS_DEVICE, - HWLOC_TYPE_FILTER_KEEP_IMPORTANT); - hwloc_topology_load(*topo); -} - -/** - * Parse a single answer from an answer file - * An answer consists of three consectutive lines with each line containing - * the thread mapping, cpu mapping, and gpu mapping in that order - * */ -static int parse_answer(mpibind_test_ans_t *expected, FILE *fp) { - if (!expected) { - return 1; - } - - char buf[BUF_SIZE]; - char *tmp; - - // Skip newlines and comments - do { - if (!fgets(buf, sizeof(buf), fp)) { - perror("error reading from file"); - exit(1); - } - } while (!strcmp(buf, "\n") || buf[0] == '#'); - - // Since we were using fgets, we need to take out the newline if present - // else it would added to the description - if ((tmp = strchr(buf, '\n')) >= 0) { - *tmp = '\0'; - } - - // Copy description -#if TEST_DEBUG - printf("%s\n", buf); -#endif - expected->description = calloc(BUF_SIZE, sizeof(char)); - strcpy(expected->description, buf); - - if (!fgets(buf, sizeof(buf), fp)) { - perror("error reading from file"); - exit(1); - } - - // Copy thread mapping -#if TEST_DEBUG - printf("%s\n", buf); -#endif - - expected->thread_mapping = calloc(BUF_SIZE, sizeof(char)); - if (sscanf(buf, "\"%[^\"]\"", expected->thread_mapping) < 0) { - perror("error parsing answers"); - exit(1); - } - - if (!fgets(buf, sizeof(buf), fp)) { - perror("error reading from file"); - exit(1); - } - - // Copy cpu mapping -#if TEST_DEBUG - printf("%s\n", buf); -#endif - expected->cpu_mapping = calloc(BUF_SIZE, sizeof(char)); - if (sscanf(buf, "\"%[^\"]\"", expected->cpu_mapping) < 0) { - perror("error parsing answers"); - exit(1); - } - - if (!fgets(buf, sizeof(buf), fp)) { - perror("error reading from file"); - exit(1); - } - - // Copy gpu mapping -#if TEST_DEBUG - printf("%s\n", buf); -#endif - expected->gpu_mapping = calloc(BUF_SIZE, sizeof(char)); - if (sscanf(buf, "\"%[^\"]\"", expected->gpu_mapping) < 0) { - perror("error parsing answers"); - exit(1); - } - - return 0; -} - -mpibind_test_ans_t **load_answers(char *filename, int *num_tests_ptr) { - int num_tests; - char buf[BUF_SIZE]; - FILE *fp = fopen(filename, "r"); - - // Remove initial whitespace - do { - if (!fgets(buf, sizeof(buf), fp)) { - perror("error reading from file"); - exit(1); - } - } while (!strcmp(buf, "\n") || buf[0] == '#'); - - // Get number of tests - sscanf(buf, "%d\n", &num_tests); -#if TEST_DEBUG - printf("load_answers: num_tests = %d\n", num_tests); -#endif - *num_tests_ptr = num_tests; - - mpibind_test_ans_t **answers = - calloc(num_tests, sizeof(mpibind_test_ans_t *)); - - // Parse answers into return pointer - int i; - for (i = 0; i < num_tests; i++) { - answers[i] = calloc(1, sizeof(mpibind_test_ans_t)); - parse_answer(answers[i], fp); - } - - // Don't forget to close the file - fclose(fp); - return answers; -} - -/** Performs a unit test using a given topology xml and an answer file. - * Test drivers should call this method - * **/ -void unit_test_topology(char *topology_filename, char *answer_filename) { - int num_answers, num_tests; - hwloc_topology_t topo; - - load_topology(&topo, topology_filename); - diag("testing %s", topology_filename); - - mpibind_test_ans_t **answers = load_answers(answer_filename, &num_answers); - mpibind_test_t **tests = generate_test_information(topo, &num_tests); - - if (num_answers != num_tests) { - BAIL_OUT("ERROR: num. answers: %d, num. tests: %d\n", num_answers, - num_tests); - } - - int i; - for (i = 0; i < num_tests; i++) { - run_test(topo, tests[i], answers[i]); - } - - // cleanup everything - for (i = 0; i < num_tests; i++) { - mpibind_test_ans_t_free(answers[i]); - mpibind_test_t_free(tests[i]); - } - free(answers); - free(tests); - hwloc_topology_destroy(topo); -} \ No newline at end of file diff --git a/tests/test_utils.h b/tests/test_utils.h deleted file mode 100644 index d502dba..0000000 --- a/tests/test_utils.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef MPIBIND_TEST_UTILS_H -#define MPIBIND_TEST_UTILS_H -#include -#include -#include - -#include "mpibind.h" -#include "mpibind-priv.h" -#include "tap.h" - -/** - * Representation of a test answer - * **/ -typedef struct { - char* description; - char* thread_mapping; - char* cpu_mapping; - char* gpu_mapping; -} mpibind_test_ans_t; -/** - * Input parameters for a test. This mimics - * the structure of mpibind_t, but is defined - * separately to make the tests independent of - * mpibind_t's definition. - * **/ -typedef struct { - /* Input parameters */ - hwloc_topology_t topo; - int ntasks; - int in_nthreads; - int greedy; - int gpu_optim; - int smt; - char* restr_set; - int restr_type; - - /* Optional place to hold an answer to a test */ - mpibind_test_ans_t* expected; -} mpibind_test_t; -/** - * Initialize a test struct to default values. - * This mimics the behavior of mpibind_init - * **/ -int mpibind_test_t_init(mpibind_test_t* hdl); -/** - * Frees an answer - * **/ -void mpibind_test_ans_t_free(mpibind_test_ans_t* t); -/** - * Frees a test object - * **/ -void mpibind_test_t_free(mpibind_test_t* t); -/** - * Prints the current state of an mpibind_test_t object - * **/ -void mpibind_test_t_print(mpibind_test_t* params); -/** Helper function to check the cpu, gpu, and thread mappings**/ -void check_mapping(mpibind_t* handle, mpibind_test_ans_t* expected); -/** - * Runs a set of tests and compares them to their answers. - * **/ -void run_test(hwloc_topology_t topo, mpibind_test_t *params, mpibind_test_ans_t *expected); -/** - * Generate unit test information from a topology - * TODO: EXPLAIN - * **/ -mpibind_test_t** generate_test_information(hwloc_topology_t topo, - int* num_test_ptr); -/** load an xml file into a topology **/ -void load_topology(hwloc_topology_t* topo, char* xml_file); -/** - * Loads a set of test answers from a file. - * num_test_ptr will be used to store the number of answers parsed - * **/ -mpibind_test_ans_t** load_answers(char* filename, int* num_tests_ptr); - -/** Performs a unit test using a given topology xml and an answer file. - * Test drivers should call this method - * **/ -void unit_test_topology(char* topology_filename, char* answer_filename); -#endif From 6289ae12d0b9cd671bbec1a9c152e6b19ed75732 Mon Sep 17 00:00:00 2001 From: Samuel Furman Date: Thu, 13 Aug 2020 10:40:20 -0700 Subject: [PATCH 9/9] working on test suite checkpoint to split --- .gitignore | 3 ++- test-suite/Makefile.am | 40 +++++++++++++++++++----------------- test-suite/python/wrapper.py | 10 ++++++--- test-suite/tap-driver-new.py | 26 +++++++++++++++++++++++ test-suite/tap-driver.py | 36 +++++++++++++++----------------- test-suite/test_utils.h | 2 +- 6 files changed, 74 insertions(+), 43 deletions(-) create mode 100644 test-suite/tap-driver-new.py diff --git a/.gitignore b/.gitignore index 2f424f5..d5d35bf 100644 --- a/.gitignore +++ b/.gitignore @@ -31,7 +31,8 @@ libltdl/ /config/lt~obsolete.m4 /config/ar-lib /config/tap-driver.sh - +/config/tap-driver.py +/config/py-compile # docs intermediate files /doc/man*/*.xml /doc/_build diff --git a/test-suite/Makefile.am b/test-suite/Makefile.am index 414b83e..755691a 100644 --- a/test-suite/Makefile.am +++ b/test-suite/Makefile.am @@ -2,18 +2,20 @@ AM_CPPFLAGS = -Wall -Werror -I$(top_srcdir)/src $(HWLOC_CFLAGS) $(TAP_CFLAGS) AM_LDFLAGS = -rpath $(TAP_LIBDIR) LDADD = $(top_srcdir)/src/libmpibind.la $(TAP_LIBS) $(HWLOC_LIBS) -TESTS = \ - error.t \ - environment.t \ - coral_lassen.t \ - epyc_corona.t \ - coral_ea.t \ - cts1_quartz.t +TEST_EXTENSIONS = .t .py -TEST_EXTENSIONS = .t +# C Tests T_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \ - $(top_srcdir)/config/tap-driver.sh + $(top_srcdir)/config/tap-driver.sh + +PROGS = \ + error.t \ + environment.t \ + coral_lassen.t \ + epyc_corona.t \ + coral_ea.t \ + cts1_quartz.t coral_lassen_t_SOURCES = coral-lassen.c test_utils.c test_utils.h epyc_corona_t_SOURCES = epyc-corona.c test_utils.c test_utils.h @@ -23,25 +25,25 @@ error_t_SOURCES = error.c test_utils.c test_utils.h environment_t_SOURCES = environment.c test_utils.c test_utils.h if HAVE_LIBTAP -check_PROGRAMS = $(TESTS) +check_PROGRAMS = $(PROGS) endif -TEST_EXTENSIONS = .t .py + +# Python Tests PY_LOG_DRIVER = $(PYTHON) $(top_srcdir)/config/tap-driver.py PYSCRIPTS = \ python/wrapper.py -TESTS = \ - $(PYSCRIPTS) - -#if HAVE_LIBTAP -#check_PROGRAMS = $(TESTS) -#endif - AM_TESTS_ENVIRONMENT = \ export PYTHONPATH="$(abs_top_builddir)/bindings/python:$(abs_top_builddir)/test-suite/python::$$PYTHONPATH";\ export PYTHON="${PYTHON}";\ - cp $(top_srcdir)/config/tap-driver.py; + cp $(top_srcdir)/test-suite/tap-driver.py $(top_srcdir)/config/tap-driver.py; + +# Run both Python and C Tests +TESTS = \ + $(PROGS) + +# $(PYSCRIPTS) clean-local: rm -rf trash-directory.* test-results .prove *.broker.log */*.broker.log *.output python/__pycache__ \ No newline at end of file diff --git a/test-suite/python/wrapper.py b/test-suite/python/wrapper.py index 83caaba..e6220a6 100644 --- a/test-suite/python/wrapper.py +++ b/test-suite/python/wrapper.py @@ -2,11 +2,15 @@ import unittest -from mpibind import wrapper +from mpibind.wrapper import MpibindWrapper + +pympibind = MpibindWrapper() + +coral_ea_topo = '../../topo-xml/coral-ea-hwloc1.xml' +coral_ea_expected = '../expected/expected.coral-ea' class WrapperTests(unittest.TestCase): - def test_placeholder(self): - self.assertTrue(True) + def test_coral_ea_1(self): if __name__ == "__main__": from pycotap import TAPTestRunner diff --git a/test-suite/tap-driver-new.py b/test-suite/tap-driver-new.py new file mode 100644 index 0000000..672cfa5 --- /dev/null +++ b/test-suite/tap-driver-new.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python +import sys +import os +import argparse + +def get_tap_driver(driver_path): + return os.path.join(os.path.dirname(os.path.realpath(__file__)), "tap-driver.sh") + +def get_python_executable(): + return sys.executable + +def split_arguments(args): + args_split_point = args.index('--') + return args[:args_split_point], args[args_split_point+1:] + +def build_command(driver_path, python_executable, args): + driver_args, test_path = split_arguments(args) + return [driver_path] + driver_args + ['--', python_executable] + test_path + +if __name__ == "__main__": + driver_path = get_tap_driver(sys.argv[1]) + args = sys.argv[2:] + + full_command = build_command(driver_path, get_python_executable(), args) + #print(full_command) + os.execv(driver_path, full_command) \ No newline at end of file diff --git a/test-suite/tap-driver.py b/test-suite/tap-driver.py index 40c1300..aa285ed 100644 --- a/test-suite/tap-driver.py +++ b/test-suite/tap-driver.py @@ -1,26 +1,24 @@ #!/usr/bin/env python import sys import os -import argparse +from os import path -def get_tap_driver(driver_path): - return os.path.join(os.path.dirname(os.path.realpath(__file__)), "tap-driver.sh") +def main(): + arguments = sys.argv[1:] # 0 is me + try: + args_split_point = arguments.index('--') + driver_args = arguments[:args_split_point] + test_command = arguments[args_split_point+1:] + except ValueError: + for idx, value in enumerate(arguments): + if not value.startswith('--'): + driver_args = arguments[:idx] + test_command = arguments[idx:] + break -def get_python_executable(): - return sys.executable - -def split_arguments(args): - args_split_point = args.index('--') - return args[:args_split_point], args[args_split_point+1:] - -def build_command(driver_path, python_executable, args): - driver_args, test_path = split_arguments(args) - return [driver_path] + driver_args + ['--', python_executable] + test_path + driver = path.join(path.dirname(path.realpath(__file__)), "tap-driver.sh") + full_command = [driver] + driver_args + ["--", sys.executable] + test_command + os.execv(driver, full_command) if __name__ == "__main__": - driver_path = get_tap_driver(sys.argv[1]) - args = sys.argv[2:] - - full_command = build_command(driver_path, get_python_executable(), args) - print(full_command) - #os.execv(driver_path, full_command) \ No newline at end of file + main() diff --git a/test-suite/test_utils.h b/test-suite/test_utils.h index fc4052e..90bb391 100644 --- a/test-suite/test_utils.h +++ b/test-suite/test_utils.h @@ -3,8 +3,8 @@ #include #include #include +#include #include "mpibind.h" -#include "tap.h" /** * The number of tests present in the test_suite.