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