ARGSUSED*/
| 249 | |
| 250 | /*ARGSUSED*/ |
| 251 | taskq_t * |
| 252 | taskq_create(const char *name, int nthreads, pri_t pri, |
| 253 | int minalloc, int maxalloc, uint_t flags) |
| 254 | { |
| 255 | taskq_t *tq = kmem_zalloc(sizeof (taskq_t), KM_SLEEP); |
| 256 | int t; |
| 257 | |
| 258 | if (flags & TASKQ_THREADS_CPU_PCT) { |
| 259 | int pct; |
| 260 | ASSERT3S(nthreads, >=, 0); |
| 261 | ASSERT3S(nthreads, <=, 100); |
| 262 | pct = MIN(nthreads, 100); |
| 263 | pct = MAX(pct, 0); |
| 264 | |
| 265 | nthreads = (sysconf(_SC_NPROCESSORS_ONLN) * pct) / 100; |
| 266 | nthreads = MAX(nthreads, 1); /* need at least 1 thread */ |
| 267 | } else { |
| 268 | ASSERT3S(nthreads, >=, 1); |
| 269 | } |
| 270 | |
| 271 | rw_init(&tq->tq_threadlock, NULL, RW_DEFAULT, NULL); |
| 272 | mutex_init(&tq->tq_lock, NULL, MUTEX_DEFAULT, NULL); |
| 273 | cv_init(&tq->tq_dispatch_cv, NULL, CV_DEFAULT, NULL); |
| 274 | cv_init(&tq->tq_wait_cv, NULL, CV_DEFAULT, NULL); |
| 275 | cv_init(&tq->tq_maxalloc_cv, NULL, CV_DEFAULT, NULL); |
| 276 | (void) strncpy(tq->tq_name, name, TASKQ_NAMELEN); |
| 277 | tq->tq_flags = flags | TASKQ_ACTIVE; |
| 278 | tq->tq_active = nthreads; |
| 279 | tq->tq_nthreads = nthreads; |
| 280 | tq->tq_minalloc = minalloc; |
| 281 | tq->tq_maxalloc = maxalloc; |
| 282 | tq->tq_task.tqent_next = &tq->tq_task; |
| 283 | tq->tq_task.tqent_prev = &tq->tq_task; |
| 284 | tq->tq_threadlist = kmem_alloc(nthreads * sizeof (kthread_t *), |
| 285 | KM_SLEEP); |
| 286 | |
| 287 | if (flags & TASKQ_PREPOPULATE) { |
| 288 | mutex_enter(&tq->tq_lock); |
| 289 | while (minalloc-- > 0) |
| 290 | task_free(tq, task_alloc(tq, KM_SLEEP)); |
| 291 | mutex_exit(&tq->tq_lock); |
| 292 | } |
| 293 | |
| 294 | for (t = 0; t < nthreads; t++) |
| 295 | VERIFY((tq->tq_threadlist[t] = thread_create(NULL, 0, |
| 296 | taskq_thread, tq, 0, &p0, TS_RUN, pri)) != NULL); |
| 297 | |
| 298 | return (tq); |
| 299 | } |
| 300 | |
| 301 | void |
| 302 | taskq_destroy(taskq_t *tq) |
no test coverage detected