Beispiel #1
0
static void continuous_insert_remove(int num_inserters, int num_removers,
				     int num_insertions)
{
	int i, ret;
	unsigned long pret;
	atomic_t done;
	fi_addr_t addresses[MT_ADDR_COUNT];
	atomic_t fe[MT_ADDR_COUNT];
	const int addrs_per_thread = MT_ADDR_COUNT/num_inserters;
	const int num_threads = num_inserters + num_removers;
	pthread_t threads[num_threads];
	void *info[num_threads][6];

	ret = pthread_barrier_init(&mtbar, NULL, num_threads);
	cr_assert_eq(ret, 0);

	init_av_lock();

	atomic_initialize(&done, 0);
	for (i = 0; i < MT_ADDR_COUNT; i++) {
		atomic_initialize(&fe[i], state_empty);
	}

	for (i = 0; i < num_inserters; i++) {
		info[i][0] = (void *) &simple_ep_names[i*addrs_per_thread];
		info[i][1] = (void *) &addresses[i*addrs_per_thread];
		info[i][2] = (void *) &fe[i*addrs_per_thread];
		info[i][3] = (void *) (uint64_t) num_insertions;
		info[i][4] = (void *) (uint64_t) addrs_per_thread;
		info[i][5] = (void *) &done;
		ret = pthread_create(&threads[i], NULL,
				     continuous_insert, &info[i]);
		cr_assert_eq(ret, 0);
	}

	for (i = num_inserters; i < num_threads; i++) {
		info[i][0] = (void *) addresses;
		info[i][1] = (void *) fe;
		info[i][2] = (void *) (uint64_t)
			(num_inserters*addrs_per_thread);
		info[i][3] = (void *) &done;
		ret = pthread_create(&threads[i], NULL,
				     continuous_remove, &info[i]);
		cr_assert_eq(ret, 0);
	}

	for (i = 0; i < num_threads; i++) {
		if (i == num_inserters) {
			atomic_set(&done, 1);
		}
		ret = pthread_join(threads[i], (void **) &pret);
		cr_assert_eq(ret, 0);
		cr_assert_eq(pret, 0UL, "thread %d failed\n", i);
	}

	ret = pthread_barrier_destroy(&mtbar);
	cr_assert_eq(ret, 0);
}
Beispiel #2
0
void gnix_init(void)
{
	__setup_precomputed_crcs();
	atomic_initialize(&gnix_id_counter, 0);
	atomic_initialize(&file_id_counter, 0);
#ifndef NDEBUG
	atomic_initialize(&gnix_debug_next_tid, 0);
#endif
}
Beispiel #3
0
static void cntr_setup_mt(void)
{
	int i, ret;

	cntr_setup_eps();
	cntr_setup_av();
	cntr_setup_cqs();
	cntr_setup_bind_cqs();

	for (i = 0; i < NUM_EPS; i++) {
		ret = fi_cntr_open(dom, &cntr_attr, &ep_write_cntrs[i], 0);
		cr_assert(!ret, "fi_cntr_open");

		ret = fi_ep_bind(ep[i], &ep_write_cntrs[i]->fid,
				 FI_WRITE | FI_SEND);
		cr_assert(!ret, "fi_ep_bind cntr");

		ret = fi_cntr_open(dom, &cntr_attr, &ep_read_cntrs[i], 0);
		cr_assert(!ret, "fi_cntr_open");

		ret = fi_ep_bind(ep[i], &ep_read_cntrs[i]->fid, FI_READ);
		cr_assert(!ret, "fi_ep_bind cntr");
	}

	cntr_setup_enable_ep();
	cntr_setup_mr();

	atomic_initialize(&cntr_test_next_tid, 0);
}
Beispiel #4
0
int fi_wait_init(struct util_fabric *fabric, struct fi_wait_attr *attr,
		 struct util_wait *wait)
{
	struct fid_poll *poll_fid;
	struct fi_poll_attr poll_attr;
	int ret;

	wait->prov = fabric->prov;
	atomic_initialize(&wait->ref, 0);
	wait->wait_fid.fid.fclass = FI_CLASS_WAIT;

	switch (attr->wait_obj) {
	case FI_WAIT_UNSPEC:
	case FI_WAIT_FD:
		wait->wait_obj = FI_WAIT_FD;
		break;
	case FI_WAIT_MUTEX_COND:
		wait->wait_obj = FI_WAIT_MUTEX_COND;
		break;
	default:
		assert(0);
		return -FI_EINVAL;
	}

	memset(&poll_attr, 0, sizeof poll_attr);
	ret = fi_poll_create_(fabric->prov, NULL, &poll_attr, &poll_fid);
	if (ret)
		return ret;

	wait->pollset = container_of(poll_fid, struct util_poll, poll_fid);
	wait->fabric = fabric;
	atomic_inc(&fabric->ref);
	return 0;
}
Beispiel #5
0
static void util_fabric_init(struct util_fabric *fabric, const char *name)
{
	atomic_initialize(&fabric->ref, 0);
	dlist_init(&fabric->domain_list);
	fastlock_init(&fabric->lock);
	fabric->name = name;
}
Beispiel #6
0
int
usdf_cq_open(struct fid_domain *domain, struct fi_cq_attr *attr,
	    struct fid_cq **cq_o, void *context)
{
	struct usdf_cq *cq;
	struct usdf_domain *udp;
	int ret;

	USDF_TRACE_SYS(CQ, "\n");

	udp = dom_ftou(domain);
	ret = usdf_cq_process_attr(attr, udp);
	if (ret != 0) {
		return ret;
	}

	cq = calloc(1, sizeof(*cq));
	if (cq == NULL) {
		return -FI_ENOMEM;
	}

	cq->cq_domain = udp;
	cq->cq_fid.fid.fclass = FI_CLASS_CQ;
	cq->cq_fid.fid.context = context;
	cq->cq_fid.fid.ops = &usdf_cq_fi_ops;
	atomic_initialize(&cq->cq_refcnt, 0);

	switch (attr->format) {
	case FI_CQ_FORMAT_CONTEXT:
		cq->cq_fid.ops = &usdf_cq_context_ops;
		break;
	case FI_CQ_FORMAT_MSG:
		cq->cq_fid.ops = &usdf_cq_msg_ops;
		break;
	case FI_CQ_FORMAT_DATA:
		cq->cq_fid.ops = &usdf_cq_data_ops;
		break;
	default:
		ret = -FI_ENOSYS;
		goto fail;
	}

	cq->cq_attr = *attr;
	*cq_o = &cq->cq_fid;
	return 0;

fail:
	if (cq != NULL) {
		if (cq->c.hard.cq_cq != NULL) {
			usd_destroy_cq(cq->c.hard.cq_cq);
		}
		free(cq);
	}
	return ret;
}
Beispiel #7
0
static int util_domain_init(struct util_domain *domain,
			    const struct fi_info *info)
{
	atomic_initialize(&domain->ref, 0);
	fastlock_init(&domain->lock);
	domain->caps = info->caps;
	domain->mode = info->mode;
	domain->addr_format = info->addr_format;
	domain->av_type = info->domain_attr->av_type;
	domain->name = strdup(info->domain_attr->name);
	return domain->name ? 0 : -FI_ENOMEM;
}
Beispiel #8
0
int fi_rbv_rdm_cntr_open(struct fid_domain *domain, struct fi_cntr_attr *attr,
			struct fid_cntr **cntr_fid, void *context)
{
	struct fi_ibv_rdm_cntr *cntr;

	struct fi_ibv_domain *dom =
		container_of(domain, struct fi_ibv_domain, domain_fid);

	if (attr) {
		switch (attr->events) {
		case FI_CNTR_EVENTS_COMP:
			break;
		default:
			return -FI_ENOSYS;
		}

		switch (attr->wait_obj) {
		case FI_WAIT_NONE:
		case FI_WAIT_UNSPEC:
			break;
		case FI_WAIT_MUTEX_COND:
		case FI_WAIT_SET:
		case FI_WAIT_FD:
		default:
			return -FI_ENOSYS;
		}

		if (attr->flags) {
			return -FI_EINVAL;
		}
	}

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

	if (attr) {
		assert(sizeof(cntr->attr) == sizeof(*attr));
		memcpy(&cntr->attr, attr, sizeof(*attr));
	}

	cntr->fid.fid.fclass = FI_CLASS_CNTR;
	cntr->fid.fid.context = context;
	cntr->fid.fid.ops = &fi_ibv_rdm_cntr_fi_ops;
	cntr->fid.ops = &fi_ibv_rdm_cntr_ops;
	cntr->domain = dom;
	atomic_initialize(&cntr->ep_ref, 0);

	*cntr_fid = &cntr->fid;

