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