Ejemplo n.º 1
0
Test(gnix_hashtable_basic, err_destroy_uninitialized)
{
	int ret;

	ret = _gnix_ht_destroy(test_ht);
	cr_assert(ret == -FI_EINVAL);

	__gnix_hashtable_test_uninitialized();
}
Ejemplo n.º 2
0
Test(gnix_hashtable_basic, destroy_twice)
{
	int ret;

	__gnix_hashtable_initialize();

	__gnix_hashtable_destroy();

	ret = _gnix_ht_destroy(test_ht);
	cr_assert(ret == -FI_EINVAL);
	__gnix_hashtable_test_destroyed_clean();
}
Ejemplo n.º 3
0
static void __av_destruct(void *obj)
{
	int ret;
	struct gnix_fid_av *av = (struct gnix_fid_av *) obj;
	struct slist_entry *blk_entry;
	struct gnix_av_block *temp;


	if (av->type == FI_AV_TABLE) {
		if (av->table) {
			free(av->table);
		}
	} else if (av->type == FI_AV_MAP) {

		while (!slist_empty(&av->block_list)) {
			blk_entry = slist_remove_head(&av->block_list);
			temp = container_of(blk_entry,
					struct gnix_av_block, slist);
			free(temp->base);
			free(temp);
		}

		ret = _gnix_ht_destroy(av->map_ht);
		if (ret != FI_SUCCESS)
			GNIX_WARN(FI_LOG_AV,
				  "_gnix_ht_destroy failed %d\n",
				  ret);
		free(av->map_ht);
	}
	if (av->valid_entry_vec) {
		free(av->valid_entry_vec);
	} else {
		GNIX_WARN(FI_LOG_AV, "valid_entry_vec is NULL\n");
	}

	free(av);
}
Ejemplo n.º 4
0
static void  __cm_nic_destruct(void *obj)
{
	int ret;
	struct gnix_cm_nic *cm_nic = (struct gnix_cm_nic *)obj;

	GNIX_TRACE(FI_LOG_EP_CTRL, "\n");

	pthread_mutex_lock(&gnix_cm_nic_list_lock);
	dlist_remove(&cm_nic->cm_nic_list);
	pthread_mutex_unlock(&gnix_cm_nic_list_lock);

	if (cm_nic->dgram_hndl != NULL) {
		ret = _gnix_dgram_hndl_free(cm_nic->dgram_hndl);
		if (ret != FI_SUCCESS)
			GNIX_WARN(FI_LOG_EP_CTRL,
				  "gnix_dgram_hndl_free returned %d\n",
				  ret);
	}

	if (cm_nic->addr_to_ep_ht != NULL) {
		ret = _gnix_ht_destroy(cm_nic->addr_to_ep_ht);
		if (ret != FI_SUCCESS)
			GNIX_WARN(FI_LOG_EP_CTRL,
				  "gnix_ht_destroy returned %d\n",
				  ret);
		free(cm_nic->addr_to_ep_ht);
		cm_nic->addr_to_ep_ht = NULL;
	}

	if (cm_nic->nic != NULL) {
		_gnix_ref_put(cm_nic->nic);
		cm_nic->nic = NULL;
	}

	cm_nic->domain->cm_nic = NULL;
	free(cm_nic);
}
Ejemplo n.º 5
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;

}
Ejemplo n.º 6
0
static int gnix_ep_close(fid_t fid)
{
	int ret = FI_SUCCESS;
	struct gnix_fid_ep *ep;
	struct gnix_fid_domain *domain;
	struct gnix_nic *nic;
	struct gnix_vc *vc;
	struct gnix_fid_av *av;
	struct gnix_cm_nic *cm_nic;
	struct dlist_entry *p, *head;


	GNIX_TRACE(FI_LOG_EP_CTRL, "\n");

	ep = container_of(fid, struct gnix_fid_ep, ep_fid.fid);
	/* TODO: lots more stuff to do here */

	if (ep->send_cq) {
		_gnix_cq_poll_nic_rem(ep->send_cq, ep->nic);
		atomic_dec(&ep->send_cq->ref_cnt);
	}

	if (ep->recv_cq) {
		_gnix_cq_poll_nic_rem(ep->recv_cq, ep->nic);
		atomic_dec(&ep->recv_cq->ref_cnt);
	}

	if (ep->send_cntr) {
		_gnix_cntr_poll_nic_rem(ep->send_cntr, ep->nic);
		atomic_dec(&ep->send_cntr->ref_cnt);
	}

	if (ep->recv_cntr) {
		_gnix_cntr_poll_nic_rem(ep->recv_cntr, ep->nic);
		atomic_dec(&ep->recv_cntr->ref_cnt);
	}

	if (ep->read_cntr) {
		_gnix_cntr_poll_nic_rem(ep->read_cntr, ep->nic);
		atomic_dec(&ep->read_cntr->ref_cnt);
	}

	if (ep->write_cntr) {
		_gnix_cntr_poll_nic_rem(ep->write_cntr, ep->nic);
		atomic_dec(&ep->write_cntr->ref_cnt);
	}

	domain = ep->domain;
	assert(domain != NULL);
	atomic_dec(&domain->ref_cnt);

	cm_nic = ep->cm_nic;
	assert(cm_nic != NULL);
	_gnix_cm_nic_free(cm_nic);

	nic = ep->nic;
	assert(nic != NULL);

	av = ep->av;
	if (av != NULL)
		atomic_dec(&av->ref_cnt);

	/*
	 * destroy any vc's being used by this EP.
	 */

	head = &ep->wc_vc_list;
	for (p = head->next; p != head; p = p->next) {
		vc = container_of(p, struct gnix_vc, entry);
		dlist_remove(&vc->entry);
		if (vc->conn_state == GNIX_VC_CONNECTED) {
			ret = _gnix_vc_disconnect(vc);
			if (ret != FI_SUCCESS) {
				GNIX_WARN(FI_LOG_EP_CTRL,
				    "_gnix_vc_disconnect returned %d\n",
				     ret);
				goto err;
			}
		}
		ret = _gnix_vc_destroy(vc);
		if (ret != FI_SUCCESS) {
			GNIX_WARN(FI_LOG_EP_CTRL,
			    "_gnix_vc_destroy returned %d\n",
			     ret);
			goto err;
		}
	}

	/*
	 * clean up any vc hash table or vector
	 */

	if (ep->type == FI_EP_RDM) {
		if (ep->vc_ht != NULL) {
			_gnix_ht_destroy(ep->vc_ht);
			free(ep->vc_ht);
			ep->vc_ht = NULL;
		}
	}

	ret = _gnix_nic_free(nic);
	if (ret != FI_SUCCESS) {
		GNIX_WARN(FI_LOG_EP_CTRL,
		    "_gnix_vc_destroy call returned %d\n",
		     ret);
		goto err;
	}

	ep->nic = NULL;

	/*
	 * Free fab_reqs
	 */
	if (atomic_get(&ep->active_fab_reqs) != 0) {
		/* Should we just assert here? */
		GNIX_WARN(FI_LOG_EP_CTRL,
			  "Active requests while closing an endpoint.");
	}
	__fr_freelist_destroy(ep);

	free(ep);

err:
	return ret;
}
Ejemplo n.º 7
0
void __gnix_hashtable_destroy(void)
{
	int ret = _gnix_ht_destroy(test_ht);
	cr_assert(ret == 0);
	__gnix_hashtable_test_destroyed_clean();
}
Ejemplo n.º 8
0
int _gnix_cm_nic_alloc(struct gnix_fid_domain *domain,
		       struct fi_info *info,
		       uint32_t cdm_id,
			   struct gnix_auth_key *auth_key,
		       struct gnix_cm_nic **cm_nic_ptr)
{
	int ret = FI_SUCCESS;
	struct gnix_cm_nic *cm_nic = NULL;
	gnix_hashtable_attr_t gnix_ht_attr = {0};
	uint32_t name_type = GNIX_EPN_TYPE_UNBOUND;
	struct gnix_nic_attr nic_attr = {0};
	struct gnix_ep_name ep_name;
	struct gnix_dgram_hndl_attr dgram_hndl_attr = {0};
	struct gnix_dgram_hndl_attr *dgram_hndl_attr_ptr = NULL;