	return FI_SUCCESS;
}
Beispiel #9
0
static void continuous_lookup(void)
{
	int i, ret;
	pthread_t thread;
	fi_addr_t addresses[MT_ADDR_COUNT];
	atomic_t done;
	void *info[2];
	const int iters = 17;

	ret = pthread_barrier_init(&mtbar, NULL, 2);
	cr_assert_eq(ret, 0);

	init_av_lock();

	atomic_initialize(&done, 0);

	memset(addresses, 0, MT_ADDR_COUNT*sizeof(fi_addr_t));

	info[0] = (void *) addresses;
	info[1] = (void *) &done;

	ret = pthread_create(&thread, NULL, lookup_random, info);
	cr_assert_eq(ret, 0);

	ret = pthread_barrier_wait(&mtbar);
	cr_assert((ret == PTHREAD_BARRIER_SERIAL_THREAD) || (ret == 0));

	for (i = 0; i < iters; i++) {
		for (i = 0; i < MT_ADDR_COUNT; i++) {
			ret = fi_av_insert(av, (void *) &simple_ep_names[i], 1,
					   &addresses[i], 0, NULL);
			cr_assert_eq(ret, 1);
		}
		for (i = 0; i < MT_ADDR_COUNT; i++) {
			ret = fi_av_remove(av, &addresses[i], 1, 0);
			cr_assert_eq(ret, FI_SUCCESS);
		}
	}

	atomic_set(&done, 1);

	ret = pthread_join(thread, NULL);
	cr_assert_eq(ret, 0);

	ret = pthread_barrier_destroy(&mtbar);
	cr_assert_eq(ret, 0);
}
Beispiel #10
0
static int util_av_init(struct util_av *av, const struct fi_av_attr *attr,
			const struct util_av_attr *util_attr)
{
	int *entry, i, ret = 0;

	atomic_initialize(&av->ref, 0);
	fastlock_init(&av->lock);
	av->count = attr->count ? attr->count : UTIL_DEFAULT_AV_SIZE;
	av->count = roundup_power_of_two(av->count);
	av->addrlen = util_attr->addrlen;
	av->flags = util_attr->flags | attr->flags;

	FI_INFO(av->prov, FI_LOG_AV, "AV size %zu\n", av->count);

	/* TODO: Handle FI_READ */
	/* TODO: Handle mmap - shared AV */

	if (util_attr->flags & FI_SOURCE) {
		av->hash.slots = av->count;
		av->hash.total_count = av->count + util_attr->overhead;
		FI_INFO(av->prov, FI_LOG_AV,
		       "FI_SOURCE requested, hash size %zu\n", av->hash.total_count);
	}

	av->data = malloc((av->count * util_attr->addrlen) +
			  (av->hash.total_count * sizeof(*av->hash.table)));
	if (!av->data)
		return -FI_ENOMEM;

	for (i = 0; i < av->count - 1; i++) {
		entry = util_av_get_data(av, i);
		*entry = i + 1;
	}
	entry = util_av_get_data(av, av->count - 1);
	*entry = UTIL_NO_ENTRY;

	if (util_attr->flags & FI_SOURCE) {
		av->hash.table = util_av_get_data(av, av->count);
		util_av_hash_init(&av->hash);
	}

	return ret;
}
Beispiel #11
0
static int
usdf_dom_rdc_alloc_data(struct usdf_domain *udp)
{
	struct usdf_rdm_connection *rdc;
	int ret;
	int i;

	udp->dom_rdc_hashtab = calloc(USDF_RDM_HASH_SIZE,
			sizeof(*udp->dom_rdc_hashtab));
	if (udp->dom_rdc_hashtab == NULL) {
		return -FI_ENOMEM;
	}
	SLIST_INIT(&udp->dom_rdc_free);
	atomic_initialize(&udp->dom_rdc_free_cnt, 0);
	for (i = 0; i < USDF_RDM_FREE_BLOCK; ++i) {
		rdc = calloc(1, sizeof(*rdc));
		if (rdc == NULL) {
			return -FI_ENOMEM;
		}
		ret = usdf_timer_alloc(usdf_rdm_rdc_timeout, rdc,
				&rdc->dc_timer);
		if (ret != 0) {
			free(rdc);
			return ret;
		}
		rdc->dc_flags = USDF_DCS_UNCONNECTED | USDF_DCF_NEW_RX;
		rdc->dc_next_rx_seq = 0;
		rdc->dc_next_tx_seq = 0;
		rdc->dc_last_rx_ack = rdc->dc_next_tx_seq - 1;
		TAILQ_INIT(&rdc->dc_wqe_posted);
		TAILQ_INIT(&rdc->dc_wqe_sent);
		SLIST_INSERT_HEAD(&udp->dom_rdc_free, rdc, dc_addr_link);
		atomic_inc(&udp->dom_rdc_free_cnt);
	}
	udp->dom_rdc_total = USDF_RDM_FREE_BLOCK;
	return 0;
}
Beispiel #12
0
int
usdf_pep_open(struct fid_fabric *fabric, struct fi_info *info,
              struct fid_pep **pep_o, void *context)
{
    struct usdf_pep *pep;
    struct usdf_fabric *fp;
    struct sockaddr_in *sin;
    int ret;
    int optval;

    USDF_TRACE_SYS(EP_CTRL, "\n");

    if (!info) {
        USDF_DBG_SYS(EP_CTRL, "null fi_info struct is invalid\n");
        return -FI_EINVAL;
    }

    if (info->ep_attr->type != FI_EP_MSG) {
        return -FI_ENODEV;
    }

    if ((info->caps & ~USDF_MSG_CAPS) != 0) {
        return -FI_EBADF;
    }

    switch (info->addr_format) {
    case FI_SOCKADDR:
        if (((struct sockaddr *)info->src_addr)->sa_family != AF_INET) {
            USDF_WARN_SYS(EP_CTRL, "non-AF_INET src_addr specified\n");
            return -FI_EINVAL;
        }
        break;
    case FI_SOCKADDR_IN:
        break;
    default:
        USDF_WARN_SYS(EP_CTRL, "unknown/unsupported addr_format\n");
        return -FI_EINVAL;
    }

    if (info->src_addrlen &&
            info->src_addrlen != sizeof(struct sockaddr_in)) {
        USDF_WARN_SYS(EP_CTRL, "unexpected src_addrlen\n");
        return -FI_EINVAL;
    }

    fp = fab_ftou(fabric);

    pep = calloc(1, sizeof(*pep));
    if (pep == NULL) {
        return -FI_ENOMEM;
    }

    pep->pep_fid.fid.fclass = FI_CLASS_PEP;
    pep->pep_fid.fid.context = context;
    pep->pep_fid.fid.ops = &usdf_pep_ops;
    pep->pep_fid.ops = &usdf_pep_base_ops;
    pep->pep_fid.cm = &usdf_pep_cm_ops;
    pep->pep_fabric = fp;

    pep->pep_state = USDF_PEP_UNBOUND;
    pep->pep_sock = socket(AF_INET, SOCK_STREAM, 0);
    if (pep->pep_sock == -1) {
        ret = -errno;
        goto fail;
    }
    ret = fcntl(pep->pep_sock, F_GETFL, 0);
    if (ret == -1) {
        ret = -errno;
        goto fail;
    }
    ret = fcntl(pep->pep_sock, F_SETFL, ret | O_NONBLOCK);
    if (ret == -1) {
        ret = -errno;
        goto fail;
    }

    /* set SO_REUSEADDR to prevent annoying "Address already in use" errors
     * on successive runs of programs listening on a well known port */
    optval = 1;
    ret = setsockopt(pep->pep_sock, SOL_SOCKET, SO_REUSEADDR, &optval,
                     sizeof(optval));
    if (ret == -1) {
        ret = -errno;
        goto fail;
    }

    pep->pep_info = fi_dupinfo(info);
    if (!pep->pep_info) {
        ret = -FI_ENOMEM;
        goto fail;
    }

    if (info->src_addrlen == 0) {
        /* Copy the source address information from the device
         * attributes.
         */
        pep->pep_info->src_addrlen = sizeof(struct sockaddr_in);
        sin = calloc(1, pep->pep_info->src_addrlen);
        if (!sin) {
            USDF_WARN_SYS(EP_CTRL,
                          "calloc for src address failed\n");
            goto fail;
        }

        sin->sin_family = AF_INET;
        sin->sin_addr.s_addr = fp->fab_dev_attrs->uda_ipaddr_be;
        pep->pep_info->src_addr = sin;
    }

    memcpy(&pep->pep_src_addr, pep->pep_info->src_addr,
           pep->pep_info->src_addrlen);

    /* initialize connreq freelist */
    ret = pthread_spin_init(&pep->pep_cr_lock, PTHREAD_PROCESS_PRIVATE);
    if (ret != 0) {
        ret = -ret;
        goto fail;
    }
    TAILQ_INIT(&pep->pep_cr_free);
    TAILQ_INIT(&pep->pep_cr_pending);
    pep->pep_backlog = 10;
    ret = usdf_pep_grow_backlog(pep);
    if (ret != 0) {
        goto fail;
    }

    atomic_initialize(&pep->pep_refcnt, 0);
    atomic_inc(&fp->fab_refcnt);

    *pep_o = pep_utof(pep);
    return 0;

fail:
    if (pep != NULL) {
        usdf_pep_free_cr_lists(pep);
        if (pep->pep_sock != -1) {
            close(pep->pep_sock);
        }
        fi_freeinfo(pep->pep_info);
        free(pep);
    }
    return ret;
}
Beispiel #13
0
int psmx_ep_open(struct fid_domain *domain, struct fi_info *info,
		struct fid_ep **ep, void *context)
{
	struct psmx_fid_domain *domain_priv;
	struct psmx_fid_ep *ep_priv;
	int err;
	uint64_t ep_cap;

	if (info)
		ep_cap = info->caps;
	else
		ep_cap = FI_TAGGED;

	domain_priv = container_of(domain, struct psmx_fid_domain,
				   util_domain.domain_fid.fid);
	if (!domain_priv)
		return -FI_EINVAL;

