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 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 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 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 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 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 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 * 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 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