예제 #1
0
void psleep(void *event)
{
	irqflags_t irq = di();
#ifdef DEBUG
	kprintf("psleep(0x%x)", event);	/* WRS */
#endif

	switch (udata.u_ptab->p_status) {
	case P_SLEEP:		// echo output from devtty happens while processes are still sleeping but in-context
		nready++;	/* We will fix this back up below */
	case P_RUNNING:	// normal process
		break;
	default:
		panic("psleep: voodoo");
	}

	if (!event)
		udata.u_ptab->p_status = P_PAUSE;
	else if (event == (char *) udata.u_ptab)
		udata.u_ptab->p_status = P_WAIT;
	else
		udata.u_ptab->p_status = P_SLEEP;
	udata.u_ptab->p_wait = event;
	udata.u_ptab->p_waitno = ++waitno;
	nready--;

	/* It is safe to restore interrupts here. We have already updated the
	   process state. The worst case is that a wakeup as we switchout
	   leads us to switch out and back in, or that we wake and run
	   after other candidates - no different to it occuring after the
	   switch */
	irqrestore(irq);
	switchout();		/* Switch us out, and start another process */
	/* Switchout doesn't return in this context until we have been switched back in, of course. */
}
예제 #2
0
void psleep(void *event)
{
	irqflags_t irq = di();
#ifdef DEBUG
	kprintf("psleep(0x%p)", event);
#endif
	switch (udata.u_ptab->p_status) {
	case P_SLEEP:		// echo output from devtty happens while processes are still sleeping but in-context
	case P_STOPPED:		// coming to a halt
		nready++;	/* We will fix this back up below */
	case P_RUNNING:		// normal process
		break;
	default:
#ifdef DEBUG
	        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_status = P_SLEEP;
	udata.u_ptab->p_wait = event;
	udata.u_ptab->p_waitno = ++waitno;
	nready--;

	/* It is safe to restore interrupts here. We have already updated the
	   process state. The worst case is that a wakeup as we switchout
	   leads us to switch out and back in, or that we wake and run
	   after other candidates - no different to it occuring after the
	   switch */
	irqrestore(irq);
	switchout();		/* Switch us out, and start another process */
	/* Switchout doesn't return in this context until we have been switched back in, of course. */
}
예제 #3
0
// Fuzix system call handler
// we arrive here from syscall.s with the kernel paged in, using the kernel stack, interrupts enabled.
void unix_syscall(void)
{
	// NO LOCAL VARIABLES PLEASE
	udata.u_error = 0;

	/* Fuzix saves the Stack Pointer and arguments in the
	 * Assembly Language Function handler in lowlevel.s
	 */
	if (udata.u_callno >= FUZIX_SYSCALL_COUNT) {
		udata.u_error = EINVAL;
	} else {
#ifdef DEBUG
		kprintf("\t\tpid %d: syscall %d\t%s(%x, %x, %x)\n",
			udata.u_ptab->p_pid, udata.u_callno,
			syscall_name[udata.u_callno], udata.u_argn,
			udata.u_argn1, udata.u_argn2);
#endif
		// dispatch system call
		udata.u_retval = (*syscall_dispatch[udata.u_callno]) ();

#ifdef DEBUG
		kprintf("\t\t\tpid %d: ret syscall %d, ret %x err %d\n",
			udata.u_ptab->p_pid, udata.u_callno,
			udata.u_retval, udata.u_error);
#endif
	}
	udata.u_ptab->p_timeout = 0;
	chksigs();

	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 */
		udata.u_ptab->p_status = P_READY;
		switchout();
	}
	ei();
}
예제 #4
0
uint8_t chksigs(void)
{
	uint8_t j;
	uint32_t pending = udata.u_ptab->p_pending & ~udata.u_ptab->p_held;
	int (**svec)(int) = &udata.u_sigvec[0];
	uint32_t m;

	/* 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 || !pending || udata.u_ptab->p_status == P_STOPPED)
		return udata.u_cursig;

	/* Dispatch the lowest numbered signal */
	for (j = 1; j < NSIGS; ++j) {
		svec++;
		m = sigmask(j);
		if (!(m & pending))
			continue;
		/* This is more complex than in V7 - we have multiple
		   behaviours plus core dump */
		if (*svec == SIG_DFL) {
		        /* SIGSTOP can't be ignored and puts the process into
		           P_STOPPED state when it is ready to handle the signal.
		           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) {
				/* 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
				irqrestore(irq);
				switchout();
				/* Other things may have happened */
				goto rescan;
	                }

			/* 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;

	                if ((m & clear) || udata.u_ptab->p_pid == 1) {
			/* SIGCONT is subtle - we woke the process to handle
			   the signal so ignoring here works fine */
				continue;
			}
#ifdef DEBUG
			kprintf("process terminated by signal %d\n", j);
#endif
			/* We may have marked ourselves as asleep and
			   then been caught by the chksigs when we tried
			   to task switch into bed. In that case we need
			   to put the process back in running state */
			if (udata.u_ptab->p_status == P_SLEEP) {
				udata.u_ptab->p_status = P_RUNNING;
				nready++;
			}
			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
#ifdef DEBUG
			kprintf("about to process signal %d\n", j);
#endif
			udata.u_cursig = j;
			break;
		}
	}
	return udata.u_cursig;
}
예제 #5
0
arg_t _sched_yield(void)
{
	if (nready > 1)
		switchout();
	return 0;
}