	GNIX_TRACE(FI_LOG_EP_CTRL, "\n");

	*cm_nic_ptr = NULL;

	/*
	 * if app has specified a src_addr in the info
	 * argument and length matches that for gnix_ep_name
	 * we must allocate a cm_nic, otherwise we first
	 * check to see if there is a cm_nic already for this domain
	 * and just use it.
	 */

	if (info->src_addr) {
		/*TODO (optimization): strchr to name_type and strtol */
		_gnix_get_ep_name(info->src_addr, 0, &ep_name, domain);
		name_type = ep_name.name_type;
	}

	GNIX_INFO(FI_LOG_EP_CTRL, "creating cm_nic for %u/0x%x/%u\n",
			auth_key->ptag, auth_key->cookie, cdm_id);

	cm_nic = (struct gnix_cm_nic *)calloc(1, sizeof(*cm_nic));
	if (cm_nic == NULL) {
		ret = -FI_ENOMEM;
		goto err;
	}

	/*
	 * we have to force allocation of a new nic since we want
	 * an a particulard cdm id
	 */
	nic_attr.must_alloc = true;
	nic_attr.use_cdm_id = true;
	nic_attr.cdm_id = cdm_id;
	nic_attr.auth_key = auth_key;

	ret = gnix_nic_alloc(domain, &nic_attr, &cm_nic->nic);
	if (ret != FI_SUCCESS) {
		GNIX_WARN(FI_LOG_EP_CTRL,
			  "gnix_nic_alloc returned %s\n",
			  fi_strerror(-ret));
		goto err;
	}

