static long evtchn_alloc_unbound(evtchn_alloc_unbound_t *alloc) { struct domain *d; long rc; d = rcu_lock_domain_by_any_id(alloc->dom); if ( d == NULL ) return -ESRCH; rc = evtchn_alloc_unbound_domain(d, &alloc->port, alloc->remote_dom); if ( rc ) ERROR_EXIT_DOM((int)rc, d); out: rcu_unlock_domain(d); return rc; } int evtchn_alloc_unbound_domain(struct domain *d, evtchn_port_t *port, domid_t remote_domid) { struct evtchn *chn; int rc; int free_port; spin_lock(&d->event_lock); rc = free_port = get_free_port(d); if ( free_port < 0 ) goto out; chn = evtchn_from_port(d, free_port); rc = xsm_evtchn_unbound(XSM_TARGET, d, chn, remote_domid); if ( rc ) goto out; chn->state = ECS_UNBOUND; if ( (chn->u.unbound.remote_domid = remote_domid) == DOMID_SELF ) chn->u.unbound.remote_domid = current->domain->domain_id; *port = free_port; /* Everything is fine, returns 0 */ rc = 0; out: spin_unlock(&d->event_lock); return rc; }