| 569 | } |
| 570 | |
| 571 | int |
| 572 | intr_event_add_handler(struct intr_event *ie, const char *name, |
| 573 | driver_filter_t filter, driver_intr_t handler, void *arg, u_char pri, |
| 574 | enum intr_type flags, void **cookiep) |
| 575 | { |
| 576 | struct intr_handler *ih, *temp_ih; |
| 577 | struct intr_handler **prevptr; |
| 578 | struct intr_thread *it; |
| 579 | |
| 580 | if (ie == NULL || name == NULL || (handler == NULL && filter == NULL)) |
| 581 | return (EINVAL); |
| 582 | |
| 583 | /* Allocate and populate an interrupt handler structure. */ |
| 584 | ih = malloc(sizeof(struct intr_handler), M_ITHREAD, M_WAITOK | M_ZERO); |
| 585 | ih->ih_filter = filter; |
| 586 | ih->ih_handler = handler; |
| 587 | ih->ih_argument = arg; |
| 588 | strlcpy(ih->ih_name, name, sizeof(ih->ih_name)); |
| 589 | ih->ih_event = ie; |
| 590 | ih->ih_pri = pri; |
| 591 | if (flags & INTR_EXCL) |
| 592 | ih->ih_flags = IH_EXCLUSIVE; |
| 593 | if (flags & INTR_MPSAFE) |
| 594 | ih->ih_flags |= IH_MPSAFE; |
| 595 | if (flags & INTR_ENTROPY) |
| 596 | ih->ih_flags |= IH_ENTROPY; |
| 597 | if (flags & INTR_TYPE_NET) |
| 598 | ih->ih_flags |= IH_NET; |
| 599 | |
| 600 | /* We can only have one exclusive handler in a event. */ |
| 601 | mtx_lock(&ie->ie_lock); |
| 602 | if (!CK_SLIST_EMPTY(&ie->ie_handlers)) { |
| 603 | if ((flags & INTR_EXCL) || |
| 604 | (CK_SLIST_FIRST(&ie->ie_handlers)->ih_flags & IH_EXCLUSIVE)) { |
| 605 | mtx_unlock(&ie->ie_lock); |
| 606 | free(ih, M_ITHREAD); |
| 607 | return (EINVAL); |
| 608 | } |
| 609 | } |
| 610 | |
| 611 | /* Create a thread if we need one. */ |
| 612 | while (ie->ie_thread == NULL && handler != NULL) { |
| 613 | if (ie->ie_flags & IE_ADDING_THREAD) |
| 614 | msleep(ie, &ie->ie_lock, 0, "ithread", 0); |
| 615 | else { |
| 616 | ie->ie_flags |= IE_ADDING_THREAD; |
| 617 | mtx_unlock(&ie->ie_lock); |
| 618 | it = ithread_create("intr: newborn"); |
| 619 | mtx_lock(&ie->ie_lock); |
| 620 | ie->ie_flags &= ~IE_ADDING_THREAD; |
| 621 | ie->ie_thread = it; |
| 622 | it->it_event = ie; |
| 623 | ithread_update(it); |
| 624 | wakeup(ie); |
| 625 | } |
| 626 | } |
| 627 | |
| 628 | /* Add the new handler to the event in priority order. */ |
no test coverage detected