Springtime at Sun


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.