| 39 | #define TASKQ_ACTIVE 0x00010000 |
| 40 | |
| 41 | static taskq_ent_t * |
| 42 | task_alloc(taskq_t *tq, int tqflags) |
| 43 | { |
| 44 | taskq_ent_t *t; |
| 45 | int rv; |
| 46 | |
| 47 | again: if ((t = tq->tq_freelist) != NULL && tq->tq_nalloc >= tq->tq_minalloc) { |
| 48 | ASSERT(!(t->tqent_flags & TQENT_FLAG_PREALLOC)); |
| 49 | tq->tq_freelist = t->tqent_next; |
| 50 | } else { |
| 51 | if (tq->tq_nalloc >= tq->tq_maxalloc) { |
| 52 | if (!(tqflags & KM_SLEEP)) |
| 53 | return (NULL); |
| 54 | |
| 55 | /* |
| 56 | * We don't want to exceed tq_maxalloc, but we can't |
| 57 | * wait for other tasks to complete (and thus free up |
| 58 | * task structures) without risking deadlock with |
| 59 | * the caller. So, we just delay for one second |
| 60 | * to throttle the allocation rate. If we have tasks |
| 61 | * complete before one second timeout expires then |
| 62 | * taskq_ent_free will signal us and we will |
| 63 | * immediately retry the allocation. |
| 64 | */ |
| 65 | tq->tq_maxalloc_wait++; |
| 66 | rv = cv_timedwait(&tq->tq_maxalloc_cv, |
| 67 | &tq->tq_lock, ddi_get_lbolt() + hz); |
| 68 | tq->tq_maxalloc_wait--; |
| 69 | if (rv > 0) |
| 70 | goto again; /* signaled */ |
| 71 | } |
| 72 | mutex_exit(&tq->tq_lock); |
| 73 | |
| 74 | t = kmem_alloc(sizeof (taskq_ent_t), tqflags); |
| 75 | |
| 76 | mutex_enter(&tq->tq_lock); |
| 77 | if (t != NULL) { |
| 78 | /* Make sure we start without any flags */ |
| 79 | t->tqent_flags = 0; |
| 80 | tq->tq_nalloc++; |
| 81 | } |
| 82 | } |
| 83 | return (t); |
| 84 | } |
| 85 | |
| 86 | static void |
| 87 | task_free(taskq_t *tq, taskq_ent_t *t) |
no test coverage detected