| 425 | } |
| 426 | |
| 427 | h2_workers *h2_workers_create(server_rec *s, apr_pool_t *pchild, |
| 428 | int max_slots, int min_active, |
| 429 | apr_time_t idle_limit) |
| 430 | { |
| 431 | apr_status_t rv; |
| 432 | h2_workers *workers; |
| 433 | apr_pool_t *pool; |
| 434 | apr_allocator_t *allocator; |
| 435 | int locked = 0; |
| 436 | apr_uint32_t i; |
| 437 | |
| 438 | ap_assert(s); |
| 439 | ap_assert(pchild); |
| 440 | ap_assert(idle_limit > 0); |
| 441 | |
| 442 | /* let's have our own pool that will be parent to all h2_worker |
| 443 | * instances we create. This happens in various threads, but always |
| 444 | * guarded by our lock. Without this pool, all subpool creations would |
| 445 | * happen on the pool handed to us, which we do not guard. |
| 446 | */ |
| 447 | rv = apr_allocator_create(&allocator); |
| 448 | if (rv != APR_SUCCESS) { |
| 449 | goto cleanup; |
| 450 | } |
| 451 | rv = apr_pool_create_ex(&pool, pchild, NULL, allocator); |
| 452 | if (rv != APR_SUCCESS) { |
| 453 | apr_allocator_destroy(allocator); |
| 454 | goto cleanup; |
| 455 | } |
| 456 | apr_allocator_owner_set(allocator, pool); |
| 457 | apr_pool_tag(pool, "h2_workers"); |
| 458 | workers = apr_pcalloc(pool, sizeof(h2_workers)); |
| 459 | if (!workers) { |
| 460 | return NULL; |
| 461 | } |
| 462 | |
| 463 | workers->s = s; |
| 464 | workers->pool = pool; |
| 465 | workers->min_active = min_active; |
| 466 | workers->max_slots = max_slots; |
| 467 | workers->idle_limit = idle_limit; |
| 468 | workers->dynamic = (workers->min_active < workers->max_slots); |
| 469 | |
| 470 | ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, |
| 471 | "h2_workers: created with min=%d max=%d idle_ms=%d", |
| 472 | workers->min_active, workers->max_slots, |
| 473 | (int)apr_time_as_msec(idle_limit)); |
| 474 | |
| 475 | APR_RING_INIT(&workers->idle, h2_slot, link); |
| 476 | APR_RING_INIT(&workers->busy, h2_slot, link); |
| 477 | APR_RING_INIT(&workers->free, h2_slot, link); |
| 478 | APR_RING_INIT(&workers->zombie, h2_slot, link); |
| 479 | |
| 480 | APR_RING_INIT(&workers->prod_active, ap_conn_producer_t, link); |
| 481 | APR_RING_INIT(&workers->prod_idle, ap_conn_producer_t, link); |
| 482 | |
| 483 | rv = apr_threadattr_create(&workers->thread_attr, workers->pool); |
| 484 | if (rv != APR_SUCCESS) goto cleanup; |
no test coverage detected