Пример #1
0
ssize_t psmx_tagged_recv_no_event_av_table(struct fid_ep *ep, void *buf,
					   size_t len, void *desc,
					   fi_addr_t src_addr,
					   uint64_t tag, uint64_t ignore,
					   void *context)
{
	struct psmx_fid_ep *ep_priv;
	psm_mq_req_t psm_req;
	uint64_t psm_tag, psm_tagsel;
	struct fi_context *fi_context;
	int err;

	ep_priv = container_of(ep, struct psmx_fid_ep, ep);

	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
	psm_tagsel = (~ignore) | ep_priv->domain->reserved_tag_bits;

	fi_context = &ep_priv->nocomp_recv_context;

	err = psm_mq_irecv(ep_priv->domain->psm_mq,
			   psm_tag, psm_tagsel, 0, /* flags */
			   buf, len, (void *)fi_context, &psm_req);

	return psmx_errno(err);
}
Пример #2
0
ssize_t psmx_tagged_recv_no_flag_av_table(struct fid_ep *ep, void *buf,
					  size_t len, void *desc,
					  fi_addr_t src_addr,
					  uint64_t tag, uint64_t ignore,
					  void *context)
{
	struct psmx_fid_ep *ep_priv;
	psm_mq_req_t psm_req;
	uint64_t psm_tag, psm_tagsel;
	struct fi_context *fi_context;
	int err;

	ep_priv = container_of(ep, struct psmx_fid_ep, ep);

	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
	psm_tagsel = (~ignore) | ep_priv->domain->reserved_tag_bits;

	fi_context = context;
	PSMX_CTXT_TYPE(fi_context) = PSMX_TRECV_CONTEXT;
	PSMX_CTXT_USER(fi_context) = buf;
	PSMX_CTXT_EP(fi_context) = ep_priv;

	err = psm_mq_irecv(ep_priv->domain->psm_mq,
			   psm_tag, psm_tagsel, 0, /* flags */
			   buf, len, (void *)fi_context, &psm_req);
	if (err != PSM_OK)
		return psmx_errno(err);

	PSMX_CTXT_REQ(fi_context) = psm_req;
	return 0;
}
Пример #3
0
ssize_t psmx_tagged_recv_no_flag_av_table(struct fid_ep *ep, void *buf,
					  size_t len, void *desc,
					  fi_addr_t src_addr,
					  uint64_t tag, uint64_t ignore,
					  void *context)
{
	struct psmx_fid_ep *ep_priv;
	psm_mq_req_t psm_req;
	uint64_t psm_tag, psm_tagsel;
#if (PSM_VERNO_MAJOR >= 2)
	psm_mq_tag_t psm_tag2, psm_tagsel2;
	struct psmx_fid_av *av;
	psm_epaddr_t psm_epaddr;
	size_t idx;
#endif
	struct fi_context *fi_context;
	int err;

	ep_priv = container_of(ep, struct psmx_fid_ep, ep);

	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
	psm_tagsel = (~ignore) | ep_priv->domain->reserved_tag_bits;

	fi_context = context;
	PSMX_CTXT_TYPE(fi_context) = PSMX_TRECV_CONTEXT;
	PSMX_CTXT_USER(fi_context) = buf;
	PSMX_CTXT_EP(fi_context) = ep_priv;

#if (PSM_VERNO_MAJOR >= 2)
	if ((ep_priv->caps & FI_DIRECTED_RECV) && src_addr != FI_ADDR_UNSPEC) {
		av = ep_priv->av;
		idx = (size_t)src_addr;
		if (idx >= av->last)
			return -FI_EINVAL;

		psm_epaddr = av->psm_epaddrs[idx];
	}
	else {
		psm_epaddr = NULL;
	}

	PSMX_SET_TAG(psm_tag2, psm_tag, 0);
	PSMX_SET_TAG(psm_tagsel2, psm_tagsel, 0);

	err = psm_mq_irecv2(ep_priv->domain->psm_mq,
			   psm_epaddr,
			   &psm_tag2, &psm_tagsel2, 0, /* flags */
			   buf, len, (void *)fi_context, &psm_req);
#else
	err = psm_mq_irecv(ep_priv->domain->psm_mq,
			   psm_tag, psm_tagsel, 0, /* flags */
			   buf, len, (void *)fi_context, &psm_req);
#endif
	if (err != PSM_OK)
		return psmx_errno(err);

	PSMX_CTXT_REQ(fi_context) = psm_req;
	return 0;
}
Пример #4
0
int
ompi_mtl_psm_irecv(struct mca_mtl_base_module_t* mtl,
                  struct ompi_communicator_t *comm,
                  int src,
                  int tag,
                  struct opal_convertor_t *convertor,
                  struct mca_mtl_request_t *mtl_request)
{
    int ret;    
    psm_error_t err;
    mca_mtl_psm_request_t * mtl_psm_request = (mca_mtl_psm_request_t*) mtl_request;
    uint64_t mqtag;
    uint64_t tagsel;
    size_t length;
    
