};
struct ibv_comp_channel {
+ struct ibv_context *context;
int fd;
+ int refcnt;
};
struct ibv_cq {
struct ibv_context *context;
+ struct ibv_comp_channel *channel;
void *cq_context;
uint32_t handle;
int cqe;
};
struct ibv_context {
- struct ibv_device *device;
- struct ibv_context_ops ops;
- int cmd_fd;
- int async_fd;
- int num_comp_vectors;
- void *abi_compat;
+ struct ibv_device *device;
+ struct ibv_context_ops ops;
+ int cmd_fd;
+ int async_fd;
+ int num_comp_vectors;
+ pthread_mutex_t mutex;
+ void *abi_compat;
};
/**
return NULL;
}
- channel->fd = resp.fd;
+ channel->context = context;
+ channel->fd = resp.fd;
+ channel->refcnt = 0;
return channel;
}
int ibv_destroy_comp_channel(struct ibv_comp_channel *channel)
{
- if (abi_ver <= 2)
- return ibv_destroy_comp_channel_v2(channel);
+ struct ibv_context *context;
+ int ret;
+
+ context = channel->context;
+ pthread_mutex_lock(&context->mutex);
+
+ if (channel->refcnt) {
+ ret = EBUSY;
+ goto out;
+ }
+
+ if (abi_ver <= 2) {
+ ret = ibv_destroy_comp_channel_v2(channel);
+ goto out;
+ }
close(channel->fd);
free(channel);
+ ret = 0;
- return 0;
+out:
+ pthread_mutex_unlock(&context->mutex);
+
+ return ret;
}
struct ibv_cq *__ibv_create_cq(struct ibv_context *context, int cqe, void *cq_context,
struct ibv_comp_channel *channel, int comp_vector)
{
- struct ibv_cq *cq = context->ops.create_cq(context, cqe, channel,
- comp_vector);
+ struct ibv_cq *cq;
+
+ pthread_mutex_lock(&context->mutex);
+
+ cq = context->ops.create_cq(context, cqe, channel, comp_vector);
if (cq) {
cq->context = context;
+ cq->channel = channel;
+ if (channel)
+ ++channel->refcnt;
cq->cq_context = cq_context;
cq->comp_events_completed = 0;
cq->async_events_completed = 0;
pthread_cond_init(&cq->cond, NULL);
}
+ pthread_mutex_unlock(&context->mutex);
+
return cq;
}
default_symver(__ibv_create_cq, ibv_create_cq);
int __ibv_destroy_cq(struct ibv_cq *cq)
{
- return cq->context->ops.destroy_cq(cq);
+ struct ibv_comp_channel *channel = cq->channel;
+ int ret;
+
+ if (channel)
+ pthread_mutex_lock(&channel->context->mutex);
+
+ ret = cq->context->ops.destroy_cq(cq);
+
+ if (channel) {
+ if (!ret)
+ --channel->refcnt;
+ pthread_mutex_unlock(&channel->context->mutex);
+ }
+
+ return ret;
}
default_symver(__ibv_destroy_cq, ibv_destroy_cq);