Пример #1
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);
        }
    }
}
Пример #2
0
static int psmx_av_insert(struct fid_av *av, const void *addr, size_t count,
			  fi_addr_t *fi_addr, uint64_t flags, void *context)
{
	struct psmx_fid_av *av_priv;
	psm_error_t *errors;
	int error_count = 0;
	int *mask;
	int i, j;
	fi_addr_t *result = NULL;
	struct psmx_epaddr_context *epaddr_context;
	struct psmx_eq_event *event;

	av_priv = container_of(av, struct psmx_fid_av, av);

	if ((av_priv->flags & FI_EVENT) && !av_priv->eq)
		return -FI_ENOEQ;

	errors = (psm_error_t *) calloc(count, sizeof *errors);
	if (!errors)
		return -FI_ENOMEM;

	mask = (int *) calloc(count, sizeof *mask);
	if (!mask) {
		free(errors);
		return -FI_ENOMEM;
	}

	if (av_priv->type == FI_AV_TABLE) {
		if (psmx_av_check_table_size(av_priv, count)) {
			free(mask);
			free(errors);
			return -FI_ENOMEM;
		}

		for (i=0; i<count; i++)
			av_priv->psm_epids[av_priv->last + i] = ((psm_epid_t *)addr)[i];

		result = fi_addr;
		addr = (const void *)(av_priv->psm_epids + av_priv->last);
		fi_addr = (fi_addr_t *)(av_priv->psm_epaddrs + av_priv->last);
	}

	/* prevent connecting to the same ep twice, which is fatal in PSM */
	for (i=0; i<count; i++) {
		psm_epconn_t epconn;
		if (psm_ep_epid_lookup(((psm_epid_t *) addr)[i], &epconn) == PSM_OK) {
			epaddr_context = psm_epaddr_getctxt(epconn.addr);
			if (epaddr_context && epaddr_context->epid  == ((psm_epid_t *) addr)[i])
				((psm_epaddr_t *) fi_addr)[i] = epconn.addr;
			else
				mask[i] = 1;
		}
		else {
			mask[i] = 1;
		}
	}

	psm_ep_connect(av_priv->domain->psm_ep, count, 
			(psm_epid_t *) addr, mask, errors,
			(psm_epaddr_t *) fi_addr, 30*1e9);

	for (i=0; i<count; i++){
		if (!mask[i])
			continue;

		if (errors[i] == PSM_OK || errors[i] == PSM_EPID_ALREADY_CONNECTED) {
			psmx_set_epaddr_context(av_priv->domain,
						((psm_epid_t *) addr)[i],
						((psm_epaddr_t *) fi_addr)[i]);
		}
		else {
			FI_INFO(&psmx_prov, FI_LOG_AV,
				"%d: psm_ep_connect returned %s. remote epid=%lx.\n",
				i, psm_error_get_string(errors[i]),
				((psm_epid_t *)addr)[i]);
			if (((psm_epid_t *)addr)[i] == 0)
				FI_INFO(&psmx_prov, FI_LOG_AV,
					"does the application depend on the provider"
					"to resolve IP address into endpoint id? if so"
					"check if the name server has started correctly"
					"at the other side.\n");
			fi_addr[i] = FI_ADDR_NOTAVAIL;
			error_count++;

			if (av_priv->flags & FI_EVENT) {
				event = psmx_eq_create_event(av_priv->eq,
							     FI_AV_COMPLETE,		/* event */
							     context,			/* context */
							     i,				/* data: failed index */
							     psmx_errno(errors[i]),	/* err */
							     errors[i],			/* prov_errno */
							     NULL,			/* err_data */
							     0);			/* err_data_size */
				if (!event)
					return -FI_ENOMEM;

				psmx_eq_enqueue_event(av_priv->eq, event);
			}
		}
	}

	free(mask);
	free(errors);

	if (av_priv->type == FI_AV_TABLE) {
		/* NOTE: unresolved addresses are left in the AV table */
		if (result) {
			for (i=0; i<count; i++) {
				j = av_priv->last + i;
				if ((fi_addr_t)av_priv->psm_epaddrs[j] == FI_ADDR_NOTAVAIL)
					result[i] = FI_ADDR_NOTAVAIL;
				else
					result[i] = j;
			}
		}
		av_priv->last += count;
	}

	if (!(av_priv->flags & FI_EVENT))
		return count - error_count;

	event = psmx_eq_create_event(av_priv->eq,
				     FI_AV_COMPLETE,		/* event */
				     context,			/* context */
				     count - error_count,	/* data: succ count */
				     0,				/* err */
				     0,				/* prov_errno */
				     NULL,			/* err_data */
				     0);			/* err_data_size */
	if (!event)
		return -FI_ENOMEM;

	psmx_eq_enqueue_event(av_priv->eq, event);
	return 0;
}