	cm_nic->my_name.gnix_addr.cdm_id = cdm_id;
	cm_nic->ptag = auth_key->ptag;
	cm_nic->my_name.cookie = auth_key->cookie;
	cm_nic->my_name.gnix_addr.device_addr = cm_nic->nic->device_addr;
	cm_nic->domain = domain;
	cm_nic->ctrl_progress = domain->control_progress;
	cm_nic->my_name.name_type = name_type;
	cm_nic->poll_cnt = 0;
	fastlock_init(&cm_nic->wq_lock);
	dlist_init(&cm_nic->cm_nic_wq);

	/*
	 * prep the cm nic's dgram component
	 */
	if (domain->control_progress == FI_PROGRESS_AUTO) {
		dgram_hndl_attr.timeout_needed = __gnix_cm_nic_timeout_needed;
		dgram_hndl_attr.timeout_progress = __gnix_cm_nic_timeout_progress;
		dgram_hndl_attr.timeout_data = (void *)cm_nic;
		dgram_hndl_attr.timeout = domain->params.dgram_progress_timeout;
		dgram_hndl_attr_ptr = &dgram_hndl_attr;
	};

	ret = _gnix_dgram_hndl_alloc(cm_nic,
				     domain->control_progress,
				     dgram_hndl_attr_ptr,
				     &cm_nic->dgram_hndl);
	if (ret != FI_SUCCESS)
		goto err;

	/*
	 * allocate hash table for translating ep addresses
	 * to ep's.
	 * This table will not be large - how many FI_EP_RDM ep's
	 * will an app create using one domain?, nor in the critical path
	 * so just use defaults.
	 */
	cm_nic->addr_to_ep_ht = calloc(1, sizeof(struct gnix_hashtable));
	if (cm_nic->addr_to_ep_ht == NULL)
		goto err;

	gnix_ht_attr.ht_initial_size = 64;
	gnix_ht_attr.ht_maximum_size = 1024;
	gnix_ht_attr.ht_increase_step = 2;
	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;
	gnix_ht_attr.destructor = NULL;

	ret = _gnix_ht_init(cm_nic->addr_to_ep_ht, &gnix_ht_attr);
	if (ret != FI_SUCCESS) {
		GNIX_WARN(FI_LOG_EP_CTRL,
			  "gnix_ht_init returned %s\n",
			  fi_strerror(-ret));
		goto err;
	}

	_gnix_ref_init(&cm_nic->ref_cnt, 1, __cm_nic_destruct);

	*cm_nic_ptr = cm_nic;

	pthread_mutex_lock(&gnix_cm_nic_list_lock);
	dlist_insert_tail(&cm_nic->cm_nic_list, &gnix_cm_nic_list);
	pthread_mutex_unlock(&gnix_cm_nic_list_lock);

	return ret;

err:
	if (cm_nic->dgram_hndl)
		_gnix_dgram_hndl_free(cm_nic->dgram_hndl);

	if (cm_nic->nic)
		_gnix_nic_free(cm_nic->nic);

	if (cm_nic->addr_to_ep_ht) {
		_gnix_ht_destroy(cm_nic->addr_to_ep_ht);
		free(cm_nic->addr_to_ep_ht);
	}

	if (cm_nic != NULL)
		free(cm_nic);

