/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ /* * Copyright (c) 2013 Mellanox Technologies, Inc. * All rights reserved. * Copyright (c) 2015 Los Alamos National Security, LLC. All rights * reserved. * $COPYRIGHT$ * * Additional copyrights may follow * * $HEADER$ */ /** * @file * * Atomic Operations Interface * */ #ifndef OSHMEM_MCA_ATOMIC_H #define OSHMEM_MCA_ATOMIC_H #include "oshmem_config.h" #include "oshmem/types.h" #include "oshmem/constants.h" #include "opal/util/output.h" #include "mpi.h" #include "oshmem/mca/mca.h" #include "opal/mca/base/base.h" #include "oshmem/mca/atomic/base/base.h" BEGIN_C_DECLS #define OSHMEM_ATOMIC_PTR_2_INT(ptr, size) ((size) == 8 ? *(uint64_t*)(ptr) : *(uint32_t*)(ptr)) #define DO_SHMEM_TYPE_OP(ctx, type_name, type, op, target, value, pe) do { \ int rc = OSHMEM_SUCCESS; \ size_t size = 0; \ \ RUNTIME_CHECK_INIT(); \ RUNTIME_CHECK_PE(pe); \ RUNTIME_CHECK_ADDR(target); \ \ size = sizeof(value); \ rc = MCA_ATOMIC_CALL(op( \ ctx, \ (void*)target, \ value, \ size, \ pe)); \ RUNTIME_CHECK_RC(rc); \ \ return; \ } while (0) #define OSHMEM_TYPE_OP(type_name, type, prefix, op) \ void prefix##_##type_name##_atomic_##op(type *target, type value, int pe) \ { \ DO_SHMEM_TYPE_OP(oshmem_ctx_default, type_name, type, op, \ target, value, pe); \ } #define OSHMEM_CTX_TYPE_OP(type_name, type, prefix, op) \ void prefix##_ctx_##type_name##_atomic_##op(shmem_ctx_t ctx, type *target, type value, int pe) \ { \ DO_SHMEM_TYPE_OP(ctx, type_name, type, op, \ target, value, pe); \ } #define DO_OSHMEM_TYPE_FOP(ctx, type_name, type, op, target, value, pe) do { \ int rc = OSHMEM_SUCCESS; \ size_t size = 0; \ type out_value; \ \ RUNTIME_CHECK_INIT(); \ RUNTIME_CHECK_PE(pe); \ RUNTIME_CHECK_ADDR(target); \ \ size = sizeof(out_value); \ rc = MCA_ATOMIC_CALL(f##op( \ ctx, \ (void*)target, \ (void*)&out_value, \ value, \ size, \ pe)); \ RUNTIME_CHECK_RC(rc); \ \ return out_value; \ } while (0) #define OSHMEM_TYPE_FOP(type_name, type, prefix, op) \ type prefix##_##type_name##_atomic_fetch_##op(type *target, type value, int pe) \ { \ DO_OSHMEM_TYPE_FOP(oshmem_ctx_default, type_name, type, op, \ target, value, pe); \ } #define OSHMEM_CTX_TYPE_FOP(type_name, type, prefix, op) \ type prefix##_ctx_##type_name##_atomic_fetch_##op(shmem_ctx_t ctx, type *target, type value, int pe) \ { \ DO_OSHMEM_TYPE_FOP(ctx, type_name, type, op, \ target, value, pe); \ } #define DO_OSHMEM_TYPE_FOP_NBI(ctx, type_name, type, op, fetch, target, value, pe) do { \ int rc = OSHMEM_SUCCESS; \ size_t size = 0; \ type out_value; \ \ RUNTIME_CHECK_INIT(); \ RUNTIME_CHECK_PE(pe); \ RUNTIME_CHECK_ADDR(target); \ \ size = sizeof(out_value); \ rc = MCA_ATOMIC_CALL(f##op##_nb( \ ctx, \ fetch, \ (void*)target, \ (void*)&out_value, \ value, \ size, \ pe)); \ RUNTIME_CHECK_RC(rc); \ \ return ; \ } while (0) #define OSHMEM_TYPE_FOP_NBI(type_name, type, prefix, op) \ void prefix##_##type_name##_atomic_fetch_##op##_nbi(type *fetch, type *target, type value, int pe) \ { \ DO_OSHMEM_TYPE_FOP_NBI(oshmem_ctx_default, type_name, type, op, \ fetch, target, value, pe); \ } #define OSHMEM_CTX_TYPE_FOP_NBI(type_name, type, prefix, op) \ void prefix##_ctx_##type_name##_atomic_fetch_##op##_nbi(shmem_ctx_t ctx, type *fetch, type *target, type value, int pe) \ { \ DO_OSHMEM_TYPE_FOP_NBI(ctx, type_name, type, op, \ fetch, target, value, pe); \ } /* ******************************************************************** */ struct oshmem_op_t; /* ******************************************************************** */ typedef int (*mca_atomic_base_component_init_fn_t)(bool enable_progress_threads, bool enable_threads); typedef int (*mca_atomic_base_component_finalize_fn_t)(void); typedef struct mca_atomic_base_module_1_0_0_t* (*mca_atomic_base_component_query_fn_t)(int *priority); /* ******************************************************************** */ /** * Atomic component interface * * Component interface for the atomic framework. A public * instance of this structure, called * mca_atomic_[component_name]_component, must exist in any atomic * component. */ struct mca_atomic_base_component_1_0_0_t { /** Base component description */ mca_base_component_t atomic_version; /** Base component data block */ mca_base_component_data_t atomic_data; /** Component initialization function */ mca_atomic_base_component_init_fn_t atomic_startup; mca_atomic_base_component_finalize_fn_t atomic_finalize; mca_atomic_base_component_query_fn_t atomic_query; /* priority for component */ int priority; }; typedef struct mca_atomic_base_component_1_0_0_t mca_atomic_base_component_1_0_0_t; /** Per guidance in mca.h, use the unversioned struct name if you just want to always keep up with the most recent version of the interface. */ typedef struct mca_atomic_base_component_1_0_0_t mca_atomic_base_component_t; /** * Atomic module interface * */ struct mca_atomic_base_module_1_0_0_t { /** Collective modules all inherit from opal_object */ opal_object_t super; /* Collective function pointers */ int (*atomic_add)(shmem_ctx_t ctx, void *target, uint64_t value, size_t size, int pe); int (*atomic_and)(shmem_ctx_t ctx, void *target, uint64_t value, size_t size, int pe); int (*atomic_or)(shmem_ctx_t ctx, void *target, uint64_t value, size_t size, int pe); int (*atomic_xor)(shmem_ctx_t ctx, void *target, uint64_t value, size_t size, int pe); int (*atomic_fadd)(shmem_ctx_t ctx, void *target, void *prev, uint64_t value, size_t size, int pe); int (*atomic_fand)(shmem_ctx_t ctx, void *target, void *prev, uint64_t value, size_t size, int pe); int (*atomic_for)(shmem_ctx_t ctx, void *target, void *prev, uint64_t value, size_t size, int pe); int (*atomic_fxor)(shmem_ctx_t ctx, void *target, void *prev, uint64_t value, size_t size, int pe); int (*atomic_swap)(shmem_ctx_t ctx, void *target, void *prev, uint64_t value, size_t size, int pe); int (*atomic_cswap)(shmem_ctx_t ctx, void *target, uint64_t *prev, /* prev is used internally by wrapper, we may always use 64-bit value */ uint64_t cond, uint64_t value, size_t size, int pe); int (*atomic_fadd_nb)(shmem_ctx_t ctx, void *fetch, void *target, void *prev, uint64_t value, size_t size, int pe); int (*atomic_cswap_nb)(shmem_ctx_t ctx, void *fetch, void *target, uint64_t *prev, /* prev is used internally by wrapper, we may always use 64-bit value */ uint64_t cond, uint64_t value, size_t size, int pe); int (*atomic_swap_nb)(shmem_ctx_t ctx, void *fetch, void *target, void *prev, uint64_t value, size_t size, int pe); int (*atomic_fand_nb)(shmem_ctx_t ctx, void *fetch, void *target, void *prev, uint64_t value, size_t size, int pe); int (*atomic_for_nb)(shmem_ctx_t ctx, void *fetch, void *target, void *prev, uint64_t value, size_t size, int pe); int (*atomic_fxor_nb)(shmem_ctx_t ctx, void *fetch, void *target, void *prev, uint64_t value, size_t size, int pe); }; typedef struct mca_atomic_base_module_1_0_0_t mca_atomic_base_module_1_0_0_t; /** Per guidance in mca.h, use the unversioned struct name if you just want to always keep up with the most recent version of the interface. */ typedef struct mca_atomic_base_module_1_0_0_t mca_atomic_base_module_t; OSHMEM_DECLSPEC OBJ_CLASS_DECLARATION(mca_atomic_base_module_t); /* ******************************************************************** */ /* * Macro for use in components */ #define MCA_ATOMIC_BASE_VERSION_2_0_0 \ OSHMEM_MCA_BASE_VERSION_2_1_0("atomic", 1, 0, 0) /* ******************************************************************** */ OSHMEM_DECLSPEC extern mca_atomic_base_component_t mca_atomic_base_selected_component; OSHMEM_DECLSPEC extern mca_atomic_base_module_t mca_atomic; #define MCA_ATOMIC_CALL(a) mca_atomic.atomic_ ## a END_C_DECLS #endif /* OSHMEM_MCA_ATOMIC_H */