Notes on "The Structuring of Systems Using Upcalls"

Introduces upcalls, which allow invoked services invoke the client (e.g. through handlers bound at runtime). A key advantage of this design is that it reduces overheads from IPCs (e.g. buffering), and simplifies OS abstractions through neater organization of parallel components and by avoiding the need for system-wide formats for messages. This was considered controversial as it challenged a widely-held assumption that layers of abstraction should only be able to invoke lower layers of abstraction. Upcalls are implemented in the prototype Swift OS.

The ideas were motivated by applications in networking, but are part of a larger theme of service-based architectures which might be found in microkernels. Indeed, the paper is cited mostly by networking and kernel papers.

Upcalls design

The paper proposes a programming model of consisting of tasks and modules (layers). Modules perform a service (e.g. transport). They may consist of several functions that may run in parallel and shared state. Tasks are a thread of execution. Each task may span several modules depending on whether other modules are invoked.

Strengths

Weaknesses

Example

The following example from the paper demonstrates how a remote login service may be implemented using upcalls. I’ve annotated the code to clearly show layers, state shared within a layer, invocations of other layers, upcalls, and interactions between tasks.

Upcalls code

Upcalls code diagram

Takeaways

The thoughts around how services interact are still relevant in internet and distributed systems architectures today. I’m reminded of this interview with Dianne Hackborn on OpenBinder which also manages IPC and enables rich OS services and applications. Performance advantages of using shared memory remain, for example the distributed system Ray uses the Plasma Object Store as a type of distributed shared memory.