int psmx2_domain_open()

in prov/psm2/src/psmx2_domain.c [298:497]


int psmx2_domain_open(struct fid_fabric *fabric, struct fi_info *info,
		      struct fid_domain **domain, void *context)
{
	struct psmx2_fid_fabric *fabric_priv;
	struct psmx2_fid_domain *domain_priv;
	struct psmx2_ep_name *src_addr = info->src_addr;
	int mr_mode = (info->domain_attr->mr_mode & FI_MR_BASIC) ? FI_MR_BASIC : 0;
	int err, tmp;

	FI_INFO(&psmx2_prov, FI_LOG_DOMAIN, "\n");

	fabric_priv = container_of(fabric, struct psmx2_fid_fabric,
				   util_fabric.fabric_fid);

	if (!info->domain_attr->name ||
	    strncmp(info->domain_attr->name, PSMX2_DOMAIN_NAME, strlen(PSMX2_DOMAIN_NAME))) {
		err = -FI_EINVAL;
		goto err_out;
	}

	domain_priv = (struct psmx2_fid_domain *) calloc(1, sizeof *domain_priv);
	if (!domain_priv) {
		err = -FI_ENOMEM;
		goto err_out;
	}

	err = ofi_domain_init(fabric, info, &domain_priv->util_domain, context);
	if (err)
		goto err_out_free_domain;

	/* fclass & context are set in ofi_domain_init */
	domain_priv->util_domain.domain_fid.fid.ops = &psmx2_fi_ops;
	domain_priv->util_domain.domain_fid.ops = &psmx2_domain_ops;
	domain_priv->util_domain.domain_fid.mr = &psmx2_mr_ops;
	domain_priv->mr_mode = mr_mode;
	domain_priv->mode = info->mode;
	domain_priv->caps = info->caps;
	domain_priv->fabric = fabric_priv;
	domain_priv->progress_thread_enabled =
		(info->domain_attr->data_progress == FI_PROGRESS_AUTO);
	domain_priv->addr_format = info->addr_format;

	if (info->addr_format == FI_ADDR_STR)
		src_addr = psmx2_string_to_ep_name(info->src_addr);

	/* Use generic lock/unlock functions by default */
	domain_priv->av_lock_fn = psmx2_lock;
	domain_priv->am_req_pool_lock_fn = psmx2_lock;
	domain_priv->trx_ctxt_lock_fn = psmx2_lock;
	domain_priv->rma_queue_lock_fn = psmx2_lock;
	domain_priv->trigger_queue_lock_fn = psmx2_lock;
	domain_priv->peer_lock_fn = psmx2_lock;
	domain_priv->sep_lock_fn = psmx2_lock;
	domain_priv->trigger_lock_fn = psmx2_lock;
	domain_priv->cq_lock_fn = psmx2_lock;
	domain_priv->mr_lock_fn = psmx2_lock;
	domain_priv->context_lock_fn = psmx2_lock;
	domain_priv->poll_trylock_fn = psmx2_trylock;

	domain_priv->av_unlock_fn = psmx2_unlock;
	domain_priv->am_req_pool_unlock_fn = psmx2_unlock;
	domain_priv->trx_ctxt_unlock_fn = psmx2_unlock;
	domain_priv->rma_queue_unlock_fn = psmx2_unlock;
	domain_priv->trigger_queue_unlock_fn = psmx2_unlock;
	domain_priv->peer_unlock_fn = psmx2_unlock;
	domain_priv->sep_unlock_fn = psmx2_unlock;
	domain_priv->trigger_unlock_fn = psmx2_unlock;
	domain_priv->cq_unlock_fn = psmx2_unlock;
	domain_priv->mr_unlock_fn = psmx2_unlock;
	domain_priv->context_unlock_fn = psmx2_unlock;
	domain_priv->poll_unlock_fn = psmx2_unlock;

