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