|
|
1.1 root 1: /* $Header: /src386/STREAMS/coh.386/RCS/ker_data.c,v 2.1 93/08/09 13:35:41 bin Exp Locker: bin $ */
2: /*
3: * This file contains definitions for the functions which support the Coherent
4: * internal binary-compatibility scheme. We select _SYSV3 to get some old
5: * definitions like makedev () visible.
6: */
7: /*
8: * $Log: ker_data.c,v $
9: * Revision 2.1 93/08/09 13:35:41 bin
10: * Kernel 82 changes
11: *
12: * Revision 2.2 93/07/26 14:55:28 nigel
13: * Nigel's R80
14: *
15: */
16:
17: #define _SYSV3 1
18:
19: #include <common/ccompat.h>
20: #include <common/_tricks.h>
21: #include <common/_gregset.h>
22: #include <kernel/sigproc.h>
23: #include <kernel/v_types.h>
24: #include <sys/debug.h>
25: #include <string.h>
26:
27: /*
28: * These two pull in all the old-style trash.
29: */
30:
31: #include <sys/coherent.h>
32: #include <sys/uproc.h>
33: #include <sys/proc.h>
34:
35: /*
36: * Stubs for the multiprocessor locking functions.
37: */
38:
39: #define PROC_STATE_LOCK(proc) sphi ()
40: #define PROC_STATE_UNLOCK(proc,pl) spl (pl)
41: #define PROC_ASSERT_LOCKED(proc) ((void) 0)
42:
43:
44: /*
45: * Initialize a freshly-allocated process structure to a copy of the current
46: * process. As a special case, if there is no current process, the new process
47: * is given some default values.
48: */
49:
50: #if __USE_PROTO__
51: void PROC_INIT (__proc_t * process)
52: #else
53: void
54: PROC_INIT (process)
55: __proc_t * process;
56: #endif
57: {
58: process->p_event = NULL; /* Wakeup event channel */
59: process->p_alarm = 0; /* Timer for alarms */
60:
61: process->p_utime = 0L; /* User time (HZ) */
62: process->p_stime = 0L; /* System time */
63: process->p_cutime = 0L; /* Sum of childs user time */
64: process->p_cstime = 0L; /* Sum of childs system time */
65: process->p_exit = 0; /* Exit status */
66: process->p_polls = NULL; /* Enabled polls */
67:
68: /* Poll timer */
69: process->p_polltim.t_next = NULL;
70: process->p_polltim.t_last = NULL;
71: process->p_polltim.t_lbolt = 0L;
72: process->p_polltim.t_func = NULL;
73: process->p_polltim.t_farg = NULL;
74:
75: /* Alarm timer */
76: process->p_alrmtim.t_next = NULL;
77: process->p_alrmtim.t_last = NULL;
78: process->p_alrmtim.t_lbolt = 0L;
79: process->p_alrmtim.t_func = NULL;
80: process->p_alrmtim.t_farg = NULL;
81:
82: process->p_prl = NULL; /* Pending record lock */
83: process->p_semu = NULL; /* Semaphore undo */
84:
85: process->p_flags = PFCORE;
86: process->p_state = PSRUN;
87: process->p_ttdev = NODEV;
88:
89: process->p_pid = 0;
90:
91: __SIGSET_EMPTY (process->p_pending_signals);
92:
93: if (SELF == NULL) {
94: process->p_ppid = 0;
95: process->p_nice = 0;
96: process->p_schedPri = 0;
97:
98: process->p_uid = 0;
99: process->p_group = 0;
100: process->p_ruid = 0;
101: process->p_rgid = 0;
102:
103: /*
104: * Set ttdev to null so that we do not accidentally set a tty
105: * for init.
106: */
107: process->p_ttdev = makedev (0, 0);
108:
109: __SIGSET_EMPTY (process->p_signal_mask);
110: __SIGSET_EMPTY (process->p_queued_signals);
111:
112: /*
113: * The default action for the following signals is to ignore
114: * them.
115: */
116:
117: #if _SIGNAL_MAX <= __LONG_BIT
118: process->p_ignored_signals._sigbits [0] =
119: __SIGSET_MASK (SIGCHLD) | __SIGSET_MASK (SIGPWR) |
120: __SIGSET_MASK (SIGWINCH) | __SIGSET_MASK (SIGURG) |
121: __SIGSET_MASK (SIGPOLL) | __SIGSET_MASK (SIGCONT);
122: #else
123: __SIGSET_EMPTY (process->p_ignored_signals);
124: __SIGSET_CLRBIT (process->p_ignored, SIGCHLD);
125: __SIGSET_CLRBIT (process->p_ignored, SIGPWR);
126: __SIGSET_CLRBIT (process->p_ignored, SIGWINCH);
127: __SIGSET_CLRBIT (process->p_ignored, SIGURG);
128: __SIGSET_CLRBIT (process->p_ignored, SIGPOLL);
129: __SIGSET_CLRBIT (process->p_ignored, SIGCONT);
130: #endif
131:
132: process->p_sigflags = 0;
133: } else {
134: process->p_ppid = SELF->p_pid;
135: process->p_nice = SELF->p_nice;
136: process->p_schedPri = SELF->p_schedPri;
137:
138: process->p_uid = SELF->p_uid;
139: process->p_group = SELF->p_group;
140: process->p_ruid = SELF->p_ruid;
141: process->p_rgid = SELF->p_rgid;
142:
143: process->p_ttdev = SELF->p_ttdev;
144:
145: process->p_signal_mask = SELF->p_signal_mask;
146: process->p_ignored_signals = SELF->p_ignored_signals;
147: process->p_queued_signals = SELF->p_queued_signals;
148:
149: process->p_sigflags = SELF->p_sigflags;
150: }
151: }
152:
153:
154: /*
155: * Wake a process from a sleep state, with the indicated "reason" code so that
156: * the process can know whether sleep was interrupted or not.
157: */
158:
159: #if __USE_PROTO__
160: void PROC_WAKE (__proc_t * process, int reason)
161: #else
162: void
163: PROC_WAKE (process, reason)
164: __proc_t * process;
165: int reason;
166: #endif
167: {
168: PROC_ASSERT_LOCKED (process);
169:
170: /*
171: * Dequeue the process from the hash list used for old-style sleep ().
172: */
173:
174: process->p_lback->p_lforw = process->p_lforw;
175: process->p_lforw->p_lback = process->p_lback;
176:
177: /*
178: * Change the process state to runnable and queue the process on the
179: * appropriate run queue.
180: */
181:
182: setrun (process);
183: }
184:
185: #define PROC_WAKE_SIGNAL(proc) PROC_WAKE (proc, PROCESS_SIGNALLED)
186:
187:
188: /*
189: * Internal version of sigaction (), which allows retrieval and optional
190: * replacement of the current signal information.
191: *
192: * Note that we take a copy of the current information in a temporary before
193: * trying to fiddle the new information; this allows the "act" and "oact"
194: * pointers to point to the same space.
195: */
196:
197: #if __USE_PROTO__
198: void curr_signal_action (int signal, __CONST__ __sigaction_t * act,
199: __sigaction_t * oact)
200: #else
201: void
202: curr_signal_action (signal, act, oact)
203: int signal;
204: __CONST__ __sigaction_t
205: * act;
206: __sigaction_t * oact;
207: #endif
208: {
209: __sigaction_t * proc_act;
210:
211: ASSERT (oact != NULL || act != NULL);
212: ASSERT (signal > 0 && signal <= _SIGNAL_MAX);
213:
214: proc_act = & u.u_sigact [signal - 1];
215:
216: if (act != NULL) {
217: __sigmask_t mask = __SIGSET_MASK (signal);
218: __sigaction_t temp;
219:
220: /*
221: * Exchange the "action" data.
222: */
223:
224: temp = * proc_act;
225: * proc_act = * act;
226: if (oact != NULL)
227: * oact = temp;
228:
229: /*
230: * The SIGILL, SIGTRAP and SIGPWR signals do not have their
231: * handlers reset to SIG_DFL even if the user requests this.
232: * Again, this is "silently enforced" so it happens at this
233: * layer.
234: */
235:
236: #if _SIGNAL_MAX <= __LONG_BIT
237: if ((mask & (__SIGSET_MASK (SIGILL) | __SIGSET_MASK (SIGTRAP) |
238: __SIGSET_MASK (SIGPWR))) == 0)
239: #else
240: if (signal == SIGILL || signal == SIGTRAP || signal == SIGPWR)
241: #endif
242: proc_act->sa_flags &= ~ __SA_RESETHAND;
243:
244: /*
245: * Set the ignore flags to match handler. Note that we do not
246: * clear the pending signals for the current process here;
247: * that will happen on the way out of the system call we are
248: * in during the check for signals to deliver.
249: */
250:
251: if (proc_act->sa_handler == SIG_IGN)
252: __SIGSET_ADDMASK (SELF->p_ignored_signals, signal,
253: mask);
254: else
255: __SIGSET_CLRMASK (SELF->p_ignored_signals, signal,
256: mask);
257:
258: /*
259: * Existing System V, Release 4 systems zero the mask if the
260: * signal is defaulted or ignored, so we copy them.
261: */
262:
263: if (proc_act->sa_handler == SIG_IGN ||
264: proc_act->sa_handler == SIG_DFL)
265: __SIGSET_EMPTY (proc_act->sa_mask);
266:
267: /*
268: * The default action for the following signals is for them to
269: * be ignored: SIGCHLD, SIGPWR, SIGWINCH, SIGURG, SIGPOLL,
270: * SIGCONT.
271: */
272:
273: #if _SIGNAL_MAX <= __LONG_BIT
274: if (((__SIGSET_MASK (SIGCHLD) | __SIGSET_MASK (SIGPWR) |
275: __SIGSET_MASK (SIGWINCH) | __SIGSET_MASK (SIGURG) |
276: __SIGSET_MASK (SIGPOLL) | __SIGSET_MASK (SIGCONT))
277: & mask) != 0
278: #else
279: if ((signal == SIGCHLD || signal == SIGPWR ||
280: signal == SIGWINCH || signal == SIGURG ||
281: signal == SIGPOLL || signal == SIGCONT)
282: #endif
283: && proc_act->sa_handler == SIG_DFL)
284: __SIGSET_ADDMASK (SELF->p_ignored_signals, signal,
285: mask);
286:
287: if ((proc_act->sa_flags & __SA_SIGINFO) != 0)
288: __SIGSET_ADDMASK (SELF->p_queued_signals, signal,
289: mask);
290: } else
291: * oact = * proc_act;
292: }
293:
294:
295: /*
296: * Obtain and possibly change the current process's signal mask. Note that
297: * we capture the current mask to a temporary before beginning, thus allowing
298: * "mask" and "omask" to point to the same storage.
299: */
300:
301: #if __USE_PROTO__
302: void curr_signal_mask (__CONST__ __sigset_t * mask, __sigset_t * omask)
303: #else
304: void
305: curr_signal_mask (mask, omask)
306: __CONST__ __sigset_t
307: * mask;
308: __sigset_t * omask;
309: #endif
310: {
311: ASSERT (omask != NULL || mask != NULL);
312:
313: if (mask != NULL) {
314: __sigset_t temp;
315:
316: /*
317: * The caller of this function should arrange for collateral
318: * actions such as checking for newly-unmasked signals in such
319: * as way as to ensure that signal actions are dealt with
320: * promptly and to ensure that locking is not needed.
321: *
322: * For instance, at this point signals may be briefly held
323: * which in fact "cannot" be. We don't care about this; the
324: * above constraint on our callers will ensure that this has
325: * no effect.
326: */
327:
328: temp = SELF->p_signal_mask;
329: SELF->p_signal_mask = * mask;
330: if (omask != NULL)
331: * omask = temp;
332:
333: /*
334: * SIGKILL and SIGSTOP may never be blocked or caught. Here we
335: * enforce the blocking part, which as the SVR4 PRM says is
336: * "silently enforced" by the system.
337: */
338:
339: __SIGSET_CLRBIT (SELF->p_signal_mask, SIGKILL);
340: __SIGSET_CLRBIT (SELF->p_signal_mask, SIGSTOP);
341: } else
342: * omask = SELF->p_signal_mask;
343: }
344:
345:
346: /*
347: * Test the signal mask of the given process to determine whether the given
348: * signal is masked.
349: */
350:
351: #if __USE_PROTO__
352: int proc_signal_masked (__proc_t * process, int signal)
353: #else
354: int
355: proc_signal_masked (process, signal)
356: __proc_t * process;
357: int signal;
358: #endif
359: {
360: ASSERT (process != NULL && signal > 0 && signal <= _SIGNAL_MAX);
361: return __SIGSET_TSTBIT (process->p_signal_mask, signal);
362: }
363:
364:
365: /*
366: * Return a zero value if there are no signals pending, otherwise return the
367: * number of the first unmasked, non-ignored signal.
368: *
369: * NOTE: The code here interacts with curr_signal_action () and
370: * proc_send_signal () in some ways that need comment; specifically, the
371: * treatment of ignored signals may seem sloppy. However, the System V usage
372: * of allowing ignored signals to be blocked, and then caught if a handler is
373: * subsequently attached means that the approach of clearing pending, ignored
374: * signals at this point is much simpler than dealing with them at all the
375: * other points (arrival, unblocking, handler attach).
376: */
377:
378: #if __USE_PROTO__
379: int curr_signal_pending (void)
380: #else
381: int
382: curr_signal_pending ()
383: #endif
384: {
385: int signo;
386:
387: /*
388: * If any signals have arrived, but which are not held, figure out
389: * what they are. This takes a little doing.
390: */
391:
392: for (signo = 0 ;
393: signo < __ARRAY_LENGTH (SELF->p_pending_signals._sigbits) ;
394: signo ++) {
395: __sigmask_t mask;
396:
397: mask = (SELF->p_pending_signals._sigbits [signo] &=
398: ~ SELF->p_ignored_signals._sigbits [signo]) &
399: ~ SELF->p_signal_mask._sigbits [signo];
400: if (mask == 0)
401: continue;
402:
403: /*
404: * There is at least one signal. Extract its number
405: * from the signal bits.
406: */
407:
408: T_HAL(8, printf ("curr_signal_pending () = %d ",
409: signo * sizeof (__sigmask_t) * __CHAR_BIT +
410: __SIGSET_FIRSTBIT (mask)));
411:
412: return signo * sizeof (__sigmask_t) * __CHAR_BIT +
413: __SIGSET_FIRSTBIT (mask);
414: }
415: return 0;
416: }
417:
418:
419: #if _SIGNAL_MAX <= __LONG_BIT
420: /*
421: * For optimizing handling of job-control signals.
422: */
423:
424: #define STOP_SIGNALS (__SIGSET_MASK (SIGSTOP) | __SIGSET_MASK (SIGTSTP) |\
425: __SIGSET_MASK (SIGTTIN) | __SIGSET_MASK (SIGTTOU))
426: #endif
427:
428: /*
429: * Add the given signal to the indicated process's pending-signal mask and if
430: * the process requires some notification (such as being woken if asleep, or
431: * interrupted if scheduled on another processor) then perform that.
432: *
433: * This function can only be called from base level, but we must be aware of
434: * the fact that process state-changes can happen at interrupt level and that
435: * we can be interacting with multiple processors.
436: */
437:
438: #if __USE_PROTO__
439: void proc_send_signal (__proc_t * process, __CONST__ __siginfo_t * siginfo)
440: #else
441: void
442: proc_send_signal (process, siginfo)
443: __proc_t * process;
444: __CONST__ __siginfo_t
445: * siginfo;
446: #endif
447: {
448: __sigmask_t mask;
449: pl_t prev_pl;
450:
451: ASSERT (process != NULL && siginfo != NULL);
452: ASSERT (siginfo->__si_signo > 0 && siginfo->__si_signo <= _SIGNAL_MAX);
453:
454: mask = __SIGSET_MASK (siginfo->__si_signo);
455:
456: if (siginfo->__si_signo == SIGCONT) {
457: /*
458: * When a SIGCONT is received, all pending stop signals are
459: * discarded and if the process is stopped, it is continued.
460: */
461:
462: #if _SIGNAL_MAX <= __LONG_BIT
463: __SIGSET_CLRMASK (process->p_pending_signals, 0,
464: STOP_SIGNALS);
465: #else
466: __SIGSET_CLRBIT (process->p_pending_signals, SIGSTOP);
467: __SIGSET_CLRBIT (process->p_pending_signals, SIGTSTP);
468: __SIGSET_CLRBIT (process->p_pending_signals, SIGTTIN);
469: __SIGSET_CLRBIT (process->p_pending_signals, SIGTTOU);
470: #endif
471:
472: #ifdef PROC_IS_STOPPED
473: if (PROC_IS_STOPPED (process))
474: PROC_CONTINUE (process);
475: #endif
476: }
477:
478: #if _SIGNAL_MAX <= __LONG_BIT
479: if ((mask & STOP_SIGNALS) != 0) {
480: #else
481: if (siginfo->__si_signo == SIGSTOP ||
482: siginfo->__si_signo == SIGTSTP ||
483: siginfo->__si_signo == SIGTTIN ||
484: siginfo->__si_signo == SIGTTOU) {
485: #endif
486: /*
487: * When a stop signal is received, any pending SIGCONT signal
488: * is discarded.
489: */
490:
491: __SIGSET_CLRBIT (process->p_pending_signals, SIGCONT);
492: }
493:
494:
495: #if 0
496: if (__SIGSET_TSTMASK (process->p_queued_signals, siginfo->__si_signo,
497: mask) != 0) {
498: /*
499: * Reliable signal-queueing is in effect, so we must stash
500: * away a copy of the structure pointed at by "siginfo" so we
501: * can deliver the information as an additional argument to
502: * the signal-catching function.
503: */
504: ASSERT ("Not implemented" == NULL);
505: }
506: #endif /* NOT IMPLEMENTED */
507:
508:
509: /*
510: * Here we are about to modify some shared per-process state; now is a
511: * good time to take a lock, so we structure the code so it can be
512: * released. We require a basic lock for the state-change code, so we
513: * use that lock to cover the process-level guard as well. In a uni-
514: * processor system, the process-level guard is not necessary, but the
515: * extra area covered is small enough that it doesn't matter.
516: */
517:
518: prev_pl = PROC_STATE_LOCK (process);
519:
520: __SIGSET_ADDMASK (process->p_pending_signals,
521: siginfo->__si_signo, mask);
522:
523: if (! __SIGSET_TSTMASK (process->p_signal_mask,
524: siginfo->__si_signo, mask) &&
525: ! __SIGSET_TSTMASK (process->p_ignored_signals,
526: siginfo->__si_signo, mask) &&
527: process->p_state == PSSLSIG) {
528: /*
529: * The process is sleeping and wants to be woken by
530: * signals, arrange for it to come out of sleep so it
531: * can get to user-level and process the signal.
532: */
533:
534: PROC_WAKE_SIGNAL (process);
535: }
536:
537: PROC_STATE_UNLOCK (process, prev_pl);
538:
539: T_HAL (8, printf (" ign = %x hold = %x pend = %x ",
540: process->p_ignored_signals._sigbits [0],
541: process->p_signal_mask._sigbits [0],
542: process->p_pending_signals._sigbits [0]));
543: }
544:
545:
546: /*
547: * Obtain and/or modify the current process's miscellaneous signal-flags. The
548: * previous flags are returned, making "curr_signal_misc (0, 0)" the fetch.
549: */
550:
551: #if __USE_PROTO__
552: __sigmiscfl_t curr_signal_misc (__sigmiscfl_t clear, __sigmiscfl_t set)
553: #else
554: __sigmiscfl_t
555: curr_signal_misc (clear, set)
556: __sigmiscfl_t clear;
557: __sigmiscfl_t set;
558: #endif
559: {
560: __sigmiscfl_t temp = SELF->p_sigflags;
561:
562: SELF->p_sigflags = (temp & ~ clear) | set;
563: return temp;
564: }
565:
566:
567: /*
568: * Return the given process's miscellaneous signal information. Note that we
569: * don't try and deal with synchronization issues here, so whatever code tests
570: * this data has to find some way of being multi-processor safe (concretely,
571: * it means that the uses of the signal information here are not atomic at the
572: * system-call level).
573: */
574:
575: #if __USE_PROTO__
576: __sigmiscfl_t proc_signal_misc (__proc_t * process)
577: #else
578: __sigmiscfl_t
579: proc_signal_misc (process)
580: __proc_t * process;
581: #endif
582: {
583: return process->p_sigflags;
584: }
585:
586:
587: /*
588: * Remove a signal from the pending signal mask.
589: */
590:
591: #if __USE_PROTO__
592: void proc_unkill (__proc_t * process, int signal)
593: #else
594: void
595: proc_unkill (process, signal)
596: __proc_t * process;
597: int signal;
598: #endif
599: {
600: __SIGSET_CLRBIT (process->p_pending_signals, signal);
601: }
602:
603:
604: /*
605: * Perform a register dump from a gregset_t, plus any useful data from the
606: * current process.
607: */
608:
609: #if __USE_PROTO__
610: void curr_register_dump (gregset_t * regsetp)
611: #else
612: void
613: curr_register_dump (regsetp)
614: gregset_t * regsetp;
615: #endif
616: {
617: printf ("\neax=%x ebx=%x ecx=%x edx=%x\n", regsetp->_i386._eax,
618: regsetp->_i386._ebx, regsetp->_i386._ecx, regsetp->_i386._edx);
619: printf ("esi=%x edi=%x ebp=%x esp=%x\n", regsetp->_i386._esi,
620: regsetp->_i386._edi, regsetp->_i386._ebp, regsetp->_i386._esp);
621: printf ("cs=%x ds=%x es=%x ss=%x fs=%x gs=%x\n",
622: regsetp->_i386._cs, regsetp->_i386._ds, regsetp->_i386._es,
623: regsetp->_i386._ss, regsetp->_i386._fs, regsetp->_i386._gs);
624: printf ("err #%d eip=%x uesp=%x cmd=%s\n", regsetp->_i386._err,
625: regsetp->_i386._eip, regsetp->_i386._uesp, u.u_comm);
626: printf ("efl=%x ", regsetp->_i386._eflags);
627:
628: if ((regsetp->_i386._cs & R_USR) != R_USR) {
629: /*
630: * This register set is indicating something that happened in
631: * the kernel, so do a call backtrace. To make this a little
632: * more robust, we only go upwards in the stack from the frame
633: * where we are, so that a smashed %ebp or frame causes no
634: * problems.
635: */
636:
637: __ulong_t * ebp = (__ulong_t *) regsetp->_i386._ebp;
638: __ulong_t * prev = & regsetp->_i386._ebp;
639: while (ebp > prev) {
640: printf (" -> %x", * (ebp + 1));
641: ebp = (__ulong_t *) * (prev = ebp);
642: }
643: printf ("\n");
644: }
645: }
646:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.