1 1.1 christos /* $NetBSD: taskpool.c,v 1.1 2024/02/18 20:57:50 christos Exp $ */ 2 1.1 christos 3 1.1 christos /* 4 1.1 christos * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 1.1 christos * 6 1.1 christos * SPDX-License-Identifier: MPL-2.0 7 1.1 christos * 8 1.1 christos * This Source Code Form is subject to the terms of the Mozilla Public 9 1.1 christos * License, v. 2.0. If a copy of the MPL was not distributed with this 10 1.1 christos * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 1.1 christos * 12 1.1 christos * See the COPYRIGHT file distributed with this work for additional 13 1.1 christos * information regarding copyright ownership. 14 1.1 christos */ 15 1.1 christos 16 1.1 christos /*! \file */ 17 1.1 christos 18 1.1 christos #include <stdbool.h> 19 1.1 christos 20 1.1 christos #include <isc/mem.h> 21 1.1 christos #include <isc/random.h> 22 1.1 christos #include <isc/taskpool.h> 23 1.1 christos #include <isc/util.h> 24 1.1 christos 25 1.1 christos /*** 26 1.1 christos *** Types. 27 1.1 christos ***/ 28 1.1 christos 29 1.1 christos struct isc_taskpool { 30 1.1 christos isc_mem_t *mctx; 31 1.1 christos isc_taskmgr_t *tmgr; 32 1.1 christos unsigned int ntasks; 33 1.1 christos unsigned int quantum; 34 1.1 christos isc_task_t **tasks; 35 1.1 christos }; 36 1.1 christos 37 1.1 christos /*** 38 1.1 christos *** Functions. 39 1.1 christos ***/ 40 1.1 christos 41 1.1 christos static void 42 1.1 christos alloc_pool(isc_taskmgr_t *tmgr, isc_mem_t *mctx, unsigned int ntasks, 43 1.1 christos unsigned int quantum, isc_taskpool_t **poolp) { 44 1.1 christos isc_taskpool_t *pool; 45 1.1 christos unsigned int i; 46 1.1 christos 47 1.1 christos pool = isc_mem_get(mctx, sizeof(*pool)); 48 1.1 christos 49 1.1 christos pool->mctx = NULL; 50 1.1 christos isc_mem_attach(mctx, &pool->mctx); 51 1.1 christos pool->ntasks = ntasks; 52 1.1 christos pool->quantum = quantum; 53 1.1 christos pool->tmgr = tmgr; 54 1.1 christos pool->tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *)); 55 1.1 christos for (i = 0; i < ntasks; i++) { 56 1.1 christos pool->tasks[i] = NULL; 57 1.1 christos } 58 1.1 christos 59 1.1 christos *poolp = pool; 60 1.1 christos } 61 1.1 christos 62 1.1 christos isc_result_t 63 1.1 christos isc_taskpool_create(isc_taskmgr_t *tmgr, isc_mem_t *mctx, unsigned int ntasks, 64 1.1 christos unsigned int quantum, bool priv, isc_taskpool_t **poolp) { 65 1.1 christos unsigned int i; 66 1.1 christos isc_taskpool_t *pool = NULL; 67 1.1 christos 68 1.1 christos INSIST(ntasks > 0); 69 1.1 christos 70 1.1 christos /* Allocate the pool structure */ 71 1.1 christos alloc_pool(tmgr, mctx, ntasks, quantum, &pool); 72 1.1 christos 73 1.1 christos /* Create the tasks */ 74 1.1 christos for (i = 0; i < ntasks; i++) { 75 1.1 christos isc_result_t result = isc_task_create_bound(tmgr, quantum, 76 1.1 christos &pool->tasks[i], i); 77 1.1 christos if (result != ISC_R_SUCCESS) { 78 1.1 christos isc_taskpool_destroy(&pool); 79 1.1 christos return (result); 80 1.1 christos } 81 1.1 christos isc_task_setprivilege(pool->tasks[i], priv); 82 1.1 christos isc_task_setname(pool->tasks[i], "taskpool", NULL); 83 1.1 christos } 84 1.1 christos 85 1.1 christos *poolp = pool; 86 1.1 christos return (ISC_R_SUCCESS); 87 1.1 christos } 88 1.1 christos 89 1.1 christos void 90 1.1 christos isc_taskpool_gettask(isc_taskpool_t *pool, isc_task_t **targetp) { 91 1.1 christos isc_task_attach(pool->tasks[isc_random_uniform(pool->ntasks)], targetp); 92 1.1 christos } 93 1.1 christos 94 1.1 christos int 95 1.1 christos isc_taskpool_size(isc_taskpool_t *pool) { 96 1.1 christos REQUIRE(pool != NULL); 97 1.1 christos return (pool->ntasks); 98 1.1 christos } 99 1.1 christos 100 1.1 christos isc_result_t 101 1.1 christos isc_taskpool_expand(isc_taskpool_t **sourcep, unsigned int size, bool priv, 102 1.1 christos isc_taskpool_t **targetp) { 103 1.1 christos isc_taskpool_t *pool; 104 1.1 christos 105 1.1 christos REQUIRE(sourcep != NULL && *sourcep != NULL); 106 1.1 christos REQUIRE(targetp != NULL && *targetp == NULL); 107 1.1 christos 108 1.1 christos pool = *sourcep; 109 1.1 christos *sourcep = NULL; 110 1.1 christos if (size > pool->ntasks) { 111 1.1 christos isc_taskpool_t *newpool = NULL; 112 1.1 christos unsigned int i; 113 1.1 christos 114 1.1 christos /* Allocate a new pool structure */ 115 1.1 christos alloc_pool(pool->tmgr, pool->mctx, size, pool->quantum, 116 1.1 christos &newpool); 117 1.1 christos 118 1.1 christos /* Copy over the tasks from the old pool */ 119 1.1 christos for (i = 0; i < pool->ntasks; i++) { 120 1.1 christos newpool->tasks[i] = pool->tasks[i]; 121 1.1 christos pool->tasks[i] = NULL; 122 1.1 christos } 123 1.1 christos 124 1.1 christos /* Create new tasks */ 125 1.1 christos for (i = pool->ntasks; i < size; i++) { 126 1.1 christos isc_result_t result = 127 1.1 christos isc_task_create_bound(pool->tmgr, pool->quantum, 128 1.1 christos &newpool->tasks[i], i); 129 1.1 christos if (result != ISC_R_SUCCESS) { 130 1.1 christos *sourcep = pool; 131 1.1 christos isc_taskpool_destroy(&newpool); 132 1.1 christos return (result); 133 1.1 christos } 134 1.1 christos isc_task_setprivilege(newpool->tasks[i], priv); 135 1.1 christos isc_task_setname(newpool->tasks[i], "taskpool", NULL); 136 1.1 christos } 137 1.1 christos 138 1.1 christos isc_taskpool_destroy(&pool); 139 1.1 christos pool = newpool; 140 1.1 christos } 141 1.1 christos 142 1.1 christos *targetp = pool; 143 1.1 christos return (ISC_R_SUCCESS); 144 1.1 christos } 145 1.1 christos 146 1.1 christos void 147 1.1 christos isc_taskpool_destroy(isc_taskpool_t **poolp) { 148 1.1 christos unsigned int i; 149 1.1 christos isc_taskpool_t *pool = *poolp; 150 1.1 christos *poolp = NULL; 151 1.1 christos for (i = 0; i < pool->ntasks; i++) { 152 1.1 christos if (pool->tasks[i] != NULL) { 153 1.1 christos isc_task_detach(&pool->tasks[i]); 154 1.1 christos } 155 1.1 christos } 156 1.1 christos isc_mem_put(pool->mctx, pool->tasks, 157 1.1 christos pool->ntasks * sizeof(isc_task_t *)); 158 1.1 christos isc_mem_putanddetach(&pool->mctx, pool, sizeof(*pool)); 159 1.1 christos } 160