Sphinx : A UNIX Emulator Extension

Last updated : Wed May 7 14:24:04 1997






Overview

Sphinx is an extension that implements the UNIX system calls. It can run programs compiled for DEC UNIX or FreeBSD.

Dynamic linking is supported on OSF/1, however with some warnings.

The PC version does not support dynlinking.

Lots of system calls are missing. You won't be able to run some applications. If you are in doubt, use the system call tracer(syscall trace) to find out what system calls your app is using.

Compilation, and Link

DEC UNIX

No special flags are needed any more.

PC Compatibles

You have to use FreeBSD statically linked binaries. At UW, /spin/bin/bsd-newcc on Linux box(es) is the cross compiler that produces FreeBSD binary. It is actually gcc, so you have to pass

-static
option when linking.

When installing GNU softwares, do


% setenv LDFLAGS -static

before running configure.

Running

The sphinx apps are first started using sphinx shell command.
Note: exec shell command does not work any more.
!>sphinx exec ~/spin/user/sphinx/progs/hello
When running a dynamically linked binary, you first have to load NFS.
!> nanny touch Sphinx
!> script ~/spin/user/script/mount.rc
!> sphinx exec /usr/local/bin/wish -f your-script
You can also pass arguments to the child proc.
!>sphinx exec /spin/yasushi/sphinx/progs/hello hi there
In the above example, hi and there are passed to the user program. In the user program, you can access them using familiar argc, argv protocol.

Shell variables are passed to the child proc as environment variables.

The sphinx shell command supports several subcommands.

sphinx install
This command installs the sphinx extension on the MachineTrap.Syscall event for any threads. This command is valid, but is deprecated. You really don't need to execute this command to run UNIX binaries.
sphinx uninstall
Uninstalls the extension installed by "sphinx install". This command is deprecated also.
sphinx ps
Lists the active processes.
sphinx kill pid signo
Send the signal signo to the process pid. This command often doesn't work especially when the process is hung inside the systemcall handler.
sphinx trace
Installs a system call tracer. For each system call, the tracer displays the name of the service and arguments.
sphinx untrace
Uninstalls the system call tracer.
sphinx exec PATH ARGS...
starts a UNIX program PATH, giving arguments ARGS.... The difference between exec shell command and this command is that the "exec" shell command starts the application without setting up any system call handlers. "sphinx exec" installs the sphinx syscall handler before starting the application.
sphinx texec PATH ARGS...
starts PATH with the tracer installed for the process. The tracer is uninstalled after the process terminates.
sphinx pexec PATH ARGS...
starts PATH with the profiler installed for the process. The tracer is uninstalled after the process terminates.

Adding Systemcalls

Sphinx has some support for nonstandard systemcall extensions. See this document for details.

Caveats

Here are some tricky functions.

Problems and Future Plan

mobj cow now only inherits the whole memory object. We should change it to inherit only part if needed.
exec coredumps when path does not exist.
Sphinx.m3 is getting too big. It has to be divided.
FreeBSD support
It is still very rudimentary.
Crappy terminal interface
Some services related to the terminal don't work. For example, ^C is delivered only when the process is executing the system call. SIGIO is not supported. I think the real reason of these problems is that the current terminal driver interface is synchronous; i.e., it is read/write, not put/get(like in System V stream). We have to switch to asynchronous one soon.
User/group management
How does this fit into the whole spin authorization mechanisms?
/dev/kmem
Alpha OSF/1 still uses this. FreeBSD seems to discourage the use of kmem, and instead it provides sysctl(2). It is a system call to access kernel resources in a manner similar to SNMP. It will be relatively easy to support sysctl.
Ad hoc conversion from exception to errno.
It's random now. There are two ways to go. One is to continue doing random conversion. The other is to make Error.E error codes conform to UNIX errno. I'm inclined to latter.
No certain way to signal kernel thread
Our current execution model is that kernel thread is a sacred entity; we can't change it's state from outside. One problem I have is UNIX signals. To implement UNIX signal, you have to wake up the target process if it's in interruptible wait state. For example, when a process X is waiting in ttyread and ^C is typed, X should be dequeued and made runnable.

The way UNIX implements this is that the signal delivery code looks into the current thread state, and if it's in interruptible wait state, the delivery code just dequeues the thread from whatever queue it is waiting on.

I found it's difficult to do this from M3 world. To make tty signal work, I added a terrible hack in tty.c. First, I added a field last_signal to struct tty. It is char. When a key that raises signal is pressed, it sets last_signal to be the signal number, and wakes up a thread. When waking up a thread for other reasons(ex, newline pressed), it sets last_signal to be -1. When thread wakes up, it checks last_signal and if it's not -1, it returns EINTR.

This is not a right solution, because last_signal is a global variable, so there is a race condition(However it would work in most cases because console access is arbitrated using some higher level protocol and there usually is only one thread waiting on struct tty). Another problem of this "solution" is that it's not generic. It works for tty, but it won't work for threads waiting on select, etc.


yasushi@cs.washington.edu