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