1 1.24 ad /* $NetBSD: sys_pset.c,v 1.24 2020/05/23 23:42:43 ad Exp $ */ 2 1.1 rmind 3 1.1 rmind /* 4 1.1 rmind * Copyright (c) 2008, Mindaugas Rasiukevicius <rmind at NetBSD org> 5 1.1 rmind * All rights reserved. 6 1.1 rmind * 7 1.1 rmind * Redistribution and use in source and binary forms, with or without 8 1.1 rmind * modification, are permitted provided that the following conditions 9 1.1 rmind * are met: 10 1.1 rmind * 1. Redistributions of source code must retain the above copyright 11 1.1 rmind * notice, this list of conditions and the following disclaimer. 12 1.1 rmind * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 rmind * notice, this list of conditions and the following disclaimer in the 14 1.1 rmind * documentation and/or other materials provided with the distribution. 15 1.1 rmind * 16 1.7 rmind * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 1.7 rmind * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 1.7 rmind * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 1.7 rmind * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 1.7 rmind * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 1.7 rmind * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 1.7 rmind * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 1.7 rmind * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 1.7 rmind * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 1.7 rmind * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 1.7 rmind * SUCH DAMAGE. 27 1.1 rmind */ 28 1.1 rmind 29 1.1 rmind /* 30 1.1 rmind * Implementation of the Processor Sets. 31 1.1 rmind * 32 1.1 rmind * Locking 33 1.1 rmind * The array of the processor-set structures and its members are protected 34 1.8 ad * by the global cpu_lock. Note that in scheduler, the very l_psid value 35 1.1 rmind * might be used without lock held. 36 1.1 rmind */ 37 1.1 rmind 38 1.1 rmind #include <sys/cdefs.h> 39 1.24 ad __KERNEL_RCSID(0, "$NetBSD: sys_pset.c,v 1.24 2020/05/23 23:42:43 ad Exp $"); 40 1.1 rmind 41 1.1 rmind #include <sys/param.h> 42 1.1 rmind 43 1.1 rmind #include <sys/cpu.h> 44 1.1 rmind #include <sys/kauth.h> 45 1.1 rmind #include <sys/kmem.h> 46 1.1 rmind #include <sys/lwp.h> 47 1.1 rmind #include <sys/mutex.h> 48 1.1 rmind #include <sys/proc.h> 49 1.1 rmind #include <sys/pset.h> 50 1.1 rmind #include <sys/sched.h> 51 1.1 rmind #include <sys/syscallargs.h> 52 1.1 rmind #include <sys/sysctl.h> 53 1.1 rmind #include <sys/systm.h> 54 1.1 rmind #include <sys/types.h> 55 1.1 rmind 56 1.1 rmind static pset_info_t ** psets; 57 1.1 rmind static u_int psets_max; 58 1.1 rmind static u_int psets_count; 59 1.13 elad static kauth_listener_t psets_listener; 60 1.1 rmind 61 1.1 rmind static int psets_realloc(int); 62 1.1 rmind static int psid_validate(psetid_t, bool); 63 1.1 rmind static int kern_pset_create(psetid_t *); 64 1.1 rmind static int kern_pset_destroy(psetid_t); 65 1.1 rmind 66 1.13 elad static int 67 1.13 elad psets_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie, 68 1.13 elad void *arg0, void *arg1, void *arg2, void *arg3) 69 1.13 elad { 70 1.13 elad psetid_t id; 71 1.13 elad enum kauth_system_req req; 72 1.13 elad int result; 73 1.13 elad 74 1.13 elad result = KAUTH_RESULT_DEFER; 75 1.23 joerg req = (enum kauth_system_req)(uintptr_t)arg0; 76 1.23 joerg id = (psetid_t)(uintptr_t)arg1; 77 1.13 elad 78 1.13 elad if (action != KAUTH_SYSTEM_PSET) 79 1.13 elad return result; 80 1.13 elad 81 1.13 elad if ((req == KAUTH_REQ_SYSTEM_PSET_ASSIGN) || 82 1.13 elad (req == KAUTH_REQ_SYSTEM_PSET_BIND)) { 83 1.13 elad if (id == PS_QUERY) 84 1.13 elad result = KAUTH_RESULT_ALLOW; 85 1.13 elad } 86 1.13 elad 87 1.13 elad return result; 88 1.13 elad } 89 1.13 elad 90 1.1 rmind /* 91 1.1 rmind * Initialization of the processor-sets. 92 1.1 rmind */ 93 1.1 rmind void 94 1.1 rmind psets_init(void) 95 1.1 rmind { 96 1.1 rmind 97 1.20 riastrad psets_max = uimax(maxcpus, 32); 98 1.1 rmind psets = kmem_zalloc(psets_max * sizeof(void *), KM_SLEEP); 99 1.1 rmind psets_count = 0; 100 1.13 elad 101 1.13 elad psets_listener = kauth_listen_scope(KAUTH_SCOPE_SYSTEM, 102 1.13 elad psets_listener_cb, NULL); 103 1.1 rmind } 104 1.1 rmind 105 1.1 rmind /* 106 1.1 rmind * Reallocate the array of the processor-set structures. 107 1.1 rmind */ 108 1.1 rmind static int 109 1.1 rmind psets_realloc(int new_psets_max) 110 1.1 rmind { 111 1.1 rmind pset_info_t **new_psets, **old_psets; 112 1.1 rmind const u_int newsize = new_psets_max * sizeof(void *); 113 1.1 rmind u_int i, oldsize; 114 1.1 rmind 115 1.1 rmind if (new_psets_max < 1) 116 1.1 rmind return EINVAL; 117 1.1 rmind 118 1.1 rmind new_psets = kmem_zalloc(newsize, KM_SLEEP); 119 1.8 ad mutex_enter(&cpu_lock); 120 1.1 rmind old_psets = psets; 121 1.1 rmind oldsize = psets_max * sizeof(void *); 122 1.1 rmind 123 1.1 rmind /* Check if we can lower the size of the array */ 124 1.1 rmind if (new_psets_max < psets_max) { 125 1.1 rmind for (i = new_psets_max; i < psets_max; i++) { 126 1.1 rmind if (psets[i] == NULL) 127 1.1 rmind continue; 128 1.8 ad mutex_exit(&cpu_lock); 129 1.1 rmind kmem_free(new_psets, newsize); 130 1.1 rmind return EBUSY; 131 1.1 rmind } 132 1.1 rmind } 133 1.1 rmind 134 1.1 rmind /* Copy all pointers to the new array */ 135 1.1 rmind memcpy(new_psets, psets, newsize); 136 1.1 rmind psets_max = new_psets_max; 137 1.1 rmind psets = new_psets; 138 1.8 ad mutex_exit(&cpu_lock); 139 1.1 rmind 140 1.1 rmind kmem_free(old_psets, oldsize); 141 1.1 rmind return 0; 142 1.1 rmind } 143 1.1 rmind 144 1.1 rmind /* 145 1.1 rmind * Validate processor-set ID. 146 1.1 rmind */ 147 1.1 rmind static int 148 1.1 rmind psid_validate(psetid_t psid, bool chkps) 149 1.1 rmind { 150 1.1 rmind 151 1.8 ad KASSERT(mutex_owned(&cpu_lock)); 152 1.1 rmind 153 1.1 rmind if (chkps && (psid == PS_NONE || psid == PS_QUERY || psid == PS_MYID)) 154 1.1 rmind return 0; 155 1.1 rmind if (psid <= 0 || psid > psets_max) 156 1.1 rmind return EINVAL; 157 1.1 rmind if (psets[psid - 1] == NULL) 158 1.1 rmind return EINVAL; 159 1.1 rmind 160 1.1 rmind return 0; 161 1.1 rmind } 162 1.1 rmind 163 1.1 rmind /* 164 1.1 rmind * Create a processor-set. 165 1.1 rmind */ 166 1.1 rmind static int 167 1.1 rmind kern_pset_create(psetid_t *psid) 168 1.1 rmind { 169 1.1 rmind pset_info_t *pi; 170 1.1 rmind u_int i; 171 1.1 rmind 172 1.1 rmind if (psets_count == psets_max) 173 1.1 rmind return ENOMEM; 174 1.1 rmind 175 1.1 rmind pi = kmem_zalloc(sizeof(pset_info_t), KM_SLEEP); 176 1.1 rmind 177 1.8 ad mutex_enter(&cpu_lock); 178 1.1 rmind if (psets_count == psets_max) { 179 1.8 ad mutex_exit(&cpu_lock); 180 1.1 rmind kmem_free(pi, sizeof(pset_info_t)); 181 1.1 rmind return ENOMEM; 182 1.1 rmind } 183 1.1 rmind 184 1.1 rmind /* Find a free entry in the array */ 185 1.1 rmind for (i = 0; i < psets_max; i++) 186 1.1 rmind if (psets[i] == NULL) 187 1.1 rmind break; 188 1.1 rmind KASSERT(i != psets_max); 189 1.1 rmind 190 1.1 rmind psets[i] = pi; 191 1.1 rmind psets_count++; 192 1.8 ad mutex_exit(&cpu_lock); 193 1.1 rmind 194 1.1 rmind *psid = i + 1; 195 1.1 rmind return 0; 196 1.1 rmind } 197 1.1 rmind 198 1.1 rmind /* 199 1.1 rmind * Destroy a processor-set. 200 1.1 rmind */ 201 1.1 rmind static int 202 1.1 rmind kern_pset_destroy(psetid_t psid) 203 1.1 rmind { 204 1.1 rmind struct cpu_info *ci; 205 1.1 rmind struct lwp *l; 206 1.1 rmind CPU_INFO_ITERATOR cii; 207 1.1 rmind int error; 208 1.1 rmind 209 1.8 ad mutex_enter(&cpu_lock); 210 1.1 rmind if (psid == PS_MYID) { 211 1.1 rmind /* Use caller's processor-set ID */ 212 1.1 rmind psid = curlwp->l_psid; 213 1.1 rmind } 214 1.1 rmind error = psid_validate(psid, false); 215 1.1 rmind if (error) { 216 1.8 ad mutex_exit(&cpu_lock); 217 1.1 rmind return error; 218 1.1 rmind } 219 1.1 rmind 220 1.1 rmind /* Release the processor-set from all CPUs */ 221 1.1 rmind for (CPU_INFO_FOREACH(cii, ci)) { 222 1.1 rmind struct schedstate_percpu *spc; 223 1.1 rmind 224 1.1 rmind spc = &ci->ci_schedstate; 225 1.1 rmind if (spc->spc_psid != psid) 226 1.1 rmind continue; 227 1.1 rmind spc->spc_psid = PS_NONE; 228 1.1 rmind } 229 1.1 rmind 230 1.1 rmind /* Unmark the processor-set ID from each thread */ 231 1.24 ad mutex_enter(&proc_lock); 232 1.1 rmind LIST_FOREACH(l, &alllwp, l_list) { 233 1.1 rmind /* Safe to check and set without lock held */ 234 1.1 rmind if (l->l_psid != psid) 235 1.1 rmind continue; 236 1.1 rmind l->l_psid = PS_NONE; 237 1.1 rmind } 238 1.24 ad mutex_exit(&proc_lock); 239 1.1 rmind 240 1.1 rmind /* Destroy the processor-set */ 241 1.22 ad kmem_free(psets[psid - 1], sizeof(pset_info_t)); 242 1.1 rmind psets[psid - 1] = NULL; 243 1.1 rmind psets_count--; 244 1.8 ad mutex_exit(&cpu_lock); 245 1.1 rmind 246 1.1 rmind return 0; 247 1.1 rmind } 248 1.1 rmind 249 1.1 rmind /* 250 1.1 rmind * General system calls for the processor-sets. 251 1.1 rmind */ 252 1.1 rmind 253 1.1 rmind int 254 1.1 rmind sys_pset_create(struct lwp *l, const struct sys_pset_create_args *uap, 255 1.1 rmind register_t *retval) 256 1.1 rmind { 257 1.1 rmind /* { 258 1.1 rmind syscallarg(psetid_t) *psid; 259 1.1 rmind } */ 260 1.1 rmind psetid_t psid; 261 1.1 rmind int error; 262 1.1 rmind 263 1.1 rmind /* Available only for super-user */ 264 1.4 elad if (kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_PSET, 265 1.4 elad KAUTH_REQ_SYSTEM_PSET_CREATE, NULL, NULL, NULL)) 266 1.1 rmind return EPERM; 267 1.1 rmind 268 1.1 rmind error = kern_pset_create(&psid); 269 1.1 rmind if (error) 270 1.1 rmind return error; 271 1.1 rmind 272 1.1 rmind error = copyout(&psid, SCARG(uap, psid), sizeof(psetid_t)); 273 1.1 rmind if (error) 274 1.1 rmind (void)kern_pset_destroy(psid); 275 1.1 rmind 276 1.1 rmind return error; 277 1.1 rmind } 278 1.1 rmind 279 1.1 rmind int 280 1.1 rmind sys_pset_destroy(struct lwp *l, const struct sys_pset_destroy_args *uap, 281 1.1 rmind register_t *retval) 282 1.1 rmind { 283 1.1 rmind /* { 284 1.1 rmind syscallarg(psetid_t) psid; 285 1.1 rmind } */ 286 1.1 rmind 287 1.1 rmind /* Available only for super-user */ 288 1.4 elad if (kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_PSET, 289 1.4 elad KAUTH_REQ_SYSTEM_PSET_DESTROY, 290 1.4 elad KAUTH_ARG(SCARG(uap, psid)), NULL, NULL)) 291 1.1 rmind return EPERM; 292 1.1 rmind 293 1.1 rmind return kern_pset_destroy(SCARG(uap, psid)); 294 1.1 rmind } 295 1.1 rmind 296 1.1 rmind int 297 1.1 rmind sys_pset_assign(struct lwp *l, const struct sys_pset_assign_args *uap, 298 1.1 rmind register_t *retval) 299 1.1 rmind { 300 1.1 rmind /* { 301 1.1 rmind syscallarg(psetid_t) psid; 302 1.1 rmind syscallarg(cpuid_t) cpuid; 303 1.1 rmind syscallarg(psetid_t) *opsid; 304 1.1 rmind } */ 305 1.10 rmind struct cpu_info *ici, *ci = NULL; 306 1.9 rmind struct schedstate_percpu *spc = NULL; 307 1.10 rmind struct lwp *t; 308 1.1 rmind psetid_t psid = SCARG(uap, psid), opsid = 0; 309 1.1 rmind CPU_INFO_ITERATOR cii; 310 1.9 rmind int error = 0, nnone = 0; 311 1.1 rmind 312 1.1 rmind /* Available only for super-user, except the case of PS_QUERY */ 313 1.4 elad if (kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_PSET, 314 1.4 elad KAUTH_REQ_SYSTEM_PSET_ASSIGN, KAUTH_ARG(SCARG(uap, psid)), NULL, 315 1.4 elad NULL)) 316 1.1 rmind return EPERM; 317 1.1 rmind 318 1.1 rmind /* Find the target CPU */ 319 1.8 ad mutex_enter(&cpu_lock); 320 1.10 rmind for (CPU_INFO_FOREACH(cii, ici)) { 321 1.10 rmind struct schedstate_percpu *ispc; 322 1.10 rmind ispc = &ici->ci_schedstate; 323 1.10 rmind if (cpu_index(ici) == SCARG(uap, cpuid)) { 324 1.10 rmind ci = ici; 325 1.10 rmind spc = ispc; 326 1.10 rmind } 327 1.10 rmind nnone += (ispc->spc_psid == PS_NONE); 328 1.8 ad } 329 1.10 rmind if (ci == NULL) { 330 1.8 ad mutex_exit(&cpu_lock); 331 1.1 rmind return EINVAL; 332 1.8 ad } 333 1.1 rmind error = psid_validate(psid, true); 334 1.1 rmind if (error) { 335 1.8 ad mutex_exit(&cpu_lock); 336 1.1 rmind return error; 337 1.1 rmind } 338 1.1 rmind opsid = spc->spc_psid; 339 1.1 rmind switch (psid) { 340 1.1 rmind case PS_QUERY: 341 1.1 rmind break; 342 1.1 rmind case PS_MYID: 343 1.1 rmind psid = curlwp->l_psid; 344 1.8 ad /* FALLTHROUGH */ 345 1.1 rmind default: 346 1.9 rmind /* 347 1.21 mlelstv * Just finish if old and new processor-sets are 348 1.21 mlelstv * the same. 349 1.21 mlelstv */ 350 1.21 mlelstv if (spc->spc_psid == psid) 351 1.21 mlelstv break; 352 1.21 mlelstv /* 353 1.9 rmind * Ensure at least one CPU stays in the default set, 354 1.9 rmind * and that specified CPU is not offline. 355 1.9 rmind */ 356 1.9 rmind if (psid != PS_NONE && ((spc->spc_flags & SPCF_OFFLINE) || 357 1.9 rmind (nnone == 1 && spc->spc_psid == PS_NONE))) { 358 1.8 ad mutex_exit(&cpu_lock); 359 1.8 ad return EBUSY; 360 1.8 ad } 361 1.24 ad mutex_enter(&proc_lock); 362 1.10 rmind /* 363 1.10 rmind * Ensure that none of the threads are using affinity mask 364 1.10 rmind * with this target CPU in it. 365 1.10 rmind */ 366 1.10 rmind LIST_FOREACH(t, &alllwp, l_list) { 367 1.17 rmind if (t->l_affinity == NULL) { 368 1.10 rmind continue; 369 1.17 rmind } 370 1.12 rmind lwp_lock(t); 371 1.17 rmind if (t->l_affinity == NULL) { 372 1.12 rmind lwp_unlock(t); 373 1.12 rmind continue; 374 1.12 rmind } 375 1.16 rmind if (kcpuset_isset(t->l_affinity, cpu_index(ci))) { 376 1.12 rmind lwp_unlock(t); 377 1.24 ad mutex_exit(&proc_lock); 378 1.10 rmind mutex_exit(&cpu_lock); 379 1.10 rmind return EPERM; 380 1.10 rmind } 381 1.19 maxv lwp_unlock(t); 382 1.10 rmind } 383 1.10 rmind /* 384 1.10 rmind * Set the processor-set ID. 385 1.10 rmind * Migrate out any threads running on this CPU. 386 1.10 rmind */ 387 1.1 rmind spc->spc_psid = psid; 388 1.10 rmind 389 1.10 rmind LIST_FOREACH(t, &alllwp, l_list) { 390 1.10 rmind struct cpu_info *tci; 391 1.10 rmind if (t->l_cpu != ci) 392 1.10 rmind continue; 393 1.10 rmind if (t->l_pflag & (LP_BOUND | LP_INTR)) 394 1.10 rmind continue; 395 1.10 rmind lwp_lock(t); 396 1.10 rmind tci = sched_takecpu(t); 397 1.10 rmind KASSERT(tci != ci); 398 1.10 rmind lwp_migrate(t, tci); 399 1.10 rmind } 400 1.24 ad mutex_exit(&proc_lock); 401 1.8 ad break; 402 1.1 rmind } 403 1.8 ad mutex_exit(&cpu_lock); 404 1.1 rmind 405 1.1 rmind if (SCARG(uap, opsid) != NULL) 406 1.1 rmind error = copyout(&opsid, SCARG(uap, opsid), sizeof(psetid_t)); 407 1.1 rmind 408 1.1 rmind return error; 409 1.1 rmind } 410 1.1 rmind 411 1.1 rmind int 412 1.1 rmind sys__pset_bind(struct lwp *l, const struct sys__pset_bind_args *uap, 413 1.1 rmind register_t *retval) 414 1.1 rmind { 415 1.1 rmind /* { 416 1.1 rmind syscallarg(idtype_t) idtype; 417 1.1 rmind syscallarg(id_t) first_id; 418 1.1 rmind syscallarg(id_t) second_id; 419 1.1 rmind syscallarg(psetid_t) psid; 420 1.1 rmind syscallarg(psetid_t) *opsid; 421 1.1 rmind } */ 422 1.1 rmind struct cpu_info *ci; 423 1.1 rmind struct proc *p; 424 1.1 rmind struct lwp *t; 425 1.1 rmind id_t id1, id2; 426 1.1 rmind pid_t pid = 0; 427 1.1 rmind lwpid_t lid = 0; 428 1.1 rmind psetid_t psid, opsid; 429 1.1 rmind int error = 0, lcnt; 430 1.1 rmind 431 1.1 rmind psid = SCARG(uap, psid); 432 1.1 rmind 433 1.1 rmind /* Available only for super-user, except the case of PS_QUERY */ 434 1.4 elad if (kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_PSET, 435 1.4 elad KAUTH_REQ_SYSTEM_PSET_BIND, KAUTH_ARG(SCARG(uap, psid)), NULL, 436 1.4 elad NULL)) 437 1.1 rmind return EPERM; 438 1.1 rmind 439 1.8 ad mutex_enter(&cpu_lock); 440 1.1 rmind error = psid_validate(psid, true); 441 1.1 rmind if (error) { 442 1.8 ad mutex_exit(&cpu_lock); 443 1.1 rmind return error; 444 1.1 rmind } 445 1.1 rmind if (psid == PS_MYID) 446 1.1 rmind psid = curlwp->l_psid; 447 1.1 rmind 448 1.1 rmind /* 449 1.1 rmind * Get PID and LID from the ID. 450 1.1 rmind */ 451 1.1 rmind p = l->l_proc; 452 1.1 rmind id1 = SCARG(uap, first_id); 453 1.1 rmind id2 = SCARG(uap, second_id); 454 1.1 rmind 455 1.24 ad mutex_enter(&proc_lock); 456 1.1 rmind switch (SCARG(uap, idtype)) { 457 1.1 rmind case P_PID: 458 1.1 rmind /* 459 1.1 rmind * Process: 460 1.1 rmind * First ID - PID; 461 1.1 rmind * Second ID - ignored; 462 1.1 rmind */ 463 1.1 rmind pid = (id1 == P_MYID) ? p->p_pid : id1; 464 1.1 rmind lid = 0; 465 1.1 rmind break; 466 1.1 rmind case P_LWPID: 467 1.1 rmind /* 468 1.1 rmind * Thread (LWP): 469 1.1 rmind * First ID - LID; 470 1.1 rmind * Second ID - PID; 471 1.1 rmind */ 472 1.1 rmind if (id1 == P_MYID) { 473 1.1 rmind pid = p->p_pid; 474 1.1 rmind lid = l->l_lid; 475 1.1 rmind break; 476 1.1 rmind } 477 1.1 rmind lid = id1; 478 1.1 rmind pid = (id2 == P_MYID) ? p->p_pid : id2; 479 1.1 rmind break; 480 1.1 rmind default: 481 1.2 yamt error = EINVAL; 482 1.2 yamt goto error; 483 1.1 rmind } 484 1.1 rmind 485 1.1 rmind /* Find the process */ 486 1.15 rmind p = proc_find(pid); 487 1.1 rmind if (p == NULL) { 488 1.1 rmind error = ESRCH; 489 1.1 rmind goto error; 490 1.1 rmind } 491 1.1 rmind /* Disallow modification of the system processes */ 492 1.1 rmind if (p->p_flag & PK_SYSTEM) { 493 1.1 rmind error = EPERM; 494 1.1 rmind goto error; 495 1.1 rmind } 496 1.1 rmind 497 1.1 rmind /* Find the LWP(s) */ 498 1.1 rmind lcnt = 0; 499 1.1 rmind ci = NULL; 500 1.22 ad mutex_enter(p->p_lock); 501 1.1 rmind LIST_FOREACH(t, &p->p_lwps, l_sibling) { 502 1.1 rmind if (lid && lid != t->l_lid) 503 1.1 rmind continue; 504 1.1 rmind /* 505 1.1 rmind * Bind the thread to the processor-set, 506 1.1 rmind * take some CPU and migrate. 507 1.1 rmind */ 508 1.1 rmind lwp_lock(t); 509 1.1 rmind opsid = t->l_psid; 510 1.1 rmind t->l_psid = psid; 511 1.11 rmind ci = sched_takecpu(t); 512 1.1 rmind /* Unlocks LWP */ 513 1.1 rmind lwp_migrate(t, ci); 514 1.1 rmind lcnt++; 515 1.1 rmind } 516 1.6 ad mutex_exit(p->p_lock); 517 1.1 rmind if (lcnt == 0) { 518 1.1 rmind error = ESRCH; 519 1.1 rmind } 520 1.22 ad error: 521 1.24 ad mutex_exit(&proc_lock); 522 1.22 ad mutex_exit(&cpu_lock); 523 1.22 ad if (error == 0 && SCARG(uap, opsid)) 524 1.1 rmind error = copyout(&opsid, SCARG(uap, opsid), sizeof(psetid_t)); 525 1.1 rmind return error; 526 1.1 rmind } 527 1.1 rmind 528 1.1 rmind /* 529 1.1 rmind * Sysctl nodes and initialization. 530 1.1 rmind */ 531 1.1 rmind 532 1.1 rmind static int 533 1.1 rmind sysctl_psets_max(SYSCTLFN_ARGS) 534 1.1 rmind { 535 1.1 rmind struct sysctlnode node; 536 1.1 rmind int error, newsize; 537 1.1 rmind 538 1.1 rmind node = *rnode; 539 1.1 rmind node.sysctl_data = &newsize; 540 1.1 rmind 541 1.1 rmind newsize = psets_max; 542 1.1 rmind error = sysctl_lookup(SYSCTLFN_CALL(&node)); 543 1.1 rmind if (error || newp == NULL) 544 1.1 rmind return error; 545 1.1 rmind 546 1.1 rmind if (newsize <= 0) 547 1.1 rmind return EINVAL; 548 1.1 rmind 549 1.1 rmind sysctl_unlock(); 550 1.1 rmind error = psets_realloc(newsize); 551 1.1 rmind sysctl_relock(); 552 1.1 rmind return error; 553 1.1 rmind } 554 1.1 rmind 555 1.8 ad static int 556 1.8 ad sysctl_psets_list(SYSCTLFN_ARGS) 557 1.8 ad { 558 1.8 ad const size_t bufsz = 1024; 559 1.8 ad char *buf, tbuf[16]; 560 1.8 ad int i, error; 561 1.8 ad size_t len; 562 1.8 ad 563 1.8 ad sysctl_unlock(); 564 1.8 ad buf = kmem_alloc(bufsz, KM_SLEEP); 565 1.8 ad snprintf(buf, bufsz, "%d:1", PS_NONE); /* XXX */ 566 1.8 ad 567 1.8 ad mutex_enter(&cpu_lock); 568 1.8 ad for (i = 0; i < psets_max; i++) { 569 1.8 ad if (psets[i] == NULL) 570 1.8 ad continue; 571 1.8 ad snprintf(tbuf, sizeof(tbuf), ",%d:2", i + 1); /* XXX */ 572 1.8 ad strlcat(buf, tbuf, bufsz); 573 1.8 ad } 574 1.8 ad mutex_exit(&cpu_lock); 575 1.8 ad len = strlen(buf) + 1; 576 1.8 ad error = 0; 577 1.8 ad if (oldp != NULL) 578 1.20 riastrad error = copyout(buf, oldp, uimin(len, *oldlenp)); 579 1.8 ad *oldlenp = len; 580 1.8 ad kmem_free(buf, bufsz); 581 1.8 ad sysctl_relock(); 582 1.8 ad return error; 583 1.8 ad } 584 1.8 ad 585 1.1 rmind SYSCTL_SETUP(sysctl_pset_setup, "sysctl kern.pset subtree setup") 586 1.1 rmind { 587 1.1 rmind const struct sysctlnode *node = NULL; 588 1.1 rmind 589 1.1 rmind sysctl_createv(clog, 0, NULL, &node, 590 1.1 rmind CTLFLAG_PERMANENT, 591 1.1 rmind CTLTYPE_NODE, "pset", 592 1.1 rmind SYSCTL_DESCR("Processor-set options"), 593 1.1 rmind NULL, 0, NULL, 0, 594 1.1 rmind CTL_KERN, CTL_CREATE, CTL_EOL); 595 1.1 rmind 596 1.1 rmind if (node == NULL) 597 1.1 rmind return; 598 1.1 rmind 599 1.1 rmind sysctl_createv(clog, 0, &node, NULL, 600 1.1 rmind CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 601 1.1 rmind CTLTYPE_INT, "psets_max", 602 1.1 rmind SYSCTL_DESCR("Maximal count of the processor-sets"), 603 1.1 rmind sysctl_psets_max, 0, &psets_max, 0, 604 1.1 rmind CTL_CREATE, CTL_EOL); 605 1.8 ad sysctl_createv(clog, 0, &node, NULL, 606 1.8 ad CTLFLAG_PERMANENT, 607 1.8 ad CTLTYPE_STRING, "list", 608 1.8 ad SYSCTL_DESCR("List of active sets"), 609 1.8 ad sysctl_psets_list, 0, NULL, 0, 610 1.8 ad CTL_CREATE, CTL_EOL); 611 1.1 rmind } 612