| 565 | static int taskq_thread_spawn(taskq_t *tq); |
| 566 | |
| 567 | taskqid_t |
| 568 | taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t flags) |
| 569 | { |
| 570 | taskq_ent_t *t; |
| 571 | taskqid_t rc = TASKQID_INVALID; |
| 572 | unsigned long irqflags; |
| 573 | |
| 574 | ASSERT(tq); |
| 575 | ASSERT(func); |
| 576 | |
| 577 | spin_lock_irqsave_nested(&tq->tq_lock, irqflags, tq->tq_lock_class); |
| 578 | |
| 579 | /* Taskq being destroyed and all tasks drained */ |
| 580 | if (!(tq->tq_flags & TASKQ_ACTIVE)) |
| 581 | goto out; |
| 582 | |
| 583 | /* Do not queue the task unless there is idle thread for it */ |
| 584 | ASSERT(tq->tq_nactive <= tq->tq_nthreads); |
| 585 | if ((flags & TQ_NOQUEUE) && (tq->tq_nactive == tq->tq_nthreads)) { |
| 586 | /* Dynamic taskq may be able to spawn another thread */ |
| 587 | if (!(tq->tq_flags & TASKQ_DYNAMIC) || |
| 588 | taskq_thread_spawn(tq) == 0) |
| 589 | goto out; |
| 590 | } |
| 591 | |
| 592 | if ((t = task_alloc(tq, flags, &irqflags)) == NULL) |
| 593 | goto out; |
| 594 | |
| 595 | spin_lock(&t->tqent_lock); |
| 596 | |
| 597 | /* Queue to the front of the list to enforce TQ_NOQUEUE semantics */ |
| 598 | if (flags & TQ_NOQUEUE) |
| 599 | list_add(&t->tqent_list, &tq->tq_prio_list); |
| 600 | /* Queue to the priority list instead of the pending list */ |
| 601 | else if (flags & TQ_FRONT) |
| 602 | list_add_tail(&t->tqent_list, &tq->tq_prio_list); |
| 603 | else |
| 604 | list_add_tail(&t->tqent_list, &tq->tq_pend_list); |
| 605 | |
| 606 | t->tqent_id = rc = tq->tq_next_id; |
| 607 | tq->tq_next_id++; |
| 608 | t->tqent_func = func; |
| 609 | t->tqent_arg = arg; |
| 610 | t->tqent_taskq = tq; |
| 611 | t->tqent_timer.function = NULL; |
| 612 | t->tqent_timer.expires = 0; |
| 613 | |
| 614 | t->tqent_birth = jiffies; |
| 615 | DTRACE_PROBE1(taskq_ent__birth, taskq_ent_t *, t); |
| 616 | |
| 617 | ASSERT(!(t->tqent_flags & TQENT_FLAG_PREALLOC)); |
| 618 | |
| 619 | spin_unlock(&t->tqent_lock); |
| 620 | |
| 621 | wake_up(&tq->tq_work_waitq); |
| 622 | out: |
| 623 | /* Spawn additional taskq threads if required. */ |
| 624 | if (!(flags & TQ_NOQUEUE) && tq->tq_nactive == tq->tq_nthreads) |
no test coverage detected