-#undef DEBUG /* turn this on to enable syscall tracing */
+#undef DEBUG_SYSCALL /* turn this on to enable syscall tracing */
+#define DEBUG_SLEEP /* turn this on to trace sleep/wakeup activity */
#undef DEBUGHARDER /* report calls to wakeup() that lead nowhere */
#undef DEBUGREALLYHARD /* turn on getproc dumping */
#undef DEBUG_PREEMPT /* debug pre-emption */
static void do_psleep(void *event, uint8_t state)
{
irqflags_t irq = di();
-#ifdef DEBUG
+#ifdef DEBUG_SLEEP
kprintf("psleep(0x%p)", event);
#endif
switch (udata.u_ptab->p_status) {
case P_RUNNING: // normal process
break;
default:
-#ifdef DEBUG
+#ifdef DEBUG_SLEEP
kprintf("psleep(0x%p) -> %d:%d", event, udata.u_ptab->p_pid, udata.u_ptab->p_status);
#endif
panic(PANIC_VOODOO);
udata.u_ptab->p_wait = event;
udata.u_ptab->p_waitno = ++waitno;
- /* Invalidate signal cache if in IOWAIT */
- if (state == P_IOWAIT)
- udata.u_cursig = 0;
-
switchout(); /* Switch us out, and start another process */
/* Switchout doesn't return in this context until we have been switched back in, of course. */
}
irq = di();
for (p = ptab; p < ptab_end; ++p) {
if (p->p_status > P_RUNNING && p->p_wait == event) {
-#ifdef DEBUG
+#ifdef DEBUG_SLEEP
kprintf("wakeup: found proc 0x%p pid %d\n",
p, p->p_pid);
#endif
void switchout(void)
{
+#ifdef DEBUG_SLEEP
+ kprintf("switchout %d\n", udata.u_ptab->p_status);
+#endif
di();
/* We do the accounting in switchout as it's cheaper and easier to
/* If only one process is ready to run and it's us then just
return. This is the normal path in most Fuzix use cases as we
are waiting for input while mostly system idle */
- if (nready == 1 && udata.u_ptab->p_status == P_READY) {
- udata.u_ptab->p_status = P_RUNNING;
- ei();
- return;
+ if (udata.u_ptab->p_status == P_RUNNING) {
+ if (nready == 1) {
+ ei();
+ return;
+ }
+ udata.u_ptab->p_status = P_READY;
}
/* We probably need to run somehting else */
platform_switchout();
ptptr getproc(void)
{
ptptr haltafter;
-#ifdef DEBUG
+#ifdef DEBUG_SLEEP
#ifdef DEBUGREALLYHARD
ptptr pp;
kputs("getproc start ... ");
case P_RUNNING:
panic(PANIC_GETPROC);
case P_READY:
-#ifdef DEBUG
+#ifdef DEBUG_SLEEP
kprintf("[getproc returning %p pid=%d]\n",
getproc_nextp, getproc_nextp->p_pid);
#endif
#endif
}
-#ifdef DEBUG
+#ifdef DEBUG_SYSCALL
#include "syscall_name.h"
#endif
if (udata.u_callno >= FUZIX_SYSCALL_COUNT) {
udata.u_error = ENOSYS;
} else {
-#ifdef DEBUG
+#ifdef DEBUG_SYSCALL
kprintf("\t\tpid %d: syscall %d\t%s(%p, %p, %p)\n",
udata.u_ptab->p_pid, udata.u_callno,
syscall_name[udata.u_callno], udata.u_argn,
// dispatch system call
udata.u_retval = (*syscall_dispatch[udata.u_callno]) ();
-#ifdef DEBUG
+#ifdef DEBUG_SYSCALL
kprintf("\t\t\tpid %d: ret syscall %d, ret %p err %p\n",
udata.u_ptab->p_pid, udata.u_callno,
udata.u_retval, udata.u_error);
di();
if (runticks >= udata.u_ptab->p_priority && nready > 1) {
/* Time to switch out? - we may have overstayed our welcome inside
- a syscall so switch straight afterwards */
+ a syscall so swtch straight afterwards */
udata.u_ptab->p_status = P_READY;
/* We know there will be a switch if we hit this point so
don't look for optimizations. Likewise we know a signal
the signal so ignoring here works fine */
continue;
}
-#ifdef DEBUG
- kprintf("process terminated by signal %d\n", j);
+#ifdef DEBUG_SLEEP
+ kprintf("process terminated by signal %d (%d)\n",
+ j, udata.u_ptab->p_status);
#endif
/* We may have marked ourselves as asleep and
then been caught by the chksigs when we tried
} else if (*svec != SIG_IGN) {
/* Arrange to call the user routine at return */
sb->s_pending &= ~m; // unset the bit
-#ifdef DEBUG
+#ifdef DEBUG_SLEEP
kprintf("about to process signal %d\n", j);
#endif
udata.u_cursig = j + (b << 4);
uint8_t r;
uint8_t b;
- /* Sleeping without signals allowed */
+ /* Sleeping without signals allowed. We rely upon the fact that
+ P_IOWAIT is never pre-empted or returns to user space so
+ udata.u_cursig is not consulted until it is safe to do so */
if (udata.u_ptab->p_status == P_IOWAIT)
return 0;
sigm = 1 << (sig & 0x0F);
+#ifdef DEBUG_SLEEP
+ kprintf("sig to %d(%d) %p %p\n",
+ proc->p_pid, proc->p_status, proc, udata.u_ptab);
+#endif
+
irq = di();
if (proc->p_status != P_EMPTY) { /* Presumably was killed just now */
}
m->s_pending |= sigm;
}
+ /* FIXME: need to clean up the way we handle ready/running
+ so we have a simple 'make runnable' */
+ if (proc->p_status == P_READY && udata.u_ptab == proc)
+ proc->p_status = P_RUNNING;
}
irqrestore(irq);
}
ptptr p;
irqflags_t irq;
-#ifdef DEBUG
+#ifdef DEBUG_SLEEP
kprintf("process %d exiting %d\n", udata.u_ptab->p_pid, val);
kprintf
}
tty_exit();
irqrestore(irq);
-#ifdef DEBUG
+#ifdef DEBUG_SLEEP
kprintf
("udata.u_page %u, udata.u_ptab %p, udata.u_ptab->p_page %u\n",
udata.u_page, udata.u_ptab, udata.u_ptab->p_page);