* Find the taskq with least # of tasks that doesn't currently have any * other queues from the uniq identifier. */
| 627 | * other queues from the uniq identifier. |
| 628 | */ |
| 629 | static int |
| 630 | taskqgroup_find(struct taskqgroup *qgroup, void *uniq) |
| 631 | { |
| 632 | struct grouptask *n; |
| 633 | int i, idx, mincnt; |
| 634 | int strict; |
| 635 | |
| 636 | mtx_assert(&qgroup->tqg_lock, MA_OWNED); |
| 637 | KASSERT(qgroup->tqg_cnt != 0, |
| 638 | ("qgroup %s has no queues", qgroup->tqg_name)); |
| 639 | |
| 640 | /* |
| 641 | * Two passes: first scan for a queue with the least tasks that |
| 642 | * does not already service this uniq id. If that fails simply find |
| 643 | * the queue with the least total tasks. |
| 644 | */ |
| 645 | for (idx = -1, mincnt = INT_MAX, strict = 1; mincnt == INT_MAX; |
| 646 | strict = 0) { |
| 647 | for (i = 0; i < qgroup->tqg_cnt; i++) { |
| 648 | if (qgroup->tqg_queue[i].tgc_cnt > mincnt) |
| 649 | continue; |
| 650 | if (strict) { |
| 651 | LIST_FOREACH(n, &qgroup->tqg_queue[i].tgc_tasks, |
| 652 | gt_list) |
| 653 | if (n->gt_uniq == uniq) |
| 654 | break; |
| 655 | if (n != NULL) |
| 656 | continue; |
| 657 | } |
| 658 | mincnt = qgroup->tqg_queue[i].tgc_cnt; |
| 659 | idx = i; |
| 660 | } |
| 661 | } |
| 662 | if (idx == -1) |
| 663 | panic("%s: failed to pick a qid.", __func__); |
| 664 | |
| 665 | return (idx); |
| 666 | } |
| 667 | |
| 668 | void |
| 669 | taskqgroup_attach(struct taskqgroup *qgroup, struct grouptask *gtask, |
no test coverage detected