The recommended reading included Shapiro’s paper entitled “Programming language challenges in systems codes: why systems programmers still use C, and what to do about it” (Proceedings of the ACM Workshop on Programming Languages and Operating Systems, San Jose, CA, USA, October 2006). This paper suggests that the C programming language is not appropriate for writing systems code, and outlines some new programming languages features that would improve systems programming. The lectures covered other topics in this space, and introduced you to the Rust programming language that attempts to innovate in the field of systems programs. Do you agree with the thesis of this paper and the lecture discussion? Discuss the extent to which you believe that changing the programming language will help to address the challenges in building secure, high performance, and robust systems programs. Outline what features of a programming language or runtime you consider important for supporting systems programming, and what are harmful. Illustrate your answer using examples from systems programming, including features that might help or hinder their implementation, to help make your argument. Answers may argue for, or against, the thesis of the paper and lecture discussion. Answers arguing in either way are acceptable provided they are supported by reasoned discussion, arguments, and examples. Of the 20 marks available for this question, [10] marks are available for technical discussion, [6] marks for the examples, and the remaining [4] marks are awarded for quality of written argument (i.e., the ability to structure and present a clear and coherent argument; not English spelling or grammar). [20]
Answer
Shapiro’s 2006 Paper, as well as the lecture contents suggest that the C programming language is not appropriate for writing systems code, and outlines some new programming languages features that would improve systems programming.
Shapiro in their analysis, which was discussed prior to Rust’s Development explained why we still used C from a more technical frame, where the lectures explained the persistant widespread usage of C over Rust currently from a more social perspective.
Shapiro helpfully outlined the core language features they believed needed for the future systems programming:
Memory Safety, without Runtime Overhead
Typically systems programming languages were faced with either a high runtime overhead in garbage collection, which is also relatively unpredictable, or with unsafe memory access like C, Rust attempted to “bridge the gap”, by using strong typing to enforce memory safety without using a slow garbage collector. In fact, it discovered that in general by enforcing some stricter rules we can move dynamic runtime analysis of memory access to be static compiler analysis, completely frontloading analysis cost to a one-time compile, instead of every run.
For instance:
fn forward_packet(source: &mut Connection, dest: &mut Connection) -> Result<(), Error> { let packet = source.take_packet()?; // Ownership transferred to dest - source can no longer access the packet // No need for manual tracking or reference counting dest.queue_packet(packet)?; // This would cause a compile error: // source.retry_packet(packet); // Error: packet already moved Ok(()) }
In general Rust also differentiates between borrowing and owning, and the way it enforces reference rules (infinite immutable, 1 mutable) completely eliminates the “classical” problems developers face with concurrent programming (though this was not potentially not developed in much depth at the time of Shapiros paper), such as race conditions.
Predictable, Transparent Performance Characteristics
Systems programs, especially in real-time system need consistent, predictable execution of their code.
This isnt possible in systems that have unpredictable garbage collection, or JIT optimization, as they add in potential variance with potentially other things happening first instead.
Shapiro also identified some aspects that are directly undesirable such as abstractions that directly induce some runtime cost, as well as languages that require runtime support. This is because systems that are responsible for OS booting for example need to interact with hardware before the runtime can start.
This is actually a feature that initially might seem like a problem with Rust’s strong-typing, as you’re not able to do zero-copy processing/conversion directly like casting:
void handle_data(char* buffer) { // Cast raw memory to structured data without copying header_t* header = (header_t*)buffer; payload_t* payload = (payload_t*)(buffer + sizeof(header_t));}
However Rust tried to alleviate this by providing many safe conversions that compile into roughly the same code, as well as providing the unsafe {} escape hatch, allowing you to do this at your own risk.
In general Rust presents a well thought-out answer to the problems that are faced by systems programmers, allowing them to not have to chose between memory safety or performance, as well as providing more expressive type systems and features. Rust in many ways benefits from not having to be backwards compatible with decades of potentially bad decisions in the same way C/C++ does. I also in general agree with the analysis presented in the lectures that the core reasons that we haven’t completely switched to Rust in general lie in:
Inertia of C/C++
Cost to rewrite
Cost to retrain developers
Tooling/Ecosystem
In general from a technical perspective, as all the potential “problems” that are induced by the strong-typing system of Rust are escapable with unsafe, its hard to argue against all the clear benefits that it introduces with memory safety.