# Changeset 3112733

Ignore:
Timestamp:
Apr 12, 2022, 1:52:32 PM (2 months ago)
Branches:
enum, master
Children:
6b06abe
Parents:
e88c2fb
Message:

Filled in all of Chapter 4.
It's not great but it's worth discussing

File:
1 edited

### Legend:

Unmodified
 re88c2fb Finally, the last important part of the \io subsystem is it's interface. There are multiple approaches that can be offered to programmers, each with advantages and disadvantages. The new \io subsystem can replace the C runtime's API or extend it. And in the later case the interface can go from very similar to vastly different. The following sections discuss some useful options using @read@ as an example. The standard Linux interface for C is : @ssize_t read(int fd, void *buf, size_t count);@. @ssize_t read(int fd, void *buf, size_t count);@ \subsection{Replacement} Replacing the C \glsxtrshort{api} Replacing the C \glsxtrshort{api} is the more intrusive and draconian approach. The goal is to convince the compiler and linker to replace any calls to @read@ to direct them to the \CFA implementation instead of glibc's. This has the advantage of potentially working transparently and supporting existing binaries without needing recompilation. It also offers a, presumably, well known and familiar API that C programmers can simply continue to work with. However, this approach also entails a plethora of subtle technical challenges which generally boils down to making a perfect replacement. If the \CFA interface replaces only \emph{some} of the calls to glibc, then this can easily lead to esoteric concurrency bugs. Since the gcc ecosystems does not offer a scheme for such perfect replacement, this approach was rejected as being laudable but infeasible. \subsection{Synchronous Extension} An other interface option is to simply offer an interface that is different in name only. For example: @ssize_t cfa_read(int fd, void *buf, size_t count);@ \noindent This is much more feasible but still familiar to C programmers. It comes with the caveat that any code attempting to use it must be recompiled, which can be a big problem considering the amount of existing legacy C binaries. However, it has the advantage of implementation simplicity. \subsection{Asynchronous Extension} It is important to mention that there is a certain irony to using only synchronous, therefore blocking, interfaces for a feature often referred to as non-blocking'' \io. A fairly traditional way of doing this is using futures\cit{wikipedia futures}. As simple way of doing so is as follows: @future(ssize_t) read(int fd, void *buf, size_t count);@ \noindent Note that this approach is not necessarily the most idiomatic usage of futures. The definition of read above returns'' the read content through an output parameter which cannot be synchronized on. A more classical asynchronous API could look more like: @future([ssize_t, void *]) read(int fd, size_t count);@ \noindent However, this interface immediately introduces memory lifetime challenges since the call must effectively allocate a buffer to be returned. Because of the performance implications of this, the first approach is considered preferable as it is more familiar to C programmers. \subsection{Interface directly to \lstinline{io_uring}} Finally, an other interface that can be relevant is to simply expose directly the underlying \texttt{io\_uring} interface. For example: @array(SQE, want) cfa_io_allocate(int want);@ @void cfa_io_submit( const array(SQE, have) & );@ \noindent This offers more flexibility to users wanting to fully use all of the \texttt{io\_uring} features. However, it is not the most user-friendly option. It obviously imposes a strong dependency between user code and \texttt{io\_uring} but at the same time restricting users to usages that are compatible with how \CFA internally uses \texttt{io\_uring}.