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