xref: /titanic_44/usr/src/uts/common/disp/class.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/class.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/cred.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/proc.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/procset.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/disp.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate static int getcidbyname_locked(char *, id_t *);
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate /*
44*7c478bd9Sstevel@tonic-gate  * Allocate a cid given a class name if one is not already allocated.
45*7c478bd9Sstevel@tonic-gate  * Returns 0 if the cid was already exists or if the allocation of a new
46*7c478bd9Sstevel@tonic-gate  * cid was successful. Nonzero return indicates error.
47*7c478bd9Sstevel@tonic-gate  */
48*7c478bd9Sstevel@tonic-gate int
49*7c478bd9Sstevel@tonic-gate alloc_cid(char *clname, id_t *cidp)
50*7c478bd9Sstevel@tonic-gate {
51*7c478bd9Sstevel@tonic-gate 	sclass_t *clp;
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&class_lock));
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate 	/*
56*7c478bd9Sstevel@tonic-gate 	 * If the clname doesn't already have a cid, allocate one.
57*7c478bd9Sstevel@tonic-gate 	 */
58*7c478bd9Sstevel@tonic-gate 	if (getcidbyname_locked(clname, cidp) != 0) {
59*7c478bd9Sstevel@tonic-gate 		/*
60*7c478bd9Sstevel@tonic-gate 		 * Allocate a class entry and a lock for it.
61*7c478bd9Sstevel@tonic-gate 		 */
62*7c478bd9Sstevel@tonic-gate 		for (clp = sclass; clp < &sclass[nclass]; clp++)
63*7c478bd9Sstevel@tonic-gate 			if (clp->cl_name[0] == '\0' && clp->cl_lock == NULL)
64*7c478bd9Sstevel@tonic-gate 				break;
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate 		if (clp == &sclass[nclass]) {
67*7c478bd9Sstevel@tonic-gate 			return (ENOSPC);
68*7c478bd9Sstevel@tonic-gate 		}
69*7c478bd9Sstevel@tonic-gate 		*cidp = clp - &sclass[0];
70*7c478bd9Sstevel@tonic-gate 		clp->cl_lock = kmem_alloc(sizeof (krwlock_t), KM_SLEEP);
71*7c478bd9Sstevel@tonic-gate 		clp->cl_name = kmem_alloc(strlen(clname) + 1, KM_SLEEP);
72*7c478bd9Sstevel@tonic-gate 		(void) strcpy(clp->cl_name, clname);
73*7c478bd9Sstevel@tonic-gate 		rw_init(clp->cl_lock, NULL, RW_DEFAULT, NULL);
74*7c478bd9Sstevel@tonic-gate 	}
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate 	/*
77*7c478bd9Sstevel@tonic-gate 	 * At this point, *cidp will contain the index into the class
78*7c478bd9Sstevel@tonic-gate 	 * array for the given class name.
79*7c478bd9Sstevel@tonic-gate 	 */
80*7c478bd9Sstevel@tonic-gate 	return (0);
81*7c478bd9Sstevel@tonic-gate }
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate int
84*7c478bd9Sstevel@tonic-gate scheduler_load(char *clname, sclass_t *clp)
85*7c478bd9Sstevel@tonic-gate {
86*7c478bd9Sstevel@tonic-gate 	int rv = 0;
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate 	if (LOADABLE_SCHED(clp)) {
89*7c478bd9Sstevel@tonic-gate 		rw_enter(clp->cl_lock, RW_READER);
90*7c478bd9Sstevel@tonic-gate 		if (!SCHED_INSTALLED(clp)) {
91*7c478bd9Sstevel@tonic-gate 			rw_exit(clp->cl_lock);
92*7c478bd9Sstevel@tonic-gate 			if (modload("sched", clname) == -1)
93*7c478bd9Sstevel@tonic-gate 				return (EINVAL);
94*7c478bd9Sstevel@tonic-gate 			rw_enter(clp->cl_lock, RW_READER);
95*7c478bd9Sstevel@tonic-gate 			/* did we really load a scheduling class? */
96*7c478bd9Sstevel@tonic-gate 			if (!SCHED_INSTALLED(clp))
97*7c478bd9Sstevel@tonic-gate 				rv = EINVAL;
98*7c478bd9Sstevel@tonic-gate 		}
99*7c478bd9Sstevel@tonic-gate 		rw_exit(clp->cl_lock);
100*7c478bd9Sstevel@tonic-gate 	}
101*7c478bd9Sstevel@tonic-gate 	return (rv);
102*7c478bd9Sstevel@tonic-gate }
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate /*
105*7c478bd9Sstevel@tonic-gate  * Get class ID given class name.
106*7c478bd9Sstevel@tonic-gate  */
107*7c478bd9Sstevel@tonic-gate int
108*7c478bd9Sstevel@tonic-gate getcid(char *clname, id_t *cidp)
109*7c478bd9Sstevel@tonic-gate {
110*7c478bd9Sstevel@tonic-gate 	sclass_t *clp;
111*7c478bd9Sstevel@tonic-gate 	int retval;
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate 	mutex_enter(&class_lock);
114*7c478bd9Sstevel@tonic-gate 	if ((retval = alloc_cid(clname, cidp)) == 0) {
115*7c478bd9Sstevel@tonic-gate 		clp = &sclass[*cidp];
116*7c478bd9Sstevel@tonic-gate 		clp->cl_count++;
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate 		/*
119*7c478bd9Sstevel@tonic-gate 		 * If it returns zero, it's loaded & locked
120*7c478bd9Sstevel@tonic-gate 		 * or we found a statically installed scheduler
121*7c478bd9Sstevel@tonic-gate 		 * module.
122*7c478bd9Sstevel@tonic-gate 		 * If it returns EINVAL, modload() failed when
123*7c478bd9Sstevel@tonic-gate 		 * it tried to load the module.
124*7c478bd9Sstevel@tonic-gate 		 */
125*7c478bd9Sstevel@tonic-gate 		mutex_exit(&class_lock);
126*7c478bd9Sstevel@tonic-gate 		retval = scheduler_load(clname, clp);
127*7c478bd9Sstevel@tonic-gate 		mutex_enter(&class_lock);
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate 		clp->cl_count--;
130*7c478bd9Sstevel@tonic-gate 		if (retval != 0 && clp->cl_count == 0) {
131*7c478bd9Sstevel@tonic-gate 			/* last guy out of scheduler_load frees the storage */
132*7c478bd9Sstevel@tonic-gate 			kmem_free(clp->cl_name, strlen(clname) + 1);
133*7c478bd9Sstevel@tonic-gate 			kmem_free(clp->cl_lock, sizeof (krwlock_t));
134*7c478bd9Sstevel@tonic-gate 			clp->cl_name = "";
135*7c478bd9Sstevel@tonic-gate 			clp->cl_lock = (krwlock_t *)NULL;
136*7c478bd9Sstevel@tonic-gate 		}
137*7c478bd9Sstevel@tonic-gate 	}
138*7c478bd9Sstevel@tonic-gate 	mutex_exit(&class_lock);
139*7c478bd9Sstevel@tonic-gate 	return (retval);
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate }
142*7c478bd9Sstevel@tonic-gate 
143*7c478bd9Sstevel@tonic-gate static int
144*7c478bd9Sstevel@tonic-gate getcidbyname_locked(char *clname, id_t *cidp)
145*7c478bd9Sstevel@tonic-gate {
146*7c478bd9Sstevel@tonic-gate 	sclass_t *clp;
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&class_lock));
149*7c478bd9Sstevel@tonic-gate 
150*7c478bd9Sstevel@tonic-gate 	if (*clname == NULL)
151*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 	for (clp = &sclass[0]; clp < &sclass[nclass]; clp++) {
154*7c478bd9Sstevel@tonic-gate 		if (strcmp(clp->cl_name, clname) == 0) {
155*7c478bd9Sstevel@tonic-gate 			*cidp = clp - &sclass[0];
156*7c478bd9Sstevel@tonic-gate 			return (0);
157*7c478bd9Sstevel@tonic-gate 		}
158*7c478bd9Sstevel@tonic-gate 	}
159*7c478bd9Sstevel@tonic-gate 	return (EINVAL);
160*7c478bd9Sstevel@tonic-gate }
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate /*
163*7c478bd9Sstevel@tonic-gate  * Lookup a module by name.
164*7c478bd9Sstevel@tonic-gate  */
165*7c478bd9Sstevel@tonic-gate int
166*7c478bd9Sstevel@tonic-gate getcidbyname(char *clname, id_t *cidp)
167*7c478bd9Sstevel@tonic-gate {
168*7c478bd9Sstevel@tonic-gate 	int retval;
169*7c478bd9Sstevel@tonic-gate 
170*7c478bd9Sstevel@tonic-gate 	mutex_enter(&class_lock);
171*7c478bd9Sstevel@tonic-gate 	retval = getcidbyname_locked(clname, cidp);
172*7c478bd9Sstevel@tonic-gate 	mutex_exit(&class_lock);
173*7c478bd9Sstevel@tonic-gate 
174*7c478bd9Sstevel@tonic-gate 	return (retval);
175*7c478bd9Sstevel@tonic-gate }
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate /*
178*7c478bd9Sstevel@tonic-gate  * Get the scheduling parameters of the thread pointed to by
179*7c478bd9Sstevel@tonic-gate  * tp into the buffer pointed to by parmsp.
180*7c478bd9Sstevel@tonic-gate  */
181*7c478bd9Sstevel@tonic-gate void
182*7c478bd9Sstevel@tonic-gate parmsget(kthread_id_t tp, pcparms_t *parmsp)
183*7c478bd9Sstevel@tonic-gate {
184*7c478bd9Sstevel@tonic-gate 	parmsp->pc_cid = tp->t_cid;
185*7c478bd9Sstevel@tonic-gate 	CL_PARMSGET(tp, parmsp->pc_clparms);
186*7c478bd9Sstevel@tonic-gate }
187*7c478bd9Sstevel@tonic-gate 
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate /*
190*7c478bd9Sstevel@tonic-gate  * Check the validity of the scheduling parameters in the buffer
191*7c478bd9Sstevel@tonic-gate  * pointed to by parmsp.
192*7c478bd9Sstevel@tonic-gate  * Note that the format of the parameters may be changed by class
193*7c478bd9Sstevel@tonic-gate  * specific code which we call.
194*7c478bd9Sstevel@tonic-gate  */
195*7c478bd9Sstevel@tonic-gate int
196*7c478bd9Sstevel@tonic-gate parmsin(pcparms_t *parmsp, pc_vaparms_t *vaparmsp)
197*7c478bd9Sstevel@tonic-gate {
198*7c478bd9Sstevel@tonic-gate 	if (parmsp->pc_cid >= loaded_classes || parmsp->pc_cid < 1)
199*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
200*7c478bd9Sstevel@tonic-gate 
201*7c478bd9Sstevel@tonic-gate 	/*
202*7c478bd9Sstevel@tonic-gate 	 * Call the class specific routine to validate class
203*7c478bd9Sstevel@tonic-gate 	 * specific parameters.
204*7c478bd9Sstevel@tonic-gate 	 * The input parameters are either in a pcparms structure (PC_SETPARMS)
205*7c478bd9Sstevel@tonic-gate 	 * or in a variable parameter structure (PC_SETXPARMS). In the
206*7c478bd9Sstevel@tonic-gate 	 * 'PC_SETPARMS' case vaparmsp is a NULL pointer and a CL_PARMSIN()
207*7c478bd9Sstevel@tonic-gate 	 * routine gets the parameter. Otherwise vaparmsp points to a variable
208*7c478bd9Sstevel@tonic-gate 	 * parameter structure and a CL_VAPARMSIN() routine gets the parameter.
209*7c478bd9Sstevel@tonic-gate 	 */
210*7c478bd9Sstevel@tonic-gate 	if (vaparmsp != NULL)
211*7c478bd9Sstevel@tonic-gate 		return (CL_VAPARMSIN(&sclass[parmsp->pc_cid],
212*7c478bd9Sstevel@tonic-gate 		    parmsp->pc_clparms, vaparmsp));
213*7c478bd9Sstevel@tonic-gate 	else
214*7c478bd9Sstevel@tonic-gate 		return (CL_PARMSIN(&sclass[parmsp->pc_cid],
215*7c478bd9Sstevel@tonic-gate 		    parmsp->pc_clparms));
216*7c478bd9Sstevel@tonic-gate }
217*7c478bd9Sstevel@tonic-gate 
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate /*
220*7c478bd9Sstevel@tonic-gate  * Call the class specific code to do the required processing
221*7c478bd9Sstevel@tonic-gate  * before the scheduling parameters are copied out to the user.
222*7c478bd9Sstevel@tonic-gate  * Note that the format of the parameters may be changed by the
223*7c478bd9Sstevel@tonic-gate  * class specific code.
224*7c478bd9Sstevel@tonic-gate  */
225*7c478bd9Sstevel@tonic-gate int
226*7c478bd9Sstevel@tonic-gate parmsout(pcparms_t *parmsp, pc_vaparms_t *vaparmsp)
227*7c478bd9Sstevel@tonic-gate {
228*7c478bd9Sstevel@tonic-gate 	return (CL_PARMSOUT(&sclass[parmsp->pc_cid], parmsp->pc_clparms,
229*7c478bd9Sstevel@tonic-gate 		vaparmsp));
230*7c478bd9Sstevel@tonic-gate }
231*7c478bd9Sstevel@tonic-gate 
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate /*
234*7c478bd9Sstevel@tonic-gate  * Set the scheduling parameters of the thread pointed to by
235*7c478bd9Sstevel@tonic-gate  * targtp to those specified in the pcparms structure pointed
236*7c478bd9Sstevel@tonic-gate  * to by parmsp.  If reqtp is non-NULL it points to the thread
237*7c478bd9Sstevel@tonic-gate  * that initiated the request for the parameter change and indicates
238*7c478bd9Sstevel@tonic-gate  * that our caller wants us to verify that the requesting thread
239*7c478bd9Sstevel@tonic-gate  * has the appropriate permissions.
240*7c478bd9Sstevel@tonic-gate  */
241*7c478bd9Sstevel@tonic-gate int
242*7c478bd9Sstevel@tonic-gate parmsset(pcparms_t *parmsp, kthread_id_t targtp)
243*7c478bd9Sstevel@tonic-gate {
244*7c478bd9Sstevel@tonic-gate 	caddr_t	clprocp;
245*7c478bd9Sstevel@tonic-gate 	int	error;
246*7c478bd9Sstevel@tonic-gate 	cred_t	*reqpcredp;
247*7c478bd9Sstevel@tonic-gate 	proc_t	*reqpp = ttoproc(curthread);
248*7c478bd9Sstevel@tonic-gate 	proc_t	*targpp = ttoproc(targtp);
249*7c478bd9Sstevel@tonic-gate 	id_t	oldcid;
250*7c478bd9Sstevel@tonic-gate 
251*7c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&pidlock));
252*7c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&targpp->p_lock));
253*7c478bd9Sstevel@tonic-gate 	if (reqpp != NULL) {
254*7c478bd9Sstevel@tonic-gate 		mutex_enter(&reqpp->p_crlock);
255*7c478bd9Sstevel@tonic-gate 		crhold(reqpcredp = reqpp->p_cred);
256*7c478bd9Sstevel@tonic-gate 		mutex_exit(&reqpp->p_crlock);
257*7c478bd9Sstevel@tonic-gate 
258*7c478bd9Sstevel@tonic-gate 		/*
259*7c478bd9Sstevel@tonic-gate 		 * Check basic permissions.
260*7c478bd9Sstevel@tonic-gate 		 */
261*7c478bd9Sstevel@tonic-gate 		if (!prochasprocperm(targpp, reqpp, reqpcredp)) {
262*7c478bd9Sstevel@tonic-gate 			crfree(reqpcredp);
263*7c478bd9Sstevel@tonic-gate 			return (EPERM);
264*7c478bd9Sstevel@tonic-gate 		}
265*7c478bd9Sstevel@tonic-gate 	} else {
266*7c478bd9Sstevel@tonic-gate 		reqpcredp = NULL;
267*7c478bd9Sstevel@tonic-gate 	}
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate 	if (parmsp->pc_cid != targtp->t_cid) {
270*7c478bd9Sstevel@tonic-gate 		void	*bufp = NULL;
271*7c478bd9Sstevel@tonic-gate 		/*
272*7c478bd9Sstevel@tonic-gate 		 * Target thread must change to new class.
273*7c478bd9Sstevel@tonic-gate 		 */
274*7c478bd9Sstevel@tonic-gate 		clprocp = (caddr_t)targtp->t_cldata;
275*7c478bd9Sstevel@tonic-gate 		oldcid  = targtp->t_cid;
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate 		/*
278*7c478bd9Sstevel@tonic-gate 		 * Purpose: allow scheduling class to veto moves
279*7c478bd9Sstevel@tonic-gate 		 * to other classes. All the classes, except FSS,
280*7c478bd9Sstevel@tonic-gate 		 * do nothing except returning 0.
281*7c478bd9Sstevel@tonic-gate 		 */
282*7c478bd9Sstevel@tonic-gate 		error = CL_CANEXIT(targtp, reqpcredp);
283*7c478bd9Sstevel@tonic-gate 		if (error) {
284*7c478bd9Sstevel@tonic-gate 			/*
285*7c478bd9Sstevel@tonic-gate 			 * Not allowed to leave the class, so return error.
286*7c478bd9Sstevel@tonic-gate 			 */
287*7c478bd9Sstevel@tonic-gate 			crfree(reqpcredp);
288*7c478bd9Sstevel@tonic-gate 			return (error);
289*7c478bd9Sstevel@tonic-gate 		} else {
290*7c478bd9Sstevel@tonic-gate 			/*
291*7c478bd9Sstevel@tonic-gate 			 * Pre-allocate scheduling class data.
292*7c478bd9Sstevel@tonic-gate 			 */
293*7c478bd9Sstevel@tonic-gate 			if (CL_ALLOC(&bufp, parmsp->pc_cid, KM_NOSLEEP) != 0) {
294*7c478bd9Sstevel@tonic-gate 				error = ENOMEM; /* no memory available */
295*7c478bd9Sstevel@tonic-gate 				crfree(reqpcredp);
296*7c478bd9Sstevel@tonic-gate 				return (error);
297*7c478bd9Sstevel@tonic-gate 			} else {
298*7c478bd9Sstevel@tonic-gate 				error = CL_ENTERCLASS(targtp, parmsp->pc_cid,
299*7c478bd9Sstevel@tonic-gate 				    parmsp->pc_clparms, reqpcredp, bufp);
300*7c478bd9Sstevel@tonic-gate 				crfree(reqpcredp);
301*7c478bd9Sstevel@tonic-gate 				if (error) {
302*7c478bd9Sstevel@tonic-gate 					CL_FREE(parmsp->pc_cid, bufp);
303*7c478bd9Sstevel@tonic-gate 					return (error);
304*7c478bd9Sstevel@tonic-gate 				}
305*7c478bd9Sstevel@tonic-gate 			}
306*7c478bd9Sstevel@tonic-gate 		}
307*7c478bd9Sstevel@tonic-gate 		CL_EXITCLASS(oldcid, clprocp);
308*7c478bd9Sstevel@tonic-gate 	} else {
309*7c478bd9Sstevel@tonic-gate 
310*7c478bd9Sstevel@tonic-gate 		/*
311*7c478bd9Sstevel@tonic-gate 		 * Not changing class
312*7c478bd9Sstevel@tonic-gate 		 */
313*7c478bd9Sstevel@tonic-gate 		error = CL_PARMSSET(targtp, parmsp->pc_clparms,
314*7c478bd9Sstevel@tonic-gate 					curthread->t_cid, reqpcredp);
315*7c478bd9Sstevel@tonic-gate 		crfree(reqpcredp);
316*7c478bd9Sstevel@tonic-gate 		if (error)
317*7c478bd9Sstevel@tonic-gate 			return (error);
318*7c478bd9Sstevel@tonic-gate 	}
319*7c478bd9Sstevel@tonic-gate 	return (0);
320*7c478bd9Sstevel@tonic-gate }
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate /*
324*7c478bd9Sstevel@tonic-gate  * Copy all selected class parameters to the user.
325*7c478bd9Sstevel@tonic-gate  * The parameters are specified by a key.
326*7c478bd9Sstevel@tonic-gate  */
327*7c478bd9Sstevel@tonic-gate int
328*7c478bd9Sstevel@tonic-gate vaparmsout(char *classp, pcparms_t *prmsp, pc_vaparms_t *vaparmsp)
329*7c478bd9Sstevel@tonic-gate {
330*7c478bd9Sstevel@tonic-gate 	char	*clname;
331*7c478bd9Sstevel@tonic-gate 
332*7c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&curproc->p_lock));
333*7c478bd9Sstevel@tonic-gate 
334*7c478bd9Sstevel@tonic-gate 	if (classp != NULL)
335*7c478bd9Sstevel@tonic-gate 		return (CL_VAPARMSOUT(&sclass[prmsp->pc_cid],
336*7c478bd9Sstevel@tonic-gate 		    prmsp->pc_clparms, vaparmsp));
337*7c478bd9Sstevel@tonic-gate 
338*7c478bd9Sstevel@tonic-gate 	switch (vaparmsp->pc_vaparmscnt) {
339*7c478bd9Sstevel@tonic-gate 	case 0:
340*7c478bd9Sstevel@tonic-gate 		return (0);
341*7c478bd9Sstevel@tonic-gate 	case 1:
342*7c478bd9Sstevel@tonic-gate 		break;
343*7c478bd9Sstevel@tonic-gate 	default:
344*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
345*7c478bd9Sstevel@tonic-gate 	}
346*7c478bd9Sstevel@tonic-gate 
347*7c478bd9Sstevel@tonic-gate 	if (vaparmsp->pc_parms[0].pc_key != PC_KY_CLNAME)
348*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
349*7c478bd9Sstevel@tonic-gate 
350*7c478bd9Sstevel@tonic-gate 	clname = sclass[prmsp->pc_cid].cl_name;
351*7c478bd9Sstevel@tonic-gate 	if (copyout(clname, (void *)(uintptr_t)vaparmsp->pc_parms[0].pc_parm,
352*7c478bd9Sstevel@tonic-gate 	    MIN(strlen(clname) + 1, PC_CLNMSZ)))
353*7c478bd9Sstevel@tonic-gate 		return (EFAULT);
354*7c478bd9Sstevel@tonic-gate 
355*7c478bd9Sstevel@tonic-gate 	return (0);
356*7c478bd9Sstevel@tonic-gate }
357