#include <stdlib.h>
#include <string.h>
#include <fi_enosys.h>
#include <fi_util.h>
static int util_poll_add(struct fid_poll *poll_fid, struct fid *event_fid,
uint64_t flags)
{
struct util_poll *pollset;
pollset = container_of(poll_fid, struct util_poll, poll_fid);
switch (event_fid->fclass) {
case FI_CLASS_CQ:
case FI_CLASS_CNTR:
break;
case FI_CLASS_EQ:
if (!pollset->domain)
break;
default:
FI_WARN(pollset->prov, FI_LOG_DOMAIN,
"invalid fid class\n");
return -FI_EINVAL;
}
return fid_list_insert(&pollset->fid_list, &pollset->lock, event_fid);
}
static int util_poll_del(struct fid_poll *poll_fid, struct fid *event_fid,
uint64_t flags)
{
struct util_poll *pollset;
pollset = container_of(poll_fid, struct util_poll, poll_fid);
fid_list_remove(&pollset->fid_list, &pollset->lock, event_fid);
return 0;
}
static int util_poll_run(struct fid_poll *poll_fid, void **context, int count)
{
struct util_poll *pollset;
struct util_eq *eq;
struct util_cq *cq;
struct util_cntr *cntr;
struct fid_list_entry *fid_entry;
struct dlist_entry *item;
int ret, i = 0, err = 0;
uint64_t val;
pollset = container_of(poll_fid, struct util_poll, poll_fid.fid);
fastlock_acquire(&pollset->lock);
dlist_foreach(&pollset->fid_list, item) {
fid_entry = container_of(item, struct fid_list_entry, entry);
switch (fid_entry->fid->fclass) {
case FI_CLASS_CQ:
cq = container_of(fid_entry->fid, struct util_cq,
cq_fid.fid);
ret = fi_cq_read(&cq->cq_fid, NULL, 0);
if (ret == 0 || ret == -FI_EAVAIL)
ret = 1;
break;
case FI_CLASS_CNTR:
cntr = container_of(fid_entry->fid, struct util_cntr,
cntr_fid.fid);
val = fi_cntr_read(&cntr->cntr_fid);
if ((ret = (val != cntr->checkpoint_cnt))) {
cntr->checkpoint_cnt = val;
} else {
val = fi_cntr_readerr(&cntr->cntr_fid);
if ((ret = (val != cntr->checkpoint_err)))
cntr->checkpoint_err = val;
}
break;
case FI_CLASS_EQ:
eq = container_of(fid_entry->fid, struct util_eq,
eq_fid.fid);
ret = fi_eq_read(&eq->eq_fid, NULL, NULL, 0, FI_PEEK);
if (ret == 0 || ret == -FI_EAVAIL)
ret = 1;
break;
default:
ret = -FI_EINVAL;
break;
}
if (ret > 0 && i < count)
context[i++] = fid_entry->fid->context;
else if (ret < 0 && ret != -FI_EAGAIN)
err = ret;
}
fastlock_release(&pollset->lock);
return i ? i : err;
}
static int util_poll_close(struct fid *fid)
{
struct util_poll *pollset;
pollset = container_of(fid, struct util_poll, poll_fid.fid);
if (ofi_atomic_get32(&pollset->ref))
return -FI_EBUSY;
if (pollset->domain)
ofi_atomic_dec32(&pollset->domain->ref);
free(pollset);
return 0;
}
static struct fi_ops_poll util_poll_ops = {
.size = sizeof(struct fi_ops_poll),
.poll = util_poll_run,
.poll_add = util_poll_add,
.poll_del = util_poll_del,
};
static struct fi_ops util_poll_fi_ops = {
.size = sizeof(struct fi_ops),
.close = util_poll_close,
.bind = fi_no_bind,
.control = fi_no_control,
.ops_open = fi_no_ops_open,
};
static int util_verify_poll_attr(const struct fi_provider *prov,
struct fi_poll_attr *attr)
{
if (attr->flags) {
FI_WARN(prov, FI_LOG_DOMAIN, "invalid flags\n");
return -FI_EINVAL;
}
return 0;
}
int fi_poll_create_(const struct fi_provider *prov, struct fid_domain *domain,
struct fi_poll_attr *attr, struct fid_poll **poll_fid)
{
struct util_poll *pollset;
int ret;
ret = util_verify_poll_attr(prov, attr);
if (ret)
return ret;
pollset = calloc(1, sizeof(*pollset));
if (!pollset)
return -FI_ENOMEM;
pollset->prov = prov;
ofi_atomic_initialize32(&pollset->ref, 0);
dlist_init(&pollset->fid_list);
fastlock_init(&pollset->lock);
pollset->poll_fid.fid.fclass = FI_CLASS_POLL;
pollset->poll_fid.fid.ops = &util_poll_fi_ops;
pollset->poll_fid.ops = &util_poll_ops;
if (domain) {
pollset->domain = container_of(domain, struct util_domain,
domain_fid);
ofi_atomic_inc32(&pollset->domain->ref);
}
*poll_fid = &pollset->poll_fid;
return 0;
}
int fi_poll_create(struct fid_domain *domain_fid, struct fi_poll_attr *attr,
struct fid_poll **poll_fid)
{
struct util_domain *domain;
domain = container_of(domain_fid, struct util_domain, domain_fid);
return fi_poll_create_(domain->prov, domain_fid, attr, poll_fid);
}