1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
|
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2014-2018 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2018 Intel, Inc, All rights reserved
*
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "btl_ofi_rdma.h"
#include <rdma/fi_atomic.h>
static inline int to_fi_op(mca_btl_base_atomic_op_t op)
{
switch (op) {
case MCA_BTL_ATOMIC_ADD:
return FI_SUM;
case MCA_BTL_ATOMIC_SWAP:
return FI_ATOMIC_WRITE;
case MCA_BTL_ATOMIC_MAX:
return FI_MAX;
case MCA_BTL_ATOMIC_MIN:
return FI_MIN;
case MCA_BTL_ATOMIC_LAND:
return FI_LAND;
case MCA_BTL_ATOMIC_AND:
return FI_BAND;
case MCA_BTL_ATOMIC_LOR:
return FI_LOR;
case MCA_BTL_ATOMIC_OR:
return FI_BOR;
case MCA_BTL_ATOMIC_LXOR:
return FI_LXOR;
case MCA_BTL_ATOMIC_XOR:
return FI_BXOR;
default:
BTL_ERROR(("Unknown or unsupported atomic op."));
MCA_BTL_OFI_ABORT();
/* just to squash the warning */
return OPAL_ERROR;
}
}
int mca_btl_ofi_afop(struct mca_btl_base_module_t *btl, struct mca_btl_base_endpoint_t *endpoint,
void *local_address, uint64_t remote_address,
mca_btl_base_registration_handle_t *local_handle,
mca_btl_base_registration_handle_t *remote_handle, mca_btl_base_atomic_op_t op,
uint64_t operand, int flags, int order,
mca_btl_base_rdma_completion_fn_t cbfunc, void *cbcontext, void *cbdata)
{
int rc;
int fi_datatype = FI_UINT64;
int fi_op;
mca_btl_ofi_module_t *ofi_btl = (mca_btl_ofi_module_t *) btl;
mca_btl_ofi_endpoint_t *btl_endpoint = (mca_btl_ofi_endpoint_t *) endpoint;
mca_btl_ofi_rdma_completion_t *comp = NULL;
mca_btl_ofi_context_t *ofi_context;
MCA_BTL_OFI_NUM_RDMA_INC(ofi_btl);
ofi_context = get_ofi_context(ofi_btl);
if (flags & MCA_BTL_ATOMIC_FLAG_32BIT) {
fi_datatype = FI_UINT32;
}
fi_op = to_fi_op(op);
comp = mca_btl_ofi_rdma_completion_alloc(btl, endpoint, ofi_context, local_address,
local_handle, cbfunc, cbcontext, cbdata,
MCA_BTL_OFI_TYPE_AFOP);
/* copy the operand because it might get freed from upper layer */
comp->operand = (uint64_t) operand;
remote_address = (remote_address - (uint64_t) remote_handle->base_addr);
rc = fi_fetch_atomic(ofi_context->tx_ctx, (void *) &comp->operand, 1, NULL, /* operand */
local_address, local_handle->desc, /* results */
btl_endpoint->peer_addr, /* remote addr */
remote_address, remote_handle->rkey, /* remote buffer */
fi_datatype, fi_op, &comp->comp_ctx);
if (rc == -FI_EAGAIN) {
MCA_BTL_OFI_NUM_RDMA_DEC(ofi_btl);
opal_free_list_return(comp->base.my_list, (opal_free_list_item_t *) comp);
return OPAL_ERR_OUT_OF_RESOURCE;
} else if (rc < 0) {
MCA_BTL_OFI_NUM_RDMA_DEC(ofi_btl);
opal_free_list_return(comp->base.my_list, (opal_free_list_item_t *) comp);
BTL_ERROR(("fi_fetch_atomic failed with rc=%d (%s)", rc, fi_strerror(-rc)));
MCA_BTL_OFI_ABORT();
}
return OPAL_SUCCESS;
}
int mca_btl_ofi_aop(struct mca_btl_base_module_t *btl, mca_btl_base_endpoint_t *endpoint,
uint64_t remote_address, mca_btl_base_registration_handle_t *remote_handle,
mca_btl_base_atomic_op_t op, uint64_t operand, int flags, int order,
mca_btl_base_rdma_completion_fn_t cbfunc, void *cbcontext, void *cbdata)
{
int rc;
int fi_datatype = FI_UINT64;
int fi_op;
mca_btl_ofi_module_t *ofi_btl = (mca_btl_ofi_module_t *) btl;
mca_btl_ofi_endpoint_t *btl_endpoint = (mca_btl_ofi_endpoint_t *) endpoint;
mca_btl_ofi_rdma_completion_t *comp = NULL;
mca_btl_ofi_context_t *ofi_context;
MCA_BTL_OFI_NUM_RDMA_INC(ofi_btl);
ofi_context = get_ofi_context(ofi_btl);
if (flags & MCA_BTL_ATOMIC_FLAG_32BIT) {
fi_datatype = FI_UINT32;
}
fi_op = to_fi_op(op);
comp = mca_btl_ofi_rdma_completion_alloc(btl, endpoint, ofi_context, NULL, NULL, cbfunc,
cbcontext, cbdata, MCA_BTL_OFI_TYPE_AOP);
/* copy the operand because it might get freed from upper layer */
comp->operand = (uint64_t) operand;
remote_address = (remote_address - (uint64_t) remote_handle->base_addr);
rc = fi_atomic(ofi_context->tx_ctx, (void *) &comp->operand, 1, NULL, /* operand */
btl_endpoint->peer_addr, /* remote addr */
remote_address, remote_handle->rkey, /* remote buffer */
fi_datatype, fi_op, &comp->comp_ctx);
if (rc == -FI_EAGAIN) {
MCA_BTL_OFI_NUM_RDMA_DEC(ofi_btl);
opal_free_list_return(comp->base.my_list, (opal_free_list_item_t *) comp);
return OPAL_ERR_OUT_OF_RESOURCE;
} else if (rc < 0) {
MCA_BTL_OFI_NUM_RDMA_DEC(ofi_btl);
opal_free_list_return(comp->base.my_list, (opal_free_list_item_t *) comp);
BTL_ERROR(("fi_atomic failed with rc=%d (%s)", rc, fi_strerror(-rc)));
MCA_BTL_OFI_ABORT();
}
return OPAL_SUCCESS;
}
int mca_btl_ofi_acswap(struct mca_btl_base_module_t *btl, struct mca_btl_base_endpoint_t *endpoint,
void *local_address, uint64_t remote_address,
mca_btl_base_registration_handle_t *local_handle,
mca_btl_base_registration_handle_t *remote_handle, uint64_t compare,
uint64_t value, int flags, int order,
mca_btl_base_rdma_completion_fn_t cbfunc, void *cbcontext, void *cbdata)
{
int rc;
int fi_datatype = FI_UINT64;
mca_btl_ofi_rdma_completion_t *comp = NULL;
mca_btl_ofi_module_t *ofi_btl = (mca_btl_ofi_module_t *) btl;
mca_btl_ofi_endpoint_t *btl_endpoint = (mca_btl_ofi_endpoint_t *) endpoint;
mca_btl_ofi_context_t *ofi_context;
MCA_BTL_OFI_NUM_RDMA_INC(ofi_btl);
ofi_context = get_ofi_context(ofi_btl);
if (flags & MCA_BTL_ATOMIC_FLAG_32BIT) {
fi_datatype = FI_UINT32;
}
comp = mca_btl_ofi_rdma_completion_alloc(btl, endpoint, ofi_context, local_address,
local_handle, cbfunc, cbcontext, cbdata,
MCA_BTL_OFI_TYPE_CSWAP);
/* copy the operand because it might get freed from upper layer */
comp->operand = (uint64_t) value;
comp->compare = (uint64_t) compare;
remote_address = (remote_address - (uint64_t) remote_handle->base_addr);
/* perform atomic */
rc = fi_compare_atomic(ofi_context->tx_ctx, (void *) &comp->operand, 1, NULL,
(void *) &comp->compare, NULL, local_address, local_handle->desc,
btl_endpoint->peer_addr, remote_address, remote_handle->rkey,
fi_datatype, FI_CSWAP, &comp->comp_ctx);
if (rc == -FI_EAGAIN) {
MCA_BTL_OFI_NUM_RDMA_DEC(ofi_btl);
opal_free_list_return(comp->base.my_list, (opal_free_list_item_t *) comp);
return OPAL_ERR_OUT_OF_RESOURCE;
} else if (rc < 0) {
MCA_BTL_OFI_NUM_RDMA_DEC(ofi_btl);
opal_free_list_return(comp->base.my_list, (opal_free_list_item_t *) comp);
BTL_ERROR(("fi_compare_atomic failed with rc=%d (%s)", rc, fi_strerror(-rc)));
MCA_BTL_OFI_ABORT();
}
return OPAL_SUCCESS;
}
|