SunSoft's experimental OS contains clues to
the future of Solaris
Doug Tamasanis
On March 21, the first day of spring, SunSoft
released to the research community a "concept
car" for the next generation of OSes. Called,
naturally enough, Spring, it is the fruit of labor
begun in the mid-1980s. The company decided to
produce a new OS, unconstrained by the requirement to
support legacy software, that was distributed,
multithreaded, and fully object-oriented.
Although Spring will not be the next version of
Solaris, many of the concepts found in Spring will
eventually migrate to SunSoft's commercial OS.
Technology developed for Spring is the foundation for
Sun's DOE (Distributed Objects Everywhere). Pieces of
Spring have also found their way into the object
technology being developed by the OMG (Object
Management Group).
Defining Interfaces
A Spring object is an abstraction containing a
state and a set of methods to manipulate that state.
SunSoft calls the description of the object and its
methods an interface. This interface defines
interactions between an object providing a service
(i.e., a server) and an object using the service
(i.e., a client).
To maintain openness and not tie developers into a
single programming language, SunSoft developed an IDL
(interface definition language) to define the
interfaces. An IDL compiler converts IDL into three
pieces of code in the chosen target implementation
language: the IDL interface, client-side stub code,
and server-side stub code (see the figure "Spring
IDL" ).
The IDL interface is language-specific. In C, for
example, this is a header file with method
definitions, constants, and types defined in the IDL
interface. Client-side stub co de is dynamically
linked to a client's program, allowing access to an
object implemented in another address space or on
another machine. Server-side stub code is linked into
an object manager to translate incoming remote object
invocations into the run-time environment of the
object's implementation.
These three pieces of code enable objects in a
particular language to treat IDL-defined objects as
if they were native-language objects. Thus, if your
client object were in C++, you would use an
IDL-to-C++ compiler to produce C++-compatible header
files and stub-code objects. If a server object's
implementation is in C, you would have to use an
IDL-to-C compiler to generate the server-side stub
code to transform incoming calls into corresponding C
procedure invocations on the C objects corresponding
to the IDL objects. Spring's IDL forms the basis of
the IDL adopted by the OMG.
Invoking Objects
All Spring interfaces are defined in IDL, yet IDL
doesn't define anything about h ow to implement
operations on an object or how to convey operation
requests to an object. To use an object, you merely
invoke operations defined in its interface. The
client and server object don't need to know if the
object on the other side of the interface is in the
same address space, in another address space on the
same machine, or on another machine.
The IDL-generated stubs use Spring's subcontract
mechanism to communicate. Subcontracts provide a
flexible way to control the implementation of object
invocations, the transmission of object references
between address spaces, the release of object
references, and similar object run-time operations.
Other uses include the implementation of a number of
object run-time mechanisms.
Server-based objects typically use the Spring
doors mechanism to communicate between client and
server (see the figure "Spring
Doors" ). Most subcontracts optimize the
case when the client and the server are in the same
address space by performin g a local call rather than
calling through the kernel.
Spring also supports serverless objects, where the
entire state of the object is always in the client's
address space. When Spring passes a serverless object
between address spaces, it copies the object's state
to the new address space. Passing a serverless object
is akin to passing a struct, while passing a
server-based object is similar to passing a pointer
to its remote state.
Spring Kernel
Spring's microkernel design has two components
that run in the kernel mode. The VMM (virtual memory
manager) provides the code facilities for paging
virtual memory. The microkernel proper is called the
nucleus.
The nucleus supports three abstractions: domains,
threads, and doors. Domains are analogous to
processes in Unix. Threads execute within domains.
Typically, each Spring domain is multithreaded, with
separate threads performing different parts of an
application. Doors support object-oriented calls
between domains. A door describes a particular entry
point to a domain, represented by both a program
counter and a unique value that is chosen by the
domain. The object server typically uses this value
to identify the state of the object.
Each domain has an associated table of doors to
which it has access. Multiple door identifiers in
different domains may reference a single door.
Possession of a valid door gives the processor the
right to send an invocation request to that door. In
the target domain, all invocations on a given door
are equivalent, specifying only that the invoker has
somehow acquired a suitable door identifier. There is
no knowledge of who the invoker is or which door
identifier it used.
Spring uses network proxies to extend the nucleus
invocation mechanism and transparently connect the
nuclei of different machines. These proxies are
normal user-mode server domains and receive no
special support from the nucleus. One Spring machine
can include several proxy domains that speak
different network protocols.
Proxies transparently forward door invocations
between domains of different machines. When a client
on machine B invokes door Y, machine B forwards the
call over the network to proxy A. Proxy A does the
door invocation, and the door invocation arrives in
the server domain. Neither the client nor the server
need be aware that proxies exist. The client just
performs a normal door invocation, and the server
just sees a normal incoming door invocation.
Spring maps door identifiers into network handles
for transmission over the network and remaps back to
the door when the door identifiers arrive from the
network. A network handle contains a network address
for the creating proxy and a set of bits to identify
a particular door that is exported by this proxy.
Spring implements an extensible, demand-paged
virtual memory system that separates caching pages
from the tasks of storing and retrieving pages. A
per-machine VMM handles mapping, sharing, protecting,
transferring, and caching o f local memory.
Most clients of the virtual memory system deal
only with address space and memory objects. An
address-space object represents the virtual address
space of a domain. A memory object is a memory
abstraction mapped into address spaces, such as a
file object. The VMM implements address-space
objects.
A memory object has operations to set and query
the length, and to bind to an object. Binding ensures
that two equivalent mapped memory objects will share
the data cached by the VMM. There are no
page-in/page-out or read/write operations on memory
objects. The Spring file interface provides file
read/write operations but not page-in/page-out
operations. By separating the memory abstraction from
the interface providing the paging operations, the
memory-object server and the pager-object server can
be in different machines.
The VMM obtains data by invoking a pager object
implemented by an external pager. An external pager
performs coherency actions by invoking a cache object
impleme nted by a VMM. When a pager asks a VMM to map
a memory object into an address space, the VMM must
be able to obtain a pager object to let it manipulate
the object's data. Association between the pager and
a cache object is necessary to ensure coherency.
Typically, there are multiple pager-cache object
channels between a given pager and a VMM. The
external pager implementing the memory object
maintains data coherency between different VMMs that
are caching a memory object.
Coherently caching data using more than one VMM
requires a two-way connection between the VMM and an
external pager or file server. The VMM needs a
connection to the external pager to let the VMM
obtain and write out data, and the external pager
needs a connection to the VMM to let the provider
perform coherency actions. Spring employs pager and
cache objects to represent these connections.
What's in a Name?
Most OSes have several name services tailored for
specific kinds of objects (e.g., files, users, and
printers). Spring provides a uniform naming service
allowing any object to be bound to any name. Use of a
common name service eliminates construction of name
spaces by all object implementations. But remember
that Spring is completely object-oriented, so it can
support multiple name servers.
Spring allows association of objects with a name
that is in a context or name binding. Contexts are
themselves objects, containing name-to-object
associations that clients use to perform naming
operations. Objects can be concurrently bound to
different names in different contexts or not bound to
any name. By binding contexts in other contexts,
Spring creates a naming graph. This is a directed
graph with nodes and labeled edges, where the nodes
with outgoing edges are contexts.
Unlike naming in traditional systems, Spring
contexts and name spaces are first-class objects.
That is, you can directly access and manipulate them.
Also, Spring objects derive persistence through
naming. Generally, applications w ill acquire their
objects from the name service. If the region of the
name space where the object is found is persistent,
the object will also be persistent.
Spring Is Not Unix
Spring is not Unix, but it does provide binary
compatibility for a number of Solaris programs by
using a Unix-emulation subsystem. The emulation runs
as user-level code and employs no Unix code. The
implementation consists of two components: a shared
library dynamically linked with each Solaris binary
and a set of Unix-specific services exported via
Spring objects implemented by a Unix process server
in a separate domain.
The Unix process server implements functions that
are not part of the base Spring system and which
cannot reside in the shared library due to security
reasons. The system provides enough Unix emulation to
support standard utilities, such as make, vi, csh
, X Window System, and various Solaris
programming tools used by the Spring developers.
Running Unix in emulatio n would clearly be
unacceptable in production environments, which is why
SunSoft wants it known that it does not intend to
make Spring the next version of Solaris. The company
has learned its lesson from the porting effort that
got it to Solaris. However, Spring demonstrates just
what you can do if given the chance to build a
sparkling-new OS with modern software engineering
methods, without worrying about legacy systems.