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