1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/signal.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/pcb.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/user.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/sysinfo.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/var.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/cred.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/proc.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/procset.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/inline.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/priocntl.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/disp.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/class.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/t_lock.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/uadmin.h> 54*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 55*7c478bd9Sstevel@tonic-gate #include <sys/policy.h> 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate /* 58*7c478bd9Sstevel@tonic-gate * Structure used to pass arguments to the proccmp() function. 59*7c478bd9Sstevel@tonic-gate * The arguments must be passed in a structure because proccmp() 60*7c478bd9Sstevel@tonic-gate * is called indirectly through the dotoprocs() function which 61*7c478bd9Sstevel@tonic-gate * will only pass through a single one word argument. 62*7c478bd9Sstevel@tonic-gate */ 63*7c478bd9Sstevel@tonic-gate struct pcmpargs { 64*7c478bd9Sstevel@tonic-gate id_t *pcmp_cidp; 65*7c478bd9Sstevel@tonic-gate int *pcmp_cntp; 66*7c478bd9Sstevel@tonic-gate kthread_id_t *pcmp_retthreadp; 67*7c478bd9Sstevel@tonic-gate }; 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate /* 70*7c478bd9Sstevel@tonic-gate * Structure used to pass arguments to the setparms() function 71*7c478bd9Sstevel@tonic-gate * which is called indirectly through dotoprocs(). 72*7c478bd9Sstevel@tonic-gate */ 73*7c478bd9Sstevel@tonic-gate struct stprmargs { 74*7c478bd9Sstevel@tonic-gate struct pcparms *stp_parmsp; /* pointer to parameters */ 75*7c478bd9Sstevel@tonic-gate int stp_error; /* some errors returned here */ 76*7c478bd9Sstevel@tonic-gate }; 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate #if defined(_SYSCALL32_IMPL) && _LONG_LONG_ALIGNMENT_32 == 4 79*7c478bd9Sstevel@tonic-gate /* 80*7c478bd9Sstevel@tonic-gate * A vaparm_t is an int followed by a long long -- this packs differently 81*7c478bd9Sstevel@tonic-gate * between the 64-bit kernel ABI and the 32-bit user ABI. 82*7c478bd9Sstevel@tonic-gate */ 83*7c478bd9Sstevel@tonic-gate static int 84*7c478bd9Sstevel@tonic-gate copyin_vaparms32(caddr_t arg, pc_vaparms_t *vap) 85*7c478bd9Sstevel@tonic-gate { 86*7c478bd9Sstevel@tonic-gate pc_vaparms32_t vaparms32; 87*7c478bd9Sstevel@tonic-gate pc_vaparm32_t *src; 88*7c478bd9Sstevel@tonic-gate pc_vaparm_t *dst; 89*7c478bd9Sstevel@tonic-gate uint_t cnt; 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate ASSERT(get_udatamodel() == DATAMODEL_ILP32); 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate if (copyin(arg, &vaparms32, sizeof (vaparms32))) 94*7c478bd9Sstevel@tonic-gate return (EFAULT); 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate vap->pc_vaparmscnt = vaparms32.pc_vaparmscnt; 97*7c478bd9Sstevel@tonic-gate if ((cnt = vaparms32.pc_vaparmscnt) > PC_VAPARMCNT) 98*7c478bd9Sstevel@tonic-gate cnt = PC_VAPARMCNT; 99*7c478bd9Sstevel@tonic-gate for (src = vaparms32.pc_parms, dst = vap->pc_parms; 100*7c478bd9Sstevel@tonic-gate cnt--; src++, dst++) { 101*7c478bd9Sstevel@tonic-gate dst->pc_key = src->pc_key; 102*7c478bd9Sstevel@tonic-gate dst->pc_parm = src->pc_parm; 103*7c478bd9Sstevel@tonic-gate } 104*7c478bd9Sstevel@tonic-gate return (0); 105*7c478bd9Sstevel@tonic-gate } 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate #define COPYIN_VAPARMS(arg, vap, size) \ 108*7c478bd9Sstevel@tonic-gate (get_udatamodel() == DATAMODEL_NATIVE ? \ 109*7c478bd9Sstevel@tonic-gate copyin(arg, vap, size) : copyin_vaparms32(arg, vap)) 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate #else 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate #define COPYIN_VAPARMS(arg, vap, size) copyin(arg, vap, size) 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate #endif 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate static int donice(procset_t *, pcnice_t *); 118*7c478bd9Sstevel@tonic-gate static int proccmp(proc_t *, struct pcmpargs *); 119*7c478bd9Sstevel@tonic-gate static int setparms(proc_t *, struct stprmargs *); 120*7c478bd9Sstevel@tonic-gate extern int threadcmp(struct pcmpargs *, kthread_id_t); 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate /* 123*7c478bd9Sstevel@tonic-gate * The priocntl system call. 124*7c478bd9Sstevel@tonic-gate */ 125*7c478bd9Sstevel@tonic-gate long 126*7c478bd9Sstevel@tonic-gate priocntlsys(int pc_version, procset_t *psp, int cmd, caddr_t arg, caddr_t arg2) 127*7c478bd9Sstevel@tonic-gate { 128*7c478bd9Sstevel@tonic-gate pcinfo_t pcinfo; 129*7c478bd9Sstevel@tonic-gate pcparms_t pcparms; 130*7c478bd9Sstevel@tonic-gate pcnice_t pcnice; 131*7c478bd9Sstevel@tonic-gate pcadmin_t pcadmin; 132*7c478bd9Sstevel@tonic-gate pcpri_t pcpri; 133*7c478bd9Sstevel@tonic-gate procset_t procset; 134*7c478bd9Sstevel@tonic-gate struct stprmargs stprmargs; 135*7c478bd9Sstevel@tonic-gate struct pcmpargs pcmpargs; 136*7c478bd9Sstevel@tonic-gate pc_vaparms_t vaparms; 137*7c478bd9Sstevel@tonic-gate char clname[PC_CLNMSZ]; 138*7c478bd9Sstevel@tonic-gate int count; 139*7c478bd9Sstevel@tonic-gate kthread_id_t retthreadp; 140*7c478bd9Sstevel@tonic-gate proc_t *initpp; 141*7c478bd9Sstevel@tonic-gate int clnullflag; 142*7c478bd9Sstevel@tonic-gate int error = 0; 143*7c478bd9Sstevel@tonic-gate int error1 = 0; 144*7c478bd9Sstevel@tonic-gate int rv = 0; 145*7c478bd9Sstevel@tonic-gate pid_t saved_pid; 146*7c478bd9Sstevel@tonic-gate id_t classid; 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate /* 149*7c478bd9Sstevel@tonic-gate * First just check the version number. Right now there is only 150*7c478bd9Sstevel@tonic-gate * one version we know about and support. If we get some other 151*7c478bd9Sstevel@tonic-gate * version number from the application it may be that the 152*7c478bd9Sstevel@tonic-gate * application was built with some future version and is trying 153*7c478bd9Sstevel@tonic-gate * to run on an old release of the system (that's us). In any 154*7c478bd9Sstevel@tonic-gate * case if we don't recognize the version number all we can do is 155*7c478bd9Sstevel@tonic-gate * return error. 156*7c478bd9Sstevel@tonic-gate */ 157*7c478bd9Sstevel@tonic-gate if (pc_version != PC_VERSION) 158*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate switch (cmd) { 161*7c478bd9Sstevel@tonic-gate case PC_GETCID: 162*7c478bd9Sstevel@tonic-gate /* 163*7c478bd9Sstevel@tonic-gate * If the arg pointer is NULL, the user just wants to 164*7c478bd9Sstevel@tonic-gate * know the number of classes. If non-NULL, the pointer 165*7c478bd9Sstevel@tonic-gate * should point to a valid user pcinfo buffer. In the 166*7c478bd9Sstevel@tonic-gate * dynamic world we need to return the number of loaded 167*7c478bd9Sstevel@tonic-gate * classes, not the max number of available classes that 168*7c478bd9Sstevel@tonic-gate * can be loaded. 169*7c478bd9Sstevel@tonic-gate */ 170*7c478bd9Sstevel@tonic-gate if (arg == NULL) { 171*7c478bd9Sstevel@tonic-gate rv = loaded_classes; 172*7c478bd9Sstevel@tonic-gate break; 173*7c478bd9Sstevel@tonic-gate } else { 174*7c478bd9Sstevel@tonic-gate if (copyin(arg, &pcinfo, sizeof (pcinfo))) 175*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate pcinfo.pc_clname[PC_CLNMSZ-1] = '\0'; 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate /* 181*7c478bd9Sstevel@tonic-gate * Get the class ID corresponding to user supplied name. 182*7c478bd9Sstevel@tonic-gate */ 183*7c478bd9Sstevel@tonic-gate error = getcid(pcinfo.pc_clname, &pcinfo.pc_cid); 184*7c478bd9Sstevel@tonic-gate if (error) 185*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate /* 188*7c478bd9Sstevel@tonic-gate * Can't get info about the sys class. 189*7c478bd9Sstevel@tonic-gate */ 190*7c478bd9Sstevel@tonic-gate if (pcinfo.pc_cid == 0) 191*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate /* 194*7c478bd9Sstevel@tonic-gate * Get the class specific information. 195*7c478bd9Sstevel@tonic-gate * we MUST make sure that the class has not already 196*7c478bd9Sstevel@tonic-gate * been unloaded before we try the CL_GETCLINFO. 197*7c478bd9Sstevel@tonic-gate * If it has then we need to load it. 198*7c478bd9Sstevel@tonic-gate */ 199*7c478bd9Sstevel@tonic-gate error = 200*7c478bd9Sstevel@tonic-gate scheduler_load(pcinfo.pc_clname, &sclass[pcinfo.pc_cid]); 201*7c478bd9Sstevel@tonic-gate if (error) 202*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 203*7c478bd9Sstevel@tonic-gate error = CL_GETCLINFO(&sclass[pcinfo.pc_cid], pcinfo.pc_clinfo); 204*7c478bd9Sstevel@tonic-gate if (error) 205*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate if (copyout(&pcinfo, arg, sizeof (pcinfo))) 208*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate rv = loaded_classes; 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate break; 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate case PC_GETCLINFO: 215*7c478bd9Sstevel@tonic-gate /* 216*7c478bd9Sstevel@tonic-gate * If the arg pointer is NULL, the user just wants to know 217*7c478bd9Sstevel@tonic-gate * the number of classes. If non-NULL, the pointer should 218*7c478bd9Sstevel@tonic-gate * point to a valid user pcinfo buffer. 219*7c478bd9Sstevel@tonic-gate */ 220*7c478bd9Sstevel@tonic-gate if (arg == NULL) { 221*7c478bd9Sstevel@tonic-gate rv = loaded_classes; 222*7c478bd9Sstevel@tonic-gate break; 223*7c478bd9Sstevel@tonic-gate } else { 224*7c478bd9Sstevel@tonic-gate if (copyin(arg, &pcinfo, sizeof (pcinfo))) 225*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 226*7c478bd9Sstevel@tonic-gate } 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate if (pcinfo.pc_cid >= loaded_classes || pcinfo.pc_cid < 1) 229*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate (void) strncpy(pcinfo.pc_clname, sclass[pcinfo.pc_cid].cl_name, 232*7c478bd9Sstevel@tonic-gate PC_CLNMSZ); 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate /* 235*7c478bd9Sstevel@tonic-gate * Get the class specific information. we MUST make sure 236*7c478bd9Sstevel@tonic-gate * that the class has not already been unloaded before we 237*7c478bd9Sstevel@tonic-gate * try the CL_GETCLINFO. If it has then we need to load 238*7c478bd9Sstevel@tonic-gate * it. 239*7c478bd9Sstevel@tonic-gate */ 240*7c478bd9Sstevel@tonic-gate error = 241*7c478bd9Sstevel@tonic-gate scheduler_load(pcinfo.pc_clname, &sclass[pcinfo.pc_cid]); 242*7c478bd9Sstevel@tonic-gate if (error) 243*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 244*7c478bd9Sstevel@tonic-gate error = CL_GETCLINFO(&sclass[pcinfo.pc_cid], pcinfo.pc_clinfo); 245*7c478bd9Sstevel@tonic-gate if (error) 246*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gate if (copyout(&pcinfo, arg, sizeof (pcinfo))) 249*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate rv = loaded_classes; 252*7c478bd9Sstevel@tonic-gate break; 253*7c478bd9Sstevel@tonic-gate 254*7c478bd9Sstevel@tonic-gate case PC_SETPARMS: 255*7c478bd9Sstevel@tonic-gate case PC_SETXPARMS: 256*7c478bd9Sstevel@tonic-gate /* 257*7c478bd9Sstevel@tonic-gate * First check the validity of the parameters we got from 258*7c478bd9Sstevel@tonic-gate * the user. We don't do any permissions checking here 259*7c478bd9Sstevel@tonic-gate * because it's done on a per thread basis by parmsset(). 260*7c478bd9Sstevel@tonic-gate */ 261*7c478bd9Sstevel@tonic-gate if (cmd == PC_SETPARMS) { 262*7c478bd9Sstevel@tonic-gate if (copyin(arg, &pcparms, sizeof (pcparms))) 263*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate error = parmsin(&pcparms, NULL); 266*7c478bd9Sstevel@tonic-gate } else { 267*7c478bd9Sstevel@tonic-gate if (copyin(arg, clname, PC_CLNMSZ) || 268*7c478bd9Sstevel@tonic-gate COPYIN_VAPARMS(arg2, &vaparms, sizeof (vaparms))) 269*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 270*7c478bd9Sstevel@tonic-gate clname[PC_CLNMSZ-1] = '\0'; 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate if (getcid(clname, &pcparms.pc_cid)) 273*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate error = parmsin(&pcparms, &vaparms); 276*7c478bd9Sstevel@tonic-gate } 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate if (error) 279*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate /* 282*7c478bd9Sstevel@tonic-gate * Get the procset from the user. 283*7c478bd9Sstevel@tonic-gate */ 284*7c478bd9Sstevel@tonic-gate if (copyin(psp, &procset, sizeof (procset))) 285*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate /* 288*7c478bd9Sstevel@tonic-gate * For performance we do a quick check here to catch 289*7c478bd9Sstevel@tonic-gate * common cases where the current thread is the only one 290*7c478bd9Sstevel@tonic-gate * in the set. In such cases we can call parmsset() 291*7c478bd9Sstevel@tonic-gate * directly, avoiding the relatively lengthy path through 292*7c478bd9Sstevel@tonic-gate * dotoprocs(). The underlying classes expect pidlock to 293*7c478bd9Sstevel@tonic-gate * be held. 294*7c478bd9Sstevel@tonic-gate */ 295*7c478bd9Sstevel@tonic-gate if (cur_inset_only(&procset) == B_TRUE) { 296*7c478bd9Sstevel@tonic-gate /* do a single LWP */ 297*7c478bd9Sstevel@tonic-gate if ((procset.p_lidtype == P_LWPID) || 298*7c478bd9Sstevel@tonic-gate (procset.p_ridtype == P_LWPID)) { 299*7c478bd9Sstevel@tonic-gate mutex_enter(&pidlock); 300*7c478bd9Sstevel@tonic-gate mutex_enter(&curproc->p_lock); 301*7c478bd9Sstevel@tonic-gate error = parmsset(&pcparms, curthread); 302*7c478bd9Sstevel@tonic-gate mutex_exit(&curproc->p_lock); 303*7c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 304*7c478bd9Sstevel@tonic-gate } else { 305*7c478bd9Sstevel@tonic-gate /* do the entire process otherwise */ 306*7c478bd9Sstevel@tonic-gate stprmargs.stp_parmsp = &pcparms; 307*7c478bd9Sstevel@tonic-gate stprmargs.stp_error = 0; 308*7c478bd9Sstevel@tonic-gate mutex_enter(&pidlock); 309*7c478bd9Sstevel@tonic-gate error = setparms(curproc, &stprmargs); 310*7c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 311*7c478bd9Sstevel@tonic-gate if (error == 0 && stprmargs.stp_error != 0) 312*7c478bd9Sstevel@tonic-gate error = stprmargs.stp_error; 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate if (error) 315*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 316*7c478bd9Sstevel@tonic-gate } else { 317*7c478bd9Sstevel@tonic-gate stprmargs.stp_parmsp = &pcparms; 318*7c478bd9Sstevel@tonic-gate stprmargs.stp_error = 0; 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate error1 = error = ESRCH; 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate /* 323*7c478bd9Sstevel@tonic-gate * The dotoprocs() call below will cause 324*7c478bd9Sstevel@tonic-gate * setparms() to be called for each thread in the 325*7c478bd9Sstevel@tonic-gate * specified procset. setparms() will in turn 326*7c478bd9Sstevel@tonic-gate * call parmsset() (which does the real work). 327*7c478bd9Sstevel@tonic-gate */ 328*7c478bd9Sstevel@tonic-gate if ((procset.p_lidtype != P_LWPID) || 329*7c478bd9Sstevel@tonic-gate (procset.p_ridtype != P_LWPID)) { 330*7c478bd9Sstevel@tonic-gate error1 = dotoprocs(&procset, setparms, 331*7c478bd9Sstevel@tonic-gate (char *)&stprmargs); 332*7c478bd9Sstevel@tonic-gate } 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate /* 335*7c478bd9Sstevel@tonic-gate * take care of the case when any of the 336*7c478bd9Sstevel@tonic-gate * operands happen to be LWP's 337*7c478bd9Sstevel@tonic-gate */ 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate if ((procset.p_lidtype == P_LWPID) || 340*7c478bd9Sstevel@tonic-gate (procset.p_ridtype == P_LWPID)) { 341*7c478bd9Sstevel@tonic-gate error = dotolwp(&procset, parmsset, 342*7c478bd9Sstevel@tonic-gate (char *)&pcparms); 343*7c478bd9Sstevel@tonic-gate /* 344*7c478bd9Sstevel@tonic-gate * Dotolwp() returns with p_lock held. 345*7c478bd9Sstevel@tonic-gate * This is required for the GETPARMS case 346*7c478bd9Sstevel@tonic-gate * below. So, here we just release the 347*7c478bd9Sstevel@tonic-gate * p_lock. 348*7c478bd9Sstevel@tonic-gate */ 349*7c478bd9Sstevel@tonic-gate if (MUTEX_HELD(&curproc->p_lock)) 350*7c478bd9Sstevel@tonic-gate mutex_exit(&curproc->p_lock); 351*7c478bd9Sstevel@tonic-gate } 352*7c478bd9Sstevel@tonic-gate 353*7c478bd9Sstevel@tonic-gate /* 354*7c478bd9Sstevel@tonic-gate * If setparms() encounters a permissions error 355*7c478bd9Sstevel@tonic-gate * for one or more of the threads it returns 356*7c478bd9Sstevel@tonic-gate * EPERM in stp_error so dotoprocs() will 357*7c478bd9Sstevel@tonic-gate * continue through the thread set. If 358*7c478bd9Sstevel@tonic-gate * dotoprocs() returned an error above, it was 359*7c478bd9Sstevel@tonic-gate * more serious than permissions and dotoprocs 360*7c478bd9Sstevel@tonic-gate * quit when the error was encountered. We 361*7c478bd9Sstevel@tonic-gate * return the more serious error if there was 362*7c478bd9Sstevel@tonic-gate * one, otherwise we return EPERM if we got that 363*7c478bd9Sstevel@tonic-gate * back. 364*7c478bd9Sstevel@tonic-gate */ 365*7c478bd9Sstevel@tonic-gate if (error1 != ESRCH) 366*7c478bd9Sstevel@tonic-gate error = error1; 367*7c478bd9Sstevel@tonic-gate if (error == 0 && stprmargs.stp_error != 0) 368*7c478bd9Sstevel@tonic-gate error = stprmargs.stp_error; 369*7c478bd9Sstevel@tonic-gate } 370*7c478bd9Sstevel@tonic-gate break; 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate case PC_GETPARMS: 373*7c478bd9Sstevel@tonic-gate case PC_GETXPARMS: 374*7c478bd9Sstevel@tonic-gate if (cmd == PC_GETPARMS) { 375*7c478bd9Sstevel@tonic-gate if (copyin(arg, &pcparms, sizeof (pcparms))) 376*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 377*7c478bd9Sstevel@tonic-gate } else { 378*7c478bd9Sstevel@tonic-gate if (arg != NULL) { 379*7c478bd9Sstevel@tonic-gate if (copyin(arg, clname, PC_CLNMSZ)) 380*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate clname[PC_CLNMSZ-1] = '\0'; 383*7c478bd9Sstevel@tonic-gate 384*7c478bd9Sstevel@tonic-gate if (getcid(clname, &pcparms.pc_cid)) 385*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 386*7c478bd9Sstevel@tonic-gate } else 387*7c478bd9Sstevel@tonic-gate pcparms.pc_cid = PC_CLNULL; 388*7c478bd9Sstevel@tonic-gate if (COPYIN_VAPARMS(arg2, &vaparms, sizeof (vaparms))) 389*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 390*7c478bd9Sstevel@tonic-gate } 391*7c478bd9Sstevel@tonic-gate 392*7c478bd9Sstevel@tonic-gate if (pcparms.pc_cid >= loaded_classes || 393*7c478bd9Sstevel@tonic-gate (pcparms.pc_cid < 1 && pcparms.pc_cid != PC_CLNULL)) 394*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate if (copyin(psp, &procset, sizeof (procset))) 397*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate /* 400*7c478bd9Sstevel@tonic-gate * Check to see if the current thread is the only one 401*7c478bd9Sstevel@tonic-gate * in the set. If not we must go through the whole set 402*7c478bd9Sstevel@tonic-gate * to select a thread. 403*7c478bd9Sstevel@tonic-gate */ 404*7c478bd9Sstevel@tonic-gate if (cur_inset_only(&procset) == B_TRUE) { 405*7c478bd9Sstevel@tonic-gate /* do a single LWP */ 406*7c478bd9Sstevel@tonic-gate if ((procset.p_lidtype == P_LWPID) || 407*7c478bd9Sstevel@tonic-gate (procset.p_ridtype == P_LWPID)) { 408*7c478bd9Sstevel@tonic-gate if (pcparms.pc_cid != PC_CLNULL && 409*7c478bd9Sstevel@tonic-gate pcparms.pc_cid != curthread->t_cid) { 410*7c478bd9Sstevel@tonic-gate /* 411*7c478bd9Sstevel@tonic-gate * Specified thread not in 412*7c478bd9Sstevel@tonic-gate * specified class. 413*7c478bd9Sstevel@tonic-gate */ 414*7c478bd9Sstevel@tonic-gate return (set_errno(ESRCH)); 415*7c478bd9Sstevel@tonic-gate } else { 416*7c478bd9Sstevel@tonic-gate mutex_enter(&curproc->p_lock); 417*7c478bd9Sstevel@tonic-gate retthreadp = curthread; 418*7c478bd9Sstevel@tonic-gate } 419*7c478bd9Sstevel@tonic-gate } else { 420*7c478bd9Sstevel@tonic-gate count = 0; 421*7c478bd9Sstevel@tonic-gate retthreadp = NULL; 422*7c478bd9Sstevel@tonic-gate pcmpargs.pcmp_cidp = &pcparms.pc_cid; 423*7c478bd9Sstevel@tonic-gate pcmpargs.pcmp_cntp = &count; 424*7c478bd9Sstevel@tonic-gate pcmpargs.pcmp_retthreadp = &retthreadp; 425*7c478bd9Sstevel@tonic-gate /* 426*7c478bd9Sstevel@tonic-gate * Specified thread not in specified class. 427*7c478bd9Sstevel@tonic-gate */ 428*7c478bd9Sstevel@tonic-gate if (pcparms.pc_cid != PC_CLNULL && 429*7c478bd9Sstevel@tonic-gate pcparms.pc_cid != curthread->t_cid) 430*7c478bd9Sstevel@tonic-gate return (set_errno(ESRCH)); 431*7c478bd9Sstevel@tonic-gate error = proccmp(curproc, &pcmpargs); 432*7c478bd9Sstevel@tonic-gate if (error) { 433*7c478bd9Sstevel@tonic-gate if (retthreadp != NULL) 434*7c478bd9Sstevel@tonic-gate mutex_exit(&(curproc->p_lock)); 435*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 436*7c478bd9Sstevel@tonic-gate } 437*7c478bd9Sstevel@tonic-gate } 438*7c478bd9Sstevel@tonic-gate } else { 439*7c478bd9Sstevel@tonic-gate /* 440*7c478bd9Sstevel@tonic-gate * get initpp early to avoid lock ordering problems 441*7c478bd9Sstevel@tonic-gate * (we cannot get pidlock while holding any p_lock). 442*7c478bd9Sstevel@tonic-gate */ 443*7c478bd9Sstevel@tonic-gate mutex_enter(&pidlock); 444*7c478bd9Sstevel@tonic-gate initpp = prfind(P_INITPID); 445*7c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate /* 448*7c478bd9Sstevel@tonic-gate * Select the thread (from the set) whose 449*7c478bd9Sstevel@tonic-gate * parameters we are going to return. First we 450*7c478bd9Sstevel@tonic-gate * set up some locations for return values, then 451*7c478bd9Sstevel@tonic-gate * we call proccmp() indirectly through 452*7c478bd9Sstevel@tonic-gate * dotoprocs(). proccmp() will call a class 453*7c478bd9Sstevel@tonic-gate * specific routine which actually does the 454*7c478bd9Sstevel@tonic-gate * selection. To understand how this works take 455*7c478bd9Sstevel@tonic-gate * a careful look at the code below, the 456*7c478bd9Sstevel@tonic-gate * dotoprocs() function, the proccmp() function, 457*7c478bd9Sstevel@tonic-gate * and the class specific cl_proccmp() functions. 458*7c478bd9Sstevel@tonic-gate */ 459*7c478bd9Sstevel@tonic-gate if (pcparms.pc_cid == PC_CLNULL) 460*7c478bd9Sstevel@tonic-gate clnullflag = 1; 461*7c478bd9Sstevel@tonic-gate else 462*7c478bd9Sstevel@tonic-gate clnullflag = 0; 463*7c478bd9Sstevel@tonic-gate count = 0; 464*7c478bd9Sstevel@tonic-gate retthreadp = NULL; 465*7c478bd9Sstevel@tonic-gate pcmpargs.pcmp_cidp = &pcparms.pc_cid; 466*7c478bd9Sstevel@tonic-gate pcmpargs.pcmp_cntp = &count; 467*7c478bd9Sstevel@tonic-gate pcmpargs.pcmp_retthreadp = &retthreadp; 468*7c478bd9Sstevel@tonic-gate error1 = error = ESRCH; 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate if ((procset.p_lidtype != P_LWPID) || 471*7c478bd9Sstevel@tonic-gate (procset.p_ridtype != P_LWPID)) { 472*7c478bd9Sstevel@tonic-gate error1 = dotoprocs(&procset, proccmp, 473*7c478bd9Sstevel@tonic-gate (char *)&pcmpargs); 474*7c478bd9Sstevel@tonic-gate } 475*7c478bd9Sstevel@tonic-gate 476*7c478bd9Sstevel@tonic-gate /* 477*7c478bd9Sstevel@tonic-gate * take care of combination of LWP and process 478*7c478bd9Sstevel@tonic-gate * set case in a procset 479*7c478bd9Sstevel@tonic-gate */ 480*7c478bd9Sstevel@tonic-gate if ((procset.p_lidtype == P_LWPID) || 481*7c478bd9Sstevel@tonic-gate (procset.p_ridtype == P_LWPID)) { 482*7c478bd9Sstevel@tonic-gate error = dotolwp(&procset, threadcmp, 483*7c478bd9Sstevel@tonic-gate (char *)&pcmpargs); 484*7c478bd9Sstevel@tonic-gate } 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate /* 487*7c478bd9Sstevel@tonic-gate * Both proccmp() and threadcmp() return with the 488*7c478bd9Sstevel@tonic-gate * p_lock held for the ttoproc(retthreadp). This 489*7c478bd9Sstevel@tonic-gate * is required to make sure that the process we 490*7c478bd9Sstevel@tonic-gate * chose as the winner doesn't go away 491*7c478bd9Sstevel@tonic-gate * i.e. retthreadp has to be a valid pointer. 492*7c478bd9Sstevel@tonic-gate * 493*7c478bd9Sstevel@tonic-gate * The case below can only happen if the thread 494*7c478bd9Sstevel@tonic-gate * with the highest priority was not in your 495*7c478bd9Sstevel@tonic-gate * process. In that case, dotolwp will return 496*7c478bd9Sstevel@tonic-gate * holding p_lock for both your process as well 497*7c478bd9Sstevel@tonic-gate * as the process in which retthreadp is a 498*7c478bd9Sstevel@tonic-gate * thread. 499*7c478bd9Sstevel@tonic-gate */ 500*7c478bd9Sstevel@tonic-gate if ((retthreadp != NULL) && 501*7c478bd9Sstevel@tonic-gate (ttoproc(retthreadp) != curproc) && 502*7c478bd9Sstevel@tonic-gate MUTEX_HELD(&(curproc)->p_lock)) 503*7c478bd9Sstevel@tonic-gate mutex_exit(&(curproc)->p_lock); 504*7c478bd9Sstevel@tonic-gate 505*7c478bd9Sstevel@tonic-gate ASSERT(retthreadp == NULL || 506*7c478bd9Sstevel@tonic-gate MUTEX_HELD(&(ttoproc(retthreadp)->p_lock))); 507*7c478bd9Sstevel@tonic-gate if (error1 != ESRCH) 508*7c478bd9Sstevel@tonic-gate error = error1; 509*7c478bd9Sstevel@tonic-gate if (error) { 510*7c478bd9Sstevel@tonic-gate if (retthreadp != NULL) 511*7c478bd9Sstevel@tonic-gate mutex_exit(&(ttoproc(retthreadp)->p_lock)); 512*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&(curproc)->p_lock)); 513*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 514*7c478bd9Sstevel@tonic-gate } 515*7c478bd9Sstevel@tonic-gate /* 516*7c478bd9Sstevel@tonic-gate * dotoprocs() ignores the init process if it is 517*7c478bd9Sstevel@tonic-gate * in the set, unless it was the only process found. 518*7c478bd9Sstevel@tonic-gate * Since we are getting parameters here rather than 519*7c478bd9Sstevel@tonic-gate * setting them, we want to make sure init is not 520*7c478bd9Sstevel@tonic-gate * excluded if it is in the set. 521*7c478bd9Sstevel@tonic-gate */ 522*7c478bd9Sstevel@tonic-gate if (initpp != NULL && 523*7c478bd9Sstevel@tonic-gate procinset(initpp, &procset) && 524*7c478bd9Sstevel@tonic-gate (retthreadp != NULL) && 525*7c478bd9Sstevel@tonic-gate ttoproc(retthreadp) != initpp) 526*7c478bd9Sstevel@tonic-gate (void) proccmp(initpp, &pcmpargs); 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate /* 529*7c478bd9Sstevel@tonic-gate * If dotoprocs returned success it found at least 530*7c478bd9Sstevel@tonic-gate * one thread in the set. If proccmp() failed to 531*7c478bd9Sstevel@tonic-gate * select a thread it is because the user specified 532*7c478bd9Sstevel@tonic-gate * a class and none of the threads in the set 533*7c478bd9Sstevel@tonic-gate * belonged to that class, or because the process 534*7c478bd9Sstevel@tonic-gate * specified was in the middle of exiting and had 535*7c478bd9Sstevel@tonic-gate * cleared its thread list. 536*7c478bd9Sstevel@tonic-gate */ 537*7c478bd9Sstevel@tonic-gate if (retthreadp == NULL) { 538*7c478bd9Sstevel@tonic-gate /* 539*7c478bd9Sstevel@tonic-gate * Might be here and still holding p_lock 540*7c478bd9Sstevel@tonic-gate * if we did a dotolwp on an lwp that 541*7c478bd9Sstevel@tonic-gate * existed but was in the wrong class. 542*7c478bd9Sstevel@tonic-gate */ 543*7c478bd9Sstevel@tonic-gate if (MUTEX_HELD(&(curproc)->p_lock)) 544*7c478bd9Sstevel@tonic-gate mutex_exit(&(curproc)->p_lock); 545*7c478bd9Sstevel@tonic-gate return (set_errno(ESRCH)); 546*7c478bd9Sstevel@tonic-gate } 547*7c478bd9Sstevel@tonic-gate 548*7c478bd9Sstevel@tonic-gate /* 549*7c478bd9Sstevel@tonic-gate * User can only use PC_CLNULL with one thread in set. 550*7c478bd9Sstevel@tonic-gate */ 551*7c478bd9Sstevel@tonic-gate if (clnullflag && count > 1) { 552*7c478bd9Sstevel@tonic-gate if (retthreadp != NULL) 553*7c478bd9Sstevel@tonic-gate mutex_exit( 554*7c478bd9Sstevel@tonic-gate &(ttoproc(retthreadp)->p_lock)); 555*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&(curproc)->p_lock)); 556*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 557*7c478bd9Sstevel@tonic-gate } 558*7c478bd9Sstevel@tonic-gate } 559*7c478bd9Sstevel@tonic-gate 560*7c478bd9Sstevel@tonic-gate ASSERT(retthreadp == NULL || 561*7c478bd9Sstevel@tonic-gate MUTEX_HELD(&(ttoproc(retthreadp)->p_lock))); 562*7c478bd9Sstevel@tonic-gate /* 563*7c478bd9Sstevel@tonic-gate * It is possible to have retthreadp == NULL. Proccmp() 564*7c478bd9Sstevel@tonic-gate * in the rare case (p_tlist == NULL) could return without 565*7c478bd9Sstevel@tonic-gate * setting a value for retthreadp. 566*7c478bd9Sstevel@tonic-gate */ 567*7c478bd9Sstevel@tonic-gate if (retthreadp == NULL) { 568*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&(curproc)->p_lock)); 569*7c478bd9Sstevel@tonic-gate return (set_errno(ESRCH)); 570*7c478bd9Sstevel@tonic-gate } 571*7c478bd9Sstevel@tonic-gate /* 572*7c478bd9Sstevel@tonic-gate * We've selected a thread so now get the parameters. 573*7c478bd9Sstevel@tonic-gate */ 574*7c478bd9Sstevel@tonic-gate parmsget(retthreadp, &pcparms); 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate /* 577*7c478bd9Sstevel@tonic-gate * Prepare to return parameters to the user 578*7c478bd9Sstevel@tonic-gate */ 579*7c478bd9Sstevel@tonic-gate error = parmsout(&pcparms, 580*7c478bd9Sstevel@tonic-gate (cmd == PC_GETPARMS ? NULL : &vaparms)); 581*7c478bd9Sstevel@tonic-gate 582*7c478bd9Sstevel@tonic-gate /* 583*7c478bd9Sstevel@tonic-gate * Save pid of selected thread before dropping p_lock. 584*7c478bd9Sstevel@tonic-gate */ 585*7c478bd9Sstevel@tonic-gate saved_pid = ttoproc(retthreadp)->p_pid; 586*7c478bd9Sstevel@tonic-gate mutex_exit(&(ttoproc(retthreadp)->p_lock)); 587*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&curproc->p_lock)); 588*7c478bd9Sstevel@tonic-gate 589*7c478bd9Sstevel@tonic-gate if (error) 590*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 591*7c478bd9Sstevel@tonic-gate 592*7c478bd9Sstevel@tonic-gate if (cmd == PC_GETPARMS) { 593*7c478bd9Sstevel@tonic-gate if (copyout(&pcparms, arg, sizeof (pcparms))) 594*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 595*7c478bd9Sstevel@tonic-gate } else if ((error = vaparmsout(arg, &pcparms, &vaparms)) != 0) 596*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 597*7c478bd9Sstevel@tonic-gate 598*7c478bd9Sstevel@tonic-gate /* 599*7c478bd9Sstevel@tonic-gate * And finally, return the pid of the selected thread. 600*7c478bd9Sstevel@tonic-gate */ 601*7c478bd9Sstevel@tonic-gate rv = saved_pid; 602*7c478bd9Sstevel@tonic-gate break; 603*7c478bd9Sstevel@tonic-gate 604*7c478bd9Sstevel@tonic-gate case PC_ADMIN: 605*7c478bd9Sstevel@tonic-gate if (get_udatamodel() == DATAMODEL_NATIVE) { 606*7c478bd9Sstevel@tonic-gate if (copyin(arg, &pcadmin, sizeof (pcadmin_t))) 607*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 608*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 609*7c478bd9Sstevel@tonic-gate } else { 610*7c478bd9Sstevel@tonic-gate /* pcadmin struct from ILP32 callers */ 611*7c478bd9Sstevel@tonic-gate pcadmin32_t pcadmin32; 612*7c478bd9Sstevel@tonic-gate 613*7c478bd9Sstevel@tonic-gate if (copyin(arg, &pcadmin32, sizeof (pcadmin32_t))) 614*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 615*7c478bd9Sstevel@tonic-gate pcadmin.pc_cid = pcadmin32.pc_cid; 616*7c478bd9Sstevel@tonic-gate pcadmin.pc_cladmin = (caddr_t)(uintptr_t) 617*7c478bd9Sstevel@tonic-gate pcadmin32.pc_cladmin; 618*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 619*7c478bd9Sstevel@tonic-gate } 620*7c478bd9Sstevel@tonic-gate 621*7c478bd9Sstevel@tonic-gate if (pcadmin.pc_cid >= loaded_classes || 622*7c478bd9Sstevel@tonic-gate pcadmin.pc_cid < 1) 623*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 624*7c478bd9Sstevel@tonic-gate 625*7c478bd9Sstevel@tonic-gate /* 626*7c478bd9Sstevel@tonic-gate * Have the class do whatever the user is requesting. 627*7c478bd9Sstevel@tonic-gate */ 628*7c478bd9Sstevel@tonic-gate mutex_enter(&ualock); 629*7c478bd9Sstevel@tonic-gate error = CL_ADMIN(&sclass[pcadmin.pc_cid], pcadmin.pc_cladmin, 630*7c478bd9Sstevel@tonic-gate CRED()); 631*7c478bd9Sstevel@tonic-gate mutex_exit(&ualock); 632*7c478bd9Sstevel@tonic-gate break; 633*7c478bd9Sstevel@tonic-gate 634*7c478bd9Sstevel@tonic-gate case PC_GETPRIRANGE: 635*7c478bd9Sstevel@tonic-gate if (copyin(arg, &pcpri, sizeof (pcpri_t))) 636*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 637*7c478bd9Sstevel@tonic-gate 638*7c478bd9Sstevel@tonic-gate if (pcpri.pc_cid >= loaded_classes || pcpri.pc_cid < 0) 639*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 640*7c478bd9Sstevel@tonic-gate 641*7c478bd9Sstevel@tonic-gate error = CL_GETCLPRI(&sclass[pcpri.pc_cid], &pcpri); 642*7c478bd9Sstevel@tonic-gate if (!error) { 643*7c478bd9Sstevel@tonic-gate if (copyout(&pcpri, arg, sizeof (pcpri))) 644*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 645*7c478bd9Sstevel@tonic-gate } 646*7c478bd9Sstevel@tonic-gate break; 647*7c478bd9Sstevel@tonic-gate 648*7c478bd9Sstevel@tonic-gate case PC_DONICE: 649*7c478bd9Sstevel@tonic-gate /* 650*7c478bd9Sstevel@tonic-gate * Get pcnice and procset structures from the user. 651*7c478bd9Sstevel@tonic-gate */ 652*7c478bd9Sstevel@tonic-gate if (copyin(arg, &pcnice, sizeof (pcnice)) || 653*7c478bd9Sstevel@tonic-gate copyin(psp, &procset, sizeof (procset))) 654*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 655*7c478bd9Sstevel@tonic-gate 656*7c478bd9Sstevel@tonic-gate error = donice(&procset, &pcnice); 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate if (!error && (pcnice.pc_op == PC_GETNICE)) { 659*7c478bd9Sstevel@tonic-gate if (copyout(&pcnice, arg, sizeof (pcnice))) 660*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 661*7c478bd9Sstevel@tonic-gate } 662*7c478bd9Sstevel@tonic-gate break; 663*7c478bd9Sstevel@tonic-gate 664*7c478bd9Sstevel@tonic-gate case PC_SETDFLCL: 665*7c478bd9Sstevel@tonic-gate if (secpolicy_dispadm(CRED()) != 0) 666*7c478bd9Sstevel@tonic-gate return (set_errno(EPERM)); 667*7c478bd9Sstevel@tonic-gate 668*7c478bd9Sstevel@tonic-gate if (copyin(arg, (caddr_t)clname, PC_CLNMSZ) != 0) 669*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 670*7c478bd9Sstevel@tonic-gate clname[PC_CLNMSZ-1] = '\0'; 671*7c478bd9Sstevel@tonic-gate 672*7c478bd9Sstevel@tonic-gate if (getcid(clname, &classid) != 0) 673*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 674*7c478bd9Sstevel@tonic-gate if (classid == syscid) 675*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 676*7c478bd9Sstevel@tonic-gate defaultcid = classid; 677*7c478bd9Sstevel@tonic-gate ASSERT(defaultcid > 0 && defaultcid < loaded_classes); 678*7c478bd9Sstevel@tonic-gate break; 679*7c478bd9Sstevel@tonic-gate 680*7c478bd9Sstevel@tonic-gate default: 681*7c478bd9Sstevel@tonic-gate error = EINVAL; 682*7c478bd9Sstevel@tonic-gate break; 683*7c478bd9Sstevel@tonic-gate } 684*7c478bd9Sstevel@tonic-gate return (error ? (set_errno(error)) : rv); 685*7c478bd9Sstevel@tonic-gate } 686*7c478bd9Sstevel@tonic-gate 687*7c478bd9Sstevel@tonic-gate 688*7c478bd9Sstevel@tonic-gate /* 689*7c478bd9Sstevel@tonic-gate * The proccmp() function is part of the implementation of the 690*7c478bd9Sstevel@tonic-gate * PC_GETPARMS command of the priocntl system call. This function works 691*7c478bd9Sstevel@tonic-gate * with the system call code and with the class specific cl_globpri() 692*7c478bd9Sstevel@tonic-gate * function to select one thread from a specified procset based on class 693*7c478bd9Sstevel@tonic-gate * specific criteria. proccmp() is called indirectly from the priocntl 694*7c478bd9Sstevel@tonic-gate * code through the dotoprocs function. Basic strategy is dotoprocs() 695*7c478bd9Sstevel@tonic-gate * calls us once for each thread in the set. We in turn call the class 696*7c478bd9Sstevel@tonic-gate * specific function to compare the current thread from dotoprocs to the 697*7c478bd9Sstevel@tonic-gate * "best" (according to the class criteria) found so far. We keep the 698*7c478bd9Sstevel@tonic-gate * "best" thread in *pcmp_retthreadp. 699*7c478bd9Sstevel@tonic-gate */ 700*7c478bd9Sstevel@tonic-gate static int 701*7c478bd9Sstevel@tonic-gate proccmp(proc_t *pp, struct pcmpargs *argp) 702*7c478bd9Sstevel@tonic-gate { 703*7c478bd9Sstevel@tonic-gate kthread_id_t tx, ty; 704*7c478bd9Sstevel@tonic-gate int last_pri = -1; 705*7c478bd9Sstevel@tonic-gate int tx_pri; 706*7c478bd9Sstevel@tonic-gate int found = 0; 707*7c478bd9Sstevel@tonic-gate 708*7c478bd9Sstevel@tonic-gate mutex_enter(&pp->p_lock); 709*7c478bd9Sstevel@tonic-gate 710*7c478bd9Sstevel@tonic-gate if (pp->p_tlist == NULL) { 711*7c478bd9Sstevel@tonic-gate mutex_exit(&pp->p_lock); 712*7c478bd9Sstevel@tonic-gate return (0); 713*7c478bd9Sstevel@tonic-gate } 714*7c478bd9Sstevel@tonic-gate (*argp->pcmp_cntp)++; /* Increment count of procs in the set */ 715*7c478bd9Sstevel@tonic-gate 716*7c478bd9Sstevel@tonic-gate if (*argp->pcmp_cidp == PC_CLNULL) { 717*7c478bd9Sstevel@tonic-gate /* 718*7c478bd9Sstevel@tonic-gate * If no cid is specified, then lets just pick the first one. 719*7c478bd9Sstevel@tonic-gate * It doesn't matter because if the number of processes in the 720*7c478bd9Sstevel@tonic-gate * set are more than 1, then we return EINVAL in priocntlsys. 721*7c478bd9Sstevel@tonic-gate */ 722*7c478bd9Sstevel@tonic-gate *argp->pcmp_cidp = pp->p_tlist->t_cid; 723*7c478bd9Sstevel@tonic-gate } 724*7c478bd9Sstevel@tonic-gate ty = tx = pp->p_tlist; 725*7c478bd9Sstevel@tonic-gate do { 726*7c478bd9Sstevel@tonic-gate if (tx->t_cid == *argp->pcmp_cidp) { 727*7c478bd9Sstevel@tonic-gate /* 728*7c478bd9Sstevel@tonic-gate * We found one which matches the required cid. 729*7c478bd9Sstevel@tonic-gate */ 730*7c478bd9Sstevel@tonic-gate found = 1; 731*7c478bd9Sstevel@tonic-gate if ((tx_pri = CL_GLOBPRI(tx)) > last_pri) { 732*7c478bd9Sstevel@tonic-gate last_pri = tx_pri; 733*7c478bd9Sstevel@tonic-gate ty = tx; 734*7c478bd9Sstevel@tonic-gate } 735*7c478bd9Sstevel@tonic-gate } 736*7c478bd9Sstevel@tonic-gate } while ((tx = tx->t_forw) != pp->p_tlist); 737*7c478bd9Sstevel@tonic-gate if (found) { 738*7c478bd9Sstevel@tonic-gate if (*argp->pcmp_retthreadp == NULL) { 739*7c478bd9Sstevel@tonic-gate /* 740*7c478bd9Sstevel@tonic-gate * First time through for this set. 741*7c478bd9Sstevel@tonic-gate * keep the mutex held. He might be the one! 742*7c478bd9Sstevel@tonic-gate */ 743*7c478bd9Sstevel@tonic-gate *argp->pcmp_retthreadp = ty; 744*7c478bd9Sstevel@tonic-gate } else { 745*7c478bd9Sstevel@tonic-gate tx = *argp->pcmp_retthreadp; 746*7c478bd9Sstevel@tonic-gate if (CL_GLOBPRI(ty) <= CL_GLOBPRI(tx)) { 747*7c478bd9Sstevel@tonic-gate mutex_exit(&pp->p_lock); 748*7c478bd9Sstevel@tonic-gate } else { 749*7c478bd9Sstevel@tonic-gate mutex_exit(&(ttoproc(tx)->p_lock)); 750*7c478bd9Sstevel@tonic-gate *argp->pcmp_retthreadp = ty; 751*7c478bd9Sstevel@tonic-gate } 752*7c478bd9Sstevel@tonic-gate } 753*7c478bd9Sstevel@tonic-gate } else { 754*7c478bd9Sstevel@tonic-gate /* 755*7c478bd9Sstevel@tonic-gate * We actually didn't find anything of the same cid in 756*7c478bd9Sstevel@tonic-gate * this process. 757*7c478bd9Sstevel@tonic-gate */ 758*7c478bd9Sstevel@tonic-gate mutex_exit(&pp->p_lock); 759*7c478bd9Sstevel@tonic-gate } 760*7c478bd9Sstevel@tonic-gate return (0); 761*7c478bd9Sstevel@tonic-gate } 762*7c478bd9Sstevel@tonic-gate 763*7c478bd9Sstevel@tonic-gate 764*7c478bd9Sstevel@tonic-gate int 765*7c478bd9Sstevel@tonic-gate threadcmp(struct pcmpargs *argp, kthread_id_t tp) 766*7c478bd9Sstevel@tonic-gate { 767*7c478bd9Sstevel@tonic-gate kthread_id_t tx; 768*7c478bd9Sstevel@tonic-gate proc_t *pp; 769*7c478bd9Sstevel@tonic-gate 770*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&(ttoproc(tp))->p_lock)); 771*7c478bd9Sstevel@tonic-gate 772*7c478bd9Sstevel@tonic-gate (*argp->pcmp_cntp)++; /* Increment count of procs in the set */ 773*7c478bd9Sstevel@tonic-gate if (*argp->pcmp_cidp == PC_CLNULL) { 774*7c478bd9Sstevel@tonic-gate /* 775*7c478bd9Sstevel@tonic-gate * If no cid is specified, then lets just pick the first one. 776*7c478bd9Sstevel@tonic-gate * It doesn't matter because if the number of threads in the 777*7c478bd9Sstevel@tonic-gate * set are more than 1, then we return EINVAL in priocntlsys. 778*7c478bd9Sstevel@tonic-gate */ 779*7c478bd9Sstevel@tonic-gate *argp->pcmp_cidp = tp->t_cid; 780*7c478bd9Sstevel@tonic-gate } 781*7c478bd9Sstevel@tonic-gate if (tp->t_cid == *argp->pcmp_cidp) { 782*7c478bd9Sstevel@tonic-gate if (*argp->pcmp_retthreadp == NULL) { 783*7c478bd9Sstevel@tonic-gate /* 784*7c478bd9Sstevel@tonic-gate * First time through for this set. 785*7c478bd9Sstevel@tonic-gate */ 786*7c478bd9Sstevel@tonic-gate *argp->pcmp_retthreadp = tp; 787*7c478bd9Sstevel@tonic-gate } else { 788*7c478bd9Sstevel@tonic-gate tx = *argp->pcmp_retthreadp; 789*7c478bd9Sstevel@tonic-gate if (CL_GLOBPRI(tp) > CL_GLOBPRI(tx)) { 790*7c478bd9Sstevel@tonic-gate /* 791*7c478bd9Sstevel@tonic-gate * Unlike proccmp(), we don't release the 792*7c478bd9Sstevel@tonic-gate * p_lock of the ttoproc(tp) if tp's global 793*7c478bd9Sstevel@tonic-gate * priority is less than tx's. We need to go 794*7c478bd9Sstevel@tonic-gate * through the entire list before we can do 795*7c478bd9Sstevel@tonic-gate * that. The p_lock is released by the caller 796*7c478bd9Sstevel@tonic-gate * of dotolwp(). 797*7c478bd9Sstevel@tonic-gate */ 798*7c478bd9Sstevel@tonic-gate pp = ttoproc(tx); 799*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&pp->p_lock)); 800*7c478bd9Sstevel@tonic-gate if (pp != curproc) { 801*7c478bd9Sstevel@tonic-gate mutex_exit(&pp->p_lock); 802*7c478bd9Sstevel@tonic-gate } 803*7c478bd9Sstevel@tonic-gate *argp->pcmp_retthreadp = tp; 804*7c478bd9Sstevel@tonic-gate } 805*7c478bd9Sstevel@tonic-gate } 806*7c478bd9Sstevel@tonic-gate } 807*7c478bd9Sstevel@tonic-gate return (0); 808*7c478bd9Sstevel@tonic-gate } 809*7c478bd9Sstevel@tonic-gate 810*7c478bd9Sstevel@tonic-gate 811*7c478bd9Sstevel@tonic-gate /* 812*7c478bd9Sstevel@tonic-gate * The setparms() function is called indirectly by priocntlsys() 813*7c478bd9Sstevel@tonic-gate * through the dotoprocs() function. setparms() acts as an 814*7c478bd9Sstevel@tonic-gate * intermediary between dotoprocs() and the parmsset() function, 815*7c478bd9Sstevel@tonic-gate * calling parmsset() for each thread in the set and handling 816*7c478bd9Sstevel@tonic-gate * the error returns on their way back up to dotoprocs(). 817*7c478bd9Sstevel@tonic-gate */ 818*7c478bd9Sstevel@tonic-gate static int 819*7c478bd9Sstevel@tonic-gate setparms(proc_t *targpp, struct stprmargs *stprmp) 820*7c478bd9Sstevel@tonic-gate { 821*7c478bd9Sstevel@tonic-gate int error = 0; 822*7c478bd9Sstevel@tonic-gate kthread_id_t t; 823*7c478bd9Sstevel@tonic-gate int err; 824*7c478bd9Sstevel@tonic-gate 825*7c478bd9Sstevel@tonic-gate mutex_enter(&targpp->p_lock); 826*7c478bd9Sstevel@tonic-gate if ((t = targpp->p_tlist) == NULL) { 827*7c478bd9Sstevel@tonic-gate mutex_exit(&targpp->p_lock); 828*7c478bd9Sstevel@tonic-gate return (0); 829*7c478bd9Sstevel@tonic-gate } 830*7c478bd9Sstevel@tonic-gate do { 831*7c478bd9Sstevel@tonic-gate err = parmsset(stprmp->stp_parmsp, t); 832*7c478bd9Sstevel@tonic-gate if (error == 0) 833*7c478bd9Sstevel@tonic-gate error = err; 834*7c478bd9Sstevel@tonic-gate } while ((t = t->t_forw) != targpp->p_tlist); 835*7c478bd9Sstevel@tonic-gate mutex_exit(&targpp->p_lock); 836*7c478bd9Sstevel@tonic-gate if (error) { 837*7c478bd9Sstevel@tonic-gate if (error == EPERM) { 838*7c478bd9Sstevel@tonic-gate stprmp->stp_error = EPERM; 839*7c478bd9Sstevel@tonic-gate return (0); 840*7c478bd9Sstevel@tonic-gate } else { 841*7c478bd9Sstevel@tonic-gate return (error); 842*7c478bd9Sstevel@tonic-gate } 843*7c478bd9Sstevel@tonic-gate } else 844*7c478bd9Sstevel@tonic-gate return (0); 845*7c478bd9Sstevel@tonic-gate } 846*7c478bd9Sstevel@tonic-gate 847*7c478bd9Sstevel@tonic-gate static int 848*7c478bd9Sstevel@tonic-gate setthreadnice(pcnice_t *pcnice, kthread_t *tp) 849*7c478bd9Sstevel@tonic-gate { 850*7c478bd9Sstevel@tonic-gate int error = 0; 851*7c478bd9Sstevel@tonic-gate int nice; 852*7c478bd9Sstevel@tonic-gate int inc; 853*7c478bd9Sstevel@tonic-gate id_t rtcid; 854*7c478bd9Sstevel@tonic-gate 855*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&pidlock)); 856*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&(ttoproc(tp)->p_lock))); 857*7c478bd9Sstevel@tonic-gate 858*7c478bd9Sstevel@tonic-gate /* 859*7c478bd9Sstevel@tonic-gate * The XPG5 standard requires that any realtime process or thread 860*7c478bd9Sstevel@tonic-gate * must be unaffected by a call to setpriority(). 861*7c478bd9Sstevel@tonic-gate */ 862*7c478bd9Sstevel@tonic-gate error = getcidbyname("RT", &rtcid); 863*7c478bd9Sstevel@tonic-gate if ((error == 0) && (tp->t_cid == rtcid)) { 864*7c478bd9Sstevel@tonic-gate if (pcnice->pc_op == PC_SETNICE) 865*7c478bd9Sstevel@tonic-gate return (error); 866*7c478bd9Sstevel@tonic-gate } 867*7c478bd9Sstevel@tonic-gate 868*7c478bd9Sstevel@tonic-gate if ((error = CL_DONICE(tp, CRED(), 0, &nice)) != 0) 869*7c478bd9Sstevel@tonic-gate return (error); 870*7c478bd9Sstevel@tonic-gate 871*7c478bd9Sstevel@tonic-gate if (pcnice->pc_op == PC_GETNICE) { 872*7c478bd9Sstevel@tonic-gate /* 873*7c478bd9Sstevel@tonic-gate * If there is no change to priority, we should return the 874*7c478bd9Sstevel@tonic-gate * highest priority (lowest numerical value) pertaining to 875*7c478bd9Sstevel@tonic-gate * any of the specified threads. 876*7c478bd9Sstevel@tonic-gate */ 877*7c478bd9Sstevel@tonic-gate if (nice < pcnice->pc_val) 878*7c478bd9Sstevel@tonic-gate pcnice->pc_val = nice; 879*7c478bd9Sstevel@tonic-gate } else { 880*7c478bd9Sstevel@tonic-gate ASSERT(pcnice->pc_op == PC_SETNICE); 881*7c478bd9Sstevel@tonic-gate /* 882*7c478bd9Sstevel@tonic-gate * Try to change the nice value of the thread. 883*7c478bd9Sstevel@tonic-gate */ 884*7c478bd9Sstevel@tonic-gate inc = pcnice->pc_val - nice; 885*7c478bd9Sstevel@tonic-gate 886*7c478bd9Sstevel@tonic-gate error = CL_DONICE(tp, CRED(), inc, &inc); 887*7c478bd9Sstevel@tonic-gate } 888*7c478bd9Sstevel@tonic-gate 889*7c478bd9Sstevel@tonic-gate return (error); 890*7c478bd9Sstevel@tonic-gate } 891*7c478bd9Sstevel@tonic-gate 892*7c478bd9Sstevel@tonic-gate static int 893*7c478bd9Sstevel@tonic-gate setprocnice(proc_t *pp, pcnice_t *pcnice) 894*7c478bd9Sstevel@tonic-gate { 895*7c478bd9Sstevel@tonic-gate kthread_t *tp; 896*7c478bd9Sstevel@tonic-gate int retval = 0; 897*7c478bd9Sstevel@tonic-gate int error = 0; 898*7c478bd9Sstevel@tonic-gate 899*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&pidlock)); 900*7c478bd9Sstevel@tonic-gate mutex_enter(&pp->p_lock); 901*7c478bd9Sstevel@tonic-gate 902*7c478bd9Sstevel@tonic-gate if ((tp = pp->p_tlist) == NULL) { 903*7c478bd9Sstevel@tonic-gate mutex_exit(&pp->p_lock); 904*7c478bd9Sstevel@tonic-gate return (ESRCH); 905*7c478bd9Sstevel@tonic-gate } 906*7c478bd9Sstevel@tonic-gate 907*7c478bd9Sstevel@tonic-gate /* 908*7c478bd9Sstevel@tonic-gate * Check permissions before changing the nice value. 909*7c478bd9Sstevel@tonic-gate */ 910*7c478bd9Sstevel@tonic-gate if (pcnice->pc_op == PC_SETNICE) { 911*7c478bd9Sstevel@tonic-gate if (!prochasprocperm(pp, curproc, CRED())) { 912*7c478bd9Sstevel@tonic-gate mutex_exit(&pp->p_lock); 913*7c478bd9Sstevel@tonic-gate return (EPERM); 914*7c478bd9Sstevel@tonic-gate } 915*7c478bd9Sstevel@tonic-gate } 916*7c478bd9Sstevel@tonic-gate 917*7c478bd9Sstevel@tonic-gate do { 918*7c478bd9Sstevel@tonic-gate error = setthreadnice(pcnice, tp); 919*7c478bd9Sstevel@tonic-gate if (error) 920*7c478bd9Sstevel@tonic-gate retval = error; 921*7c478bd9Sstevel@tonic-gate } while ((tp = tp->t_forw) != pp->p_tlist); 922*7c478bd9Sstevel@tonic-gate 923*7c478bd9Sstevel@tonic-gate mutex_exit(&pp->p_lock); 924*7c478bd9Sstevel@tonic-gate return (retval); 925*7c478bd9Sstevel@tonic-gate } 926*7c478bd9Sstevel@tonic-gate 927*7c478bd9Sstevel@tonic-gate /* 928*7c478bd9Sstevel@tonic-gate * Update the nice value of the specified LWP or set of processes. 929*7c478bd9Sstevel@tonic-gate */ 930*7c478bd9Sstevel@tonic-gate static int 931*7c478bd9Sstevel@tonic-gate donice(procset_t *procset, pcnice_t *pcnice) 932*7c478bd9Sstevel@tonic-gate { 933*7c478bd9Sstevel@tonic-gate int err_proc = 0; 934*7c478bd9Sstevel@tonic-gate int err_thread = 0; 935*7c478bd9Sstevel@tonic-gate int err = 0; 936*7c478bd9Sstevel@tonic-gate 937*7c478bd9Sstevel@tonic-gate /* 938*7c478bd9Sstevel@tonic-gate * Sanity check. 939*7c478bd9Sstevel@tonic-gate */ 940*7c478bd9Sstevel@tonic-gate if (pcnice->pc_op != PC_GETNICE && pcnice->pc_op != PC_SETNICE) 941*7c478bd9Sstevel@tonic-gate return (EINVAL); 942*7c478bd9Sstevel@tonic-gate 943*7c478bd9Sstevel@tonic-gate /* 944*7c478bd9Sstevel@tonic-gate * If it is PC_GETNICE operation then set pc_val to the largest 945*7c478bd9Sstevel@tonic-gate * possible nice value to help us find the lowest nice value 946*7c478bd9Sstevel@tonic-gate * pertaining to any of the specified processes. 947*7c478bd9Sstevel@tonic-gate */ 948*7c478bd9Sstevel@tonic-gate if (pcnice->pc_op == PC_GETNICE) 949*7c478bd9Sstevel@tonic-gate pcnice->pc_val = NZERO; 950*7c478bd9Sstevel@tonic-gate 951*7c478bd9Sstevel@tonic-gate if (procset->p_lidtype != P_LWPID || 952*7c478bd9Sstevel@tonic-gate procset->p_ridtype != P_LWPID) 953*7c478bd9Sstevel@tonic-gate err_proc = dotoprocs(procset, setprocnice, (char *)pcnice); 954*7c478bd9Sstevel@tonic-gate 955*7c478bd9Sstevel@tonic-gate if (procset->p_lidtype == P_LWPID || procset->p_ridtype == P_LWPID) { 956*7c478bd9Sstevel@tonic-gate err_thread = dotolwp(procset, setthreadnice, (char *)pcnice); 957*7c478bd9Sstevel@tonic-gate /* 958*7c478bd9Sstevel@tonic-gate * dotolwp() can return with p_lock held. This is required 959*7c478bd9Sstevel@tonic-gate * for the priocntl GETPARMS case. So, here we just release 960*7c478bd9Sstevel@tonic-gate * the p_lock. 961*7c478bd9Sstevel@tonic-gate */ 962*7c478bd9Sstevel@tonic-gate if (MUTEX_HELD(&curproc->p_lock)) 963*7c478bd9Sstevel@tonic-gate mutex_exit(&curproc->p_lock); 964*7c478bd9Sstevel@tonic-gate 965*7c478bd9Sstevel@tonic-gate /* 966*7c478bd9Sstevel@tonic-gate * If we were called for a single LWP, then ignore ESRCH 967*7c478bd9Sstevel@tonic-gate * returned by the previous dotoprocs() call. 968*7c478bd9Sstevel@tonic-gate */ 969*7c478bd9Sstevel@tonic-gate if (err_proc == ESRCH) 970*7c478bd9Sstevel@tonic-gate err_proc = 0; 971*7c478bd9Sstevel@tonic-gate } 972*7c478bd9Sstevel@tonic-gate 973*7c478bd9Sstevel@tonic-gate /* 974*7c478bd9Sstevel@tonic-gate * dotoprocs() ignores the init process if it is in the set, unless 975*7c478bd9Sstevel@tonic-gate * it was the only process found. We want to make sure init is not 976*7c478bd9Sstevel@tonic-gate * excluded if we're going PC_GETNICE operation. 977*7c478bd9Sstevel@tonic-gate */ 978*7c478bd9Sstevel@tonic-gate if (pcnice->pc_op == PC_GETNICE) { 979*7c478bd9Sstevel@tonic-gate proc_t *initpp; 980*7c478bd9Sstevel@tonic-gate 981*7c478bd9Sstevel@tonic-gate mutex_enter(&pidlock); 982*7c478bd9Sstevel@tonic-gate initpp = prfind(P_INITPID); 983*7c478bd9Sstevel@tonic-gate if (initpp != NULL && procinset(initpp, procset)) 984*7c478bd9Sstevel@tonic-gate err = setprocnice(initpp, pcnice); 985*7c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 986*7c478bd9Sstevel@tonic-gate } 987*7c478bd9Sstevel@tonic-gate 988*7c478bd9Sstevel@tonic-gate /* 989*7c478bd9Sstevel@tonic-gate * We're returning the latest error here that we've got back from 990*7c478bd9Sstevel@tonic-gate * the setthreadnice() or setprocnice(). That is, err_thread and/or 991*7c478bd9Sstevel@tonic-gate * err_proc can be replaced by err. 992*7c478bd9Sstevel@tonic-gate */ 993*7c478bd9Sstevel@tonic-gate if (!err) 994*7c478bd9Sstevel@tonic-gate err = err_thread ? err_thread : err_proc; 995*7c478bd9Sstevel@tonic-gate 996*7c478bd9Sstevel@tonic-gate return (err); 997*7c478bd9Sstevel@tonic-gate } 998