	err = psmx_domain_check_features(domain_priv, ep_cap);
	if (err)
		return err; 

	ep_priv = (struct psmx_fid_ep *) calloc(1, sizeof *ep_priv);
	if (!ep_priv)
		return -FI_ENOMEM;

	ep_priv->ep.fid.fclass = FI_CLASS_EP;
	ep_priv->ep.fid.context = context;
	ep_priv->ep.fid.ops = &psmx_fi_ops;
	ep_priv->ep.ops = &psmx_ep_ops;
	ep_priv->ep.cm = &psmx_cm_ops;
	ep_priv->domain = domain_priv;
	atomic_initialize(&ep_priv->ref, 0);

	PSMX_CTXT_TYPE(&ep_priv->nocomp_send_context) = PSMX_NOCOMP_SEND_CONTEXT;
	PSMX_CTXT_EP(&ep_priv->nocomp_send_context) = ep_priv;
	PSMX_CTXT_TYPE(&ep_priv->nocomp_recv_context) = PSMX_NOCOMP_RECV_CONTEXT;
	PSMX_CTXT_EP(&ep_priv->nocomp_recv_context) = ep_priv;

	if (ep_cap & FI_TAGGED)
		ep_priv->ep.tagged = &psmx_tagged_ops;
	if (ep_cap & FI_MSG)
		ep_priv->ep.msg = &psmx_msg_ops;
	if ((ep_cap & FI_MSG) && psmx_env.am_msg)
		ep_priv->ep.msg = &psmx_msg2_ops;
	if (ep_cap & FI_RMA)
		ep_priv->ep.rma = &psmx_rma_ops;
	if (ep_cap & FI_ATOMICS)
		ep_priv->ep.atomic = &psmx_atomic_ops;

	ep_priv->caps = ep_cap;

	err = psmx_domain_enable_ep(domain_priv, ep_priv);
	if (err) {
		free(ep_priv);
		return err;
	}

	psmx_domain_acquire(domain_priv);

	if (info) {
		if (info->tx_attr)
			ep_priv->tx_flags = info->tx_attr->op_flags;
		if (info->rx_attr)
			ep_priv->rx_flags = info->rx_attr->op_flags;
	}

	psmx_ep_optimize_ops(ep_priv);

	*ep = &ep_priv->ep;

	return 0;
}
Beispiel #14
0
int gnix_ep_open(struct fid_domain *domain, struct fi_info *info,
		 struct fid_ep **ep, void *context)
{
	int ret = FI_SUCCESS;
	struct gnix_fid_domain *domain_priv;
	struct gnix_fid_ep *ep_priv;
	gnix_hashtable_attr_t gnix_ht_attr;

	GNIX_TRACE(FI_LOG_EP_CTRL, "\n");

	if ((domain == NULL) || (info == NULL) || (ep == NULL))
		return -FI_EINVAL;

	if (info->ep_attr->type != FI_EP_RDM)
		return -FI_ENOSYS;

	domain_priv = container_of(domain, struct gnix_fid_domain, domain_fid);

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

	ep_priv->ep_fid.fid.fclass = FI_CLASS_EP;
	ep_priv->ep_fid.fid.context = context;

	ep_priv->ep_fid.fid.ops = &gnix_ep_fi_ops;
	ep_priv->ep_fid.ops = &gnix_ep_ops;
	ep_priv->domain = domain_priv;
	ep_priv->type = info->ep_attr->type;

	fastlock_init(&ep_priv->vc_list_lock);
	dlist_init(&ep_priv->wc_vc_list);
	atomic_initialize(&ep_priv->active_fab_reqs, 0);
	atomic_initialize(&ep_priv->ref_cnt, 0);

	fastlock_init(&ep_priv->recv_queue_lock);
	slist_init(&ep_priv->unexp_recv_queue);
	slist_init(&ep_priv->posted_recv_queue);
	slist_init(&ep_priv->pending_recv_comp_queue);

	if (info->tx_attr)
		ep_priv->op_flags = info->tx_attr->op_flags;
	if (info->rx_attr)
		ep_priv->op_flags |= info->rx_attr->op_flags;

	ret = __fr_freelist_init(ep_priv);
	if (ret != FI_SUCCESS) {
		GNIX_ERR(FI_LOG_EP_CTRL,
			 "Error allocating gnix_fab_req freelist (%s)",
			 fi_strerror(-ret));
		goto err1;
	}

	ep_priv->ep_fid.msg = &gnix_ep_msg_ops;
	ep_priv->ep_fid.rma = &gnix_ep_rma_ops;
	ep_priv->ep_fid.tagged = &gnix_ep_tagged_ops;
	ep_priv->ep_fid.atomic = NULL;

	ep_priv->ep_fid.cm = &gnix_cm_ops;

	/*
	 * TODO, initialize vc hash table
	 */
	if (ep_priv->type == FI_EP_RDM) {
		ret = _gnix_cm_nic_alloc(domain_priv,
					 &ep_priv->cm_nic);
		if (ret != FI_SUCCESS)
			goto err;

		gnix_ht_attr.ht_initial_size = domain_priv->params.ct_init_size;
		gnix_ht_attr.ht_maximum_size = domain_priv->params.ct_max_size;
		gnix_ht_attr.ht_increase_step = domain_priv->params.ct_step;
		gnix_ht_attr.ht_increase_type = GNIX_HT_INCREASE_MULT;
		gnix_ht_attr.ht_collision_thresh = 500;
		gnix_ht_attr.ht_hash_seed = 0xdeadbeefbeefdead;
		gnix_ht_attr.ht_internal_locking = 1;

		ep_priv->vc_ht = calloc(1, sizeof(struct gnix_hashtable));
		if (ep_priv->vc_ht == NULL)
			goto err;
		ret = _gnix_ht_init(ep_priv->vc_ht, &gnix_ht_attr);
		if (ret != FI_SUCCESS) {
			GNIX_WARN(FI_LOG_EP_CTRL,
				    "gnix_ht_init call returned %d\n",
				     ret);
			goto err;
		}

	} else {
		ep_priv->cm_nic = NULL;
		ep_priv->vc = NULL;
	}

	ep_priv->progress_fn = NULL;
	ep_priv->rx_progress_fn = NULL;

	ret = gnix_nic_alloc(domain_priv, &ep_priv->nic);
	if (ret != FI_SUCCESS) {
		GNIX_WARN(FI_LOG_EP_CTRL,
			    "_gnix_nic_alloc call returned %d\n",
			     ret);
		goto err;
	}

	/*
	 * if smsg callbacks not present hook them up now
	 */

	if (ep_priv->nic->smsg_callbacks == NULL)
		ep_priv->nic->smsg_callbacks = gnix_ep_smsg_callbacks;

	atomic_inc(&domain_priv->ref_cnt);
	*ep = &ep_priv->ep_fid;
	return ret;

err1:
	__fr_freelist_destroy(ep_priv);
err:
	if (ep_priv->vc_ht != NULL) {
		_gnix_ht_destroy(ep_priv->vc_ht); /* may not be initialized but
						     okay */
		free(ep_priv->vc_ht);
		ep_priv->vc_ht = NULL;
	}
	if (ep_priv->cm_nic != NULL)
		ret = _gnix_cm_nic_free(ep_priv->cm_nic);
	free(ep_priv);
	return ret;

}
Beispiel #15
0
int sock_domain(struct fid_fabric *fabric, struct fi_info *info,
		struct fid_domain **dom, void *context)
{
	struct sock_domain *sock_domain;
	struct sock_fabric *fab;
	int ret;

	fab = container_of(fabric, struct sock_fabric, fab_fid);
	if (info && info->domain_attr) {
		ret = sock_verify_domain_attr(info->domain_attr);
		if (ret)
			return -FI_EINVAL;
	}

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

	fastlock_init(&sock_domain->lock);
	atomic_initialize(&sock_domain->ref, 0);

	if (info) {
		sock_domain->info = *info;
	} else {
		SOCK_LOG_ERROR("invalid fi_info\n");
		goto err;
	}

	sock_domain->dom_fid.fid.fclass = FI_CLASS_DOMAIN;
	sock_domain->dom_fid.fid.context = context;
	sock_domain->dom_fid.fid.ops = &sock_dom_fi_ops;
	sock_domain->dom_fid.ops = &sock_dom_ops;
	sock_domain->dom_fid.mr = &sock_dom_mr_ops;

	if (!info->domain_attr ||
	    info->domain_attr->data_progress == FI_PROGRESS_UNSPEC)
		sock_domain->progress_mode = FI_PROGRESS_AUTO;
	else
		sock_domain->progress_mode = info->domain_attr->data_progress;

	sock_domain->pe = sock_pe_init(sock_domain);
	if (!sock_domain->pe) {
		SOCK_LOG_ERROR("Failed to init PE\n");
		goto err;
	}

	sock_domain->mr_heap = rbtNew(&sock_compare_mr_keys);
	if (!sock_domain->mr_heap) {
		goto err;
	}
	sock_domain->fab = fab;
	*dom = &sock_domain->dom_fid;

	if (info->domain_attr)
		sock_domain->attr = *(info->domain_attr);
	else
		sock_domain->attr = sock_domain_attr;

