|
|
1.1 ! root 1: #define _DDI_DKI 1 ! 2: #define _DDI_DKI_IMPL 1 ! 3: #define _SYSV3 1 ! 4: ! 5: /* ! 6: * This file contains the implementations of the abstract scheduling ! 7: * interface functions defined in <sys/v_proc.h>. ! 8: * ! 9: * The functions defined here are used only by the code that needs to sleep ! 10: * processes to implement the DDI/DKI sleep lock and synchronization variable ! 11: * functionality. The code here has been broken out into a separate file and ! 12: * a formal interface specified purely to separate the abstract and ! 13: * implementation-dependent aspects of the DDI/DKI locking functions, ie to ! 14: * stop the original code being infected with #ifdefs. ! 15: * ! 16: * This module runs in the _SYSV3 compilation mode to interface with the iBCS2 ! 17: * Coherent kernel. ! 18: */ ! 19: ! 20: /* ! 21: *-IMPORTS: ! 22: * <common/ccompat.h> ! 23: * __CONST__ ! 24: * __USE_PROTO__ ! 25: * __ARGS () ! 26: * <common/xdebug.h> ! 27: * __LOCAL__ ! 28: * <kernel/ddi_proc.h> ! 29: * ddi_proc_data () ! 30: * <kernel/ddi_glob.h> ! 31: * ddi_global_data () ! 32: * <kernel/ddi_lock.h> ! 33: * proc_global_priority ! 34: * <sys/debug.h> ! 35: * ASSERT () ! 36: * <sys/types.h> ! 37: * plhi ! 38: * <sys/inline.h> ! 39: * splbase () ! 40: * <sys/ksynch.h> ! 41: * LOCK () ! 42: * UNLOCK () ! 43: * <sys/signal.h> ! 44: * SIGTSTP ! 45: */ ! 46: ! 47: #include <common/ccompat.h> ! 48: #include <common/xdebug.h> ! 49: #include <kernel/ddi_proc.h> ! 50: #include <kernel/ddi_glob.h> ! 51: #include <kernel/ddi_lock.h> ! 52: #include <sys/debug.h> ! 53: #include <sys/types.h> ! 54: #include <sys/inline.h> ! 55: #include <sys/ksynch.h> ! 56: #include <sys/signal.h> ! 57: #include <stddef.h> ! 58: ! 59: #include <kernel/v_proc.h> ! 60: ! 61: /* ! 62: * Type used in comparisons of process priority. ! 63: */ ! 64: ! 65: typedef unsigned short pri_t; ! 66: ! 67: ! 68: #define PROCESS_PNODE() (& ddi_proc_data ()->dp_pnode) ! 69: ! 70: ! 71: /* ! 72: * Here we deal with the implementation-specifics. ! 73: */ ! 74: ! 75: #if __COHERENT__ ! 76: ! 77: #define __KERNEL__ 2 ! 78: #include <sys/sched.h> ! 79: #undef __KERNEL__ ! 80: ! 81: #define PNODE_TO_PROC(pnode) __DOWNCAST (PROC, p_nigel, \ ! 82: __DOWNCAST (dpdata_t, dp_pnode, pnode)) ! 83: ! 84: ! 85: /* ! 86: * Implementation-specific version of KERNEL_SLEEP (). ! 87: */ ! 88: ! 89: #if __USE_PROTO__ ! 90: __LOCAL__ int (KERNEL_SLEEP) (plist_t * plistp, int priority, int flag) ! 91: #else ! 92: __LOCAL__ int ! 93: (KERNEL_SLEEP) __ARGS ((plistp, priority, flag)) ! 94: plist_t * plistp; ! 95: int priority; ! 96: int flag; ! 97: #endif ! 98: { ! 99: pnode_t * pnode = PROCESS_PNODE (); ! 100: int state; ! 101: ! 102: /* ! 103: * Since Coherent's signal-checking causes a longjump out to the ! 104: * top-level, we'll check for signals here ourself. ! 105: */ ! 106: ! 107: if (flag == SLEEP_INTERRUPTIBLE && nondsig ()) { ! 108: /* ! 109: * We have pending signals that need processing, dequeue us ! 110: * from the plist, ulock the plist, and return an appropriate ! 111: * indication to the caller. ! 112: */ ! 113: ! 114: plistp->pl_head = pnode->pn_next; ! 115: pnode->pn_next->pn_prev = NULL; ! 116: ! 117: ATOMIC_CLEAR_PTR (pnode->pn_plistp); ! 118: ! 119: PLIST_UNLOCK (plistp, plbase); ! 120: ! 121: return PROCESS_SIGNALLED; ! 122: } ! 123: ! 124: ! 125: /* ! 126: * We expect to be running with interrupts disabled, so there's no ! 127: * reason not to just unlock the basic lock now and use the standard ! 128: * off-the-shelf Coherent kernel sleep function. ! 129: */ ! 130: ! 131: for (;;) { ! 132: PLIST_UNLOCK (plistp, plhi); ! 133: ! 134: x_sleep (pnode, priority, slpriNoSig, "STREAMS"); ! 135: ! 136: /* ! 137: * The Coherent kernel won't dequeue us from the process list ! 138: * if it awakens us via a signal, so we use that fact to ! 139: * figure out why we are awake (sleep () does not return any ! 140: * useful value). ! 141: * ! 142: * To do anything about this in a multiprocessor-friendly ! 143: * fashion, we have to re-acquire the process list lock. ! 144: */ ! 145: ! 146: (void) PLIST_LOCK (plistp, "KERNEL_SLEEP"); ! 147: ! 148: if (ATOMIC_FETCH_PTR (pnode->pn_plistp) == 0) { ! 149: state = PROCESS_NORMAL_WAKE; ! 150: break; /* dequeued, normal wakeup */ ! 151: } ! 152: ! 153: ! 154: /* ! 155: * We were signalled; our caller may have requested non- ! 156: * interruptible sleep, so we go back to sleep on the caller's ! 157: * behalf (Coherent will always wake up a sleeper on receipt ! 158: * of a signal). ! 159: */ ! 160: ! 161: if (flag == SLEEP_INTERRUPTIBLE) { ! 162: /* ! 163: * We were woken by a signal and the caller wants to ! 164: * know about it, so dequeue us from the list and ! 165: * return the indication. ! 166: */ ! 167: ! 168: plistp->pl_head = pnode->pn_next; ! 169: pnode->pn_next->pn_prev = NULL; ! 170: ! 171: ATOMIC_CLEAR_PTR (pnode->pn_plistp); ! 172: ! 173: state = PROCESS_SIGNALLED; ! 174: break; ! 175: } ! 176: } ! 177: ! 178: /* ! 179: * Since we acquired a lock on the process list in order to safely ! 180: * test the reason why we awoke, release that lock now. Since we can, ! 181: * we'll set the interrupt priority down low. ! 182: */ ! 183: ! 184: PLIST_UNLOCK (plistp, plbase); ! 185: ! 186: return state; ! 187: } ! 188: ! 189: ! 190: /* ! 191: * Implementation-specific version of KERNEL_WAKE (). ! 192: */ ! 193: ! 194: #if __USE_PROTO__ ! 195: __LOCAL__ void (KERNEL_WAKE) (pnode_t * pnodep) ! 196: #else ! 197: __LOCAL__ void ! 198: KERNEL_WAKE __ARGS ((pnodep)) ! 199: pnode_t * pnodep; ! 200: #endif ! 201: { ! 202: dwakeup (pnodep); /* don't defer this */ ! 203: } ! 204: ! 205: ! 206: /* ! 207: * Implementation-specific code to send a signal to a process. ! 208: */ ! 209: ! 210: #if __USE_PROTO__ ! 211: __LOCAL__ void (KERNEL_SIGNAL) (dpdata_t * dpdatap, int sig) ! 212: #else ! 213: __LOCAL__ void ! 214: KERNEL_SIGNAL __ARGS ((dpdatap, sig)) ! 215: dpdata_t * dpdatap; ! 216: int sig; ! 217: #endif ! 218: { ! 219: /* ! 220: * Since the Coherent process management system is ... not very ! 221: * sophisticated, and fixing it is less important than getting STREAMS ! 222: * out the door, we punt on some issues such as process reference ! 223: * counts and state checking. This is just glue to the old, broken ! 224: * system. ! 225: */ ! 226: ! 227: } ! 228: ! 229: ! 230: #else ! 231: ! 232: ! 233: uarea_t _dos_uarea_; ! 234: proc_t _dos_proc_; ! 235: ! 236: #define PNODE_TO_PROC(pnodep) __DOWNCAST (proc_t, p_nigel, \ ! 237: __DOWNCAST (dpdata_t, dp_pnode, pnodep)) ! 238: ! 239: #include <sys/cmn_err.h> ! 240: #include <bios.h> ! 241: ! 242: ! 243: /* ! 244: * Implementation-specific version of KERNEL_SLEEP (). ! 245: */ ! 246: ! 247: #if __USE_PROTO__ ! 248: __LOCAL__ int (KERNEL_SLEEP) (plist_t * plistp, int priority, int flag) ! 249: #else ! 250: __LOCAL__ int ! 251: (KERNEL_SLEEP) __ARGS ((plistp, priority, flag)) ! 252: plist_t * plistp; ! 253: int priority; ! 254: int flag; ! 255: #endif ! 256: { ! 257: int state; ! 258: ! 259: ! 260: CURRENT_PROCESS ()->p_state = PS_SLEEP; ! 261: ! 262: PLIST_UNLOCK (plistp, plhi); ! 263: (void) splbase (); ! 264: ! 265: while ((state = CURRENT_PROCESS ()->p_state) != PS_RUN && ! 266: state != PS_SIGNALLED) ! 267: if (_bios_keybrd (_KEYBRD_READY)) ! 268: switch (_bios_keybrd (_KEYBRD_READ) & 0xFF) { ! 269: ! 270: case 0x1B: ! 271: cmn_err (CE_PANIC, "Abort!"); ! 272: break; ! 273: ! 274: default: ! 275: break; ! 276: } ! 277: ! 278: return (state == PS_RUN ? PROCESS_NORMAL_WAKE : PROCESS_SIGNALLED); ! 279: } ! 280: ! 281: ! 282: /* ! 283: * Implementation-specific version of KERNEL_WAKE () ! 284: */ ! 285: ! 286: #if __USE_PROTO__ ! 287: __LOCAL__ void (KERNEL_WAKE) (pnode_t * pnodep) ! 288: #else ! 289: __LOCAL__ void ! 290: KERNEL_WAKE __ARGS ((pnodep)) ! 291: pnode_t * pnodep; ! 292: #endif ! 293: { ! 294: ASSERT (pnodep == PROCESS_PNODE ()); ! 295: ! 296: if (CURRENT_PROCESS ()->p_state == PS_SLEEP || ! 297: CURRENT_PROCESS ()->p_state == PS_SLEEP_NO_SIG) ! 298: CURRENT_PROCESS ()->p_state = PS_RUN; ! 299: } ! 300: ! 301: ! 302: /* ! 303: * Implementation-specific code to send a signal to a process. ! 304: */ ! 305: ! 306: #if __USE_PROTO__ ! 307: __LOCAL__ int (KERNEL_SIGNAL) (dpdata_t * dpdatap, int sig) ! 308: #else ! 309: __LOCAL__ int ! 310: KERNEL_SIGNAL __ARGS ((dpdatap, sig)) ! 311: dpdata_t * dpdatap; ! 312: int sig; ! 313: #endif ! 314: { ! 315: if (CURRENT_PROCESS ()->p_state == PS_SLEEP) ! 316: CURRENT_PROCESS ()->p_state = PS_SIGNALLED; ! 317: ! 318: return 0; ! 319: } ! 320: ! 321: #endif ! 322: ! 323: ! 324: /* ! 325: * Table to define the mapping between abstract processor priority and the ! 326: * priority levels used in the comparisons between priority levels. ! 327: */ ! 328: ! 329: __LOCAL__ pri_t _pri_map [] = { ! 330: 0, 1, 2, 3, 4, 5, 6, /* prilo */ ! 331: 7, 8, 9, 10, 11, 12, 13, /* pritape */ ! 332: 14, 15, 16, 17, 18, 19, 20, /* primed */ ! 333: 21, 22, 23, 24, 25, 26, 27, /* pritty */ ! 334: 28, 29, 30, 31, 32, 33, 34, /* pridisk */ ! 335: 35, 36, 37, 38, 39, 40, 41, /* prinet */ ! 336: 42, 43, 44, 45, 46, 47, 48 /* prihi */ ! 337: }; ! 338: ! 339: ! 340: ! 341: /* ! 342: * This function is the abstract interface used by the DDI/DKI functions to ! 343: * invoke kernel sleep. ! 344: * ! 345: * This function is charged with sleeping the current process (possibly such ! 346: * that it may be interrupted by signals). It is passed a pointer to a locked ! 347: * process list structure on which the current process is to be threaded if ! 348: * it is actually going to sleep. After moving the process to a "slept" ! 349: * state and saving the process context the process list is unlocked before ! 350: * the main kernel dispatched is invoked. ! 351: */ ! 352: ! 353: #define ARRAY_MAX(array) (sizeof (array) / sizeof ((array) [0])) ! 354: ! 355: #if __USE_PROTO__ ! 356: int (MAKE_SLEEPING) (plist_t * plistp, int priority, int flag) ! 357: #else ! 358: int ! 359: MAKE_SLEEPING __ARGS ((plistp, priority, flag)) ! 360: plist_t * plistp; ! 361: int priority; ! 362: int flag; ! 363: #endif ! 364: { ! 365: pnode_t * pnodep = PROCESS_PNODE (); ! 366: pnode_t * pscan; ! 367: pnode_t * pprev; ! 368: unsigned my_pri = _pri_map [priority]; ! 369: ! 370: ASSERT (plistp != NULL); ! 371: PLIST_ASSERT_LOCKED (plistp); ! 372: ! 373: ASSERT (priority >= 0 && priority < ARRAY_MAX (_pri_map)); ! 374: ASSERT (flag == SLEEP_NO_SIGNALS || flag == SLEEP_INTERRUPTIBLE); ! 375: ! 376: /* ! 377: * Walk down the list of processes until one is found with a lower ! 378: * abstract priority than the process we are going to put to sleep. ! 379: */ ! 380: ! 381: for (pscan = plistp->pl_head, pprev = NULL ; pscan != NULL ; ! 382: pscan = (pprev = pscan)->pn_next) { ! 383: /* ! 384: * Don't forget to map the stored priority... ! 385: */ ! 386: ! 387: if (_pri_map [pscan->pn_priority] < my_pri) ! 388: break; ! 389: } ! 390: ! 391: ! 392: /* ! 393: * Now insert the current process between pprev and pscan. ! 394: */ ! 395: ! 396: if (pprev == NULL) ! 397: plistp->pl_head = pnodep; ! 398: else ! 399: pprev->pn_next = pnodep; ! 400: ! 401: if (pscan != NULL) ! 402: pscan->pn_prev = pnodep; ! 403: ! 404: pnodep->pn_prev = pprev; ! 405: pnodep->pn_next = pscan; ! 406: ! 407: ! 408: /* ! 409: * We store the unmapped (abstract) priority since it should make more ! 410: * sense for a "ps"-like utility, and mapping it is cheap. ! 411: */ ! 412: ! 413: pnodep->pn_priority = priority; ! 414: pnodep->pn_flag = flag; ! 415: ATOMIC_STORE_PTR (pnodep->pn_plistp, plistp); ! 416: ! 417: ! 418: /* ! 419: * Now we are going to actually perform the low-level sleep. ! 420: * ! 421: * This thing gets to perform the kernel-specific bit of sleeping the ! 422: * process, possibly with signal checks and whatnot, unlocking the ! 423: * plist, and running the next process. ! 424: */ ! 425: ! 426: return KERNEL_SLEEP (plistp, priority, flag); ! 427: } ! 428: ! 429: ! 430: /* ! 431: * This function wakes one of the processes queued on a plist; since the ! 432: * MAKE_SLEEPING () function queues them in priority order, let's wake up ! 433: * the first... ! 434: */ ! 435: ! 436: #if __USE_PROTO__ ! 437: __VOID__ * (WAKE_ONE) (plist_t * plistp) ! 438: #else ! 439: __VOID__ * ! 440: WAKE_ONE __ARGS ((plistp)) ! 441: plist_t * plistp; ! 442: #endif ! 443: { ! 444: pnode_t * pnodep; ! 445: ! 446: ASSERT (plistp != NULL); ! 447: PLIST_ASSERT_LOCKED (plistp); ! 448: ! 449: if ((pnodep = plistp->pl_head) != NULL) { ! 450: /* ! 451: * Given that we have something to awaken, dequeue it and ! 452: * make it runnable. ! 453: */ ! 454: ! 455: plistp->pl_head = pnodep->pn_next; ! 456: pnodep->pn_next->pn_prev = NULL; ! 457: ! 458: KERNEL_WAKE (pnodep); ! 459: ! 460: /* ! 461: * Return the identity of the person we gave the lock to. ! 462: */ ! 463: ! 464: return pnodep; ! 465: } ! 466: ! 467: /* ! 468: * Indicate that we found no-one to take over the mantle... ! 469: */ ! 470: ! 471: return NULL; ! 472: } ! 473: ! 474: ! 475: /* ! 476: * This function wakes all of the processes queued on a plist. ! 477: */ ! 478: ! 479: #if __USE_PROTO__ ! 480: void (WAKE_ALL) (plist_t * plistp) ! 481: #else ! 482: void ! 483: WAKE_ALL __ARGS ((plistp)) ! 484: plist_t * plistp; ! 485: #endif ! 486: { ! 487: pnode_t * pnodep; ! 488: pnode_t * pnext; ! 489: ! 490: ASSERT (plistp != NULL); ! 491: PLIST_ASSERT_LOCKED (plistp); ! 492: ! 493: for (pnodep = plistp->pl_head ; pnodep != NULL ; pnodep = pnext) { ! 494: /* ! 495: * We take the value of the "pn_next" member now, because the ! 496: * MAKE_RUNNABLE () call has the freedom to alter any of the ! 497: * members of the pnode to deal with such things as ! 498: * signalling. ! 499: */ ! 500: ! 501: pnext = pnodep->pn_next; ! 502: ! 503: KERNEL_WAKE (pnodep); ! 504: } ! 505: ! 506: plistp->pl_head = NULL; ! 507: } ! 508: ! 509: ! 510: /* ! 511: * This function returns a value suitable for use as a process identifier for ! 512: * the DDI/DKI SLEEP_LOCKOWNED () function to identify the current context. ! 513: */ ! 514: ! 515: #if __USE_PROTO__ ! 516: __VOID__ * (PROC_HANDLE) (void) ! 517: #else ! 518: __VOID__ * ! 519: PROC_HANDLE __ARGS (()) ! 520: #endif ! 521: { ! 522: return PROCESS_PNODE (); ! 523: } ! 524: ! 525: ! 526: /* ! 527: *-STATUS: ! 528: * DDI/DKI ! 529: * ! 530: *-NAME: ! 531: * proc_ref Obtain a reference to a process for signalling. ! 532: * ! 533: *-SYNOPSIS: ! 534: * #include <sys/types.h> ! 535: * ! 536: * void * proc_ref (); ! 537: * ! 538: *-DESCRIPTION: ! 539: * A non-STREAMS character driver can call proc_ref () to obtain a ! 540: * reference to the process in whose context it is running. The value ! 541: * returned can be used in subsequent calls to proc_signal () to post a ! 542: * signal to the process. The return value should not be used in any ! 543: * other way (ie, the driver should not attempt to interpret its ! 544: * meaning). ! 545: * ! 546: *-RETURN VALUE: ! 547: * An identifier that can be used in calls to proc_signal () and ! 548: * proc_unref (). ! 549: * ! 550: *-LEVEL: ! 551: * Base only. ! 552: * ! 553: *-NOTES: ! 554: * Processes can exit even though they are referenced by drivers. In this ! 555: * event, reuse of the identifier will be deferred until all driver ! 556: * references are given up. ! 557: * ! 558: * There must be a matching call to proc_unref () for every call to ! 559: * proc_ref (), when the driver no longer needs to reference the process. ! 560: * This is typically done as part of close () processing. ! 561: * ! 562: * Requires user context. ! 563: * ! 564: * Does not sleep. ! 565: * ! 566: * Driver-defined basic locks, read/write locks, and sleep locks may be ! 567: * held across calls to this function. ! 568: * ! 569: *-SEE ALSO: ! 570: * proc_signal (), proc_unref () ! 571: */ ! 572: ! 573: #if __USE_PROTO__ ! 574: __VOID__ * (proc_ref) (void) ! 575: #else ! 576: __VOID__ * ! 577: proc_ref __ARGS (()) ! 578: #endif ! 579: { ! 580: pl_t prev_pl; ! 581: dpdata_t * dpdatap; ! 582: ! 583: ASSERT_BASE_LEVEL (); ! 584: ! 585: ! 586: /* ! 587: * This implementation is a really just a stub for testing. Later ! 588: * revisions of the code (especially in proc_unref () will deal with ! 589: * the synchronization and storage management issues properly. ! 590: * ! 591: * In addition, leaving the multiprocessor rewrite of the process ! 592: * system for another time will be good for ensuring that proper ! 593: * encapsulation boundaries are created and respected, and will ensure ! 594: * that the ideas prototypes here have been properly tested before ! 595: * they are incorporated into other kernel areas. ! 596: */ ! 597: ! 598: dpdatap = ddi_proc_data (); ! 599: ! 600: prev_pl = LOCK (ddi_global_data ()->dg_proclock, ! 601: proc_global_priority); ! 602: ! 603: dpdatap->dp_refcount ++; ! 604: ! 605: UNLOCK (ddi_global_data ()->dg_proclock, prev_pl); ! 606: ! 607: return dpdatap; ! 608: } ! 609: ! 610: ! 611: /* ! 612: *-STATUS: ! 613: * DDI/DKI ! 614: * ! 615: *-NAME: ! 616: * proc_signal Send a signal to a process. ! 617: * ! 618: *-SYNOPSIS: ! 619: * #include <sys/types.h> ! 620: * #include <sys/signal.h> ! 621: * ! 622: * int proc_signal (void * pref, int sig); ! 623: * ! 624: *-ARGUMENTS: ! 625: * pref Identifier obtained by a previous call to proc_ref (). ! 626: * ! 627: * sig Signal number to be sent. Valid signal numbers to be ! 628: * sent are: ! 629: * SIGHUP The device has been disconnected. ! 630: * SIGINT The interrupt character has been ! 631: * received. ! 632: * SIGQUIT The quit character has been received. ! 633: * SIGWINCH The window size has changed. ! 634: * SIGURG Urgent data are available. ! 635: * SIGPOLL A pollable event has occurred. ! 636: * ! 637: *-DESCRIPTION: ! 638: * The proc_signal () function can be used to post a signal to the ! 639: * process represented by "pref". This will interrupt any process blocked ! 640: * in SV_WAIT_SIG () or SLEEP_LOCK_SIG () at the time the signal is ! 641: * posted, causing those functions to return prematurely in most cases. ! 642: * If the process has exited then this function has no effect. ! 643: * ! 644: *-RETURN VALUE: ! 645: * If the process still exists, 0 is returned. Otherwise, -1 is returned ! 646: * to indicate that the process no longer exists. ! 647: * ! 648: *-LEVEL: ! 649: * Base or interrupt. ! 650: * ! 651: *-NOTES: ! 652: * STREAMS drivers and modules should not use this mechanism for ! 653: * signalling processes. Instead, they can send M_SIG or M_PCSIG STREAMS ! 654: * messages to the stream head. ! 655: * ! 656: * proc_signal () must not be used to send SIGTSTP to a process. ! 657: * ! 658: * Does not sleep. ! 659: * ! 660: * Driver-defined basic locks, read/write locks, and sleep locks may be ! 661: * held across calls to this function. ! 662: * ! 663: *-SEE ALSO: ! 664: * proc_ref (), proc_unref () ! 665: */ ! 666: ! 667: #if __USE_PROTO__ ! 668: int (proc_signal) (__VOID__ * pref, int sig) ! 669: #else ! 670: int ! 671: proc_signal __ARGS ((pref, sig)) ! 672: __VOID__ * pref; ! 673: int sig; ! 674: #endif ! 675: { ! 676: dpdata_t * dpdatap = (dpdata_t *) pref; ! 677: ! 678: ASSERT (pref != NULL); ! 679: ASSERT (sig != SIGTSTP); ! 680: ! 681: return KERNEL_SIGNAL (dpdatap, sig); ! 682: } ! 683: ! 684: ! 685: /* ! 686: *-STATUS: ! 687: * DDI/DKI ! 688: * ! 689: *-SYNOPSIS: ! 690: * #include <sys/types.h> ! 691: * ! 692: * void proc_unref (void * pref); ! 693: * ! 694: *-ARGUMENTS: ! 695: * pref Identifier obtained by a previous call to proc_ref (). ! 696: * ! 697: *-DESCRIPTION: ! 698: * The proc_unref () function can be used to release a reference to a ! 699: * process identified by the parameter "pref". There must be a matching ! 700: * call to proc_unref () for every previous call to proc_ref (). ! 701: * ! 702: *-RETURN VALUE: ! 703: * None. ! 704: * ! 705: *-LEVEL: ! 706: * Base or interrupt. ! 707: * ! 708: *-NOTE: ! 709: * Processes can exit even though they are referenced by drivers. In this ! 710: * event, reuse of "pref" will be deferred until all driver references ! 711: * are given up. ! 712: * ! 713: * Does not sleep. ! 714: * ! 715: * Driver-defined basic locks, read/write locks, and sleep locks may be ! 716: * held across calls to this function. ! 717: * ! 718: *-SEE ALSO: ! 719: * proc_ref (), proc_signal () ! 720: */ ! 721: ! 722: #if __USE_PROTO__ ! 723: void (proc_unref) (__VOID__ * pref) ! 724: #else ! 725: void ! 726: proc_unref __ARGS ((pref)) ! 727: __VOID__ * pref; ! 728: #endif ! 729: { ! 730: pl_t prev_pl; ! 731: dpdata_t * dpdatap = (dpdata_t *) pref; ! 732: ! 733: ASSERT (pref != NULL); ! 734: ! 735: /* ! 736: * This implementation is a really just a stub for testing. Later ! 737: * revisions of the code will deal with the synchronization and ! 738: * storage management issues properly. ! 739: */ ! 740: ! 741: prev_pl = LOCK (ddi_global_data ()->dg_proclock, ! 742: proc_global_priority); ! 743: ! 744: dpdatap->dp_refcount --; ! 745: ! 746: UNLOCK (ddi_global_data ()->dg_proclock, prev_pl); ! 747: } ! 748: ! 749: ! 750: /* ! 751: *-STATUS: ! 752: * Internal ! 753: * ! 754: *-SYNOPSIS: ! 755: * #include <sys/types.h> ! 756: * ! 757: * void proc_kill_group (pid_t group, int sig); ! 758: * ! 759: *-ARGUMENTS: ! 760: * group Process group ID to which the signal will be sent. All ! 761: * members of the indicated process group will be sent ! 762: * the signal. ! 763: * ! 764: * sig Signal number to be sent. Valid signal numbers are: ! 765: * SIGHUP The device has been disconnected. ! 766: * SIGINT The interrupt character has been ! 767: * received. ! 768: * SIGQUIT The quit character has been received. ! 769: * SIGWINCH The window size has changed. ! 770: * SIGURG Urgent data are available. ! 771: * SIGPOLL A pollable event has occurred. ! 772: * ! 773: *-DESCRIPTION: ! 774: * The proc_kill_group () function can be used to post a signal to a ! 775: * group of processes. This will interrupt any process blocked in ! 776: * SV_WAIT_SIG () or SLEEP_LOCK_SIG () at the time the signal is posted, ! 777: * causing those functions to return prematurely in most cases. ! 778: * ! 779: *-RETURN VALUE: ! 780: * None. ! 781: * ! 782: *-LEVEL: ! 783: * Base or interrupt. ! 784: * ! 785: *-NOTES: ! 786: * STREAMS drivers and modules should not use this mechanism for ! 787: * signalling processes. Instead, they can send M_SIG or M_PCSIG STREAMS ! 788: * messages to the stream head. ! 789: * ! 790: * proc_kill_group () must not be used to send SIGTSTP to a process. ! 791: * ! 792: * Does not sleep. ! 793: * ! 794: * Driver-defined basic locks, read/write locks, and sleep locks may be ! 795: * held across calls to this function. ! 796: * ! 797: *-SEE ALSO: ! 798: * proc_ref (), proc_signal (), proc_unref () ! 799: */ ! 800: ! 801: #if __USE_PROTO__ ! 802: void (proc_kill_group) (pid_t group, int sig) ! 803: #else ! 804: void ! 805: proc_kill_group __ARGS ((group, sig)) ! 806: pid_t group; ! 807: int sig; ! 808: #endif ! 809: { ! 810: ASSERT ("proc_kill_group () : not implemented" == 0); ! 811: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.