procset.c revision 4253:15bf3036ed96
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 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
27/*	  All Rights Reserved  	*/
28
29
30#pragma ident	"%Z%%M%	%I%	%E% SMI"	/* from SVr4.0 1.25 */
31
32#include <sys/types.h>
33#include <sys/sysmacros.h>
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/vfs.h>
37#include <sys/cred.h>
38#include <sys/vnode.h>
39#include <sys/file.h>
40#include <sys/errno.h>
41#include <sys/kmem.h>
42#include <sys/user.h>
43#include <sys/buf.h>
44#include <sys/var.h>
45#include <sys/conf.h>
46#include <sys/debug.h>
47#include <sys/proc.h>
48#include <sys/signal.h>
49#include <sys/siginfo.h>
50#include <sys/acct.h>
51#include <sys/procset.h>
52#include <sys/cmn_err.h>
53#include <sys/fault.h>
54#include <sys/syscall.h>
55#include <sys/ucontext.h>
56#include <sys/procfs.h>
57#include <sys/session.h>
58#include <sys/task.h>
59#include <sys/project.h>
60#include <sys/pool.h>
61#include <sys/zone.h>
62#include <sys/contract/process_impl.h>
63
64id_t	getmyid(idtype_t);
65int	checkprocset(procset_t *);
66static	kthread_t *getlwpptr(id_t);
67int	procinset(proc_t *, procset_t *);
68static	int lwpinset(proc_t *, procset_t *, kthread_t *, int *);
69
70/*
71 * The dotoprocs function locates the process(es) specified
72 * by the procset structure pointed to by psp.  funcp points to a
73 * function which dotoprocs will call for each process in the
74 * specified set.  The arguments to this function will be a pointer
75 * to the current process from the set and arg.
76 * If the called function returns -1, it means that processing of the
77 * procset should stop and a normal (non-error) return should be made
78 * to the caller of dotoprocs.
79 * If the called function returns any other non-zero value the search
80 * is terminated and the function's return value is returned to
81 * the caller of dotoprocs.  This will normally be an error code.
82 * Otherwise, dotoprocs will return zero after processing the entire
83 * process set unless no processes were found in which case ESRCH will
84 * be returned.
85 */
86int
87dotoprocs(procset_t *psp, int (*funcp)(), char *arg)
88{
89	proc_t	*prp;	/* A process from the set */
90	int	error;
91	int	nfound;	/* Nbr of processes found.	*/
92	proc_t	*lastprp;	/* Last proc found.	*/
93
94	ASSERT(funcp != NULL);
95
96	/*
97	 * Check that the procset_t is valid.
98	 */
99	error = checkprocset(psp);
100	if (error) {
101		return (error);
102	}
103	/*
104	 * Check for the special value P_MYID in either operand
105	 * and replace it with the correct value.  We don't check
106	 * for an error return from getmyid() because the idtypes
107	 * have been validated by the checkprocset() call above.
108	 */
109	mutex_enter(&pidlock);
110	if (psp->p_lid == P_MYID) {
111		psp->p_lid = getmyid(psp->p_lidtype);
112	}
113	if (psp->p_rid == P_MYID) {
114		psp->p_rid = getmyid(psp->p_ridtype);
115	}
116
117	/*
118	 * If psp only acts on a single proc, we can reduce pidlock hold time
119	 * by avoiding a needless scan of the entire proc list.  Although
120	 * there are many procset_t combinations which might boil down to a
121	 * single proc, the most common case is an AND operation where one
122	 * side is a specific pid, and the other side is P_ALL, so that is
123	 * the case for which we will provide a fast path.  Other cases could
124	 * be added in a similar fashion if they were to become significant
125	 * pidlock bottlenecks.
126	 *
127	 * Perform the check symmetrically:  either the left or right side may
128	 * specify a pid, with the opposite side being 'all'.
129	 */
130	if (psp->p_op == POP_AND) {
131		if (((psp->p_lidtype == P_PID) && (psp->p_ridtype == P_ALL)) ||
132		    ((psp->p_ridtype == P_PID) && (psp->p_lidtype == P_ALL))) {
133			id_t pid;
134
135			pid = (psp->p_lidtype == P_PID) ?
136			    psp->p_lid : psp->p_rid;
137			if (((prp = prfind((pid_t)pid)) == NULL) ||
138			    (prp->p_stat == SIDL || prp->p_stat == SZOMB ||
139			    prp->p_tlist == NULL || prp->p_flag & SSYS)) {
140				/*
141				 * Specified proc doesn't exist or should
142				 * not be operated on.
143				 * Don't need to make HASZONEACCESS check
144				 * here since prfind() takes care of that.
145				 */
146				mutex_exit(&pidlock);
147				return (ESRCH);
148			}
149			/*
150			 * Operate only on the specified proc.  It's okay
151			 * if it's init.
152			 */
153			error = (*funcp)(prp, arg);
154			mutex_exit(&pidlock);
155			if (error == -1)
156				error = 0;
157			return (error);
158		}
159	}
160
161	nfound = 0;
162	error  = 0;
163
164	for (prp = practive; prp != NULL; prp = prp->p_next) {
165		/*
166		 * If caller is in a non-global zone, skip processes
167		 * in other zones.
168		 */
169		if (!HASZONEACCESS(curproc, prp->p_zone->zone_id))
170			continue;
171		if (prp->p_stat == SIDL || prp->p_stat == SZOMB ||
172		    prp->p_tlist == NULL || prp->p_flag & SSYS)
173			continue;
174		if (procinset(prp, psp)) {
175			nfound++;
176			lastprp = prp;
177			if (prp != proc_init) {
178				error = (*funcp)(prp, arg);
179				if (error == -1) {
180					mutex_exit(&pidlock);
181					return (0);
182				} else if (error) {
183					mutex_exit(&pidlock);
184					return (error);
185				}
186			}
187		}
188	}
189	if (nfound == 0) {
190		mutex_exit(&pidlock);
191		return (ESRCH);
192	}
193	if (nfound == 1 && lastprp == proc_init)
194		error = (*funcp)(lastprp, arg);
195	if (error == -1)
196		error = 0;
197	mutex_exit(&pidlock);
198	return (error);
199}
200
201/*
202 * Check if a procset_t is valid.  Return zero or an errno.
203 */
204int
205checkprocset(procset_t *psp)
206{
207	switch (psp->p_lidtype) {
208	case P_LWPID:
209	case P_PID:
210	case P_PPID:
211	case P_PGID:
212	case P_SID:
213	case P_TASKID:
214	case P_CID:
215	case P_UID:
216	case P_GID:
217	case P_PROJID:
218	case P_POOLID:
219	case P_ZONEID:
220	case P_CTID:
221	case P_ALL:
222		break;
223	default:
224		return (EINVAL);
225	}
226
227	switch (psp->p_ridtype) {
228	case P_LWPID:
229	case P_PID:
230	case P_PPID:
231	case P_PGID:
232	case P_SID:
233	case P_TASKID:
234	case P_CID:
235	case P_UID:
236	case P_GID:
237	case P_PROJID:
238	case P_POOLID:
239	case P_ZONEID:
240	case P_CTID:
241	case P_ALL:
242		break;
243	default:
244		return (EINVAL);
245	}
246
247	switch (psp->p_op) {
248	case POP_DIFF:
249	case POP_AND:
250	case POP_OR:
251	case POP_XOR:
252		break;
253	default:
254		return (EINVAL);
255	}
256
257	return (0);
258}
259
260/*
261 * procinset returns 1 if the process pointed to
262 * by pp is in the process set specified by psp, otherwise 0 is returned.
263 * The caller should check that the process is not exiting and is not
264 * in the SYS scheduling class.
265 *
266 * This function expects to be called with a valid procset_t.
267 * The set should be checked using checkprocset() before calling
268 * this function.
269 */
270int
271procinset(proc_t *pp, procset_t *psp)
272{
273	int	loperand = 0;
274	int	roperand = 0;
275	int	lwplinproc = 0;
276	int	lwprinproc = 0;
277	kthread_t	*tp = proctot(pp);
278
279	switch (psp->p_lidtype) {
280
281	case P_LWPID:
282		if (pp == ttoproc(curthread))
283			if (getlwpptr(psp->p_lid) != NULL)
284				lwplinproc++;
285		break;
286
287	case P_PID:
288		if (pp->p_pid == psp->p_lid)
289			loperand++;
290		break;
291
292	case P_PPID:
293		if (pp->p_ppid == psp->p_lid)
294			loperand++;
295		break;
296
297	case P_PGID:
298		if (pp->p_pgrp == psp->p_lid)
299			loperand++;
300		break;
301
302	case P_SID:
303		mutex_enter(&pp->p_splock);
304		if (pp->p_sessp->s_sid == psp->p_lid)
305			loperand++;
306		mutex_exit(&pp->p_splock);
307		break;
308
309	case P_CID:
310		ASSERT(tp != NULL);
311		/* This case is broken for now. Need to be fixed XXX */
312		if (tp->t_cid == psp->p_lid)
313			/*
314			 * if (checkcid(psp->p_lid))
315			 */
316			loperand++;
317		break;
318
319	case P_TASKID:
320		if (pp->p_task->tk_tkid == psp->p_lid)
321			loperand++;
322		break;
323
324	case P_UID:
325		mutex_enter(&pp->p_crlock);
326		if (crgetuid(pp->p_cred) == psp->p_lid)
327			loperand++;
328		mutex_exit(&pp->p_crlock);
329		break;
330
331	case P_GID:
332		mutex_enter(&pp->p_crlock);
333		if (crgetgid(pp->p_cred) == psp->p_lid)
334			loperand++;
335		mutex_exit(&pp->p_crlock);
336		break;
337
338	case P_PROJID:
339		if (pp->p_task->tk_proj->kpj_id == psp->p_lid)
340			loperand++;
341		break;
342
343	case P_POOLID:
344		if (pp->p_pool->pool_id == psp->p_lid)
345			loperand++;
346		break;
347
348	case P_ZONEID:
349		if (pp->p_zone->zone_id == psp->p_lid)
350			loperand++;
351		break;
352
353	case P_CTID:
354		if (PRCTID(pp) == psp->p_lid)
355			loperand++;
356		break;
357
358	case P_ALL:
359		loperand++;
360		break;
361
362	default:
363#ifdef DEBUG
364		cmn_err(CE_WARN, "procinset called with bad set");
365		return (0);
366#else
367		return (0);
368#endif
369	}
370
371	switch (psp->p_ridtype) {
372
373	case P_LWPID:
374		if (pp == ttoproc(curthread))
375			if (getlwpptr(psp->p_rid) != NULL)
376				lwprinproc++;
377		break;
378
379	case P_PID:
380		if (pp->p_pid == psp->p_rid)
381			roperand++;
382		break;
383
384	case P_PPID:
385		if (pp->p_ppid == psp->p_rid)
386			roperand++;
387		break;
388
389	case P_PGID:
390		if (pp->p_pgrp == psp->p_rid)
391			roperand++;
392		break;
393
394	case P_SID:
395		mutex_enter(&pp->p_splock);
396		if (pp->p_sessp->s_sid == psp->p_rid)
397			roperand++;
398		mutex_exit(&pp->p_splock);
399		break;
400
401	case P_TASKID:
402		if (pp->p_task->tk_tkid == psp->p_rid)
403			roperand++;
404		break;
405
406	case P_CID:
407		ASSERT(tp != NULL);
408		/* This case is broken for now. Need to be fixed XXX */
409		if (tp->t_cid == psp->p_rid)
410			/*
411			 * if (checkcid(psp->p_rid))
412			 */
413			roperand++;
414		break;
415
416	case P_UID:
417		mutex_enter(&pp->p_crlock);
418		if (crgetuid(pp->p_cred) == psp->p_rid)
419			roperand++;
420		mutex_exit(&pp->p_crlock);
421		break;
422
423	case P_GID:
424		mutex_enter(&pp->p_crlock);
425		if (crgetgid(pp->p_cred) == psp->p_rid)
426			roperand++;
427		mutex_exit(&pp->p_crlock);
428		break;
429
430	case P_PROJID:
431		if (pp->p_task->tk_proj->kpj_id == psp->p_rid)
432			roperand++;
433		break;
434
435	case P_POOLID:
436		if (pp->p_pool->pool_id == psp->p_rid)
437			roperand++;
438		break;
439
440	case P_ZONEID:
441		if (pp->p_zone->zone_id == psp->p_rid)
442			roperand++;
443		break;
444
445	case P_CTID:
446		if (PRCTID(pp) == psp->p_rid)
447			roperand++;
448		break;
449
450	case P_ALL:
451		roperand++;
452		break;
453
454	default:
455#ifdef DEBUG
456		cmn_err(CE_WARN, "procinset called with bad set");
457		return (0);
458#else
459		return (0);
460#endif
461	}
462
463	switch (psp->p_op) {
464
465	case POP_DIFF:
466		if (loperand && !lwprinproc && !roperand)
467			return (1);
468		else
469			return (0);
470
471	case POP_AND:
472		if (loperand && roperand)
473			return (1);
474		else
475			return (0);
476
477	case POP_OR:
478		if (loperand || roperand)
479			return (1);
480		else
481			return (0);
482
483	case POP_XOR:
484		if ((loperand && !lwprinproc && !roperand) ||
485		    (roperand && !lwplinproc && !loperand))
486			return (1);
487		else
488			return (0);
489
490	default:
491#ifdef DEBUG
492		cmn_err(CE_WARN, "procinset called with bad set");
493		return (0);
494#else
495		return (0);
496#endif
497	}
498	/* NOTREACHED */
499}
500
501/*
502 * lwpinset returns 1 if the thread pointed to
503 * by tp is in the process set specified by psp and is not in
504 * the sys scheduling class - otherwise 0 is returned.
505 *
506 * This function expects to be called with a valid procset_t.
507 * The set should be checked using checkprocset() before calling
508 * this function.
509 */
510int
511lwpinset(proc_t *pp, procset_t *psp, kthread_t *tp, int *done)
512{
513	int	loperand = 0;
514	int	roperand = 0;
515	int	lwplinset  = 0;
516	int	lwprinset  = 0;
517
518	ASSERT(ttoproc(tp) == pp);
519
520	/*
521	 * If process is in the sys class return (0).
522	 */
523	if (proctot(pp)->t_cid == 0) {
524		return (0);
525	}
526
527	switch (psp->p_lidtype) {
528
529	case P_LWPID:
530		if (tp->t_tid == psp->p_lid)
531			lwplinset ++;
532		break;
533
534	case P_PID:
535		if (pp->p_pid == psp->p_lid)
536			loperand++;
537		break;
538
539	case P_PPID:
540		if (pp->p_ppid == psp->p_lid)
541			loperand++;
542		break;
543
544	case P_PGID:
545		if (pp->p_pgrp == psp->p_lid)
546			loperand++;
547		break;
548
549	case P_SID:
550		mutex_enter(&pp->p_splock);
551		if (pp->p_sessp->s_sid == psp->p_lid)
552			loperand++;
553		mutex_exit(&pp->p_splock);
554		break;
555
556	case P_TASKID:
557		if (pp->p_task->tk_tkid == psp->p_lid)
558			loperand++;
559		break;
560
561	case P_CID:
562		if (tp->t_cid == psp->p_lid)
563			loperand++;
564		break;
565
566	case P_UID:
567		mutex_enter(&pp->p_crlock);
568		if (crgetuid(pp->p_cred) == psp->p_lid)
569			loperand++;
570		mutex_exit(&pp->p_crlock);
571		break;
572
573	case P_GID:
574		mutex_enter(&pp->p_crlock);
575		if (crgetgid(pp->p_cred) == psp->p_lid)
576			loperand++;
577		mutex_exit(&pp->p_crlock);
578		break;
579
580	case P_PROJID:
581		if (pp->p_task->tk_proj->kpj_id == psp->p_lid)
582			loperand++;
583		break;
584
585	case P_POOLID:
586		if (pp->p_pool->pool_id == psp->p_lid)
587			loperand++;
588		break;
589
590	case P_ZONEID:
591		if (pp->p_zone->zone_id == psp->p_lid)
592			loperand++;
593		break;
594
595	case P_CTID:
596		if (PRCTID(pp) == psp->p_lid)
597			loperand++;
598		break;
599
600	case P_ALL:
601		loperand++;
602		break;
603
604	default:
605#ifdef DEBUG
606		cmn_err(CE_WARN, "lwpinset called with bad set");
607		return (0);
608#else
609		return (0);
610#endif
611	}
612
613	switch (psp->p_ridtype) {
614
615	case P_LWPID:
616		if (tp->t_tid == psp->p_rid)
617			lwprinset ++;
618		break;
619
620	case P_PID:
621		if (pp->p_pid == psp->p_rid)
622			roperand++;
623		break;
624
625	case P_PPID:
626		if (pp->p_ppid == psp->p_rid)
627			roperand++;
628		break;
629
630	case P_PGID:
631		if (pp->p_pgrp == psp->p_rid)
632			roperand++;
633		break;
634
635	case P_SID:
636		mutex_enter(&pp->p_splock);
637		if (pp->p_sessp->s_sid == psp->p_rid)
638			roperand++;
639		mutex_exit(&pp->p_splock);
640		break;
641
642	case P_TASKID:
643		if (pp->p_task->tk_tkid == psp->p_rid)
644			roperand++;
645		break;
646
647	case P_CID:
648		if (tp->t_cid == psp->p_rid)
649			roperand++;
650		break;
651
652	case P_UID:
653		mutex_enter(&pp->p_crlock);
654		if (crgetuid(pp->p_cred) == psp->p_rid)
655			roperand++;
656		mutex_exit(&pp->p_crlock);
657		break;
658
659	case P_GID:
660		mutex_enter(&pp->p_crlock);
661		if (crgetgid(pp->p_cred) == psp->p_rid)
662			roperand++;
663		mutex_exit(&pp->p_crlock);
664		break;
665
666	case P_PROJID:
667		if (pp->p_task->tk_proj->kpj_id == psp->p_rid)
668			roperand++;
669		break;
670
671	case P_POOLID:
672		if (pp->p_pool->pool_id == psp->p_rid)
673			roperand++;
674		break;
675
676	case P_ZONEID:
677		if (pp->p_zone->zone_id == psp->p_rid)
678			roperand++;
679		break;
680
681	case P_CTID:
682		if (PRCTID(pp) == psp->p_rid)
683			roperand++;
684		break;
685
686	case P_ALL:
687		roperand++;
688		break;
689
690	default:
691#ifdef DEBUG
692		cmn_err(CE_WARN, "lwpinset called with bad set");
693		return (0);
694#else
695		return (0);
696#endif
697	}
698
699	if (lwplinset && lwprinset)
700		*done = 1;
701
702	switch (psp->p_op) {
703
704	case POP_DIFF:
705		if ((loperand || lwplinset) && !(lwprinset || roperand))
706			return (1);
707		else
708			return (0);
709
710	case POP_AND:
711		if ((loperand || lwplinset) && (roperand || lwprinset))
712			return (1);
713		else
714			return (0);
715
716	case POP_OR:
717		if (loperand || roperand || lwplinset || lwprinset)
718			return (1);
719		else
720			return (0);
721
722	case POP_XOR:
723		if (((loperand || lwplinset) &&
724					!(lwprinset || roperand)) ||
725		    ((roperand || lwprinset) &&
726					!(lwplinset || loperand)))
727			return (1);
728		else
729			return (0);
730
731	default:
732#ifdef DEBUG
733		cmn_err(CE_WARN, "lwpinset called with bad set");
734		return (0);
735#else
736		return (0);
737#endif
738	}
739	/* NOTREACHED */
740}
741/*
742 * Check for common cases of procsets which specify only the
743 * current process.  cur_inset_only() returns B_TRUE when
744 * the current process is the only one in the set.  B_FALSE
745 * is returned to indicate that this may not be the case.
746 */
747boolean_t
748cur_inset_only(procset_t *psp)
749{
750	if (((psp->p_lidtype == P_PID &&
751		(psp->p_lid == P_MYID ||
752		psp->p_lid == ttoproc(curthread)->p_pid)) ||
753		((psp->p_lidtype == P_LWPID) &&
754		(psp->p_lid == P_MYID ||
755		psp->p_lid == curthread->t_tid))) &&
756		psp->p_op == POP_AND && psp->p_ridtype == P_ALL)
757			return (B_TRUE);
758
759	if (((psp->p_ridtype == P_PID &&
760		(psp->p_rid == P_MYID ||
761		psp->p_rid == ttoproc(curthread)->p_pid)) ||
762		((psp->p_ridtype == P_LWPID) &&
763		(psp->p_rid == P_MYID ||
764		psp->p_rid == curthread->t_tid))) &&
765		psp->p_op == POP_AND && psp->p_lidtype == P_ALL)
766			return (B_TRUE);
767
768	return (B_FALSE);
769}
770
771id_t
772getmyid(idtype_t idtype)
773{
774	proc_t	*pp;
775	uid_t uid;
776	gid_t gid;
777	pid_t sid;
778
779	pp = ttoproc(curthread);
780
781	switch (idtype) {
782	case P_LWPID:
783		return (curthread->t_tid);
784
785	case P_PID:
786		return (pp->p_pid);
787
788	case P_PPID:
789		return (pp->p_ppid);
790
791	case P_PGID:
792		return (pp->p_pgrp);
793
794	case P_SID:
795		mutex_enter(&pp->p_splock);
796		sid = pp->p_sessp->s_sid;
797		mutex_exit(&pp->p_splock);
798		return (sid);
799
800	case P_TASKID:
801		return (pp->p_task->tk_tkid);
802
803	case P_CID:
804		return (curthread->t_cid);
805
806	case P_UID:
807		mutex_enter(&pp->p_crlock);
808		uid = crgetuid(pp->p_cred);
809		mutex_exit(&pp->p_crlock);
810		return (uid);
811
812	case P_GID:
813		mutex_enter(&pp->p_crlock);
814		gid = crgetgid(pp->p_cred);
815		mutex_exit(&pp->p_crlock);
816		return (gid);
817
818	case P_PROJID:
819		return (pp->p_task->tk_proj->kpj_id);
820
821	case P_POOLID:
822		return (pp->p_pool->pool_id);
823
824	case P_ZONEID:
825		return (pp->p_zone->zone_id);
826
827	case P_CTID:
828		return (PRCTID(pp));
829
830	case P_ALL:
831		/*
832		 * The value doesn't matter for P_ALL.
833		 */
834		return (0);
835
836	default:
837		return (-1);
838	}
839}
840
841static kthread_t *
842getlwpptr(id_t id)
843{
844	proc_t		*p;
845	kthread_t	*t;
846
847	if (id == P_MYID)
848		t = curthread;
849	else {
850		p = ttoproc(curthread);
851		mutex_enter(&p->p_lock);
852		t = idtot(p, id);
853		mutex_exit(&p->p_lock);
854	}
855
856	return (t);
857}
858
859/*
860 * The dotolwp function locates the LWP(s) specified by the procset structure
861 * pointed to by psp.  If funcp is non-NULL then it points to a function
862 * which dotolwp will call for each LWP in the specified set.
863 * LWPIDs specified in the procset structure always refer to lwps in curproc.
864 * The arguments for this function must be "char *arg", and "kthread_t *tp",
865 * where tp is a pointer to the current thread from the set.
866 * Note that these arguments are passed to the function in reversed order
867 * than the order of arguments passed by dotoprocs() to its callback function.
868 * Also note that there are two separate cases where this routine returns zero.
869 * In the first case no mutex is grabbed, in the second the p_lock mutex
870 * is NOT RELEASED. The priocntl code is expecting this behaviour.
871 */
872int
873dotolwp(procset_t *psp, int (*funcp)(), char *arg)
874{
875	int		error = 0;
876	int		nfound = 0;
877	kthread_t	*tp;
878	proc_t		*pp;
879	int		done = 0;
880
881	/*
882	 * Check that the procset_t is valid.
883	 */
884	error = checkprocset(psp);
885	if (error) {
886		return (error);
887	}
888
889	mutex_enter(&pidlock);
890
891	/*
892	 * Check for the special value P_MYID in either operand
893	 * and replace it with the correct value.  We don't check
894	 * for an error return from getmyid() because the idtypes
895	 * have been validated by the checkprocset() call above.
896	 */
897	if (psp->p_lid == P_MYID) {
898		psp->p_lid = getmyid(psp->p_lidtype);
899	}
900	if (psp->p_rid == P_MYID) {
901		psp->p_rid = getmyid(psp->p_ridtype);
902	}
903
904	pp = ttoproc(curthread);
905
906	if (procinset(pp, psp)) {
907		mutex_exit(&pidlock);
908		return (0);
909	}
910	mutex_enter(&pp->p_lock);
911	if ((tp = pp->p_tlist) == NULL) {
912		mutex_exit(&pp->p_lock);
913		mutex_exit(&pidlock);
914		return (0);
915	}
916	do {
917		if (lwpinset(pp, psp, tp, &done)) {
918			nfound ++;
919			error = (*funcp)(arg, tp);
920			if (error) {
921				mutex_exit(&pp->p_lock);
922				mutex_exit(&pidlock);
923				return (error);
924			}
925		}
926	} while (((tp = tp->t_forw) != pp->p_tlist) && !done);
927
928	if (nfound == 0) {
929		mutex_exit(&pp->p_lock);
930		mutex_exit(&pidlock);
931		return (ESRCH);
932	}
933
934	mutex_exit(&pidlock);
935	return (error);
936}
937