	sock_dom_add_to_list(sock_domain);
	return 0;

err:
	free(sock_domain);
	return -FI_EINVAL;
}
Beispiel #16
0
int
usdf_cq_make_soft(struct usdf_cq *cq)
{
        struct fi_ops_cq *hard_ops;
        struct fi_ops_cq *soft_ops;
	struct usdf_cq_hard *hcq;
	struct usd_cq *ucq;
	void (*rtn)(struct usdf_cq_hard *hcq);

        switch (cq->cq_attr.format) {
        case FI_CQ_FORMAT_CONTEXT:
                hard_ops = &usdf_cq_context_ops;
                soft_ops = &usdf_cq_context_soft_ops;
                break;
        case FI_CQ_FORMAT_MSG:
                hard_ops = &usdf_cq_msg_ops;
                soft_ops = &usdf_cq_msg_soft_ops;
                break;
        case FI_CQ_FORMAT_DATA:
                hard_ops = &usdf_cq_data_ops;
                soft_ops = &usdf_cq_data_soft_ops;
                break;
	default:
		return 0;
        }

	rtn = usdf_progress_hard_cq;

        if (cq->cq_fid.ops == hard_ops) {

		/* save the CQ before we trash the union */
		ucq = cq->c.hard.cq_cq;

		/* fill in the soft part of union */
		TAILQ_INIT(&cq->c.soft.cq_list);
		cq->c.soft.cq_comps = calloc(cq->cq_attr.size,
					sizeof(struct usdf_cq_soft_entry));
		if (cq->c.soft.cq_comps == NULL) {
			return -FI_ENOMEM;
		}
		cq->c.soft.cq_end = cq->c.soft.cq_comps + cq->cq_attr.size;
		cq->c.soft.cq_head = cq->c.soft.cq_comps;
		cq->c.soft.cq_tail = cq->c.soft.cq_comps;

		/* need to add hard queue to list? */
		if (ucq != NULL) {
			hcq = malloc(sizeof(*hcq));
			if (hcq == NULL) {
				free(cq->c.soft.cq_comps);
				cq->c.hard.cq_cq = ucq;	/* restore */
				return -FI_ENOMEM;
			}

			hcq->cqh_cq = cq;
			hcq->cqh_ucq = ucq;
			hcq->cqh_progress = rtn;

			atomic_initialize(&hcq->cqh_refcnt,
					atomic_get(&cq->cq_refcnt));
			TAILQ_INSERT_HEAD(&cq->c.soft.cq_list, hcq, cqh_link);
		}

                cq->cq_fid.ops = soft_ops;
        }
	return 0;
}
Beispiel #17
0
int psmx_ep_open(struct fid_domain *domain, struct fi_info *info,
		struct fid_ep **ep, void *context)
{
	struct psmx_fid_domain *domain_priv;
	struct psmx_fid_ep *ep_priv;
	int err;
	uint64_t ep_cap;

	if (info)
		ep_cap = info->caps;
	else
		ep_cap = FI_TAGGED;

	domain_priv = container_of(domain, struct psmx_fid_domain,
				   util_domain.domain_fid.fid);
	if (!domain_priv)
		return -FI_EINVAL;

	if (info && info->ep_attr && info->ep_attr->auth_key) {
		if (info->ep_attr->auth_keylen != sizeof(psm_uuid_t)) {
			FI_WARN(&psmx_prov, FI_LOG_EP_CTRL,
				"Invalid auth_key_len %d, should be %d.\n",
				info->ep_attr->auth_keylen,
				sizeof(psm_uuid_t));
			return -FI_EINVAL;
		}
		if (memcmp(domain_priv->fabric->uuid, info->ep_attr->auth_key,
			   sizeof(psm_uuid_t))) {
			FI_WARN(&psmx_prov, FI_LOG_EP_CTRL,
				"Invalid auth_key: %s\n",
				psmx_uuid_to_string((void *)info->ep_attr->auth_key));
			return -FI_EINVAL;
		}
	}

	err = psmx_domain_check_features(domain_priv, ep_cap);
	if (err)
		return err; 

	ep_priv = (struct psmx_fid_ep *) calloc(1, sizeof *ep_priv);
	if (!ep_priv)
		return -FI_ENOMEM;

	ep_priv->ep.fid.fclass = FI_CLASS_EP;
	ep_priv->ep.fid.context = context;
	ep_priv->ep.fid.ops = &psmx_fi_ops;
	ep_priv->ep.ops = &psmx_ep_ops;
	ep_priv->ep.cm = &psmx_cm_ops;
	ep_priv->domain = domain_priv;
	atomic_initialize(&ep_priv->ref, 0);

	PSMX_CTXT_TYPE(&ep_priv->nocomp_send_context) = PSMX_NOCOMP_SEND_CONTEXT;
	PSMX_CTXT_EP(&ep_priv->nocomp_send_context) = ep_priv;
	PSMX_CTXT_TYPE(&ep_priv->nocomp_recv_context) = PSMX_NOCOMP_RECV_CONTEXT;
	PSMX_CTXT_EP(&ep_priv->nocomp_recv_context) = ep_priv;

	if (ep_cap & FI_TAGGED)
		ep_priv->ep.tagged = &psmx_tagged_ops;
	if (ep_cap & FI_MSG)
		ep_priv->ep.msg = &psmx_msg_ops;
	if ((ep_cap & FI_MSG) && psmx_env.am_msg)
		ep_priv->ep.msg = &psmx_msg2_ops;
	if (ep_cap & FI_RMA)
		ep_priv->ep.rma = &psmx_rma_ops;
	if (ep_cap & FI_ATOMICS)
		ep_priv->ep.atomic = &psmx_atomic_ops;

	ep_priv->caps = ep_cap;

	err = psmx_domain_enable_ep(domain_priv, ep_priv);
	if (err) {
		free(ep_priv);
		return err;
	}

	psmx_domain_acquire(domain_priv);

	if (info) {
		if (info->tx_attr)
			ep_priv->tx_flags = info->tx_attr->op_flags;
		if (info->rx_attr)
			ep_priv->rx_flags = info->rx_attr->op_flags;
	}

	psmx_ep_optimize_ops(ep_priv);

	ep_priv->service = PSMX_ANY_SERVICE;
	if (info && info->src_addr)
		ep_priv->service = ((struct psmx_src_name *)info->src_addr)->service;

	if (ep_priv->service == PSMX_ANY_SERVICE)
		ep_priv->service = ((getpid() & 0x7FFF) << 16) +
				   ((uintptr_t)ep_priv & 0xFFFF);

       psmx_ns_add_local_name(ep_priv->service, domain_priv->psm_epid);

	*ep = &ep_priv->ep;

	return 0;
}
Beispiel #18
0
ssize_t _gnix_rma(struct gnix_fid_ep *ep, enum gnix_fab_req_type fr_type,
		  uint64_t loc_addr, size_t len, void *mdesc,
		  uint64_t dest_addr, uint64_t rem_addr, uint64_t mkey,
		  void *context, uint64_t flags, uint64_t data)
{
	struct gnix_vc *vc;
	struct gnix_fab_req *req;
	struct gnix_fid_mem_desc *md = NULL;
	int rc;
	int rdma;
	struct fid_mr *auto_mr = NULL;

	if (!ep) {
		return -FI_EINVAL;
	}

	if ((flags & FI_INJECT) && (len > GNIX_INJECT_SIZE)) {
		GNIX_INFO(FI_LOG_EP_DATA,
			  "RMA length %d exceeds inject max size: %d\n",
			  len, GNIX_INJECT_SIZE);
		return -FI_EINVAL;
	}

	/* find VC for target */
	rc = _gnix_ep_get_vc(ep, dest_addr, &vc);
	if (rc) {
		GNIX_INFO(FI_LOG_EP_DATA,
			  "_gnix_ep_get_vc() failed, addr: %lx, rc:\n",
			  dest_addr, rc);
		return rc;
	}

	/* setup fabric request */
	req = _gnix_fr_alloc(ep);
	if (!req) {
		GNIX_INFO(FI_LOG_EP_DATA, "_gnix_fr_alloc() failed\n");
		return -FI_ENOSPC;
	}

	rdma = len >= ep->domain->params.rma_rdma_thresh;

	req->type = fr_type;
	req->gnix_ep = ep;
	req->vc = vc;
	req->user_context = context;
	req->work_fn = _gnix_rma_post_req;
	atomic_initialize(&req->rma.outstanding_txds, 0);

	if (fr_type == GNIX_FAB_RQ_RDMA_READ &&
	    (rem_addr & GNI_READ_ALIGN_MASK || len & GNI_READ_ALIGN_MASK)) {
		if (len >= GNIX_RMA_UREAD_CHAINED_THRESH) {
			GNIX_INFO(FI_LOG_EP_DATA,
				  "Using CT for unaligned GET, req: %p\n",
				  req);
			flags |= GNIX_RMA_CHAINED;
		} else {
			GNIX_INFO(FI_LOG_EP_DATA,
				  "Using tmp buf for unaligned GET, req: %p\n",
				  req);
			flags |= GNIX_RMA_INDIRECT;
		}

		if (rdma)
			req->work_fn = _gnix_rma_post_rdma_chain_req;
	}

	if (!(flags & GNIX_RMA_INDIRECT) && !mdesc &&
	    (rdma || fr_type == GNIX_FAB_RQ_RDMA_READ)) {
		/* We need to auto-register the source buffer. */
		rc = gnix_mr_reg(&ep->domain->domain_fid.fid, (void *)loc_addr,
				 len, FI_READ | FI_WRITE, 0, 0, 0, &auto_mr,
				 NULL);
		if (rc != FI_SUCCESS) {
			GNIX_INFO(FI_LOG_EP_DATA,
				  "Failed to auto-register local buffer: %d\n",
				  rc);
			goto err_auto_reg;
		}
		flags |= FI_LOCAL_MR;
		mdesc = (void *)auto_mr;
		GNIX_INFO(FI_LOG_EP_DATA, "auto-reg MR: %p\n", auto_mr);
	}

	if (mdesc)
		md = container_of(mdesc, struct gnix_fid_mem_desc, mr_fid);
	req->rma.loc_md = (void *)md;

	req->rma.rem_addr = rem_addr;
	req->rma.rem_mr_key = mkey;
	req->rma.len = len;
	req->rma.imm = data;
	req->flags = flags;

	if (req->flags & FI_INJECT) {
		memcpy(req->inject_buf, (void *)loc_addr, len);
		req->rma.loc_addr = (uint64_t)req->inject_buf;
	} else {
		req->rma.loc_addr = loc_addr;
	}

	/* Inject interfaces always suppress completions.  If
	 * SELECTIVE_COMPLETION is set, honor any setting.  Otherwise, always
	 * deliver a completion. */
	if ((flags & GNIX_SUPPRESS_COMPLETION) ||
	    (ep->send_selective_completion && !(flags & FI_COMPLETION))) {
		req->flags &= ~FI_COMPLETION;
	} else {
		req->flags |= FI_COMPLETION;
	}

	if (rdma) {
		req->flags |= GNIX_RMA_RDMA;
	}

	GNIX_INFO(FI_LOG_EP_DATA, "Queuing (%p %p %d)\n",
		  (void *)loc_addr, (void *)rem_addr, len);

	return _gnix_vc_queue_tx_req(req);

err_auto_reg:
	_gnix_fr_free(req->vc->ep, req);
	return rc;
}
Beispiel #19
0
int _gnix_vc_alloc(struct gnix_fid_ep *ep_priv,
		   struct gnix_av_addr_entry *entry, struct gnix_vc **vc)

