#include <sys/types.h>
#include <sys/param.h>
#include <sys/sysmacros.h>
#include <sys/signal.h>
#include <sys/pcb.h>
#include <sys/user.h>
#include <sys/systm.h>
#include <sys/sysinfo.h>
#include <sys/var.h>
#include <sys/errno.h>
#include <sys/cred.h>
#include <sys/proc.h>
#include <sys/procset.h>
#include <sys/debug.h>
#include <sys/inline.h>
#include <sys/priocntl.h>
#include <sys/disp.h>
#include <sys/class.h>
#include <sys/modctl.h>
#include <sys/t_lock.h>
#include <sys/uadmin.h>
#include <sys/cmn_err.h>
#include <sys/policy.h>
#include <sys/schedctl.h>
struct pcmpargs {
id_t *pcmp_cidp;
int *pcmp_cntp;
kthread_t **pcmp_retthreadp;
};
struct stprmargs {
struct pcparms *stp_parmsp;
int stp_error;
};
#if defined(_SYSCALL32_IMPL) && _LONG_LONG_ALIGNMENT_32 == 4
static int
copyin_vaparms32(caddr_t arg, pc_vaparms_t *vap, uio_seg_t seg)
{
pc_vaparms32_t vaparms32;
pc_vaparm32_t *src;
pc_vaparm_t *dst;
uint_t cnt;
ASSERT(get_udatamodel() == DATAMODEL_ILP32);
if ((seg == UIO_USERSPACE ? copyin : kcopy)(arg, &vaparms32,
sizeof (vaparms32)))
return (EFAULT);
vap->pc_vaparmscnt = vaparms32.pc_vaparmscnt;
if ((cnt = vaparms32.pc_vaparmscnt) > PC_VAPARMCNT)
cnt = PC_VAPARMCNT;
for (src = vaparms32.pc_parms, dst = vap->pc_parms;
cnt--; src++, dst++) {
dst->pc_key = src->pc_key;
dst->pc_parm = src->pc_parm;
}
return (0);
}
#define COPYIN_VAPARMS(arg, vap, size, seg) \
(get_udatamodel() == DATAMODEL_NATIVE ? \
(*copyinfn)(arg, vap, size) : copyin_vaparms32(arg, vap, seg))
#else
#define COPYIN_VAPARMS(arg, vap, size, seg) (*copyinfn)(arg, vap, size)
#endif
static int donice(procset_t *, pcnice_t *);
static int doprio(procset_t *, pcprio_t *);
static int proccmp(proc_t *, struct pcmpargs *);
static int setparms(proc_t *, struct stprmargs *);
extern int threadcmp(struct pcmpargs *, kthread_t *);
long
priocntl_common(int pc_version, procset_t *psp, int cmd, caddr_t arg,
caddr_t arg2, uio_seg_t seg)
{
pcinfo_t pcinfo;
pcparms_t pcparms;
pcnice_t pcnice;
pcprio_t pcprio;
pcadmin_t pcadmin;
pcpri_t pcpri;
procset_t procset;
struct stprmargs stprmargs;
struct pcmpargs pcmpargs;
pc_vaparms_t vaparms;
char clname[PC_CLNMSZ];
char *outstr;
int count;
kthread_t *retthreadp;
proc_t *initpp;
int clnullflag;
int error = 0;
int error1 = 0;
int rv = 0;
pid_t saved_pid;
id_t classid;
int size;
int (*copyinfn)(const void *, void *, size_t);
int (*copyoutfn)(const void *, void *, size_t);
if (pc_version != PC_VERSION)
return (set_errno(EINVAL));
if (seg == UIO_USERSPACE) {
copyinfn = copyin;
copyoutfn = copyout;
} else {
copyinfn = kcopy;
copyoutfn = kcopy;
}
switch (cmd) {
case PC_GETCID:
if (arg == NULL) {
rv = loaded_classes;
break;
} else {
if ((*copyinfn)(arg, &pcinfo, sizeof (pcinfo)))
return (set_errno(EFAULT));
}
pcinfo.pc_clname[PC_CLNMSZ-1] = '\0';
error = getcid(pcinfo.pc_clname, &pcinfo.pc_cid);
if (error)
return (set_errno(error));
if (pcinfo.pc_cid == 0)
return (set_errno(EINVAL));
error =
scheduler_load(pcinfo.pc_clname, &sclass[pcinfo.pc_cid]);
if (error)
return (set_errno(error));
error = CL_GETCLINFO(&sclass[pcinfo.pc_cid], pcinfo.pc_clinfo);
if (error)
return (set_errno(error));
if ((*copyoutfn)(&pcinfo, arg, sizeof (pcinfo)))
return (set_errno(EFAULT));
rv = loaded_classes;
break;
case PC_GETCLINFO:
if (arg == NULL) {
rv = loaded_classes;
break;
} else {
if ((*copyinfn)(arg, &pcinfo, sizeof (pcinfo)))
return (set_errno(EFAULT));
}
if (pcinfo.pc_cid >= loaded_classes || pcinfo.pc_cid < 1)
return (set_errno(EINVAL));
(void) strncpy(pcinfo.pc_clname, sclass[pcinfo.pc_cid].cl_name,
PC_CLNMSZ);
error =
scheduler_load(pcinfo.pc_clname, &sclass[pcinfo.pc_cid]);
if (error)
return (set_errno(error));
error = CL_GETCLINFO(&sclass[pcinfo.pc_cid], pcinfo.pc_clinfo);
if (error)
return (set_errno(error));
if ((*copyoutfn)(&pcinfo, arg, sizeof (pcinfo)))
return (set_errno(EFAULT));
rv = loaded_classes;
break;
case PC_SETPARMS:
case PC_SETXPARMS:
if (cmd == PC_SETPARMS) {
if ((*copyinfn)(arg, &pcparms, sizeof (pcparms)))
return (set_errno(EFAULT));
error = parmsin(&pcparms, NULL);
} else {
if ((*copyinfn)(arg, clname, PC_CLNMSZ) ||
COPYIN_VAPARMS(arg2, &vaparms, sizeof (vaparms),
seg))
return (set_errno(EFAULT));
clname[PC_CLNMSZ-1] = '\0';
if (getcid(clname, &pcparms.pc_cid))
return (set_errno(EINVAL));
error = parmsin(&pcparms, &vaparms);
}
if (error)
return (set_errno(error));
if ((*copyinfn)(psp, &procset, sizeof (procset)))
return (set_errno(EFAULT));
if (cur_inset_only(&procset) == B_TRUE) {
if ((procset.p_lidtype == P_LWPID) ||
(procset.p_ridtype == P_LWPID)) {
mutex_enter(&pidlock);
mutex_enter(&curproc->p_lock);
error = parmsset(&pcparms, curthread);
mutex_exit(&curproc->p_lock);
mutex_exit(&pidlock);
} else {
stprmargs.stp_parmsp = &pcparms;
stprmargs.stp_error = 0;
mutex_enter(&pidlock);
error = setparms(curproc, &stprmargs);
mutex_exit(&pidlock);
if (error == 0 && stprmargs.stp_error != 0)
error = stprmargs.stp_error;
}
if (error)
return (set_errno(error));
} else {
stprmargs.stp_parmsp = &pcparms;
stprmargs.stp_error = 0;
error1 = error = ESRCH;
if ((procset.p_lidtype != P_LWPID) ||
(procset.p_ridtype != P_LWPID)) {
error1 = dotoprocs(&procset, setparms,
(char *)&stprmargs);
}
if ((procset.p_lidtype == P_LWPID) ||
(procset.p_ridtype == P_LWPID)) {
error = dotolwp(&procset, parmsset,
(char *)&pcparms);
if (MUTEX_HELD(&curproc->p_lock))
mutex_exit(&curproc->p_lock);
}
if (error1 != ESRCH)
error = error1;
if (error == 0 && stprmargs.stp_error != 0)
error = stprmargs.stp_error;
}
break;
case PC_GETPARMS:
case PC_GETXPARMS:
if (cmd == PC_GETPARMS) {
if ((*copyinfn)(arg, &pcparms, sizeof (pcparms)))
return (set_errno(EFAULT));
} else {
if (arg != NULL) {
if ((*copyinfn)(arg, clname, PC_CLNMSZ))
return (set_errno(EFAULT));
clname[PC_CLNMSZ-1] = '\0';
if (getcid(clname, &pcparms.pc_cid))
return (set_errno(EINVAL));
} else
pcparms.pc_cid = PC_CLNULL;
if (COPYIN_VAPARMS(arg2, &vaparms, sizeof (vaparms),
seg))
return (set_errno(EFAULT));
}
if (pcparms.pc_cid >= loaded_classes ||
(pcparms.pc_cid < 1 && pcparms.pc_cid != PC_CLNULL))
return (set_errno(EINVAL));
if ((*copyinfn)(psp, &procset, sizeof (procset)))
return (set_errno(EFAULT));
if (cur_inset_only(&procset) == B_TRUE) {
if ((procset.p_lidtype == P_LWPID) ||
(procset.p_ridtype == P_LWPID)) {
if (pcparms.pc_cid != PC_CLNULL &&
pcparms.pc_cid != curthread->t_cid) {
return (set_errno(ESRCH));
} else {
mutex_enter(&curproc->p_lock);
retthreadp = curthread;
}
} else {
count = 0;
retthreadp = NULL;
pcmpargs.pcmp_cidp = &pcparms.pc_cid;
pcmpargs.pcmp_cntp = &count;
pcmpargs.pcmp_retthreadp = &retthreadp;
if (pcparms.pc_cid != PC_CLNULL &&
pcparms.pc_cid != curthread->t_cid)
return (set_errno(ESRCH));
error = proccmp(curproc, &pcmpargs);
if (error) {
if (retthreadp != NULL)
mutex_exit(&(curproc->p_lock));
return (set_errno(error));
}
}
} else {
mutex_enter(&pidlock);
initpp = prfind(P_INITPID);
mutex_exit(&pidlock);
if (pcparms.pc_cid == PC_CLNULL)
clnullflag = 1;
else
clnullflag = 0;
count = 0;
retthreadp = NULL;
pcmpargs.pcmp_cidp = &pcparms.pc_cid;
pcmpargs.pcmp_cntp = &count;
pcmpargs.pcmp_retthreadp = &retthreadp;
error1 = error = ESRCH;
if ((procset.p_lidtype != P_LWPID) ||
(procset.p_ridtype != P_LWPID)) {
error1 = dotoprocs(&procset, proccmp,
(char *)&pcmpargs);
}
if ((procset.p_lidtype == P_LWPID) ||
(procset.p_ridtype == P_LWPID)) {
error = dotolwp(&procset, threadcmp,
(char *)&pcmpargs);
}
if ((retthreadp != NULL) &&
(ttoproc(retthreadp) != curproc) &&
MUTEX_HELD(&(curproc)->p_lock))
mutex_exit(&(curproc)->p_lock);
ASSERT(retthreadp == NULL ||
MUTEX_HELD(&(ttoproc(retthreadp)->p_lock)));
if (error1 != ESRCH)
error = error1;
if (error) {
if (retthreadp != NULL)
mutex_exit(&(ttoproc(retthreadp)->p_lock));
ASSERT(MUTEX_NOT_HELD(&(curproc)->p_lock));
return (set_errno(error));
}
if (initpp != NULL && retthreadp != NULL &&
ttoproc(retthreadp) != initpp) {
mutex_enter(&initpp->p_lock);
if (procinset(initpp, &procset)) {
mutex_exit(&initpp->p_lock);
(void) proccmp(initpp, &pcmpargs);
} else {
mutex_exit(&initpp->p_lock);
}
}
if (retthreadp == NULL) {
if (MUTEX_HELD(&(curproc)->p_lock))
mutex_exit(&(curproc)->p_lock);
return (set_errno(ESRCH));
}
if (clnullflag && count > 1) {
if (retthreadp != NULL)
mutex_exit(
&(ttoproc(retthreadp)->p_lock));
ASSERT(MUTEX_NOT_HELD(&(curproc)->p_lock));
return (set_errno(EINVAL));
}
}
ASSERT(retthreadp == NULL ||
MUTEX_HELD(&(ttoproc(retthreadp)->p_lock)));
if (retthreadp == NULL) {
ASSERT(MUTEX_NOT_HELD(&(curproc)->p_lock));
return (set_errno(ESRCH));
}
parmsget(retthreadp, &pcparms);
error = parmsout(&pcparms,
(cmd == PC_GETPARMS ? NULL : &vaparms));
saved_pid = ttoproc(retthreadp)->p_pid;
mutex_exit(&(ttoproc(retthreadp)->p_lock));
ASSERT(MUTEX_NOT_HELD(&curproc->p_lock));
if (error)
return (set_errno(error));
if (cmd == PC_GETPARMS) {
if ((*copyoutfn)(&pcparms, arg, sizeof (pcparms)))
return (set_errno(EFAULT));
} else if ((error = vaparmsout(arg, &pcparms, &vaparms,
seg)) != 0)
return (set_errno(error));
rv = saved_pid;
break;
case PC_ADMIN:
if (get_udatamodel() == DATAMODEL_NATIVE) {
if ((*copyinfn)(arg, &pcadmin, sizeof (pcadmin_t)))
return (set_errno(EFAULT));
#ifdef _SYSCALL32_IMPL
} else {
pcadmin32_t pcadmin32;
if ((*copyinfn)(arg, &pcadmin32, sizeof (pcadmin32_t)))
return (set_errno(EFAULT));
pcadmin.pc_cid = pcadmin32.pc_cid;
pcadmin.pc_cladmin = (caddr_t)(uintptr_t)
pcadmin32.pc_cladmin;
#endif
}
if (pcadmin.pc_cid >= loaded_classes ||
pcadmin.pc_cid < 1)
return (set_errno(EINVAL));
mutex_enter(&ualock);
error = CL_ADMIN(&sclass[pcadmin.pc_cid], pcadmin.pc_cladmin,
CRED());
mutex_exit(&ualock);
break;
case PC_GETPRIRANGE:
if ((*copyinfn)(arg, &pcpri, sizeof (pcpri_t)))
return (set_errno(EFAULT));
if (pcpri.pc_cid >= loaded_classes || pcpri.pc_cid < 0)
return (set_errno(EINVAL));
error = CL_GETCLPRI(&sclass[pcpri.pc_cid], &pcpri);
if (!error) {
if ((*copyoutfn)(&pcpri, arg, sizeof (pcpri)))
return (set_errno(EFAULT));
}
break;
case PC_DONICE:
if ((*copyinfn)(arg, &pcnice, sizeof (pcnice)) ||
(*copyinfn)(psp, &procset, sizeof (procset)))
return (set_errno(EFAULT));
error = donice(&procset, &pcnice);
if (!error && (pcnice.pc_op == PC_GETNICE)) {
if ((*copyoutfn)(&pcnice, arg, sizeof (pcnice)))
return (set_errno(EFAULT));
}
break;
case PC_DOPRIO:
if ((*copyinfn)(arg, &pcprio, sizeof (pcprio)) ||
(*copyinfn)(psp, &procset, sizeof (procset)))
return (set_errno(EFAULT));
error = doprio(&procset, &pcprio);
if (!error && (pcprio.pc_op == PC_GETPRIO)) {
if ((*copyoutfn)(&pcprio, arg, sizeof (pcprio)))
return (set_errno(EFAULT));
}
break;
case PC_SETDFLCL:
if (secpolicy_dispadm(CRED()) != 0)
return (set_errno(EPERM));
if (copyin(arg, (caddr_t)clname, PC_CLNMSZ) != 0)
return (set_errno(EFAULT));
clname[PC_CLNMSZ-1] = '\0';
if (getcid(clname, &classid) != 0)
return (set_errno(EINVAL));
if (CLASS_KERNEL(classid))
return (set_errno(EINVAL));
defaultcid = classid;
ASSERT(defaultcid > 0 && defaultcid < loaded_classes);
break;
case PC_GETDFLCL:
mutex_enter(&class_lock);
if (defaultcid >= loaded_classes)
outstr = "";
else
outstr = sclass[defaultcid].cl_name;
size = strlen(outstr) + 1;
if (arg != NULL)
if ((*copyoutfn)(outstr, arg, size) != 0)
error = EFAULT;
mutex_exit(&class_lock);
break;
default:
error = EINVAL;
break;
}
return (error ? (set_errno(error)) : rv);
}
long
priocntlsys(int pc_version, procset_t *psp, int cmd, caddr_t arg, caddr_t arg2)
{
return (priocntl_common(pc_version, psp, cmd, arg, arg2,
UIO_USERSPACE));
}
static int
proccmp(proc_t *pp, struct pcmpargs *argp)
{
kthread_t *tx;
kthread_t *ty;
int last_pri = -1;
int tx_pri;
int found = 0;
mutex_enter(&pp->p_lock);
if (pp->p_tlist == NULL) {
mutex_exit(&pp->p_lock);
return (0);
}
(*argp->pcmp_cntp)++;
if (*argp->pcmp_cidp == PC_CLNULL) {
*argp->pcmp_cidp = pp->p_tlist->t_cid;
}
ty = tx = pp->p_tlist;
do {
if (tx->t_cid == *argp->pcmp_cidp) {
found = 1;
if ((tx_pri = CL_GLOBPRI(tx)) > last_pri) {
last_pri = tx_pri;
ty = tx;
}
}
} while ((tx = tx->t_forw) != pp->p_tlist);
if (found) {
if (*argp->pcmp_retthreadp == NULL) {
*argp->pcmp_retthreadp = ty;
} else {
tx = *argp->pcmp_retthreadp;
if (CL_GLOBPRI(ty) <= CL_GLOBPRI(tx)) {
mutex_exit(&pp->p_lock);
} else {
mutex_exit(&(ttoproc(tx)->p_lock));
*argp->pcmp_retthreadp = ty;
}
}
} else {
mutex_exit(&pp->p_lock);
}
return (0);
}
int
threadcmp(struct pcmpargs *argp, kthread_t *tp)
{
kthread_t *tx;
proc_t *pp;
ASSERT(MUTEX_HELD(&(ttoproc(tp))->p_lock));
(*argp->pcmp_cntp)++;
if (*argp->pcmp_cidp == PC_CLNULL) {
*argp->pcmp_cidp = tp->t_cid;
}
if (tp->t_cid == *argp->pcmp_cidp) {
if (*argp->pcmp_retthreadp == NULL) {
*argp->pcmp_retthreadp = tp;
} else {
tx = *argp->pcmp_retthreadp;
if (CL_GLOBPRI(tp) > CL_GLOBPRI(tx)) {
pp = ttoproc(tx);
ASSERT(MUTEX_HELD(&pp->p_lock));
if (pp != curproc) {
mutex_exit(&pp->p_lock);
}
*argp->pcmp_retthreadp = tp;
}
}
}
return (0);
}
static int
setparms(proc_t *targpp, struct stprmargs *stprmp)
{
int error = 0;
kthread_t *t;
int err;
mutex_enter(&targpp->p_lock);
if ((t = targpp->p_tlist) == NULL) {
mutex_exit(&targpp->p_lock);
return (0);
}
do {
err = parmsset(stprmp->stp_parmsp, t);
if (error == 0)
error = err;
} while ((t = t->t_forw) != targpp->p_tlist);
mutex_exit(&targpp->p_lock);
if (error) {
if (error == EPERM) {
stprmp->stp_error = EPERM;
return (0);
} else {
return (error);
}
} else
return (0);
}
int
setthreadnice(pcnice_t *pcnice, kthread_t *tp)
{
int error;
int nice;
int inc;
id_t rtcid;
ASSERT(MUTEX_HELD(&pidlock));
ASSERT(MUTEX_HELD(&(ttoproc(tp)->p_lock)));
error = getcidbyname("RT", &rtcid);
if (error == 0 && tp->t_cid == rtcid) {
if (pcnice->pc_op == PC_SETNICE)
return (0);
}
if ((error = CL_DONICE(tp, CRED(), 0, &nice)) != 0)
return (error);
if (pcnice->pc_op == PC_GETNICE) {
if (nice < pcnice->pc_val)
pcnice->pc_val = nice;
} else {
ASSERT(pcnice->pc_op == PC_SETNICE);
inc = pcnice->pc_val - nice;
error = CL_DONICE(tp, CRED(), inc, &inc);
schedctl_set_cidpri(tp);
}
return (error);
}
int
setprocnice(proc_t *pp, pcnice_t *pcnice)
{
kthread_t *tp;
int retval = 0;
int error;
ASSERT(MUTEX_HELD(&pidlock));
mutex_enter(&pp->p_lock);
if ((tp = pp->p_tlist) == NULL) {
mutex_exit(&pp->p_lock);
return (ESRCH);
}
if (pcnice->pc_op == PC_SETNICE) {
if (!prochasprocperm(pp, curproc, CRED())) {
mutex_exit(&pp->p_lock);
return (EPERM);
}
}
do {
error = setthreadnice(pcnice, tp);
if (error)
retval = error;
} while ((tp = tp->t_forw) != pp->p_tlist);
mutex_exit(&pp->p_lock);
return (retval);
}
static int
donice(procset_t *procset, pcnice_t *pcnice)
{
int err_proc = 0;
int err_thread = 0;
int err = 0;
if (pcnice->pc_op != PC_GETNICE && pcnice->pc_op != PC_SETNICE)
return (EINVAL);
if (pcnice->pc_op == PC_GETNICE)
pcnice->pc_val = NZERO;
if (procset->p_lidtype != P_LWPID ||
procset->p_ridtype != P_LWPID)
err_proc = dotoprocs(procset, setprocnice, (char *)pcnice);
if (procset->p_lidtype == P_LWPID || procset->p_ridtype == P_LWPID) {
err_thread = dotolwp(procset, setthreadnice, (char *)pcnice);
if (MUTEX_HELD(&curproc->p_lock))
mutex_exit(&curproc->p_lock);
if (err_proc == ESRCH)
err_proc = 0;
}
if (pcnice->pc_op == PC_GETNICE) {
proc_t *initpp;
mutex_enter(&pidlock);
if ((initpp = prfind(P_INITPID)) != NULL) {
mutex_enter(&initpp->p_lock);
if (procinset(initpp, procset)) {
mutex_exit(&initpp->p_lock);
err = setprocnice(initpp, pcnice);
} else {
mutex_exit(&initpp->p_lock);
}
}
mutex_exit(&pidlock);
}
if (!err)
err = err_thread ? err_thread : err_proc;
return (err);
}
int
setthreadprio(pcprio_t *pcprio, kthread_t *tp)
{
int prio = 0;
int incr;
int error;
ASSERT(MUTEX_HELD(&pidlock));
ASSERT(MUTEX_HELD(&(ttoproc(tp)->p_lock)));
if (pcprio->pc_op == PC_SETPRIO && pcprio->pc_cid != tp->t_cid) {
void *bufp = NULL;
caddr_t clprocp = (caddr_t)tp->t_cldata;
id_t oldcid = tp->t_cid;
error = CL_CANEXIT(tp, NULL);
if (error)
return (error);
if (CL_ALLOC(&bufp, pcprio->pc_cid, KM_NOSLEEP) != 0)
return (ENOMEM);
error = CL_ENTERCLASS(tp, pcprio->pc_cid, NULL, CRED(), bufp);
if (error) {
CL_FREE(pcprio->pc_cid, bufp);
return (error);
}
CL_EXITCLASS(oldcid, clprocp);
schedctl_set_cidpri(tp);
}
if ((error = CL_DOPRIO(tp, CRED(), 0, &prio)) != 0)
return (error);
if (pcprio->pc_op == PC_GETPRIO) {
if (prio > pcprio->pc_val) {
pcprio->pc_cid = tp->t_cid;
pcprio->pc_val = prio;
}
} else if (prio != pcprio->pc_val) {
incr = pcprio->pc_val - prio;
error = CL_DOPRIO(tp, CRED(), incr, &prio);
schedctl_set_cidpri(tp);
}
return (error);
}
int
setprocprio(proc_t *pp, pcprio_t *pcprio)
{
kthread_t *tp;
int retval = 0;
int error;
ASSERT(MUTEX_HELD(&pidlock));
mutex_enter(&pp->p_lock);
if ((tp = pp->p_tlist) == NULL) {
mutex_exit(&pp->p_lock);
return (ESRCH);
}
if (pcprio->pc_op == PC_SETPRIO) {
if (!prochasprocperm(pp, curproc, CRED())) {
mutex_exit(&pp->p_lock);
return (EPERM);
}
}
do {
error = setthreadprio(pcprio, tp);
if (error)
retval = error;
} while ((tp = tp->t_forw) != pp->p_tlist);
mutex_exit(&pp->p_lock);
return (retval);
}
static int
doprio(procset_t *procset, pcprio_t *pcprio)
{
int err_proc = 0;
int err_thread = 0;
int err = 0;
if (pcprio->pc_op != PC_GETPRIO && pcprio->pc_op != PC_SETPRIO)
return (EINVAL);
if (pcprio->pc_op == PC_SETPRIO &&
(pcprio->pc_cid >= loaded_classes || pcprio->pc_cid < 1))
return (EINVAL);
if (pcprio->pc_op == PC_GETPRIO)
pcprio->pc_val = SHRT_MIN;
if (procset->p_lidtype != P_LWPID ||
procset->p_ridtype != P_LWPID)
err_proc = dotoprocs(procset, setprocprio, (char *)pcprio);
if (procset->p_lidtype == P_LWPID || procset->p_ridtype == P_LWPID) {
err_thread = dotolwp(procset, setthreadprio, (char *)pcprio);
if (MUTEX_HELD(&curproc->p_lock))
mutex_exit(&curproc->p_lock);
if (err_proc == ESRCH)
err_proc = 0;
}
if (pcprio->pc_op == PC_GETPRIO) {
proc_t *initpp;
mutex_enter(&pidlock);
if ((initpp = prfind(P_INITPID)) != NULL) {
mutex_enter(&initpp->p_lock);
if (procinset(initpp, procset)) {
mutex_exit(&initpp->p_lock);
err = setprocprio(initpp, pcprio);
} else {
mutex_exit(&initpp->p_lock);
}
}
mutex_exit(&pidlock);
}
if (!err)
err = err_thread ? err_thread : err_proc;
return (err);
}