Changeset View
Changeset View
Standalone View
Standalone View
sys/x86/xen/xen_intr.c
Show First 20 Lines • Show All 312 Lines • ▼ Show 20 Lines | |||||
xen_intr_alloc_isrc(enum evtchn_type type) | xen_intr_alloc_isrc(enum evtchn_type type) | ||||
{ | { | ||||
static int warned; | static int warned; | ||||
struct xenisrc *isrc; | struct xenisrc *isrc; | ||||
unsigned int vector; | unsigned int vector; | ||||
int error; | int error; | ||||
KASSERT(mtx_owned(&xen_intr_isrc_lock), ("Evtchn alloc lock not held")); | KASSERT(mtx_owned(&xen_intr_isrc_lock), ("Evtchn alloc lock not held")); | ||||
isrc = xen_intr_find_unused_isrc(type); | |||||
if (isrc != NULL) { | |||||
return (isrc); | |||||
} | |||||
if (xen_intr_auto_vector_count >= NR_EVENT_CHANNELS) { | if (xen_intr_auto_vector_count >= NR_EVENT_CHANNELS) { | ||||
if (!warned) { | if (!warned) { | ||||
warned = 1; | warned = 1; | ||||
printf("%s: Xen interrupts exhausted.\n", __func__); | printf("%s: Xen interrupts exhausted.\n", __func__); | ||||
} | } | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | xen_intr_release_isrc(struct xenisrc *isrc) | ||||
mtx_unlock(&xen_intr_isrc_lock); | mtx_unlock(&xen_intr_isrc_lock); | ||||
return (0); | return (0); | ||||
} | } | ||||
/** | /** | ||||
* Associate an interrupt handler with an already allocated local Xen | * Associate an interrupt handler with an already allocated local Xen | ||||
* event channel port. | * event channel port. | ||||
* | * | ||||
* \param isrcp The returned Xen interrupt object associated with | * \param isrcp The returned Xen interrupt object associated with | ||||
royger: I'm not a huge fan of doing this kind of tricks, as such open coded locking primitives often… | |||||
Done Inline ActionsYes, I was wondering about this. Problem is if you leave me waiting with time on my hands, sometimes code gets even more optimized... Can indeed simply be lock, isrc->xi_type = EVTCHN_TYPE_UNBOUND;, unlock. I've been wondering about whether it is worth clearing isrc here. The x86 architecture side only looks at ->xi_type and the other values should be cleared during allocation. ehem_freebsd_m5p.com: Yes, I was wondering about this. Problem is if you leave me waiting with time on my hands… | |||||
* the specified local port. | * the specified local port. | ||||
* \param local_port The event channel to bind. | * \param local_port The event channel to bind. | ||||
* \param type The event channel type of local_port. | * \param type The event channel type of local_port. | ||||
* \param intr_owner The device making this bind request. | * \param intr_owner The device making this bind request. | ||||
* \param filter An interrupt filter handler. Specify NULL | * \param filter An interrupt filter handler. Specify NULL | ||||
* to always dispatch to the ithread handler. | * to always dispatch to the ithread handler. | ||||
* \param handler An interrupt ithread handler. Optional (can | * \param handler An interrupt ithread handler. Optional (can | ||||
* specify NULL) if all necessary event actions | * specify NULL) if all necessary event actions | ||||
Show All 17 Lines | xen_intr_bind_isrc(struct xenisrc **isrcp, evtchn_port_t local_port, | ||||
*isrcp = NULL; | *isrcp = NULL; | ||||
if (port_handlep == NULL) { | if (port_handlep == NULL) { | ||||
printf("%s: %s: Bad event handle\n", intr_owner, __func__); | printf("%s: %s: Bad event handle\n", intr_owner, __func__); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
*port_handlep = NULL; | *port_handlep = NULL; | ||||
mtx_lock(&xen_intr_isrc_lock); | mtx_lock(&xen_intr_isrc_lock); | ||||
isrc = xen_intr_find_unused_isrc(type); | |||||
if (isrc == NULL) { | |||||
isrc = xen_intr_alloc_isrc(type); | isrc = xen_intr_alloc_isrc(type); | ||||
if (isrc == NULL) { | if (isrc == NULL) { | ||||
mtx_unlock(&xen_intr_isrc_lock); | mtx_unlock(&xen_intr_isrc_lock); | ||||
return (ENOSPC); | return (ENOSPC); | ||||
} | |||||
} | } | ||||
isrc->xi_port = local_port; | isrc->xi_port = local_port; | ||||
isrc->xi_close = false; | isrc->xi_close = false; | ||||
xen_intr_port_to_isrc[local_port] = isrc; | xen_intr_port_to_isrc[local_port] = isrc; | ||||
refcount_init(&isrc->xi_refcount, 1); | refcount_init(&isrc->xi_refcount, 1); | ||||
mtx_unlock(&xen_intr_isrc_lock); | mtx_unlock(&xen_intr_isrc_lock); | ||||
#ifdef SMP | #ifdef SMP | ||||
▲ Show 20 Lines • Show All 187 Lines • ▼ Show 20 Lines | _Static_assert(!is_valid_evtchn(~(evtchn_port_t)0), | ||||
"is_valid_evtchn(maxint) fails (overflow?)"); | "is_valid_evtchn(maxint) fails (overflow?)"); | ||||
_Static_assert(!is_valid_evtchn(INVALID_EVTCHN), | _Static_assert(!is_valid_evtchn(INVALID_EVTCHN), | ||||
"is_valid_evtchn(INVALID_EVTCHN) fails (must be invalid!)"); | "is_valid_evtchn(INVALID_EVTCHN) fails (must be invalid!)"); | ||||
_Static_assert(!is_valid_evtchn(-1), | _Static_assert(!is_valid_evtchn(-1), | ||||
"is_valid_evtchn(-1) fails (negative are invalid)"); | "is_valid_evtchn(-1) fails (negative are invalid)"); | ||||
mtx_init(&xen_intr_isrc_lock, "xen-irq-lock", NULL, MTX_DEF); | mtx_init(&xen_intr_isrc_lock, "xen-irq-lock", NULL, MTX_DEF); | ||||
/* | /* | ||||
Not Done Inline Actionstable? xen-x86-irq-lock it's maybe better? royger: table? xen-x86-irq-lock it's maybe better? | |||||
Done Inline ActionsI was thinking of it being the lock for the x86 interrupt table. One can also think of it handling the Xen section of interrupt_sources[], so seemed like a table lock. No objection with renaming "xen-x86-irq-lock". This seems like an adjust when it gets into freebsd-src. ehem_freebsd_m5p.com: I was thinking of it being the lock for the x86 interrupt table. One can also think of it… | |||||
* Set the per-cpu mask of CPU#0 to enable all, since by default all | * Set the per-cpu mask of CPU#0 to enable all, since by default all | ||||
* event channels are bound to CPU#0. | * event channels are bound to CPU#0. | ||||
*/ | */ | ||||
CPU_FOREACH(i) { | CPU_FOREACH(i) { | ||||
pcpu = DPCPU_ID_PTR(i, xen_intr_pcpu); | pcpu = DPCPU_ID_PTR(i, xen_intr_pcpu); | ||||
memset(pcpu->evtchn_enabled, i == 0 ? ~0 : 0, | memset(pcpu->evtchn_enabled, i == 0 ? ~0 : 0, | ||||
sizeof(pcpu->evtchn_enabled)); | sizeof(pcpu->evtchn_enabled)); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 770 Lines • Show Last 20 Lines |
I'm not a huge fan of doing this kind of tricks, as such open coded locking primitives often turn out to make the whole thing more fragile in the long term. Isn't there a way you could also hold xen_intr_x86_lock here, which is the one used by xen_intr_find_unused_isrc?