{
	int ret = FI_SUCCESS;
	int remote_id;
	struct gnix_vc *vc_ptr = NULL;
	struct gnix_cm_nic *cm_nic = NULL;
	struct gnix_nic *nic = NULL;

	GNIX_TRACE(FI_LOG_EP_CTRL, "\n");

	nic = ep_priv->nic;
	if (nic == NULL)
		return -FI_EINVAL;

	cm_nic = ep_priv->cm_nic;
	if (cm_nic == NULL)
		return -FI_EINVAL;

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

	vc_ptr->conn_state = GNIX_VC_CONN_NONE;
	if (entry) {
		memcpy(&vc_ptr->peer_addr,
			&entry->gnix_addr,
			sizeof(struct gnix_address));
		vc_ptr->peer_cm_nic_addr.device_addr =
			entry->gnix_addr.device_addr;
		vc_ptr->peer_cm_nic_addr.cdm_id =
			entry->cm_nic_cdm_id;
	} else {
		vc_ptr->peer_addr.device_addr = -1;
		vc_ptr->peer_addr.cdm_id = -1;
		vc_ptr->peer_cm_nic_addr.device_addr = -1;
		vc_ptr->peer_cm_nic_addr.cdm_id = -1;
	}
	vc_ptr->ep = ep_priv;

	slist_init(&vc_ptr->work_queue);
	fastlock_init(&vc_ptr->work_queue_lock);
	slist_init(&vc_ptr->tx_queue);
	fastlock_init(&vc_ptr->tx_queue_lock);
	dlist_init(&vc_ptr->rx_list);
	dlist_init(&vc_ptr->work_list);
	dlist_init(&vc_ptr->tx_list);
	vc_ptr->peer_fi_addr = FI_ADDR_NOTAVAIL;

	atomic_initialize(&vc_ptr->outstanding_tx_reqs, 0);
	ret = _gnix_alloc_bitmap(&vc_ptr->flags, 1);
	assert(!ret);

	/*
	 * we need an id for the vc to allow for quick lookup
	 * based on GNI_CQ_GET_INST_ID
	 */

	ret = _gnix_nic_get_rem_id(nic, &remote_id, vc_ptr);
	if (ret != FI_SUCCESS)
		goto err;
	vc_ptr->vc_id = remote_id;

	*vc = vc_ptr;

	return ret;

err:
	if (vc_ptr)
		free(vc_ptr);
	return ret;
}
Beispiel #20
0
int sock_av_open(struct fid_domain *domain, struct fi_av_attr *attr,
		 struct fid_av **av, void *context)
{
	int ret = 0;
	struct sock_domain *dom;
	struct sock_av *_av;
	size_t table_sz, i;
	uint64_t flags = O_RDWR;

	if (!attr || sock_verify_av_attr(attr))
		return -FI_EINVAL;

	dom = container_of(domain, struct sock_domain, dom_fid);
	if (dom->attr.av_type != FI_AV_UNSPEC && attr &&
	    dom->attr.av_type != attr->type)
		return -FI_EINVAL;

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

	_av->attr = *attr;
	_av->attr.count = (attr->count) ? attr->count : sock_av_def_sz;

	table_sz = sizeof(struct sock_av_table_hdr) +
		_av->attr.count * sizeof(struct sock_av_addr);

	if (attr->name) {
		_av->name = strdup(attr->name);
		if (!_av->name) {
			ret = -FI_ENOMEM;
			goto err1;
		}
		if (!(attr->flags & FI_READ))
			flags |= O_CREAT;

		for (i = 0; i < strlen(_av->name); i++)
			if (_av->name[i] == ' ')
				_av->name[i] = '_';

		SOCK_LOG_DBG("Creating shm segment :%s (size: %lu)\n",
			      _av->name, table_sz);

		_av->shared_fd = shm_open(_av->name, flags, S_IRUSR | S_IWUSR);
		if (_av->shared_fd < 0) {
			SOCK_LOG_ERROR("shm_open failed\n");
			ret = -FI_EINVAL;
			goto err2;
		}

		if (ftruncate(_av->shared_fd, table_sz) == -1) {
			SOCK_LOG_ERROR("ftruncate failed\n");
			shm_unlink(_av->name);
			ret = -FI_EINVAL;
			goto err2;
		}

		_av->table_hdr = mmap(NULL, table_sz, PROT_READ | PROT_WRITE,
				      MAP_SHARED, _av->shared_fd, 0);
		if (attr->flags & FI_READ) {
			if (_av->table_hdr->size != _av->attr.count) {
				ret = -FI_EINVAL;
				goto err2;
			}
		} else {
			_av->table_hdr->size = _av->attr.count;
			_av->table_hdr->stored = 0;
		}

		if (_av->table_hdr == MAP_FAILED) {
			SOCK_LOG_ERROR("mmap failed\n");
			shm_unlink(_av->name);
			ret = -FI_EINVAL;
			goto err2;
		}
	} else {
		_av->table_hdr = calloc(1, table_sz);
		if (!_av->table_hdr) {
			ret = -FI_ENOMEM;
			goto err3;
		}
		_av->table_hdr->size = _av->attr.count;
		_av->table_hdr->req_sz = attr->count;
	}

	_av->table = (struct sock_av_addr *)((char *)_av->table_hdr +
					    sizeof(struct sock_av_table_hdr));
	_av->av_fid.fid.fclass = FI_CLASS_AV;
	_av->av_fid.fid.context = context;
	_av->av_fid.fid.ops = &sock_av_fi_ops;

	switch (attr->type) {
	case FI_AV_MAP:
		_av->av_fid.ops = &sock_am_ops;
		break;
	case FI_AV_TABLE:
		_av->av_fid.ops = &sock_at_ops;
		break;
	default:
		ret = -FI_EINVAL;
		goto err3;
	}

	atomic_initialize(&_av->ref, 0);
	atomic_inc(&dom->ref);
	_av->domain = dom;
	switch (dom->info.addr_format) {
	case FI_SOCKADDR_IN:
		_av->addrlen = sizeof(struct sockaddr_in);
		break;
	default:
		SOCK_LOG_ERROR("Invalid address format: only IPv4 supported\n");
		ret = -FI_EINVAL;
		goto err3;
	}
	_av->rx_ctx_bits = attr->rx_ctx_bits;
	_av->mask = attr->rx_ctx_bits ?
		((uint64_t)1 << (64 - attr->rx_ctx_bits)) - 1 : ~0;
	*av = &_av->av_fid;
	return 0;

err3:
	free(_av->table_hdr);
err2:
	free(_av->name);
err1:
	free(_av);

