nready++; /* runnable process count */
p->p_pptr = udata.u_ptab;
- p->p_ignored = udata.u_ptab->p_ignored;
+ p->p_sig[0].s_ignored = udata.u_ptab->p_sig[0].s_ignored;
+ p->p_sig[1].s_ignored = udata.u_ptab->p_sig[1].s_ignored;
+ p->p_sig[0].s_held = udata.u_ptab->p_sig[0].s_held;
+ p->p_sig[1].s_held = udata.u_ptab->p_sig[1].s_held;
p->p_tty = udata.u_ptab->p_tty;
p->p_uid = udata.u_ptab->p_uid;
/* Set default priority */
}
#endif
+
+/* FIXME: we should keep a dirty flag so we know if we need to check for
+ signals so we can optimise this path */
+
/* This sees if the current process has any signals set, and handles them.
*/
-static const uint32_t stopper = (1UL << SIGSTOP) | (1UL << SIGTTIN) | (1UL << SIGTTOU) | (1UL << SIGTSTP);
-static const uint32_t clear = (1UL << SIGSTOP) | (1UL << SIGTTIN) | (1UL << SIGTTOU) | (1UL << SIGTSTP) |
- (1UL << SIGCHLD) | (1UL << SIGURG) | (1UL << SIGWINCH) | (1UL << SIGIO) |
- (1UL << SIGCONT);
-uint8_t chksigs(void)
+#define SIGBIT(x) (1 << (x & 15))
+
+static const uint16_t stopper[2] = {
+ 0,
+ /* And the high signals */
+ SIGBIT(SIGSTOP) | SIGBIT(SIGTTIN) | SIGBIT(SIGTTOU) | SIGBIT(SIGTSTP)
+};
+
+static const uint16_t clear[2] = {
+ 0,
+ /* And the high signals */
+ SIGBIT(SIGSTOP) | SIGBIT(SIGTTIN) | SIGBIT(SIGTTOU) | SIGBIT(SIGTSTP) |
+ SIGBIT(SIGCHLD) | SIGBIT(SIGURG) | SIGBIT(SIGWINCH) | SIGBIT(SIGIO) |
+ SIGBIT(SIGCONT)
+};
+
+/* Process a block of 16 signals so we can avoid using longs */
+
+static uint8_t chksigset(struct sigbits *sb, uint8_t b)
{
- uint8_t j;
- uint32_t pending = udata.u_ptab->p_pending & ~udata.u_ptab->p_held;
+ uint8_t j = 1;
int (**svec)(int) = &udata.u_sigvec[0];
- uint32_t m;
+ uint16_t m;
+ uint16_t pending = sb->s_pending & ~sb->s_held;
- /* Fast path - no signals pending means no work.
- Cursig being set means we've already worked out what to do.
- */
+ if (pending == 0)
+ return 0;
-rescan:
- if (udata.u_cursig || !pending || udata.u_ptab->p_status == P_STOPPED)
- return udata.u_cursig;
+ if (b == 1) {
+ j = 0;
+ svec = &udata.u_sigvec[15]; /* ++ done at start */
+ }
/* Dispatch the lowest numbered signal */
- for (j = 1; j < NSIGS; ++j) {
+ for (; j < 15; ++j) {
svec++;
- m = sigmask(j);
+ /* FIXME: optimise by setting up m once and shifting */
+ m = 1 << j;
if (!(m & pending))
continue;
/* This is more complex than in V7 - we have multiple
Annoyingly right now we have to context switch to the task
in order to stop it in the right place. That would be nice
to fix */
- if (m & stopper) {
+ if (m & stopper[b]) {
/* Don't allow us to race SIGCONT */
irqflags_t irq = di();
/* FIXME: can we ever end up here not in READY/RUNNING ? */
nready--;
udata.u_ptab->p_status = P_STOPPED;
udata.u_ptab->p_event = j;
- udata.u_ptab->p_pending &= ~m; // unset the bit
+ sb->s_pending &= ~m; // unset the bit
irqrestore(irq);
switchout();
/* Other things may have happened */
- goto rescan;
+ return 0xFF;
}
/* The signal is being handled, so clear it even if
we are exiting (otherwise we'll loop in
chksigs) */
- udata.u_ptab->p_pending &= ~m;
+ sb->s_pending &= ~m;
- if ((m & clear) || udata.u_ptab->p_pid == 1) {
+ if ((m & clear[b]) || udata.u_ptab->p_pid == 1) {
/* SIGCONT is subtle - we woke the process to handle
the signal so ignoring here works fine */
continue;
doexit(dump_core(j));
} else if (*svec != SIG_IGN) {
/* Arrange to call the user routine at return */
- udata.u_ptab->p_pending &= ~m; // unset the bit
+ sb->s_pending &= ~m; // unset the bit
#ifdef DEBUG
kprintf("about to process signal %d\n", j);
#endif
- udata.u_cursig = j;
+ udata.u_cursig = j + b << 4;
break;
}
}
return udata.u_cursig;
}
+uint8_t chksigs(void)
+{
+ struct sigbits *sb = udata.u_ptab->p_sig;
+ uint8_t r;
+ uint8_t b;
+
+ /* Fast path - no signals pending means no work.
+ Cursig being set means we've already worked out what to do.
+ */
+rescan:
+ if (udata.u_cursig || udata.u_ptab->p_status == P_STOPPED)
+ return udata.u_cursig;
+
+ for (b = 0; b < 2; b++, sb++) {
+ r = chksigset(sb, b);
+ if (r == 0xFF)
+ goto rescan;
+ else if (r)
+ return udata.u_cursig;
+ }
+ return 0;
+}
+
/*
* Send signal, avoid touching uarea
*/
/* SDCC bug #2472: SDCC generates hideous code for this function due to bad
code generation when masking longs. Not clear we can do much about it but
file a bug */
+
void ssig(ptptr proc, uint8_t sig)
{
+ struct sigbits *m = proc->p_sig;
uint32_t sigm;
+ uint8_t sigbit = sig & 0x0F;
irqflags_t irq;
- sigm = sigmask(sig);
+ if (sig > 15)
+ m++;
+
+ sigm = 1 << sigbit;
irq = di();
nready++;
}
/* CONT discards pending stops */
- proc->p_pending &= ~((1L << SIGSTOP) | (1L << SIGTTIN) |
- (1L << SIGTTOU) | (1L << SIGTSTP));
+ proc->p_sig[1].s_pending &= ~(SIGBIT(SIGSTOP) | SIGBIT(SIGTTIN)
+ | SIGBIT(SIGTTOU) | SIGBIT(SIGTSTP));
}
/* STOP discards pending conts */
if (sig >= SIGSTOP && sig <= SIGTTOU)
- proc->p_pending &= ~(1L << SIGCONT);
+ proc->p_sig[0].s_pending &= ~SIGBIT(SIGCONT);
/* Routine signal behaviour */
- if (!(proc->p_ignored & sigm)) {
+ if (!(m->s_ignored & sigm)) {
/* Don't wake for held signals */
- if (!(proc->p_held & sigm)) {
+ if (!(m->s_held & sigm)) {
switch (proc->p_status) {
case P_SLEEP:
proc->p_status = P_READY;
}
proc->p_wait = NULL;
}
- proc->p_pending |= sigm;
+ m->s_pending |= sigm;
}
}
irqrestore(irq);
/* FIXME: why return a value - we don't use it */
static int signal_parent(ptptr p)
{
- if (p->p_ignored & (1UL << SIGCHLD)) {
+ if (p->p_sig[1].s_ignored & (1UL << SIGCHLD)) {
/* POSIX.1 says that SIG_IGN for SIGCHLD means don't go
zombie, just clean up as we go */
udata.u_ptab->p_status = P_EMPTY;
/* We are exiting, hold all signals (they will never be
delivered). If we don't do this we might take a signal
while exiting which would be ... unfortunate */
- udata.u_ptab->p_held = 0xFFFFFFFFUL;
+ udata.u_ptab->p_sig[0].s_held = 0xFFFFU;
+ udata.u_ptab->p_sig[1].s_held = 0xFFFFU;
udata.u_cursig = 0;
/* Discard our memory before we blow away and reuse the memory */
p->p_pptr = ptab; /* ptab is always init */
/* Suppose our child is a zombie and init has
SIGCLD blocked */
- if (ptab[0].p_ignored & (1UL << SIGCHLD)) {
+ if (ptab[0].p_sig[1].s_ignored & SIGBIT(SIGCHLD)) {
p->p_status = P_EMPTY;
} else {
ssig(&ptab[0], SIGCHLD);