	/* If lock_level env is unset, then set locks based off threading model*/
	err = fi_param_get_bool(&psmx2_prov, "lock_level", &tmp);
	if (err < 0) {
		switch (info->domain_attr->threading) {
		case FI_THREAD_DOMAIN:
			/* Disable locks not required when serializing access to a domain */
			domain_priv->av_lock_fn = psmx2_lock_disabled;
			domain_priv->trx_ctxt_lock_fn = psmx2_lock_disabled;
			domain_priv->trigger_queue_lock_fn = psmx2_lock_disabled;
			domain_priv->sep_lock_fn = psmx2_lock_disabled;
			domain_priv->trigger_lock_fn = psmx2_lock_disabled;
			domain_priv->cq_lock_fn = psmx2_lock_disabled;
			domain_priv->mr_lock_fn = psmx2_lock_disabled;
			domain_priv->context_lock_fn = psmx2_lock_disabled;
			domain_priv->poll_trylock_fn = psmx2_trylock_disabled;

			domain_priv->av_unlock_fn = psmx2_lock_disabled;
			domain_priv->trx_ctxt_unlock_fn = psmx2_lock_disabled;
			domain_priv->trigger_queue_unlock_fn = psmx2_lock_disabled;
			domain_priv->sep_unlock_fn = psmx2_lock_disabled;
			domain_priv->trigger_unlock_fn = psmx2_lock_disabled;
			domain_priv->cq_unlock_fn = psmx2_lock_disabled;
			domain_priv->mr_unlock_fn = psmx2_lock_disabled;
			domain_priv->context_unlock_fn = psmx2_lock_disabled;
			domain_priv->poll_unlock_fn = psmx2_lock_disabled;

			/* Enable lock accessed by the disconnection thread */
			domain_priv->peer_lock_fn = psmx2_lock_enabled;
			domain_priv->peer_unlock_fn = psmx2_unlock_enabled;

			/*
			 * If FI_RMA or FI_ATOMIC caps are enabled, then locks are
			 * required for the CQ, am_req_pool, & rma_queue
			 * due to the PSM2 Recv thread.
			 * NOTE: am_req_pool & rma_queue are only used when FI_RMA
			 * and FI_ATOMIC capabilities are enabled.
			 */
			if ((info->caps & FI_RMA) || (info->caps & FI_ATOMIC)) {
				domain_priv->cq_lock_fn = psmx2_lock_enabled;
				domain_priv->am_req_pool_lock_fn = psmx2_lock_enabled;
				domain_priv->rma_queue_lock_fn = psmx2_lock_enabled;
				domain_priv->cq_unlock_fn = psmx2_unlock_enabled;
				domain_priv->am_req_pool_unlock_fn = psmx2_unlock_enabled;
				domain_priv->rma_queue_unlock_fn = psmx2_unlock_enabled;
			}

			/*
			 * Locks accessed by the progress thread are required because
			 * they are outside the scope of domain access serialization
			 * implied by FI_THREAD_DOMAIN.
			 */
			if (domain_priv->progress_thread_enabled) {
				domain_priv->trx_ctxt_lock_fn = psmx2_lock_enabled;
				domain_priv->poll_trylock_fn = psmx2_trylock_enabled;
				domain_priv->cq_lock_fn = psmx2_lock_enabled;
				domain_priv->trx_ctxt_unlock_fn = psmx2_unlock_enabled;
				domain_priv->poll_unlock_fn = psmx2_unlock_enabled;
				domain_priv->cq_unlock_fn = psmx2_unlock_enabled;
				if (info->caps & FI_TRIGGER) {
					domain_priv->trigger_queue_lock_fn = psmx2_lock_enabled;
					domain_priv->trigger_lock_fn = psmx2_lock_enabled;
					domain_priv->av_lock_fn = psmx2_lock_enabled;
					domain_priv->mr_lock_fn = psmx2_lock_enabled;
					domain_priv->context_lock_fn = psmx2_lock_enabled;
					domain_priv->trigger_queue_unlock_fn = psmx2_unlock_enabled;
					domain_priv->trigger_unlock_fn = psmx2_unlock_enabled;
					domain_priv->av_unlock_fn = psmx2_unlock_enabled;
					domain_priv->mr_unlock_fn = psmx2_unlock_enabled;
					domain_priv->context_unlock_fn = psmx2_unlock_enabled;
				}
			}
			break;
		default:
			/* Otherwise, enable all locks */
			domain_priv->av_lock_fn = psmx2_lock_enabled;
			domain_priv->am_req_pool_lock_fn = psmx2_lock_enabled;
			domain_priv->trx_ctxt_lock_fn = psmx2_lock_enabled;
			domain_priv->rma_queue_lock_fn = psmx2_lock_enabled;
			domain_priv->trigger_queue_lock_fn = psmx2_lock_enabled;
			domain_priv->peer_lock_fn = psmx2_lock_enabled;
			domain_priv->sep_lock_fn = psmx2_lock_enabled;
			domain_priv->trigger_lock_fn = psmx2_lock_enabled;
			domain_priv->cq_lock_fn = psmx2_lock_enabled;
			domain_priv->mr_lock_fn = psmx2_lock_enabled;
			domain_priv->context_lock_fn = psmx2_lock_enabled;
			domain_priv->poll_trylock_fn = psmx2_trylock_enabled;

			domain_priv->av_unlock_fn = psmx2_unlock_enabled;
			domain_priv->am_req_pool_unlock_fn = psmx2_unlock_enabled;
			domain_priv->trx_ctxt_unlock_fn = psmx2_unlock_enabled;
			domain_priv->rma_queue_unlock_fn = psmx2_unlock_enabled;
			domain_priv->trigger_queue_unlock_fn = psmx2_unlock_enabled;
			domain_priv->peer_unlock_fn = psmx2_unlock_enabled;
			domain_priv->sep_unlock_fn = psmx2_unlock_enabled;
			domain_priv->trigger_unlock_fn = psmx2_unlock_enabled;
			domain_priv->cq_unlock_fn = psmx2_unlock_enabled;
			domain_priv->mr_unlock_fn = psmx2_unlock_enabled;
			domain_priv->context_unlock_fn = psmx2_unlock_enabled;
			domain_priv->poll_unlock_fn = psmx2_unlock_enabled;
			break;
		}
	}

	err = psmx2_domain_init(domain_priv, src_addr);
	if (info->addr_format == FI_ADDR_STR)
		free(src_addr);
	if (err)
		goto err_out_close_domain;

	psmx2_fabric_acquire(fabric_priv);
	psmx2_lock(&fabric_priv->domain_lock, 1);
	dlist_insert_before(&domain_priv->entry, &fabric_priv->domain_list);
	psmx2_unlock(&fabric_priv->domain_lock, 1);

	psmx2_init_tag_layout(info);

	*domain = &domain_priv->util_domain.domain_fid;
	return 0;

err_out_close_domain:
	ofi_domain_close(&domain_priv->util_domain);

err_out_free_domain:
	free(domain_priv);

err_out:
	return err;
}