	return ret;
}
Ejemplo n.º 9
0
int gnix_ep_open(struct fid_domain *domain, struct fi_info *info,
		 struct fid_ep **ep, void *context)
{
	int ret = FI_SUCCESS;
	int tsret = FI_SUCCESS;
	uint32_t cdm_id;
	struct gnix_fid_domain *domain_priv;
	struct gnix_fid_ep *ep_priv;
	gnix_hashtable_attr_t gnix_ht_attr;
	gnix_ht_key_t *key_ptr;
	struct gnix_tag_storage_attr untagged_attr = {
			.type = GNIX_TAG_LIST,
			.use_src_addr_matching = 1,
	};
	bool free_list_inited = false;

	GNIX_TRACE(FI_LOG_EP_CTRL, "\n");

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

	/*
	 * TODO: need to implement other endpoint types
	 */
	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;

	/* init untagged storages */
	tsret = _gnix_posted_tag_storage_init(
			&ep_priv->posted_recv_queue, &untagged_attr);
	if (tsret)
		return tsret;

	tsret = _gnix_unexpected_tag_storage_init(
			&ep_priv->unexp_recv_queue, &untagged_attr);
	if (tsret)
		return tsret;

	/* init tagged storages */
	tsret = _gnix_posted_tag_storage_init(
			&ep_priv->tagged_posted_recv_queue, NULL);
	if (tsret)
		return tsret;

	tsret = _gnix_unexpected_tag_storage_init(
			&ep_priv->tagged_unexp_recv_queue, NULL);
	if (tsret)
		return tsret;

	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;

	_gnix_ref_init(&ep_priv->ref_cnt, 1, __ep_destruct);

	fastlock_init(&ep_priv->recv_comp_lock);
	fastlock_init(&ep_priv->recv_queue_lock);
	fastlock_init(&ep_priv->tagged_queue_lock);
	slist_init(&ep_priv->pending_recv_comp_queue);

	ep_priv->caps = info->caps & GNIX_EP_RDM_CAPS;

	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;
	ep_priv->op_flags &= GNIX_EP_OP_FLAGS;

	ep_priv->min_multi_recv = GNIX_OPT_MIN_MULTI_RECV_DEFAULT;

	ret = __fr_freelist_init(ep_priv);
	if (ret != FI_SUCCESS) {
		GNIX_WARN(FI_LOG_EP_CTRL,
			 "Error allocating gnix_fab_req freelist (%s)",
			 fi_strerror(-ret));
		goto err;
	} else
		free_list_inited = true;

	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 = &gnix_ep_atomic_ops;

	ep_priv->ep_fid.cm = &gnix_cm_ops;

