Select Git revision
fmpi_futhark.c
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)