    ret = ompi_mtl_datatype_recv_buf(convertor,
                                     &mtl_psm_request->buf,
                                     &length, 
                                     &mtl_psm_request->free_after);
    
    if (OMPI_SUCCESS != ret) return ret;

    mtl_psm_request->length = length;
    mtl_psm_request->convertor = convertor;
    mtl_psm_request->type = OMPI_MTL_PSM_IRECV;

    PSM_MAKE_TAGSEL(src, tag, comm->c_contextid, mqtag, tagsel);

#if 0
    printf("recv bits:   0x%016llx 0x%016llx\n", mqtag, tagsel);
#endif
    err = psm_mq_irecv(ompi_mtl_psm.mq, 
		       mqtag,
		       tagsel,
		       0,
		       mtl_psm_request->buf,
		       length,
		       mtl_psm_request,
		       &mtl_psm_request->psm_request);
    
    if (err) {
      orte_show_help("help-mtl-psm.txt",
		     "error posting receive", true,
		     psm_error_get_string(err),
		     mtl_psm_request->buf, length);
      return OMPI_ERROR;
    }

    return OMPI_SUCCESS;
}
Пример #5
0
int main(void)
{
  psm_ep_t ep;
  psm_epid_t epid, remote_epid;
  psm_mq_t mq;

  psm_epaddr_t *epaddrs;

  char *send = (char*)malloc(BUF_SIZE);
  memset(send, 1, BUF_SIZE);
  char *recv = (char*)malloc(BUF_SIZE);
  memset(recv, 1, BUF_SIZE);
  psm_mq_req_t req;

  init_ep(&ep, &epid);
  write_epid((char*)&epid, sizeof(psm_epid_t), SPATH);
  sleep(5);
  read_epid((char*)&remote_epid, sizeof(psm_epid_t), CPATH);

  fprintf(stderr, "connecting...");
  connect_endpoints(ep, 1, &remote_epid, &epaddrs);
  fprintf(stderr, "done\n");

  init_mq(&ep, &mq);
  int len = 128;
  int repeat;
  int i ;
  while (len < BUF_SIZE) {
    if (len < 8388608) repeat = 1000;
    if (len < BUF_SIZE) repeat = 10;
    repeat = 10;
    for (i = 0; i < repeat; i++) {
      //      fprintf(stderr, "recv: %d\n", len);
      psm_mq_irecv(mq, 0, 0, 0, recv, len, NULL, &req);
      psm_mq_wait(&req, NULL);
      //      fprintf(stderr, "send: %d\n", len);
      psm_mq_send(mq, *epaddrs, 0, 0, send, len);
      //    fprintf(stderr, "recvd: \n");
    }
    len = len << 1;
  }

  sleep(100000);
  return 1;
}
Пример #6
0
int psmx_am_process_rma(struct psmx_fid_domain *domain, struct psmx_am_request *req)
{
	int err;
	psm_mq_req_t psm_req;

	if ((req->op & PSMX_AM_OP_MASK) == PSMX_AM_REQ_WRITE_LONG) {
		err = psm_mq_irecv(domain->psm_mq, (uint64_t)req->write.context, -1ULL,
				0, (void *)req->write.addr, req->write.len,
				(void *)&req->fi_context, &psm_req);
	} else {
		err = psm_mq_isend(domain->psm_mq, (psm_epaddr_t)req->read.peer_addr,
				0, (uint64_t)req->read.context,
				(void *)req->read.addr, req->read.len,
				(void *)&req->fi_context, &psm_req);
	}

	return psmx_errno(err);
}
Пример #7
0
ssize_t psmx_tagged_recv_no_event_av_map(struct fid_ep *ep, void *buf,
					 size_t len, void *desc,
					 fi_addr_t src_addr,
					 uint64_t tag, uint64_t ignore,
					 void *context)
{
	struct psmx_fid_ep *ep_priv;
	psm_mq_req_t psm_req;
	uint64_t psm_tag, psm_tagsel;
#if (PSM_VERNO_MAJOR >= 2)
	psm_mq_tag_t psm_tag2, psm_tagsel2;
#endif
	struct fi_context *fi_context;
	int err;

	ep_priv = container_of(ep, struct psmx_fid_ep, ep);

	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
	psm_tagsel = (~ignore) | ep_priv->domain->reserved_tag_bits;

	fi_context = &ep_priv->nocomp_recv_context;

#if (PSM_VERNO_MAJOR >= 2)
	if (! ((ep_priv->caps & FI_DIRECTED_RECV) && src_addr != FI_ADDR_UNSPEC))
		src_addr = 0;

	PSMX_SET_TAG(psm_tag2, psm_tag, 0);
	PSMX_SET_TAG(psm_tagsel2, psm_tagsel, 0);

	err = psm_mq_irecv2(ep_priv->domain->psm_mq,
			   (psm_epaddr_t)src_addr,
			   &psm_tag2, &psm_tagsel2, 0, /* flags */
			   buf, len, (void *)fi_context, &psm_req);
#else
	err = psm_mq_irecv(ep_priv->domain->psm_mq,
			   psm_tag, psm_tagsel, 0, /* flags */
			   buf, len, (void *)fi_context, &psm_req);
#endif

	return psmx_errno(err);
}
Пример #8
0
static
int pspsm_recvlook(pspsm_con_info_t *con_info)
{
	/* ToDo: rename me to something like "post a receive". */
	psm_error_t ret;
	uint64_t rtag = con_info->recv_id;
	void *context = (void *)((uintptr_t)con_info | 2);

	assert(con_info->rreq == PSM_MQ_REQINVALID);
	ret = psm_mq_irecv(pspsm_mq, rtag, mask, 0 /*flags*/,
			   con_info->rbuf, con_info->rbuflen,
			   context, &con_info->rreq);
	if (ret != PSM_OK) goto out_err;

	/* FIXME: Should probably not return an error code to indicate
	   success. */
	return -EAGAIN;

 out_err:
	pspsm_err(psm_error_get_string(ret));
	pspsm_dprint(1, "pspsm_recvlook: %s", pspsm_err_str);
	return -1;
}
Пример #9
0
int psmx_eq_poll_mq(struct psmx_fid_eq *eq, struct psmx_fid_domain *domain_if_null_eq)
{
    psm_mq_req_t psm_req;
    psm_mq_status_t psm_status;
    struct fi_context *fi_context;
    struct psmx_fid_domain *domain;
    struct psmx_fid_ep *tmp_ep;
    struct psmx_fid_eq *tmp_eq;
    struct psmx_fid_cntr *tmp_cntr;
    struct psmx_event *event;
    int multi_recv;
    int err;

    if (eq)
        domain = eq->domain;
    else
        domain = domain_if_null_eq;

    while (1) {
        err = psm_mq_ipeek(domain->psm_mq, &psm_req, NULL);

        if (err == PSM_OK) {
            err = psm_mq_test(&psm_req, &psm_status);

            fi_context = psm_status.context;

            tmp_ep = PSMX_CTXT_EP(fi_context);
            tmp_eq = NULL;
            tmp_cntr = NULL;
            multi_recv = 0;

            switch (PSMX_CTXT_TYPE(fi_context)) {
            case PSMX_NOCOMP_SEND_CONTEXT:
                tmp_ep->pending_sends--;
                if (!tmp_ep->send_cntr_event_flag)
                    tmp_cntr = tmp_ep->send_cntr;
                break;

            case PSMX_NOCOMP_RECV_CONTEXT:
                if (!tmp_ep->recv_cntr_event_flag)
                    tmp_cntr = tmp_ep->recv_cntr;
                break;

            case PSMX_NOCOMP_WRITE_CONTEXT:
                tmp_ep->pending_writes--;
                if (!tmp_ep->write_cntr_event_flag)
                    tmp_cntr = tmp_ep->write_cntr;
                break;

            case PSMX_NOCOMP_READ_CONTEXT:
                tmp_ep->pending_reads--;
                if (!tmp_ep->read_cntr_event_flag)
                    tmp_cntr = tmp_ep->read_cntr;
                break;

            case PSMX_INJECT_CONTEXT:
                tmp_ep->pending_sends--;
                if (!tmp_ep->send_cntr_event_flag)
                    tmp_cntr = tmp_ep->send_cntr;
                free(fi_context);
                break;

            case PSMX_INJECT_WRITE_CONTEXT:
                tmp_ep->pending_writes--;
                if (!tmp_ep->write_cntr_event_flag)
                    tmp_cntr = tmp_ep->write_cntr;
                free(fi_context);
                break;

            case PSMX_SEND_CONTEXT:
                tmp_ep->pending_sends--;
                tmp_eq = tmp_ep->send_eq;
                tmp_cntr = tmp_ep->send_cntr;
                break;

            case PSMX_RECV_CONTEXT:
                tmp_eq = tmp_ep->recv_eq;
                tmp_cntr = tmp_ep->recv_cntr;
                break;

            case PSMX_MULTI_RECV_CONTEXT:
                multi_recv = 1;
                tmp_eq = tmp_ep->recv_eq;
                tmp_cntr = tmp_ep->recv_cntr;
                break;

            case PSMX_READ_CONTEXT:
                tmp_ep->pending_reads--;
                tmp_eq = tmp_ep->send_eq;
                tmp_cntr = tmp_ep->read_cntr;
                break;

            case PSMX_WRITE_CONTEXT:
                tmp_ep->pending_writes--;
                tmp_eq = tmp_ep->send_eq;
                tmp_cntr = tmp_ep->write_cntr;
                break;
            }

            if (tmp_eq) {
                event = psmx_eq_create_event_from_status(tmp_eq, &psm_status);
                if (!event)
                    return -ENOMEM;

                psmx_eq_enqueue_event(tmp_eq, event);
            }

            if (tmp_cntr)
                tmp_cntr->cntr.ops->add(&tmp_cntr->cntr, 1);

            if (multi_recv) {
                struct psmx_multi_recv *req;
                psm_mq_req_t psm_req;

                req = PSMX_CTXT_USER(fi_context);
                req->offset += psm_status.nbytes;
                if (req->offset + req->min_buf_size <= req->len) {
                    err = psm_mq_irecv(tmp_ep->domain->psm_mq,
                                       req->tag, req->tagsel, req->flag,
                                       req->buf + req->offset,
                                       req->len - req->offset,
                                       (void *)fi_context, &psm_req);
                    if (err != PSM_OK)
                        return psmx_errno(err);

                    PSMX_CTXT_REQ(fi_context) = psm_req;
                }
                else {
                    if (tmp_eq) {
                        event = psmx_eq_create_event(
                                    tmp_eq,
                                    req->context,
                                    req->buf,
                                    FI_MULTI_RECV,
                                    req->len,
                                    req->len - req->offset, /* data */
                                    0,	/* tag */
                                    0,	/* olen */
                                    0);	/* err */
                        if (!event)
                            return -ENOMEM;

                        psmx_eq_enqueue_event(tmp_eq, event);
                    }

                    free(req);
                }
            }

            if (!eq || tmp_eq == eq)
                return 1;
        }
        else if (err == PSM_MQ_NO_COMPLETIONS) {
            return 0;
        }
        else {
            return psmx_errno(err);
        }
    }
}
Пример #10
0
ssize_t _psmx_readfrom(struct fid_ep *ep, void *buf, size_t len,
		       void *desc, fi_addr_t src_addr,
		       uint64_t addr, uint64_t key, void *context,
		       uint64_t flags)
{
	struct psmx_fid_ep *ep_priv;
	struct psmx_fid_av *av;
	struct psmx_epaddr_context *epaddr_context;
	struct psmx_am_request *req;
	psm_amarg_t args[8];
	int err;
	int chunk_size;
	size_t offset = 0;
	uint64_t psm_tag;
	psm_mq_req_t psm_req;
	size_t idx;

	if (flags & FI_TRIGGER) {
		struct psmx_trigger *trigger;
		struct fi_triggered_context *ctxt = context;

		trigger = calloc(1, sizeof(*trigger));
		if (!trigger)
			return -ENOMEM;

		trigger->op = PSMX_TRIGGERED_READ;
		trigger->cntr = container_of(ctxt->threshold.cntr,
					     struct psmx_fid_cntr, cntr);
		trigger->threshold = ctxt->threshold.threshold;
		trigger->read.ep = ep;
		trigger->read.buf = buf;
		trigger->read.len = len;
		trigger->read.desc = desc;
		trigger->read.src_addr = src_addr;
		trigger->read.addr = addr;
		trigger->read.key = key;
		trigger->read.context = context;
		trigger->read.flags = flags & ~FI_TRIGGER;

		psmx_cntr_add_trigger(trigger->cntr, trigger);
		return 0;
	}

	ep_priv = container_of(ep, struct psmx_fid_ep, ep);
	assert(ep_priv->domain);

	if (!buf)
		return -EINVAL;

	av = ep_priv->av;
	if (av && av->type == FI_AV_TABLE) {
		idx = src_addr;
		if (idx >= av->last)
			return -EINVAL;

		src_addr = (fi_addr_t) av->psm_epaddrs[idx];
	}
	else if (!src_addr) {
		return -EINVAL;
	}

	epaddr_context = psm_epaddr_getctxt((void *)src_addr);
	if (epaddr_context->epid == ep_priv->domain->psm_epid)
		return psmx_rma_self(PSMX_AM_REQ_READ,
				     ep_priv, buf, len, desc,
				     addr, key, context, flags, 0);

	req = calloc(1, sizeof(*req));
	if (!req)
		return -ENOMEM;

	req->op = PSMX_AM_REQ_READ;
	req->read.buf = buf;
	req->read.len = len;
	req->read.addr = addr;	/* needed? */
	req->read.key = key; 	/* needed? */
	req->read.context = context;
	req->ep = ep_priv;
	PSMX_CTXT_TYPE(&req->fi_context) = PSMX_READ_CONTEXT;
	PSMX_CTXT_USER(&req->fi_context) = context;

	if (ep_priv->send_cq_event_flag && !(flags & FI_EVENT)) {
		PSMX_CTXT_TYPE(&req->fi_context) = PSMX_NOCOMP_READ_CONTEXT;
		req->no_event = 1;
	}

	chunk_size = MIN(PSMX_AM_CHUNK_SIZE, psmx_am_param.max_reply_short);

	if (psmx_env.tagged_rma && len > chunk_size) {
		psm_tag = PSMX_RMA_BIT | ep_priv->domain->psm_epid;
		err = psm_mq_irecv(ep_priv->domain->psm_mq, psm_tag, -1ULL,
			0, buf, len, (void *)&req->fi_context, &psm_req);

		args[0].u32w0 = PSMX_AM_REQ_READ_LONG;
		args[0].u32w1 = len;
		args[1].u64 = (uint64_t)req;
		args[2].u64 = addr;
		args[3].u64 = key;
		args[4].u64 = psm_tag;
		err = psm_am_request_short((psm_epaddr_t) src_addr,
					PSMX_AM_RMA_HANDLER, args, 5, NULL, 0,
					PSM_AM_FLAG_NOREPLY, NULL, NULL);

		return 0;
	}

	args[0].u32w0 = PSMX_AM_REQ_READ;
	args[1].u64 = (uint64_t)(uintptr_t)req;
	args[3].u64 = key;
	while (len > chunk_size) {
		args[0].u32w1 = chunk_size;
		args[2].u64 = addr;
		args[4].u64 = offset;
		err = psm_am_request_short((psm_epaddr_t) src_addr,
					PSMX_AM_RMA_HANDLER, args, 5, NULL, 0,
					0, NULL, NULL);
		addr += chunk_size;
		len -= chunk_size;
		offset += chunk_size;
	}

	args[0].u32w0 = PSMX_AM_REQ_READ | PSMX_AM_EOM;
	args[0].u32w1 = len;
	args[2].u64 = addr;
	args[4].u64 = offset;
	err = psm_am_request_short((psm_epaddr_t) src_addr,
				PSMX_AM_RMA_HANDLER, args, 5, NULL, 0,
				0, NULL, NULL);

	return 0;
}
Пример #11
0
ssize_t _psmx_tagged_recv(struct fid_ep *ep, void *buf, size_t len,
			  void *desc, fi_addr_t src_addr,
			  uint64_t tag, uint64_t ignore,
			  void *context, uint64_t flags)
{
	struct psmx_fid_ep *ep_priv;
	psm_mq_req_t psm_req;
	uint64_t psm_tag, psm_tagsel;
#if (PSM_VERNO_MAJOR >= 2)
	psm_mq_tag_t psm_tag2, psm_tagsel2;
	struct psmx_fid_av *av;
	size_t idx;
#endif
	struct fi_context *fi_context;
	int err;

	ep_priv = container_of(ep, struct psmx_fid_ep, ep);

	if (flags & FI_PEEK)
		return _psmx_tagged_peek(ep, buf, len, desc, src_addr,
					 tag, ignore, context, flags);

	if (flags & FI_TRIGGER) {
		struct psmx_trigger *trigger;
		struct fi_triggered_context *ctxt = context;

		trigger = calloc(1, sizeof(*trigger));
		if (!trigger)
			return -FI_ENOMEM;

		trigger->op = PSMX_TRIGGERED_TRECV;
		trigger->cntr = container_of(ctxt->trigger.threshold.cntr,
					     struct psmx_fid_cntr, cntr);
		trigger->threshold = ctxt->trigger.threshold.threshold;
		trigger->trecv.ep = ep;
		trigger->trecv.buf = buf;
		trigger->trecv.len = len;
		trigger->trecv.desc = desc;
		trigger->trecv.src_addr = src_addr;
		trigger->trecv.tag = tag;
		trigger->trecv.ignore = ignore;
		trigger->trecv.context = context;
		trigger->trecv.flags = flags & ~FI_TRIGGER;

		psmx_cntr_add_trigger(trigger->cntr, trigger);
		return 0;
	}

#if (PSM_VERNO_MAJOR >= 2)
	if (flags & FI_CLAIM) {
		if (!context)
			return -FI_EINVAL;

		/* TODO: handle FI_DISCARD */

		fi_context = context;
		psm_req = PSMX_CTXT_REQ(fi_context);
		PSMX_CTXT_TYPE(fi_context) = PSMX_TRECV_CONTEXT;
		PSMX_CTXT_USER(fi_context) = buf;
		PSMX_CTXT_EP(fi_context) = ep_priv;

		err = psm_mq_imrecv(ep_priv->domain->psm_mq, 0, /*flags*/
				    buf, len, context, &psm_req);
		if (err != PSM_OK)
			return psmx_errno(err);

		PSMX_CTXT_REQ(fi_context) = psm_req;
		return 0;
	}
#endif

	if (tag & ep_priv->domain->reserved_tag_bits) {
		FI_WARN(&psmx_prov, FI_LOG_EP_DATA,
			"using reserved tag bits."
			"tag=%lx. reserved_bits=%lx.\n", tag,
			ep_priv->domain->reserved_tag_bits);
	}

	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
	psm_tagsel = (~ignore) | ep_priv->domain->reserved_tag_bits;

	if (ep_priv->recv_selective_completion && !(flags & FI_COMPLETION) && !context) {
		fi_context = &ep_priv->nocomp_recv_context;
	}
	else {
		if (!context)
			return -FI_EINVAL;

		fi_context = context;
		PSMX_CTXT_TYPE(fi_context) = PSMX_TRECV_CONTEXT;
		PSMX_CTXT_USER(fi_context) = buf;
		PSMX_CTXT_EP(fi_context) = ep_priv;
	}

#if (PSM_VERNO_MAJOR >= 2)
	if ((ep_priv->caps & FI_DIRECTED_RECV) && src_addr != FI_ADDR_UNSPEC) {
		av = ep_priv->av;
		if (av && av->type == FI_AV_TABLE) {
			idx = (size_t)src_addr;
			if (idx >= av->last)
				return -FI_EINVAL;

			src_addr = (fi_addr_t)av->psm_epaddrs[idx];
		}
	}
	else {
		src_addr = 0;
	}

	PSMX_SET_TAG(psm_tag2, psm_tag, 0);
	PSMX_SET_TAG(psm_tagsel2, psm_tagsel, 0);

	err = psm_mq_irecv2(ep_priv->domain->psm_mq,
			   (psm_epaddr_t)src_addr,
			   &psm_tag2, &psm_tagsel2, 0, /* flags */
			   buf, len, (void *)fi_context, &psm_req);
#else
	err = psm_mq_irecv(ep_priv->domain->psm_mq,
			   psm_tag, psm_tagsel, 0, /* flags */
			   buf, len, (void *)fi_context, &psm_req);
#endif

	if (err != PSM_OK)
		return psmx_errno(err);

	if (fi_context == context)
		PSMX_CTXT_REQ(fi_context) = psm_req;

	return 0;
}
Пример #12
0
ssize_t _psmx_tagged_recv(struct fid_ep *ep, void *buf, size_t len,
			  void *desc, fi_addr_t src_addr,
			  uint64_t tag, uint64_t ignore,
			  void *context, uint64_t flags)
{
	struct psmx_fid_ep *ep_priv;
	psm_mq_req_t psm_req;
	uint64_t psm_tag, psm_tagsel;
	struct fi_context *fi_context;
	int err;

	ep_priv = container_of(ep, struct psmx_fid_ep, ep);

	if (flags & FI_PEEK)
		return _psmx_tagged_peek(ep, buf, len, desc, src_addr,
					 tag, ignore, context, flags);

	if (flags & FI_TRIGGER) {
		struct psmx_trigger *trigger;
		struct fi_triggered_context *ctxt = context;

		trigger = calloc(1, sizeof(*trigger));
		if (!trigger)
			return -FI_ENOMEM;

		trigger->op = PSMX_TRIGGERED_TRECV;
		trigger->cntr = container_of(ctxt->trigger.threshold.cntr,
					     struct psmx_fid_cntr, cntr);
		trigger->threshold = ctxt->trigger.threshold.threshold;
		trigger->trecv.ep = ep;
		trigger->trecv.buf = buf;
		trigger->trecv.len = len;
		trigger->trecv.desc = desc;
		trigger->trecv.src_addr = src_addr;
		trigger->trecv.tag = tag;
		trigger->trecv.ignore = ignore;
		trigger->trecv.context = context;
		trigger->trecv.flags = flags & ~FI_TRIGGER;

		psmx_cntr_add_trigger(trigger->cntr, trigger);
		return 0;
	}

	if (tag & ep_priv->domain->reserved_tag_bits) {
		FI_WARN(&psmx_prov, FI_LOG_EP_DATA,
			"using reserved tag bits."
			"tag=%lx. reserved_bits=%lx.\n", tag,
			ep_priv->domain->reserved_tag_bits);
	}

	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
	psm_tagsel = (~ignore) | ep_priv->domain->reserved_tag_bits;

	if (ep_priv->recv_selective_completion && !(flags & FI_COMPLETION) && !context) {
		fi_context = &ep_priv->nocomp_recv_context;
	}
	else {
		if (!context)
			return -FI_EINVAL;

		fi_context = context;
		PSMX_CTXT_TYPE(fi_context) = PSMX_TRECV_CONTEXT;
		PSMX_CTXT_USER(fi_context) = buf;
		PSMX_CTXT_EP(fi_context) = ep_priv;
	}

	err = psm_mq_irecv(ep_priv->domain->psm_mq,
			   psm_tag, psm_tagsel, 0, /* flags */
			   buf, len, (void *)fi_context, &psm_req);

	if (err != PSM_OK)
		return psmx_errno(err);

	if (fi_context == context)
		PSMX_CTXT_REQ(fi_context) = psm_req;

	return 0;
}