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 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 64 id_t getmyid(idtype_t); 65 int checkprocset(procset_t *); 66 static kthread_t *getlwpptr(id_t); 67 int procinset(proc_t *, procset_t *); 68 static 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 */ 86 int 87 dotoprocs(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 172 /* 173 * Ignore this process if it's coming or going, 174 * if it's a system process or if it's not in 175 * the given procset_t. 176 */ 177 if (prp->p_stat == SIDL || prp->p_stat == SZOMB) 178 continue; 179 180 mutex_enter(&prp->p_lock); 181 if (prp->p_flag & SSYS || procinset(prp, psp) == 0) { 182 mutex_exit(&prp->p_lock); 183 } else { 184 mutex_exit(&prp->p_lock); 185 nfound++; 186 lastprp = prp; 187 if (prp != proc_init) { 188 error = (*funcp)(prp, arg); 189 if (error == -1) { 190 mutex_exit(&pidlock); 191 return (0); 192 } else if (error) { 193 mutex_exit(&pidlock); 194 return (error); 195 } 196 } 197 } 198 } 199 if (nfound == 0) { 200 mutex_exit(&pidlock); 201 return (ESRCH); 202 } 203 if (nfound == 1 && lastprp == proc_init) 204 error = (*funcp)(lastprp, arg); 205 if (error == -1) 206 error = 0; 207 mutex_exit(&pidlock); 208 return (error); 209 } 210 211 /* 212 * Check if a procset_t is valid. Return zero or an errno. 213 */ 214 int 215 checkprocset(procset_t *psp) 216 { 217 switch (psp->p_lidtype) { 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_ridtype) { 238 case P_LWPID: 239 case P_PID: 240 case P_PPID: 241 case P_PGID: 242 case P_SID: 243 case P_TASKID: 244 case P_CID: 245 case P_UID: 246 case P_GID: 247 case P_PROJID: 248 case P_POOLID: 249 case P_ZONEID: 250 case P_CTID: 251 case P_ALL: 252 break; 253 default: 254 return (EINVAL); 255 } 256 257 switch (psp->p_op) { 258 case POP_DIFF: 259 case POP_AND: 260 case POP_OR: 261 case POP_XOR: 262 break; 263 default: 264 return (EINVAL); 265 } 266 267 return (0); 268 } 269 270 /* 271 * procinset returns 1 if the process pointed to by pp is in the process 272 * set specified by psp, otherwise 0 is returned. A process that is 273 * exiting, by which we mean that its p_tlist is NULL, cannot belong 274 * to any set; pp's p_lock must be held across the call to this function. 275 * The caller should ensure that the process does not belong to the SYS 276 * scheduling class. 277 * 278 * This function expects to be called with a valid procset_t. 279 * The set should be checked using checkprocset() before calling 280 * this function. 281 */ 282 int 283 procinset(proc_t *pp, procset_t *psp) 284 { 285 int loperand = 0; 286 int roperand = 0; 287 int lwplinproc = 0; 288 int lwprinproc = 0; 289 kthread_t *tp = proctot(pp); 290 291 ASSERT(MUTEX_HELD(&pp->p_lock)); 292 293 if (tp == NULL) 294 return (0); 295 296 switch (psp->p_lidtype) { 297 298 case P_LWPID: 299 if (pp == ttoproc(curthread)) 300 if (getlwpptr(psp->p_lid) != NULL) 301 lwplinproc++; 302 break; 303 304 case P_PID: 305 if (pp->p_pid == psp->p_lid) 306 loperand++; 307 break; 308 309 case P_PPID: 310 if (pp->p_ppid == psp->p_lid) 311 loperand++; 312 break; 313 314 case P_PGID: 315 if (pp->p_pgrp == psp->p_lid) 316 loperand++; 317 break; 318 319 case P_SID: 320 mutex_enter(&pp->p_splock); 321 if (pp->p_sessp->s_sid == psp->p_lid) 322 loperand++; 323 mutex_exit(&pp->p_splock); 324 break; 325 326 case P_CID: 327 ASSERT(tp != NULL); 328 /* This case is broken for now. Need to be fixed XXX */ 329 if (tp->t_cid == psp->p_lid) 330 /* 331 * if (checkcid(psp->p_lid)) 332 */ 333 loperand++; 334 break; 335 336 case P_TASKID: 337 if (pp->p_task->tk_tkid == psp->p_lid) 338 loperand++; 339 break; 340 341 case P_UID: 342 mutex_enter(&pp->p_crlock); 343 if (crgetuid(pp->p_cred) == psp->p_lid) 344 loperand++; 345 mutex_exit(&pp->p_crlock); 346 break; 347 348 case P_GID: 349 mutex_enter(&pp->p_crlock); 350 if (crgetgid(pp->p_cred) == psp->p_lid) 351 loperand++; 352 mutex_exit(&pp->p_crlock); 353 break; 354 355 case P_PROJID: 356 if (pp->p_task->tk_proj->kpj_id == psp->p_lid) 357 loperand++; 358 break; 359 360 case P_POOLID: 361 if (pp->p_pool->pool_id == psp->p_lid) 362 loperand++; 363 break; 364 365 case P_ZONEID: 366 if (pp->p_zone->zone_id == psp->p_lid) 367 loperand++; 368 break; 369 370 case P_CTID: 371 if (PRCTID(pp) == psp->p_lid) 372 loperand++; 373 break; 374 375 case P_ALL: 376 loperand++; 377 break; 378 379 default: 380 #ifdef DEBUG 381 cmn_err(CE_WARN, "procinset called with bad set"); 382 return (0); 383 #else 384 return (0); 385 #endif 386 } 387 388 switch (psp->p_ridtype) { 389 390 case P_LWPID: 391 if (pp == ttoproc(curthread)) 392 if (getlwpptr(psp->p_rid) != NULL) 393 lwprinproc++; 394 break; 395 396 case P_PID: 397 if (pp->p_pid == psp->p_rid) 398 roperand++; 399 break; 400 401 case P_PPID: 402 if (pp->p_ppid == psp->p_rid) 403 roperand++; 404 break; 405 406 case P_PGID: 407 if (pp->p_pgrp == psp->p_rid) 408 roperand++; 409 break; 410 411 case P_SID: 412 mutex_enter(&pp->p_splock); 413 if (pp->p_sessp->s_sid == psp->p_rid) 414 roperand++; 415 mutex_exit(&pp->p_splock); 416 break; 417 418 case P_TASKID: 419 if (pp->p_task->tk_tkid == psp->p_rid) 420 roperand++; 421 break; 422 423 case P_CID: 424 ASSERT(tp != NULL); 425 /* This case is broken for now. Need to be fixed XXX */ 426 if (tp->t_cid == psp->p_rid) 427 /* 428 * if (checkcid(psp->p_rid)) 429 */ 430 roperand++; 431 break; 432 433 case P_UID: 434 mutex_enter(&pp->p_crlock); 435 if (crgetuid(pp->p_cred) == psp->p_rid) 436 roperand++; 437 mutex_exit(&pp->p_crlock); 438 break; 439 440 case P_GID: 441 mutex_enter(&pp->p_crlock); 442 if (crgetgid(pp->p_cred) == psp->p_rid) 443 roperand++; 444 mutex_exit(&pp->p_crlock); 445 break; 446 447 case P_PROJID: 448 if (pp->p_task->tk_proj->kpj_id == psp->p_rid) 449 roperand++; 450 break; 451 452 case P_POOLID: 453 if (pp->p_pool->pool_id == psp->p_rid) 454 roperand++; 455 break; 456 457 case P_ZONEID: 458 if (pp->p_zone->zone_id == psp->p_rid) 459 roperand++; 460 break; 461 462 case P_CTID: 463 if (PRCTID(pp) == psp->p_rid) 464 roperand++; 465 break; 466 467 case P_ALL: 468 roperand++; 469 break; 470 471 default: 472 #ifdef DEBUG 473 cmn_err(CE_WARN, "procinset called with bad set"); 474 return (0); 475 #else 476 return (0); 477 #endif 478 } 479 480 switch (psp->p_op) { 481 482 case POP_DIFF: 483 if (loperand && !lwprinproc && !roperand) 484 return (1); 485 else 486 return (0); 487 488 case POP_AND: 489 if (loperand && roperand) 490 return (1); 491 else 492 return (0); 493 494 case POP_OR: 495 if (loperand || roperand) 496 return (1); 497 else 498 return (0); 499 500 case POP_XOR: 501 if ((loperand && !lwprinproc && !roperand) || 502 (roperand && !lwplinproc && !loperand)) 503 return (1); 504 else 505 return (0); 506 507 default: 508 #ifdef DEBUG 509 cmn_err(CE_WARN, "procinset called with bad set"); 510 return (0); 511 #else 512 return (0); 513 #endif 514 } 515 /* NOTREACHED */ 516 } 517 518 /* 519 * lwpinset returns 1 if the thread pointed to 520 * by tp is in the process set specified by psp and is not in 521 * the sys scheduling class - otherwise 0 is returned. 522 * 523 * This function expects to be called with a valid procset_t. 524 * The set should be checked using checkprocset() before calling 525 * this function. 526 */ 527 int 528 lwpinset(proc_t *pp, procset_t *psp, kthread_t *tp, int *done) 529 { 530 int loperand = 0; 531 int roperand = 0; 532 int lwplinset = 0; 533 int lwprinset = 0; 534 535 ASSERT(ttoproc(tp) == pp); 536 537 /* 538 * If process is in the sys class return (0). 539 */ 540 if (proctot(pp)->t_cid == 0) { 541 return (0); 542 } 543 544 switch (psp->p_lidtype) { 545 546 case P_LWPID: 547 if (tp->t_tid == psp->p_lid) 548 lwplinset ++; 549 break; 550 551 case P_PID: 552 if (pp->p_pid == psp->p_lid) 553 loperand++; 554 break; 555 556 case P_PPID: 557 if (pp->p_ppid == psp->p_lid) 558 loperand++; 559 break; 560 561 case P_PGID: 562 if (pp->p_pgrp == psp->p_lid) 563 loperand++; 564 break; 565 566 case P_SID: 567 mutex_enter(&pp->p_splock); 568 if (pp->p_sessp->s_sid == psp->p_lid) 569 loperand++; 570 mutex_exit(&pp->p_splock); 571 break; 572 573 case P_TASKID: 574 if (pp->p_task->tk_tkid == psp->p_lid) 575 loperand++; 576 break; 577 578 case P_CID: 579 if (tp->t_cid == psp->p_lid) 580 loperand++; 581 break; 582 583 case P_UID: 584 mutex_enter(&pp->p_crlock); 585 if (crgetuid(pp->p_cred) == psp->p_lid) 586 loperand++; 587 mutex_exit(&pp->p_crlock); 588 break; 589 590 case P_GID: 591 mutex_enter(&pp->p_crlock); 592 if (crgetgid(pp->p_cred) == psp->p_lid) 593 loperand++; 594 mutex_exit(&pp->p_crlock); 595 break; 596 597 case P_PROJID: 598 if (pp->p_task->tk_proj->kpj_id == psp->p_lid) 599 loperand++; 600 break; 601 602 case P_POOLID: 603 if (pp->p_pool->pool_id == psp->p_lid) 604 loperand++; 605 break; 606 607 case P_ZONEID: 608 if (pp->p_zone->zone_id == psp->p_lid) 609 loperand++; 610 break; 611 612 case P_CTID: 613 if (PRCTID(pp) == psp->p_lid) 614 loperand++; 615 break; 616 617 case P_ALL: 618 loperand++; 619 break; 620 621 default: 622 #ifdef DEBUG 623 cmn_err(CE_WARN, "lwpinset called with bad set"); 624 return (0); 625 #else 626 return (0); 627 #endif 628 } 629 630 switch (psp->p_ridtype) { 631 632 case P_LWPID: 633 if (tp->t_tid == psp->p_rid) 634 lwprinset ++; 635 break; 636 637 case P_PID: 638 if (pp->p_pid == psp->p_rid) 639 roperand++; 640 break; 641 642 case P_PPID: 643 if (pp->p_ppid == psp->p_rid) 644 roperand++; 645 break; 646 647 case P_PGID: 648 if (pp->p_pgrp == psp->p_rid) 649 roperand++; 650 break; 651 652 case P_SID: 653 mutex_enter(&pp->p_splock); 654 if (pp->p_sessp->s_sid == psp->p_rid) 655 roperand++; 656 mutex_exit(&pp->p_splock); 657 break; 658 659 case P_TASKID: 660 if (pp->p_task->tk_tkid == psp->p_rid) 661 roperand++; 662 break; 663 664 case P_CID: 665 if (tp->t_cid == psp->p_rid) 666 roperand++; 667 break; 668 669 case P_UID: 670 mutex_enter(&pp->p_crlock); 671 if (crgetuid(pp->p_cred) == psp->p_rid) 672 roperand++; 673 mutex_exit(&pp->p_crlock); 674 break; 675 676 case P_GID: 677 mutex_enter(&pp->p_crlock); 678 if (crgetgid(pp->p_cred) == psp->p_rid) 679 roperand++; 680 mutex_exit(&pp->p_crlock); 681 break; 682 683 case P_PROJID: 684 if (pp->p_task->tk_proj->kpj_id == psp->p_rid) 685 roperand++; 686 break; 687 688 case P_POOLID: 689 if (pp->p_pool->pool_id == psp->p_rid) 690 roperand++; 691 break; 692 693 case P_ZONEID: 694 if (pp->p_zone->zone_id == psp->p_rid) 695 roperand++; 696 break; 697 698 case P_CTID: 699 if (PRCTID(pp) == psp->p_rid) 700 roperand++; 701 break; 702 703 case P_ALL: 704 roperand++; 705 break; 706 707 default: 708 #ifdef DEBUG 709 cmn_err(CE_WARN, "lwpinset called with bad set"); 710 return (0); 711 #else 712 return (0); 713 #endif 714 } 715 716 if (lwplinset && lwprinset) 717 *done = 1; 718 719 switch (psp->p_op) { 720 721 case POP_DIFF: 722 if ((loperand || lwplinset) && !(lwprinset || roperand)) 723 return (1); 724 else 725 return (0); 726 727 case POP_AND: 728 if ((loperand || lwplinset) && (roperand || lwprinset)) 729 return (1); 730 else 731 return (0); 732 733 case POP_OR: 734 if (loperand || roperand || lwplinset || lwprinset) 735 return (1); 736 else 737 return (0); 738 739 case POP_XOR: 740 if (((loperand || lwplinset) && 741 !(lwprinset || roperand)) || 742 ((roperand || lwprinset) && 743 !(lwplinset || loperand))) 744 return (1); 745 else 746 return (0); 747 748 default: 749 #ifdef DEBUG 750 cmn_err(CE_WARN, "lwpinset called with bad set"); 751 return (0); 752 #else 753 return (0); 754 #endif 755 } 756 /* NOTREACHED */ 757 } 758 /* 759 * Check for common cases of procsets which specify only the 760 * current process. cur_inset_only() returns B_TRUE when 761 * the current process is the only one in the set. B_FALSE 762 * is returned to indicate that this may not be the case. 763 */ 764 boolean_t 765 cur_inset_only(procset_t *psp) 766 { 767 if (((psp->p_lidtype == P_PID && 768 (psp->p_lid == P_MYID || 769 psp->p_lid == ttoproc(curthread)->p_pid)) || 770 ((psp->p_lidtype == P_LWPID) && 771 (psp->p_lid == P_MYID || 772 psp->p_lid == curthread->t_tid))) && 773 psp->p_op == POP_AND && psp->p_ridtype == P_ALL) 774 return (B_TRUE); 775 776 if (((psp->p_ridtype == P_PID && 777 (psp->p_rid == P_MYID || 778 psp->p_rid == ttoproc(curthread)->p_pid)) || 779 ((psp->p_ridtype == P_LWPID) && 780 (psp->p_rid == P_MYID || 781 psp->p_rid == curthread->t_tid))) && 782 psp->p_op == POP_AND && psp->p_lidtype == P_ALL) 783 return (B_TRUE); 784 785 return (B_FALSE); 786 } 787 788 id_t 789 getmyid(idtype_t idtype) 790 { 791 proc_t *pp; 792 uid_t uid; 793 gid_t gid; 794 pid_t sid; 795 796 pp = ttoproc(curthread); 797 798 switch (idtype) { 799 case P_LWPID: 800 return (curthread->t_tid); 801 802 case P_PID: 803 return (pp->p_pid); 804 805 case P_PPID: 806 return (pp->p_ppid); 807 808 case P_PGID: 809 return (pp->p_pgrp); 810 811 case P_SID: 812 mutex_enter(&pp->p_splock); 813 sid = pp->p_sessp->s_sid; 814 mutex_exit(&pp->p_splock); 815 return (sid); 816 817 case P_TASKID: 818 return (pp->p_task->tk_tkid); 819 820 case P_CID: 821 return (curthread->t_cid); 822 823 case P_UID: 824 mutex_enter(&pp->p_crlock); 825 uid = crgetuid(pp->p_cred); 826 mutex_exit(&pp->p_crlock); 827 return (uid); 828 829 case P_GID: 830 mutex_enter(&pp->p_crlock); 831 gid = crgetgid(pp->p_cred); 832 mutex_exit(&pp->p_crlock); 833 return (gid); 834 835 case P_PROJID: 836 return (pp->p_task->tk_proj->kpj_id); 837 838 case P_POOLID: 839 return (pp->p_pool->pool_id); 840 841 case P_ZONEID: 842 return (pp->p_zone->zone_id); 843 844 case P_CTID: 845 return (PRCTID(pp)); 846 847 case P_ALL: 848 /* 849 * The value doesn't matter for P_ALL. 850 */ 851 return (0); 852 853 default: 854 return (-1); 855 } 856 } 857 858 static kthread_t * 859 getlwpptr(id_t id) 860 { 861 proc_t *p; 862 kthread_t *t; 863 864 ASSERT(MUTEX_HELD(&(ttoproc(curthread)->p_lock))); 865 866 if (id == P_MYID) 867 t = curthread; 868 else { 869 p = ttoproc(curthread); 870 t = idtot(p, id); 871 } 872 873 return (t); 874 } 875 876 /* 877 * The dotolwp function locates the LWP(s) specified by the procset structure 878 * pointed to by psp. If funcp is non-NULL then it points to a function 879 * which dotolwp will call for each LWP in the specified set. 880 * LWPIDs specified in the procset structure always refer to lwps in curproc. 881 * The arguments for this function must be "char *arg", and "kthread_t *tp", 882 * where tp is a pointer to the current thread from the set. 883 * Note that these arguments are passed to the function in reversed order 884 * than the order of arguments passed by dotoprocs() to its callback function. 885 * Also note that there are two separate cases where this routine returns zero. 886 * In the first case no mutex is grabbed, in the second the p_lock mutex 887 * is NOT RELEASED. The priocntl code is expecting this behaviour. 888 */ 889 int 890 dotolwp(procset_t *psp, int (*funcp)(), char *arg) 891 { 892 int error = 0; 893 int nfound = 0; 894 kthread_t *tp; 895 proc_t *pp; 896 int done = 0; 897 898 /* 899 * Check that the procset_t is valid. 900 */ 901 error = checkprocset(psp); 902 if (error) { 903 return (error); 904 } 905 906 mutex_enter(&pidlock); 907 908 /* 909 * Check for the special value P_MYID in either operand 910 * and replace it with the correct value. We don't check 911 * for an error return from getmyid() because the idtypes 912 * have been validated by the checkprocset() call above. 913 */ 914 if (psp->p_lid == P_MYID) { 915 psp->p_lid = getmyid(psp->p_lidtype); 916 } 917 if (psp->p_rid == P_MYID) { 918 psp->p_rid = getmyid(psp->p_ridtype); 919 } 920 921 pp = ttoproc(curthread); 922 923 mutex_enter(&pp->p_lock); 924 if (procinset(pp, psp) || 925 (tp = pp->p_tlist) == NULL) { 926 mutex_exit(&pp->p_lock); 927 mutex_exit(&pidlock); 928 return (0); 929 } 930 do { 931 if (lwpinset(pp, psp, tp, &done)) { 932 nfound ++; 933 error = (*funcp)(arg, tp); 934 if (error) { 935 mutex_exit(&pp->p_lock); 936 mutex_exit(&pidlock); 937 return (error); 938 } 939 } 940 } while (((tp = tp->t_forw) != pp->p_tlist) && !done); 941 942 if (nfound == 0) { 943 mutex_exit(&pp->p_lock); 944 mutex_exit(&pidlock); 945 return (ESRCH); 946 } 947 948 mutex_exit(&pidlock); 949 return (error); 950 } 951