Merge branch 'black_magic'
[unleashed.git] / kernel / os / procset.c
blob9e612c649e7fc712d81e5ae429cabfd1c5c36e8b
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
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>
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 *);
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.
83 int
84 dotoprocs(procset_t *psp, int (*funcp)(), char *arg)
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. */
91 ASSERT(funcp != NULL);
94 * Check that the procset_t is valid.
96 error = checkprocset(psp);
97 if (error) {
98 return (error);
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.
106 mutex_enter(&pidlock);
107 if (psp->p_lid == P_MYID) {
108 psp->p_lid = getmyid(psp->p_lidtype);
110 if (psp->p_rid == P_MYID) {
111 psp->p_rid = getmyid(psp->p_ridtype);
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.
124 * Perform the check symmetrically: either the left or right side may
125 * specify a pid, with the opposite side being 'all'.
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;
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)) {
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.
143 mutex_exit(&pidlock);
144 return (ESRCH);
147 * Operate only on the specified proc. It's okay
148 * if it's init.
150 error = (*funcp)(prp, arg);
151 mutex_exit(&pidlock);
152 if (error == -1)
153 error = 0;
154 return (error);
158 nfound = 0;
159 error = 0;
161 for (prp = practive; prp != NULL; prp = prp->p_next) {
163 * If caller is in a non-global zone, skip processes
164 * in other zones.
166 if (!HASZONEACCESS(curproc, prp->p_zone->zone_id))
167 continue;
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.
174 if (prp->p_stat == SIDL || prp->p_stat == SZOMB)
175 continue;
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);
197 if (nfound == 0) {
198 mutex_exit(&pidlock);
199 return (ESRCH);
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);
210 * Check if a procset_t is valid. Return zero or an errno.
213 checkprocset(procset_t *psp)
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);
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);
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);
265 return (0);
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.
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.
281 procinset(proc_t *pp, procset_t *psp)
283 int loperand = 0;
284 int roperand = 0;
285 int lwplinproc = 0;
286 int lwprinproc = 0;
287 kthread_t *tp;
289 ASSERT(MUTEX_HELD(&pp->p_lock));
291 switch (psp->p_lidtype) {
293 case P_LWPID:
294 if (pp == ttoproc(curthread))
295 if (getlwpptr(psp->p_lid) != NULL)
296 lwplinproc++;
297 break;
299 case P_PID:
300 if (pp->p_pid == psp->p_lid)
301 loperand++;
302 break;
304 case P_PPID:
305 if (pp->p_ppid == psp->p_lid)
306 loperand++;
307 break;
309 case P_PGID:
310 if (pp->p_pgrp == psp->p_lid)
311 loperand++;
312 break;
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;
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;
329 case P_TASKID:
330 if (pp->p_task->tk_tkid == psp->p_lid)
331 loperand++;
332 break;
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;
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;
348 case P_PROJID:
349 if (pp->p_task->tk_proj->kpj_id == psp->p_lid)
350 loperand++;
351 break;
353 case P_POOLID:
354 if (pp->p_pool->pool_id == psp->p_lid)
355 loperand++;
356 break;
358 case P_ZONEID:
359 if (pp->p_zone->zone_id == psp->p_lid)
360 loperand++;
361 break;
363 case P_CTID:
364 if (PRCTID(pp) == psp->p_lid)
365 loperand++;
366 break;
368 case P_ALL:
369 loperand++;
370 break;
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
381 switch (psp->p_ridtype) {
383 case P_LWPID:
384 if (pp == ttoproc(curthread))
385 if (getlwpptr(psp->p_rid) != NULL)
386 lwprinproc++;
387 break;
389 case P_PID:
390 if (pp->p_pid == psp->p_rid)
391 roperand++;
392 break;
394 case P_PPID:
395 if (pp->p_ppid == psp->p_rid)
396 roperand++;
397 break;
399 case P_PGID:
400 if (pp->p_pgrp == psp->p_rid)
401 roperand++;
402 break;
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;
411 case P_TASKID:
412 if (pp->p_task->tk_tkid == psp->p_rid)
413 roperand++;
414 break;
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;
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;
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;
438 case P_PROJID:
439 if (pp->p_task->tk_proj->kpj_id == psp->p_rid)
440 roperand++;
441 break;
443 case P_POOLID:
444 if (pp->p_pool->pool_id == psp->p_rid)
445 roperand++;
446 break;
448 case P_ZONEID:
449 if (pp->p_zone->zone_id == psp->p_rid)
450 roperand++;
451 break;
453 case P_CTID:
454 if (PRCTID(pp) == psp->p_rid)
455 roperand++;
456 break;
458 case P_ALL:
459 roperand++;
460 break;
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
471 switch (psp->p_op) {
473 case POP_DIFF:
474 if (loperand && !lwprinproc && !roperand)
475 return (1);
476 else
477 return (0);
479 case POP_AND:
480 if (loperand && roperand)
481 return (1);
482 else
483 return (0);
485 case POP_OR:
486 if (loperand || roperand)
487 return (1);
488 else
489 return (0);
491 case POP_XOR:
492 if ((loperand && !lwprinproc && !roperand) ||
493 (roperand && !lwplinproc && !loperand))
494 return (1);
495 else
496 return (0);
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
506 /* NOTREACHED */
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.
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.
519 lwpinset(proc_t *pp, procset_t *psp, kthread_t *tp, int *done)
521 int loperand = 0;
522 int roperand = 0;
523 int lwplinset = 0;
524 int lwprinset = 0;
526 ASSERT(ttoproc(tp) == pp);
529 * If process is in the sys class return (0).
531 if (proctot(pp)->t_cid == 0) {
532 return (0);
535 switch (psp->p_lidtype) {
537 case P_LWPID:
538 if (tp->t_tid == psp->p_lid)
539 lwplinset ++;
540 break;
542 case P_PID:
543 if (pp->p_pid == psp->p_lid)
544 loperand++;
545 break;
547 case P_PPID:
548 if (pp->p_ppid == psp->p_lid)
549 loperand++;
550 break;
552 case P_PGID:
553 if (pp->p_pgrp == psp->p_lid)
554 loperand++;
555 break;
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;
564 case P_TASKID:
565 if (pp->p_task->tk_tkid == psp->p_lid)
566 loperand++;
567 break;
569 case P_CID:
570 if (tp->t_cid == psp->p_lid)
571 loperand++;
572 break;
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;
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;
588 case P_PROJID:
589 if (pp->p_task->tk_proj->kpj_id == psp->p_lid)
590 loperand++;
591 break;
593 case P_POOLID:
594 if (pp->p_pool->pool_id == psp->p_lid)
595 loperand++;
596 break;
598 case P_ZONEID:
599 if (pp->p_zone->zone_id == psp->p_lid)
600 loperand++;
601 break;
603 case P_CTID:
604 if (PRCTID(pp) == psp->p_lid)
605 loperand++;
606 break;
608 case P_ALL:
609 loperand++;
610 break;
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
621 switch (psp->p_ridtype) {
623 case P_LWPID:
624 if (tp->t_tid == psp->p_rid)
625 lwprinset ++;
626 break;
628 case P_PID:
629 if (pp->p_pid == psp->p_rid)
630 roperand++;
631 break;
633 case P_PPID:
634 if (pp->p_ppid == psp->p_rid)
635 roperand++;
636 break;
638 case P_PGID:
639 if (pp->p_pgrp == psp->p_rid)
640 roperand++;
641 break;
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;
650 case P_TASKID:
651 if (pp->p_task->tk_tkid == psp->p_rid)
652 roperand++;
653 break;
655 case P_CID:
656 if (tp->t_cid == psp->p_rid)
657 roperand++;
658 break;
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;
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;
674 case P_PROJID:
675 if (pp->p_task->tk_proj->kpj_id == psp->p_rid)
676 roperand++;
677 break;
679 case P_POOLID:
680 if (pp->p_pool->pool_id == psp->p_rid)
681 roperand++;
682 break;
684 case P_ZONEID:
685 if (pp->p_zone->zone_id == psp->p_rid)
686 roperand++;
687 break;
689 case P_CTID:
690 if (PRCTID(pp) == psp->p_rid)
691 roperand++;
692 break;
694 case P_ALL:
695 roperand++;
696 break;
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
707 if (lwplinset && lwprinset)
708 *done = 1;
710 switch (psp->p_op) {
712 case POP_DIFF:
713 if ((loperand || lwplinset) && !(lwprinset || roperand))
714 return (1);
715 else
716 return (0);
718 case POP_AND:
719 if ((loperand || lwplinset) && (roperand || lwprinset))
720 return (1);
721 else
722 return (0);
724 case POP_OR:
725 if (loperand || roperand || lwplinset || lwprinset)
726 return (1);
727 else
728 return (0);
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);
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
747 /* NOTREACHED */
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.
755 boolean_t
756 cur_inset_only(procset_t *psp)
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);
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);
776 return (B_FALSE);
779 id_t
780 getmyid(idtype_t idtype)
782 proc_t *pp;
783 uid_t uid;
784 gid_t gid;
785 pid_t sid;
787 pp = ttoproc(curthread);
789 switch (idtype) {
790 case P_LWPID:
791 return (curthread->t_tid);
793 case P_PID:
794 return (pp->p_pid);
796 case P_PPID:
797 return (pp->p_ppid);
799 case P_PGID:
800 return (pp->p_pgrp);
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);
808 case P_TASKID:
809 return (pp->p_task->tk_tkid);
811 case P_CID:
812 return (curthread->t_cid);
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);
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);
826 case P_PROJID:
827 return (pp->p_task->tk_proj->kpj_id);
829 case P_POOLID:
830 return (pp->p_pool->pool_id);
832 case P_ZONEID:
833 return (pp->p_zone->zone_id);
835 case P_CTID:
836 return (PRCTID(pp));
838 case P_ALL:
840 * The value doesn't matter for P_ALL.
842 return (0);
844 default:
845 return (-1);
849 static kthread_t *
850 getlwpptr(id_t id)
852 proc_t *p;
853 kthread_t *t;
855 ASSERT(MUTEX_HELD(&(ttoproc(curthread)->p_lock)));
857 if (id == P_MYID)
858 t = curthread;
859 else {
860 p = ttoproc(curthread);
861 t = idtot(p, id);
864 return (t);
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.
881 dotolwp(procset_t *psp, int (*funcp)(), char *arg)
883 int error = 0;
884 int nfound = 0;
885 kthread_t *tp;
886 proc_t *pp;
887 int done = 0;
890 * Check that the procset_t is valid.
892 error = checkprocset(psp);
893 if (error) {
894 return (error);
897 mutex_enter(&pidlock);
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.
905 if (psp->p_lid == P_MYID) {
906 psp->p_lid = getmyid(psp->p_lidtype);
908 if (psp->p_rid == P_MYID) {
909 psp->p_rid = getmyid(psp->p_ridtype);
912 pp = ttoproc(curthread);
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);
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);
931 } while (((tp = tp->t_forw) != pp->p_tlist) && !done);
933 if (nfound == 0) {
934 mutex_exit(&pp->p_lock);
935 mutex_exit(&pidlock);
936 return (ESRCH);
939 mutex_exit(&pidlock);
940 return (error);