	if (ep_priv->type == FI_EP_RDM) {
		if (info->src_addr != NULL) {
			ret = __gnix_ep_bound_prep(domain_priv,
						   info,
						   ep_priv);
			if (ret != FI_SUCCESS) {
				GNIX_WARN(FI_LOG_EP_CTRL,
				 "__gnix_ep_bound_prep returned error (%s)",
				 fi_strerror(-ret));
				goto err;
			}
		} else {
			fastlock_acquire(&domain_priv->cm_nic_lock);

			/*
			 * if a cm_nic has not yet been allocated for this
			 * domain, do it now.  Reuse the embedded gnix_nic
			 * in the cm_nic as the nic for this endpoint
			 * to reduce demand on Aries hw resources.
			 */
			if (domain_priv->cm_nic == NULL) {
				ret = _gnix_cm_nic_alloc(domain_priv,
							 info,
							 &domain_priv->cm_nic);
				if (ret != FI_SUCCESS) {
					GNIX_WARN(FI_LOG_EP_CTRL,
						"_gnix_cm_nic_alloc returned %s\n",
						fi_strerror(-ret));
					fastlock_release(
						 &domain_priv->cm_nic_lock);
					goto err;
				}
				ep_priv->cm_nic = domain_priv->cm_nic;
				ep_priv->nic = ep_priv->cm_nic->nic;
				_gnix_ref_get(ep_priv->nic);
			} else {
				ep_priv->cm_nic = domain_priv->cm_nic;
				_gnix_ref_get(ep_priv->cm_nic);
			}

			fastlock_release(&domain_priv->cm_nic_lock);

			ep_priv->my_name.gnix_addr.device_addr =
				ep_priv->cm_nic->my_name.gnix_addr.device_addr;
			ep_priv->my_name.cm_nic_cdm_id =
				ep_priv->cm_nic->my_name.gnix_addr.cdm_id;
			ret = _gnix_get_new_cdm_id(domain_priv, &cdm_id);
			if (ret != FI_SUCCESS) {
				GNIX_WARN(FI_LOG_EP_CTRL,
					    "gnix_get_new_cdm_id call returned %s\n",
					     fi_strerror(-ret));
				goto err;
			}
			ep_priv->my_name.gnix_addr.cdm_id = cdm_id;
		}

		key_ptr = (gnix_ht_key_t *)&ep_priv->my_name.gnix_addr;
		ret = _gnix_ht_insert(ep_priv->cm_nic->addr_to_ep_ht,
					*key_ptr,
					ep_priv);
		if ((ret != FI_SUCCESS) && (ret != -FI_ENOSPC)) {
			GNIX_WARN(FI_LOG_EP_CTRL,
				  "__gnix_ht_insert returned %d\n",
				  ret);
			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 = 0;
		gnix_ht_attr.destructor = __gnix_vc_destroy_ht_entry;

		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;
		}
		fastlock_init(&ep_priv->vc_ht_lock);

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

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

	if (ep_priv->nic == NULL) {
		ret = gnix_nic_alloc(domain_priv, NULL, &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;

	_gnix_ref_get(ep_priv->domain);
	*ep = &ep_priv->ep_fid;
	return ret;

err:
	if (free_list_inited == true)
		__fr_freelist_destroy(ep_priv);

	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);

	if (ep_priv->nic != NULL)
		ret = _gnix_nic_free(ep_priv->nic);

	free(ep_priv);
	return ret;

}

static int __match_context(struct slist_entry *item, const void *arg)
{
	struct gnix_fab_req *req;

	req = container_of(item, struct gnix_fab_req, slist);

	return req->user_context == arg;
}

static inline struct gnix_fab_req *__find_tx_req(
		struct gnix_fid_ep *ep,
		void *context)
{
	struct gnix_fab_req *req = NULL;
	struct slist_entry *entry;
	struct gnix_vc *vc;
	GNIX_HASHTABLE_ITERATOR(ep->vc_ht, iter);

	GNIX_DEBUG(FI_LOG_EP_CTRL, "searching VCs for the correct context to"
			" cancel, context=%p", context);

	fastlock_acquire(&ep->vc_ht_lock);
	while ((vc = _gnix_ht_iterator_next(&iter))) {
		fastlock_acquire(&vc->tx_queue_lock);
		entry = slist_remove_first_match(&vc->tx_queue,
				__match_context, context);
		fastlock_release(&vc->tx_queue_lock);
		if (entry) {
			req = container_of(entry, struct gnix_fab_req, slist);
			break;
		}
	}
	fastlock_release(&ep->vc_ht_lock);

	return req;
}

static inline struct gnix_fab_req *__find_rx_req(
		struct gnix_fid_ep *ep,
		void *context)
{
	struct gnix_fab_req *req = NULL;

	fastlock_acquire(&ep->recv_queue_lock);
	req = _gnix_remove_req_by_context(&ep->posted_recv_queue, context);
	fastlock_release(&ep->recv_queue_lock);

	if (req)
		return req;

	fastlock_acquire(&ep->tagged_queue_lock);
	req = _gnix_remove_req_by_context(&ep->tagged_posted_recv_queue,
			context);
	fastlock_release(&ep->tagged_queue_lock);

	return req;
}

static ssize_t gnix_ep_cancel(fid_t fid, void *context)
{
	int ret = FI_SUCCESS;
	struct gnix_fid_ep *ep;
	struct gnix_fab_req *req;
	struct gnix_fid_cq *err_cq = NULL;
	struct gnix_fid_cntr *err_cntr = NULL;
	void *addr;
	uint64_t tag, flags;
	size_t len;
	int is_send = 0;

	GNIX_TRACE(FI_LOG_EP_CTRL, "\n");

	ep = container_of(fid, struct gnix_fid_ep, ep_fid.fid);

	if (!ep->domain)
		return -FI_EDOMAIN;

	/* without context, we will have to find a request that matches
	 * a recv or send request. Try the send requests first.
	 */
	GNIX_INFO(FI_LOG_EP_CTRL, "looking for event to cancel\n");

	req = __find_tx_req(ep, context);
	if (!req) {
		req = __find_rx_req(ep, context);
		if (req) {
			err_cq = ep->recv_cq;
			err_cntr = ep->recv_cntr;
		}
	} else {
		is_send = 1;
		err_cq = ep->send_cq;
		err_cntr = ep->send_cntr;
	}
	GNIX_INFO(FI_LOG_EP_CTRL, "finished searching\n");

	if (!req)
		return -FI_ENOENT;

	if (err_cq) {
		/* add canceled event */
		if (!(req->type == GNIX_FAB_RQ_RDMA_READ ||
				req->type == GNIX_FAB_RQ_RDMA_WRITE)) {
			if (!is_send) {
				addr = (void *) req->msg.recv_addr;
				len = req->msg.recv_len;
			} else {
				addr = (void *) req->msg.send_addr;
				len = req->msg.send_len;
			}
			tag = req->msg.tag;
		} else {
			/* rma information */
			addr = (void *) req->rma.loc_addr;
			len = req->rma.len;
			tag = 0;
		}
		flags = req->flags;

		_gnix_cq_add_error(err_cq, context, flags, len, addr, 0 /* data */,
				tag, len, FI_ECANCELED, FI_ECANCELED, 0);

	}

	if (err_cntr) {
		/* signal increase in cntr errs */
		_gnix_cntr_inc_err(err_cntr);
	}

	_gnix_fr_free(ep, req);

	return ret;
}
Ejemplo n.º 10
0
static void __ep_destruct(void *obj)
{
	int __attribute__((unused)) ret;
	struct gnix_fid_domain *domain;
	struct gnix_nic *nic;
	struct gnix_fid_av *av;
	struct gnix_cm_nic *cm_nic;
	gnix_ht_key_t *key_ptr;
	struct gnix_fid_ep *ep = (struct gnix_fid_ep *) obj;

	GNIX_TRACE(FI_LOG_EP_CTRL, "\n");

	/*
	 * clean up any vc hash table or vector,
	 * remove entry from addr_to_ep ht.
	 * any outstanding GNI internal requests on
	 * the VC's will be completed prior to
	 * destroying the VC entries in the ht.
	 */

	if (ep->type == FI_EP_RDM) {

		key_ptr = (gnix_ht_key_t *)&ep->my_name.gnix_addr;
		ret =  _gnix_ht_remove(ep->cm_nic->addr_to_ep_ht,
				       *key_ptr);
		if (ep->vc_ht != NULL) {
			ret = _gnix_ht_destroy(ep->vc_ht);
			if (ret == FI_SUCCESS) {
				free(ep->vc_ht);
				ep->vc_ht = NULL;
			} else {
				GNIX_WARN(FI_LOG_EP_CTRL,
					"_gnix_ht_destroy returned %s\n",
					  fi_strerror(-ret));
			}
		}
	}

	if (ep->send_cq) {
		_gnix_cq_poll_nic_rem(ep->send_cq, ep->nic);
		_gnix_ref_put(ep->send_cq);
	}

	if (ep->recv_cq) {
		_gnix_cq_poll_nic_rem(ep->recv_cq, ep->nic);
		_gnix_ref_put(ep->recv_cq);
	}

	if (ep->send_cntr) {
		_gnix_cntr_poll_nic_rem(ep->send_cntr, ep->nic);
		_gnix_ref_put(ep->send_cntr);
	}

	if (ep->recv_cntr) {
		_gnix_cntr_poll_nic_rem(ep->recv_cntr, ep->nic);
		_gnix_ref_put(ep->recv_cntr);
	}

	if (ep->read_cntr) {
		_gnix_cntr_poll_nic_rem(ep->read_cntr, ep->nic);
		_gnix_ref_put(ep->read_cntr);
	}

	if (ep->write_cntr) {
		_gnix_cntr_poll_nic_rem(ep->write_cntr, ep->nic);
		_gnix_ref_put(ep->write_cntr);
	}

	if (ep->stx_ctx)
		_gnix_ref_put(ep->stx_ctx);

	domain = ep->domain;
	assert(domain != NULL);
	_gnix_ref_put(domain);

	cm_nic = ep->cm_nic;
	assert(cm_nic != NULL);

	nic = ep->nic;
	assert(nic != NULL);

	av = ep->av;
	if (av != NULL)
		_gnix_ref_put(av);

	/* There is no other choice here, we need to assert if we can't free */
	ret = _gnix_nic_free(nic);
	assert(ret == FI_SUCCESS);

	ep->nic = NULL;

	/* This currently always returns FI_SUCCESS */
	ret = _gnix_cm_nic_free(cm_nic);
	assert(ret == FI_SUCCESS);

	/*
	 * Free fab_reqs
	 */

	__fr_freelist_destroy(ep);

	free(ep);
}