diff options
author | Jan Beulich <jbeulich@novell.com> | 2011-05-01 13:17:44 +0100 |
---|---|---|
committer | Jan Beulich <jbeulich@novell.com> | 2011-05-01 13:17:44 +0100 |
commit | 76ce27755b87aa5a91ce0f5a02e560ab5c0515e4 (patch) | |
tree | f2a7fcbd31e863d8a0238782c12a716bbc0f21e9 /xen/common/event_channel.c | |
parent | f22f2fe48d144141fffd42a380383f45efbea8e3 (diff) | |
download | xen-76ce27755b87aa5a91ce0f5a02e560ab5c0515e4.tar.gz xen-76ce27755b87aa5a91ce0f5a02e560ab5c0515e4.tar.bz2 xen-76ce27755b87aa5a91ce0f5a02e560ab5c0515e4.zip |
replace d->nr_pirqs sized arrays with radix tree
With this it is questionable whether retaining struct domain's
nr_pirqs is actually necessary - the value now only serves for bounds
checking, and this boundary could easily be nr_irqs.
Another thing to consider is whether it's worth storing the pirq
number in struct pirq, to avoid passing the number and a pointer to
quite a number of functions.
Note that ia64, the build of which is broken currently anyway, is only
partially fixed up.
Signed-off-by: Jan Beulich <jbeulich@novell.com>
Diffstat (limited to 'xen/common/event_channel.c')
-rw-r--r-- | xen/common/event_channel.c | 42 |
1 files changed, 25 insertions, 17 deletions
diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c index 558fbb1256..56d80b9bed 100644 --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -325,6 +325,7 @@ static long evtchn_bind_pirq(evtchn_bind_pirq_t *bind) struct evtchn *chn; struct domain *d = current->domain; struct vcpu *v = d->vcpu[0]; + struct pirq *info; int port, pirq = bind->pirq; long rc; @@ -336,7 +337,7 @@ static long evtchn_bind_pirq(evtchn_bind_pirq_t *bind) spin_lock(&d->event_lock); - if ( d->pirq_to_evtchn[pirq] != 0 ) + if ( pirq_to_evtchn(d, pirq) != 0 ) ERROR_EXIT(-EEXIST); if ( (port = get_free_port(d)) < 0 ) @@ -344,14 +345,18 @@ static long evtchn_bind_pirq(evtchn_bind_pirq_t *bind) chn = evtchn_from_port(d, port); - d->pirq_to_evtchn[pirq] = port; + info = pirq_get_info(d, pirq); + if ( !info ) + ERROR_EXIT(-ENOMEM); + info->evtchn = port; rc = (!is_hvm_domain(d) - ? pirq_guest_bind( - v, pirq, !!(bind->flags & BIND_PIRQ__WILL_SHARE)) + ? pirq_guest_bind(v, pirq, info, + !!(bind->flags & BIND_PIRQ__WILL_SHARE)) : 0); if ( rc != 0 ) { - d->pirq_to_evtchn[pirq] = 0; + info->evtchn = 0; + pirq_cleanup_check(info, d, pirq); goto out; } @@ -404,12 +409,18 @@ static long __evtchn_close(struct domain *d1, int port1) case ECS_UNBOUND: break; - case ECS_PIRQ: + case ECS_PIRQ: { + struct pirq *pirq = pirq_info(d1, chn1->u.pirq.irq); + + if ( !pirq ) + break; if ( !is_hvm_domain(d1) ) - pirq_guest_unbind(d1, chn1->u.pirq.irq); - d1->pirq_to_evtchn[chn1->u.pirq.irq] = 0; + pirq_guest_unbind(d1, chn1->u.pirq.irq, pirq); + pirq->evtchn = 0; + pirq_cleanup_check(pirq, d1, chn1->u.pirq.irq); unlink_pirq_port(chn1, d1->vcpu[chn1->notify_vcpu_id]); break; + } case ECS_VIRQ: for_each_vcpu ( d1, v ) @@ -659,9 +670,9 @@ void send_guest_global_virq(struct domain *d, int virq) spin_unlock_irqrestore(&v->virq_lock, flags); } -int send_guest_pirq(struct domain *d, int pirq) +int send_guest_pirq(struct domain *d, const struct pirq *pirq) { - int port = d->pirq_to_evtchn[pirq]; + int port; struct evtchn *chn; /* @@ -670,7 +681,7 @@ int send_guest_pirq(struct domain *d, int pirq) * HVM guests: Port is legitimately zero when the guest disables the * emulated interrupt/evtchn. */ - if ( port == 0 ) + if ( pirq == NULL || (port = pirq->evtchn) == 0 ) { BUG_ON(!is_hvm_domain(d)); return 0; @@ -812,13 +823,10 @@ int evtchn_unmask(unsigned int port) struct domain *d = current->domain; struct vcpu *v; - spin_lock(&d->event_lock); + ASSERT(spin_is_locked(&d->event_lock)); if ( unlikely(!port_is_valid(d, port)) ) - { - spin_unlock(&d->event_lock); return -EINVAL; - } v = d->vcpu[evtchn_from_port(d, port)->notify_vcpu_id]; @@ -834,8 +842,6 @@ int evtchn_unmask(unsigned int port) vcpu_mark_events_pending(v); } - spin_unlock(&d->event_lock); - return 0; } @@ -960,7 +966,9 @@ long do_event_channel_op(int cmd, XEN_GUEST_HANDLE(void) arg) struct evtchn_unmask unmask; if ( copy_from_guest(&unmask, arg, 1) != 0 ) return -EFAULT; + spin_lock(¤t->domain->event_lock); rc = evtchn_unmask(unmask.port); + spin_unlock(¤t->domain->event_lock); break; } |