	return ret;
}
Beispiel #21
0
static int
usdf_fabric_open(struct fi_fabric_attr *fattrp, struct fid_fabric **fabric,
	       void *context)
{
	struct fid_fabric *ff;
	struct usdf_fabric *fp;
	struct usdf_usnic_info *dp;
	struct usdf_dev_entry *dep;
	struct epoll_event ev;
	struct sockaddr_in sin;
	int ret;
	int d;

	USDF_TRACE("\n");

	/* Make sure this fabric exists */
	dp = __usdf_devinfo;
	for (d = 0; d < dp->uu_num_devs; ++d) {
		dep = &dp->uu_info[d];
		if (dep->ue_dev_ok &&
			strcmp(fattrp->name, dep->ue_dattr.uda_devname) == 0) {
			break;
		}
	}
	if (d >= dp->uu_num_devs) {
		USDF_INFO("device \"%s\" does not exit, returning -FI_ENODEV\n",
				fattrp->name);
		return -FI_ENODEV;
	}

	fp = calloc(1, sizeof(*fp));
	if (fp == NULL) {
		USDF_INFO("unable to allocate memory for fabric\n");
		return -FI_ENOMEM;
	}
	fp->fab_epollfd = -1;
	fp->fab_arp_sockfd = -1;
	LIST_INIT(&fp->fab_domain_list);

	fp->fab_attr.fabric = fab_utof(fp);
	fp->fab_attr.name = strdup(fattrp->name);
	fp->fab_attr.prov_name = strdup(USDF_PROV_NAME);
	fp->fab_attr.prov_version = USDF_PROV_VERSION;
	if (fp->fab_attr.name == NULL ||
			fp->fab_attr.prov_name == NULL) {
		ret = -FI_ENOMEM;
		goto fail;
	}

	fp->fab_fid.fid.fclass = FI_CLASS_FABRIC;
	fp->fab_fid.fid.context = context;
	fp->fab_fid.fid.ops = &usdf_fi_ops;
	fp->fab_fid.ops = &usdf_ops_fabric;

	fp->fab_dev_attrs = &dep->ue_dattr;

	fp->fab_epollfd = epoll_create(1024);
	if (fp->fab_epollfd == -1) {
		ret = -errno;
		USDF_INFO("unable to allocate epoll fd\n");
		goto fail;
	}

	fp->fab_eventfd = eventfd(0, EFD_NONBLOCK | EFD_SEMAPHORE);
	if (fp->fab_eventfd == -1) {
		ret = -errno;
		USDF_INFO("unable to allocate event fd\n");
		goto fail;
	}
	fp->fab_poll_item.pi_rtn = usdf_fabric_progression_cb;
	fp->fab_poll_item.pi_context = fp;
	ev.events = EPOLLIN;
	ev.data.ptr = &fp->fab_poll_item;
	ret = epoll_ctl(fp->fab_epollfd, EPOLL_CTL_ADD, fp->fab_eventfd, &ev);
	if (ret == -1) {
		ret = -errno;
		USDF_INFO("unable to EPOLL_CTL_ADD\n");
		goto fail;
	}

	/* initialize timer subsystem */
	ret = usdf_timer_init(fp);
	if (ret != 0) {
		USDF_INFO("unable to initialize timer\n");
		goto fail;
	}

	ret = pthread_create(&fp->fab_thread, NULL,
			usdf_fabric_progression_thread, fp);
	if (ret != 0) {
		ret = -ret;
		USDF_INFO("unable to create progress thread\n");
		goto fail;
	}

	/* create and bind socket for ARP resolution */
	memset(&sin, 0, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = fp->fab_dev_attrs->uda_ipaddr_be;
	fp->fab_arp_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if (fp->fab_arp_sockfd == -1) {
		USDF_INFO("unable to create socket\n");
		goto fail;
	}
	ret = bind(fp->fab_arp_sockfd, (struct sockaddr *) &sin, sizeof(sin));
	if (ret == -1) {
		ret = -errno;
		goto fail;
	}

	atomic_initialize(&fp->fab_refcnt, 0);
	fattrp->fabric = fab_utof(fp);
	fattrp->prov_version = USDF_PROV_VERSION;
	*fabric = fab_utof(fp);
	USDF_INFO("successfully opened %s/%s\n", fattrp->name,
			fp->fab_dev_attrs->uda_ifname);
	return 0;

fail:
	ff = fab_utof(fp);
	usdf_fabric_close(&ff->fid);
	USDF_DBG("returning %d (%s)\n", ret, fi_strerror(-ret));
	return ret;
}
Beispiel #22
0
int sock_cntr_open(struct fid_domain *domain, struct fi_cntr_attr *attr,
                   struct fid_cntr **cntr, void *context)
{
    int ret;
    struct sock_domain *dom;
    struct sock_cntr *_cntr;
    struct fi_wait_attr wait_attr;
    struct sock_fid_list *list_entry;
    struct sock_wait *wait;

    dom = container_of(domain, struct sock_domain, dom_fid);
    if (attr && sock_cntr_verify_attr(attr))
        return -FI_ENOSYS;

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

    ret = pthread_cond_init(&_cntr->cond, NULL);
    if (ret)
        goto err;

    if (attr == NULL)
        memcpy(&_cntr->attr, &sock_cntr_add, sizeof(sock_cntr_attr));
    else
        memcpy(&_cntr->attr, attr, sizeof(sock_cntr_attr));

    switch (_cntr->attr.wait_obj) {

    case FI_WAIT_NONE:
    case FI_WAIT_UNSPEC:
    case FI_WAIT_MUTEX_COND:
        _cntr->signal = 0;
        break;

    case FI_WAIT_FD:
        wait_attr.flags = 0;
        wait_attr.wait_obj = FI_WAIT_FD;
        ret = sock_wait_open(&dom->fab->fab_fid, &wait_attr,
                             &_cntr->waitset);
        if (ret) {
            ret = FI_EINVAL;
            goto err;
        }
        _cntr->signal = 1;
        break;

    case FI_WAIT_SET:
        if (!attr) {
            ret = FI_EINVAL;
            goto err;
        }

        _cntr->waitset = attr->wait_set;
        _cntr->signal = 1;
        wait = container_of(attr->wait_set, struct sock_wait, wait_fid);
        list_entry = calloc(1, sizeof(*list_entry));
        dlist_init(&list_entry->entry);
        list_entry->fid = &_cntr->cntr_fid.fid;
        dlist_insert_after(&list_entry->entry, &wait->fid_list);
        break;

    default:
        break;
    }

    pthread_mutex_init(&_cntr->mut, NULL);
    fastlock_init(&_cntr->list_lock);

    atomic_initialize(&_cntr->ref, 0);
    atomic_initialize(&_cntr->err_cnt, 0);

    atomic_initialize(&_cntr->value, 0);
    atomic_initialize(&_cntr->threshold, ~0);

    dlist_init(&_cntr->tx_list);
    dlist_init(&_cntr->rx_list);

    dlist_init(&_cntr->trigger_list);
    fastlock_init(&_cntr->trigger_lock);

    _cntr->cntr_fid.fid.fclass = FI_CLASS_CNTR;
    _cntr->cntr_fid.fid.context = context;
    _cntr->cntr_fid.fid.ops = &sock_cntr_fi_ops;
    _cntr->cntr_fid.ops = &sock_cntr_ops;

    atomic_inc(&dom->ref);
    _cntr->domain = dom;
    *cntr = &_cntr->cntr_fid;
    return 0;

err:
    free(_cntr);
    return -ret;
}
Beispiel #23
0
int psmx2_ep_open(struct fid_domain *domain, struct fi_info *info,
		  struct fid_ep **ep, void *context)
{
	struct psmx2_fid_domain *domain_priv;
	struct psmx2_fid_ep *ep_priv;
	struct psmx2_context *item;
	uint8_t vlane;
	uint64_t ep_cap;
	int err = -FI_EINVAL;
	int i;

	if (info)
		ep_cap = info->caps;
	else
		ep_cap = FI_TAGGED;

	domain_priv = container_of(domain, struct psmx2_fid_domain,	
				   util_domain.domain_fid.fid);
	if (!domain_priv)
		goto errout;

	err = psmx2_domain_check_features(domain_priv, ep_cap);
	if (err)
		goto errout;

	err = psmx2_alloc_vlane(domain_priv, &vlane);
	if (err)
		goto errout;

	ep_priv = (struct psmx2_fid_ep *) calloc(1, sizeof *ep_priv);
	if (!ep_priv) {
		err = -FI_ENOMEM;
		goto errout_free_vlane;
	}

	ep_priv->ep.fid.fclass = FI_CLASS_EP;
	ep_priv->ep.fid.context = context;
	ep_priv->ep.fid.ops = &psmx2_fi_ops;
	ep_priv->ep.ops = &psmx2_ep_ops;
	ep_priv->ep.cm = &psmx2_cm_ops;
	ep_priv->domain = domain_priv;
	ep_priv->vlane = vlane;
	atomic_initialize(&ep_priv->ref, 0);

	PSMX2_CTXT_TYPE(&ep_priv->nocomp_send_context) = PSMX2_NOCOMP_SEND_CONTEXT;
	PSMX2_CTXT_EP(&ep_priv->nocomp_send_context) = ep_priv;
	PSMX2_CTXT_TYPE(&ep_priv->nocomp_recv_context) = PSMX2_NOCOMP_RECV_CONTEXT;
	PSMX2_CTXT_EP(&ep_priv->nocomp_recv_context) = ep_priv;

	if (ep_cap & FI_TAGGED)
		ep_priv->ep.tagged = &psmx2_tagged_ops;
	if (ep_cap & FI_MSG)
		ep_priv->ep.msg = &psmx2_msg_ops;
	if (ep_cap & FI_RMA)
		ep_priv->ep.rma = &psmx2_rma_ops;
	if (ep_cap & FI_ATOMICS)
		ep_priv->ep.atomic = &psmx2_atomic_ops;

	ep_priv->caps = ep_cap;

	err = psmx2_domain_enable_ep(domain_priv, ep_priv);
	if (err)
		goto errout_free_ep;

	psmx2_domain_acquire(domain_priv);
	domain_priv->eps[ep_priv->vlane] = ep_priv;

	if (info) {
		if (info->tx_attr)
			ep_priv->tx_flags = info->tx_attr->op_flags;
		if (info->rx_attr)
			ep_priv->rx_flags = info->rx_attr->op_flags;
	}

	psmx2_ep_optimize_ops(ep_priv);

	slist_init(&ep_priv->free_context_list);
	fastlock_init(&ep_priv->context_lock);

#define PSMX2_FREE_CONTEXT_LIST_SIZE	64
	for (i=0; i<PSMX2_FREE_CONTEXT_LIST_SIZE; i++) {
		item = calloc(1, sizeof(*item));
		if (!item) {
			FI_WARN(&psmx2_prov, FI_LOG_EP_CTRL, "out of memory.\n");
			exit(-1);
		}
		slist_insert_tail(&item->list_entry, &ep_priv->free_context_list);
	}

	*ep = &ep_priv->ep;

	return 0;

errout_free_ep:
	free(ep_priv);

errout_free_vlane:
	psmx2_free_vlane(domain_priv, vlane);

errout:
	return err;
}
Beispiel #24
0
int sock_av_open(struct fid_domain *domain, struct fi_av_attr *attr,
		 struct fid_av **av, void *context)
{
	int ret = 0;
	struct sock_domain *dom;
	struct sock_av *_av;
	size_t table_sz;

	if (!attr || sock_verify_av_attr(attr))
		return -FI_EINVAL;

	if (attr->type == FI_AV_UNSPEC)
		attr->type = FI_AV_TABLE;

	dom = container_of(domain, struct sock_domain, dom_fid);
	if (dom->attr.av_type != FI_AV_UNSPEC &&
	    dom->attr.av_type != attr->type)
		return -FI_EINVAL;

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

	_av->attr = *attr;
	_av->attr.count = (attr->count) ? attr->count : sock_av_def_sz;
	table_sz = SOCK_AV_TABLE_SZ(_av->attr.count, attr->name);

	if (attr->name) {
		ret = ofi_shm_map(&_av->shm, attr->name, table_sz,
				attr->flags & FI_READ, (void**)&_av->table_hdr);

		if (ret || _av->table_hdr == MAP_FAILED) {
			SOCK_LOG_ERROR("map failed\n");
			ret = -FI_EINVAL;
			goto err;
		}

		_av->idx_arr = (uint64_t *)(_av->table_hdr + 1);
		_av->attr.map_addr = _av->idx_arr;
		attr->map_addr = _av->attr.map_addr;
		SOCK_LOG_DBG("Updating map_addr: %p\n", _av->attr.map_addr);

		if (attr->flags & FI_READ) {
			if (_av->table_hdr->size != _av->attr.count) {
				ret = -FI_EINVAL;
				goto err2;
			}
		} else {
			_av->table_hdr->size = _av->attr.count;
			_av->table_hdr->stored = 0;
		}
		_av->shared = 1;
	} else {
		_av->table_hdr = calloc(1, table_sz);
		if (!_av->table_hdr) {
			ret = -FI_ENOMEM;
			goto err;
		}
		_av->table_hdr->size = _av->attr.count;
		_av->table_hdr->req_sz = attr->count;
	}
	sock_update_av_table(_av, _av->attr.count);

	_av->av_fid.fid.fclass = FI_CLASS_AV;
	_av->av_fid.fid.context = context;
	_av->av_fid.fid.ops = &sock_av_fi_ops;

	switch (attr->type) {
	case FI_AV_MAP:
		_av->av_fid.ops = &sock_am_ops;
		break;
	case FI_AV_TABLE:
		_av->av_fid.ops = &sock_at_ops;
		break;
	default:
		ret = -FI_EINVAL;
		goto err2;
	}

	atomic_initialize(&_av->ref, 0);
	atomic_inc(&dom->ref);
	_av->domain = dom;
	switch (dom->info.addr_format) {
	case FI_SOCKADDR_IN:
		_av->addrlen = sizeof(struct sockaddr_in);
		break;
	default:
		SOCK_LOG_ERROR("Invalid address format: only IPv4 supported\n");
		ret = -FI_EINVAL;
		goto err2;
	}
	_av->rx_ctx_bits = attr->rx_ctx_bits;
	_av->mask = attr->rx_ctx_bits ?
		((uint64_t)1 << (64 - attr->rx_ctx_bits)) - 1 : ~0;
	*av = &_av->av_fid;
	return 0;

err2:
	if(attr->name) {
		ofi_shm_unmap(&_av->shm);
	} else {
		if(_av->table_hdr && _av->table_hdr != MAP_FAILED)
			free(_av->table_hdr);
	}
err:
	free(_av);
	return ret;
}
Beispiel #25
0
int
usdf_domain_open(struct fid_fabric *fabric, struct fi_info *info,
	   struct fid_domain **domain, void *context)
{
	struct usdf_fabric *fp;
	struct usdf_domain *udp;
	struct sockaddr_in *sin;
	size_t addrlen;
	int ret;
#if ENABLE_DEBUG
	char requested[INET_ADDRSTRLEN], actual[INET_ADDRSTRLEN];
#endif

	USDF_TRACE_SYS(DOMAIN, "\n");

	if (info->domain_attr != NULL) {
		switch (info->domain_attr->mr_mode) {
		case FI_MR_UNSPEC:
		case FI_MR_BASIC:
			break;
		default:
			/* the caller ignored our fi_getinfo results */
			USDF_WARN_SYS(DOMAIN, "MR mode (%d) not supported\n",
				info->domain_attr->mr_mode);
			return -FI_ENODATA;
		}
	}

	udp = calloc(1, sizeof *udp);
	if (udp == NULL) {
		USDF_DBG("unable to alloc mem for domain\n");
		ret = -FI_ENOMEM;
		goto fail;
	}

	fp = fab_fidtou(fabric);

	USDF_DBG("uda_devname=%s\n", fp->fab_dev_attrs->uda_devname);

	/*
	 * Make sure address format is good and matches this fabric
	 */
	switch (info->addr_format) {
	case FI_SOCKADDR:
		addrlen = sizeof(struct sockaddr);
		break;
	case FI_SOCKADDR_IN:
		addrlen = sizeof(struct sockaddr_in);
		break;
	default:
		ret = -FI_EINVAL;
		goto fail;
	}
	sin = info->src_addr;
	if (info->src_addrlen != addrlen || sin->sin_family != AF_INET ||
	    sin->sin_addr.s_addr != fp->fab_dev_attrs->uda_ipaddr_be) {
		USDF_DBG_SYS(DOMAIN, "requested src_addr (%s) != fabric addr (%s)\n",
			inet_ntop(AF_INET, &sin->sin_addr.s_addr,
				requested, sizeof(requested)),
			inet_ntop(AF_INET, &fp->fab_dev_attrs->uda_ipaddr_be,
				actual, sizeof(actual)));

		ret = -FI_EINVAL;
		goto fail;
	}

	ret = usd_open(fp->fab_dev_attrs->uda_devname, &udp->dom_dev);
	if (ret != 0) {
		goto fail;
	}

	udp->dom_fid.fid.fclass = FI_CLASS_DOMAIN;
	udp->dom_fid.fid.context = context;
	udp->dom_fid.fid.ops = &usdf_fid_ops;
	udp->dom_fid.ops = &usdf_domain_ops;
	udp->dom_fid.mr = &usdf_domain_mr_ops;

	ret = pthread_spin_init(&udp->dom_progress_lock,
			PTHREAD_PROCESS_PRIVATE);
	if (ret != 0) {
		ret = -ret;
		goto fail;
	}
	TAILQ_INIT(&udp->dom_tx_ready);
	TAILQ_INIT(&udp->dom_hcq_list);

	udp->dom_info = fi_dupinfo(info);
	if (udp->dom_info == NULL) {
		ret = -FI_ENOMEM;
		goto fail;
	}
	if (udp->dom_info->dest_addr != NULL) {
		free(udp->dom_info->dest_addr);
		udp->dom_info->dest_addr = NULL;
	}

	ret = usdf_dom_rdc_alloc_data(udp);
	if (ret != 0) {
		goto fail;
	}

	udp->dom_fabric = fp;
	LIST_INSERT_HEAD(&fp->fab_domain_list, udp, dom_link);
	atomic_initialize(&udp->dom_refcnt, 0);
	atomic_inc(&fp->fab_refcnt);

	*domain = &udp->dom_fid;
	return 0;

fail:
	if (udp != NULL) {
		if (udp->dom_info != NULL) {
			fi_freeinfo(udp->dom_info);
		}
		if (udp->dom_dev != NULL) {
			usd_close(udp->dom_dev);
		}
		usdf_dom_rdc_free_data(udp);
		free(udp);
	}
	return ret;
}
Beispiel #26
0
int psmx2_cntr_open(struct fid_domain *domain, struct fi_cntr_attr *attr,
			struct fid_cntr **cntr, void *context)
{
	struct psmx2_fid_domain *domain_priv;
	struct psmx2_fid_cntr *cntr_priv;
	struct fid_wait *wait = NULL;
	struct fi_wait_attr wait_attr;
	int wait_is_local = 0;
	int events;
	uint64_t flags;
	int err;

	events = FI_CNTR_EVENTS_COMP;
	flags = 0;
	domain_priv = container_of(domain, struct psmx2_fid_domain,
				   util_domain.domain_fid);

	switch (attr->events) {
	case FI_CNTR_EVENTS_COMP:
		events = attr->events;
		break;

	default:
		FI_INFO(&psmx2_prov, FI_LOG_CQ,
			"attr->events=%d, supported=%d\n",
			attr->events, FI_CNTR_EVENTS_COMP);
		return -FI_EINVAL;
	}

	switch (attr->wait_obj) {
	case FI_WAIT_NONE:
		break;

	case FI_WAIT_SET:
		if (!attr->wait_set) {
			FI_INFO(&psmx2_prov, FI_LOG_CQ,
				"FI_WAIT_SET is specified but attr->wait_set is NULL\n");
			return -FI_EINVAL;
		}
		wait = attr->wait_set;
		break;

	case FI_WAIT_UNSPEC:
	case FI_WAIT_FD:
	case FI_WAIT_MUTEX_COND:
		wait_attr.wait_obj = attr->wait_obj;
		wait_attr.flags = 0;
		err = fi_wait_open(&domain_priv->fabric->util_fabric.fabric_fid,
				      &wait_attr, (struct fid_wait **)&wait);
		if (err)
			return err;
		wait_is_local = 1;
		break;

	default:
		FI_INFO(&psmx2_prov, FI_LOG_CQ,
			"attr->wait_obj=%d, supported=%d...%d\n",
			attr->wait_obj, FI_WAIT_NONE, FI_WAIT_MUTEX_COND);
		return -FI_EINVAL;
	}

	cntr_priv = (struct psmx2_fid_cntr *) calloc(1, sizeof *cntr_priv);
	if (!cntr_priv) {
		err = -FI_ENOMEM;
		goto fail;
	}


	cntr_priv->domain = domain_priv;
	cntr_priv->events = events;
	if (wait)
		cntr_priv->wait = container_of(wait, struct util_wait, wait_fid);
	cntr_priv->wait_is_local = wait_is_local;
	cntr_priv->flags = flags;
	cntr_priv->cntr.fid.fclass = FI_CLASS_CNTR;
	cntr_priv->cntr.fid.context = context;
	cntr_priv->cntr.fid.ops = &psmx2_fi_ops;
	cntr_priv->cntr.ops = &psmx2_cntr_ops;
	atomic_initialize(&cntr_priv->counter, 0);
	atomic_initialize(&cntr_priv->error_counter, 0);

	pthread_mutex_init(&cntr_priv->trigger_lock, NULL);

	if (wait)
		fi_poll_add(&cntr_priv->wait->pollset->poll_fid,
			    &cntr_priv->cntr.fid, 0);

	psmx2_domain_acquire(domain_priv);
	*cntr = &cntr_priv->cntr;
	return 0;
fail:
	if (wait && wait_is_local)
		fi_close(&wait->fid);
	return err;
}
Beispiel #27
0
int sock_cq_open(struct fid_domain *domain, struct fi_cq_attr *attr,
		 struct fid_cq **cq, void *context)
{
	struct sock_domain *sock_dom;
	struct sock_cq *sock_cq;
	struct fi_wait_attr wait_attr;
	struct sock_fid_list *list_entry;
	struct sock_wait *wait;
	int ret;

	sock_dom = container_of(domain, struct sock_domain, dom_fid);
	ret = sock_cq_verify_attr(attr);
	if (ret)
		return ret;

	sock_cq = calloc(1, sizeof(*sock_cq));
	if (!sock_cq)
		return -FI_ENOMEM;
	
	atomic_initialize(&sock_cq->ref, 0);
	sock_cq->cq_fid.fid.fclass = FI_CLASS_CQ;
	sock_cq->cq_fid.fid.context = context;
	sock_cq->cq_fid.fid.ops = &sock_cq_fi_ops;
	sock_cq->cq_fid.ops = &sock_cq_ops;

	if (attr == NULL) 
		sock_cq->attr = _sock_cq_def_attr;
	else {
		sock_cq->attr = *attr;
		if (attr->size == 0) 
			sock_cq->attr.size = _sock_cq_def_attr.size;
	}
	
	sock_cq->domain = sock_dom;
	sock_cq->cq_entry_size = sock_cq_entry_size(sock_cq);
	sock_cq_set_report_fn(sock_cq);

	dlist_init(&sock_cq->tx_list);
	dlist_init(&sock_cq->rx_list);
	dlist_init(&sock_cq->ep_list);
	dlist_init(&sock_cq->overflow_list);

	if ((ret = rbfdinit(&sock_cq->cq_rbfd, sock_cq->attr.size *
		    sock_cq->cq_entry_size)))
		goto err1;

	if ((ret = rbinit(&sock_cq->addr_rb, 
			 sock_cq->attr.size * sizeof(fi_addr_t))))
		goto err2;
	
	if ((ret = rbinit(&sock_cq->cqerr_rb, sock_cq->attr.size * 
			 sizeof(struct fi_cq_err_entry))))
		goto err3;

	fastlock_init(&sock_cq->lock);

	switch (sock_cq->attr.wait_obj) {
	case FI_WAIT_NONE:
	case FI_WAIT_UNSPEC:
	case FI_WAIT_FD:
		break;

	case FI_WAIT_MUTEX_COND:
		wait_attr.flags = 0;
		wait_attr.wait_obj = FI_WAIT_MUTEX_COND;
		ret = sock_wait_open(&sock_dom->fab->fab_fid, &wait_attr,
				     &sock_cq->waitset);
		if (ret) {
			ret = -FI_EINVAL;
			goto err4;
		}
		sock_cq->signal = 1;
		break;

	case FI_WAIT_SET:
		if (!attr) {
			ret = -FI_EINVAL;
			goto err4;
		}

		sock_cq->waitset = attr->wait_set;
		sock_cq->signal = 1;
		wait = container_of(attr->wait_set, struct sock_wait, wait_fid);
		list_entry = calloc(1, sizeof(*list_entry));
		dlist_init(&list_entry->entry);
		list_entry->fid = &sock_cq->cq_fid.fid;
		dlist_insert_after(&list_entry->entry, &wait->fid_list);
		break;

	default:
		break;
	}
	
	*cq = &sock_cq->cq_fid;
	atomic_inc(&sock_dom->ref);
	fastlock_init(&sock_cq->list_lock);

	return 0;

err4:
	rbfree(&sock_cq->cqerr_rb);
err3:
	rbfree(&sock_cq->addr_rb);
err2:
	rbfdfree(&sock_cq->cq_rbfd);
err1:
	free(sock_cq);
	return ret;
}
Beispiel #28
0
int
usdf_pep_open(struct fid_fabric *fabric, struct fi_info *info,
	    struct fid_pep **pep_o, void *context)
{
	struct usdf_pep *pep;
	struct usdf_fabric *fp;
	int ret;
	int optval;

	USDF_TRACE_SYS(EP_CTRL, "\n");

	if (info->ep_attr->type != FI_EP_MSG) {
		return -FI_ENODEV;
	}

	if ((info->caps & ~USDF_MSG_CAPS) != 0) {
		return -FI_EBADF;
	}

	fp = fab_ftou(fabric);

	pep = calloc(1, sizeof(*pep));
	if (pep == NULL) {
		return -FI_ENOMEM;
	}

	pep->pep_fid.fid.fclass = FI_CLASS_PEP;
	pep->pep_fid.fid.context = context;
	pep->pep_fid.fid.ops = &usdf_pep_ops;
	pep->pep_fid.ops = &usdf_pep_base_ops;
	pep->pep_fid.cm = &usdf_pep_cm_ops;
	pep->pep_fabric = fp;

	pep->pep_sock = socket(AF_INET, SOCK_STREAM, 0);
	if (pep->pep_sock == -1) {
		ret = -errno;
		goto fail;
	}
        ret = fcntl(pep->pep_sock, F_GETFL, 0);
        if (ret == -1) {
                ret = -errno;
                goto fail;
        }
        ret = fcntl(pep->pep_sock, F_SETFL, ret | O_NONBLOCK);
        if (ret == -1) {
                ret = -errno;
                goto fail;
        }

	/* set SO_REUSEADDR to prevent annoying "Address already in use" errors
	 * on successive runs of programs listening on a well known port */
	optval = 1;
	ret = setsockopt(pep->pep_sock, SOL_SOCKET, SO_REUSEADDR, &optval,
				sizeof(optval));
	if (ret == -1) {
		ret = -errno;
		goto fail;
	}

	ret = bind(pep->pep_sock, (struct sockaddr *)info->src_addr,
			info->src_addrlen);
	if (ret == -1) {
		ret = -errno;
		goto fail;
	}

	/* initialize connreq freelist */
	ret = pthread_spin_init(&pep->pep_cr_lock, PTHREAD_PROCESS_PRIVATE);
	if (ret != 0) {
		ret = -ret;
		goto fail;
	}
	TAILQ_INIT(&pep->pep_cr_free);
	TAILQ_INIT(&pep->pep_cr_pending);
	pep->pep_backlog = 10;
	ret = usdf_pep_grow_backlog(pep);
	if (ret != 0) {
		goto fail;
	}

	atomic_initialize(&pep->pep_refcnt, 0);
	atomic_inc(&fp->fab_refcnt);

	*pep_o = pep_utof(pep);
	return 0;

fail:
	if (pep != NULL) {
		usdf_pep_free_cr_lists(pep);
		if (pep->pep_sock != -1) {
			close(pep->pep_sock);
		}
		free(pep);
	}
	return ret;
}