Skip to content
Snippets Groups Projects
Select Git revision
  • 10bcb1fcad02e8f20e0c41903218fa829c297e3b
  • master default protected
  • 1.1.1
  • 1.1
  • 1.0
5 results

display.c

Blame
  • fmpi_futhark.c 6.86 KiB
    // SPDX-License-Identifier: 0BSD
    /*!
     * @file
     * @license{
     * BSD Zero Clause License
     *
     * Copyright (c) 2022 by Raphael Bach
     *
     * Permission to use, copy, modify, and/or distribute this software for any
     * purpose with or without fee is hereby granted.
     *
     * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
     * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
     * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
     * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
     * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
     * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     * PERFORMANCE OF THIS SOFTWARE.
     * }
     */
    /*==============================================================================
        INCLUDE
    ==============================================================================*/
    // Own header
    #include "internal/fmpi_futhark.h"
    // C Standard Library
    #include <assert.h>
    #include <stdbool.h>
    #include <stdlib.h> // NULL, size_t, free(), malloc()
    // Internal
    #include "internal/fmpi_common.h"
    #include "internal/fmpi_futhark_entry.h"
    #include "internal/generic/fmpi_generic.h"
    /*==============================================================================
        STATIC
    ==============================================================================*/
    typedef void * (*fmpi_futhark_new_data_func)(
        const struct fmpi_futhark_ctx * ctx, const void * data,
        size_t x, size_t y, size_t z
    );
    static const fmpi_futhark_new_data_func fmpi_futhark_new_data_func_list[] = {
       FMPI_FUTHARK_ARRAY_ENTRY_LIST(1),
       FMPI_FUTHARK_ARRAY_ENTRY_LIST(2),
       FMPI_FUTHARK_ARRAY_ENTRY_LIST(3)
    };
    /*==============================================================================
        MACRO
    ==============================================================================*/
    #define FMPI_RAISE_FUTHARK_ERROR(ctx, ...) \
    do { \
        if((ctx)->err_handler.func != NULL) { \
            FMPI_RAISE_ERROR((ctx)->err_handler, "FUTHARK", __VA_ARGS__); \
        } \
    } while(0)
    /*==============================================================================
        PUBLIC FUNCTION DEFINITION
    ==============================================================================*/
    /*------------------------------------------------------------------------------
        fmpi_futhark_init()
    ------------------------------------------------------------------------------*/
    struct fmpi_futhark_ctx * fmpi_futhark_init(
        const struct fmpi_error_handler err_handler
    ){
        struct fmpi_futhark_ctx * ctx = malloc(sizeof(*ctx));
        if(ctx == NULL) {
            FMPI_RAISE_ERROR(err_handler, "FUTHARK", "malloc(fmpi_futhark_ctx) failed!");
            return NULL;
        }
        ctx->err_handler = err_handler;
        ctx->cfg = futhark_context_config_new();
        if(ctx->cfg == NULL) {
            FMPI_RAISE_FUTHARK_ERROR(ctx, "futhark_context_config_new() failed!");
            return ctx;
        }
        ctx->ctx = futhark_context_new(ctx->cfg);
        // The doc says in case of error futhark_context_free() should be called
        // anyway, implying that futhark_context_new() returns a non-null pointer
        // even on error.
        // The code generated by futhark 0.22 says otherwise by clearly returning
        // NULL if malloc() fails.
        if(ctx->ctx == NULL) {
            FMPI_RAISE_FUTHARK_ERROR(ctx, "futhark_context_new() failed!");
            futhark_context_config_free(ctx->cfg);
            return ctx;
        }
        if(fmpi_futhark_check_error(ctx, "futhark_context_new") == true) {
            fmpi_futhark_sync(ctx);
            futhark_context_free(ctx->ctx);
            futhark_context_config_free(ctx->cfg);
        }
        return ctx;
    }
    /*------------------------------------------------------------------------------
        fmpi_futhark_exit()
    ------------------------------------------------------------------------------*/
    int fmpi_futhark_exit(struct fmpi_futhark_ctx ** const ctx)
    {
        assert(ctx != NULL);
        assert(*ctx != NULL);
    
        int err_id = 0;
        if(futhark_context_sync((*ctx)->ctx) != 0) {
            err_id = -1;
        }
        futhark_context_free((*ctx)->ctx);
        futhark_context_config_free((*ctx)->cfg);
        free(*ctx); *ctx = NULL;
        return err_id;
    }
    /*------------------------------------------------------------------------------
        fmpi_futhark_sync()
    ------------------------------------------------------------------------------*/
    int fmpi_futhark_sync(const struct fmpi_futhark_ctx * const ctx)
    {
        assert(ctx != NULL);
        const int err = futhark_context_sync(ctx->ctx);
        if(err != 0) {
            fmpi_futhark_check_error(ctx, "futhark_context_sync");
            return -1;
        }
        return 0;
    }
    /*------------------------------------------------------------------------------
        fmpi_futhark_check_error()
    ------------------------------------------------------------------------------*/
    _Bool fmpi_futhark_check_error(
        const struct fmpi_futhark_ctx * const ctx, const char * const func
    ){
        assert(ctx != NULL);
        assert(func != NULL);
        char * err_str = futhark_context_get_error(ctx->ctx);
        if(err_str != NULL) {
            FMPI_RAISE_FUTHARK_ERROR(ctx, "%s() failed! %s", func, err_str);
            free(err_str); err_str = NULL;
            return true;
        }
        return false;
    }
    /*------------------------------------------------------------------------------
        fmpi_futhark_new_data()
    ------------------------------------------------------------------------------*/
    void * fmpi_futhark_new_data(
        const struct fmpi_futhark_ctx * ctx, const void * const data,
        const enum fmpi_type type, const size_t dim_cnt,
        const size_t x, const size_t y, const size_t z
    ){
        assert(ctx != NULL);
        assert(data != NULL);
        assert(dim_cnt <= FMPI_DIM_MAX);
        const size_t idx = (type * (FMPI_DIM_MAX) + ((dim_cnt)-1));
        return fmpi_futhark_new_data_func_list[idx](ctx, data, x, y, z);
    }
    
    #define FMPI_FUTHARK_DEFINITION(D, T) \
    void * fmpi_futhark_new_##D##d_##T( \
        const struct fmpi_futhark_ctx * const ctx, const void * const array, \
        const size_t x, const size_t y, const size_t z \
    ){ \
        assert(ctx != NULL); \
        assert(array != NULL); \
        struct futhark_##T##_##D##d * data = FMPI_FUTHARK_NEW_##D(D, T, ctx->ctx, array, x, y, z); \
        if(data == NULL) { \
            fmpi_futhark_check_error(ctx, CPL_STRINGIFY(futhark_new_##T##_##D##d)); \
        } \
        fmpi_futhark_sync(ctx); \
        return data; \
    }\
    void fmpi_futhark_free_##D##d_##T( \
        const struct fmpi_futhark_ctx * const ctx, void * const array \
    ){ \
        assert(ctx != NULL); \
        assert(array != NULL); \
        fmpi_futhark_sync(ctx);\
        const int err = futhark_free_##T##_##D##d(ctx->ctx, array); \
        if(err != 0) { \
            fmpi_futhark_check_error(ctx, CPL_STRINGIFY(futhark_free_##T##_##D##d)); \
        } \
    }
    
    FMPI_DEFINE_DIM_FUNCS(FMPI_FUTHARK_DEFINITION, 1, FMPI_FUTHARK_TYPES)
    FMPI_DEFINE_DIM_FUNCS(FMPI_FUTHARK_DEFINITION, 2, FMPI_FUTHARK_TYPES)
    FMPI_DEFINE_DIM_FUNCS(FMPI_FUTHARK_DEFINITION, 3, FMPI_FUTHARK_TYPES)