Yes. There has been decades of academic and systems research into making system calls asynchronous, although the approaches vary considerably. The motivation is usually one (or more) of these goals:
- Avoid blocking a thread while the kernel performs I/O.
- Improve scalability for servers handling many concurrent operations.
- Reduce context switches.
- Better overlap computation with I/O.
- Enable event-driven programming models.
Here are the main research directions.
1. Asynchronous I/O (AIO)
One of the oldest lines of work was making I/O syscalls asynchronous rather than making all syscalls async.
Typical interface:
read(fd, buf, size);
becomes
aio_read(...);
or
submit_read(...)
...
completion = wait()
Academic work explored:
- completion queues
- callback-based interfaces
- futures/promises
- event queues
The challenge is that POSIX AIO had an awkward API and many implementations simply delegated work to helper threads rather than performing true kernel-level asynchronous execution.
2. Scheduler Activations (1991)
A famous paper by Thomas E. Anderson, Brian Bershad, and colleagues introduced Scheduler Activations.
While not directly about async syscalls, it addressed a related problem:
How can user-level thread schedulers coexist with blocking kernel operations?
Instead of simply blocking an entire user runtime, the kernel informed the runtime about blocking events.
This influenced many later runtime systems.
3. Exokernel (MIT)
The MIT Parallel and Distributed Operating Systems Group Exokernel work argued that the kernel should expose low-level resources directly.
In this model:
- applications manage resources themselves
- syscall overhead decreases
- asynchronous interfaces become easier
Rather than hiding latency, applications explicitly manage it.
4. Event-driven operating systems
Researchers observed that high-performance servers spend much of their time blocked in:
This led to work on:
- event loops
- readiness notification
- completion notification
Examples include interfaces such as:
These aren't asynchronous syscalls in the sense that every syscall returns immediately, but they let applications structure work around asynchronous events.
5. Capriccio (2003)
The University of California, Berkeley Capriccio project investigated scalable threading for servers.
The idea:
- keep programming with blocking code
- transform execution so that blocking operations don't require one kernel thread per client
It was an important bridge between synchronous programming models and asynchronous execution.
6. libasync
One influential research project was libasync, which treated nearly every potentially blocking operation as an asynchronous event.
The philosophy was:
- never block
- continue execution when callbacks fire
Many later asynchronous frameworks inherited these ideas.
7. io_uring
More recently, Linux introduced io_uring.
Although it's an engineering project rather than an academic one, it embodies ideas explored in earlier research:
- submission queues
- completion queues
- batching
- reduced syscall overhead
- kernel-managed asynchronous execution
Instead of
read()
read()
write()
you enqueue operations:
SQE
SQE
SQE
and later consume completion events:
CQE
CQE
CQE
This is probably the closest mainstream implementation of the "everything async" philosophy for I/O.
8. Language runtime research
Many runtime systems effectively make blocking syscalls asynchronous under the hood.
Examples include:
- Go's network poller
- Erlang's schedulers
- Rust's Tokio runtime
- Java virtual threads (combined with async I/O where possible)
These systems present blocking APIs while internally using nonblocking operations and scheduling other work when a syscall would otherwise block.
9. "Everything is a future"
Several research operating systems explored treating every syscall as returning a future or promise.
Conceptually:
let data = read(fd);
becomes
Future<Buffer>
The kernel performs the operation in the background.
Programs compose futures instead of blocking.
Research operating systems like Barrelfish, Arrakis, and Shenango investigated related ideas, though each had different goals such as multicore scalability, user-level networking, or kernel bypass.
Why haven't fully asynchronous syscalls become the norm?
Researchers repeatedly encountered several practical issues:
- Many syscalls complete immediately, so making them asynchronous adds overhead.
- Some operations (e.g.
getpid()) are effectively instantaneous.
- Many syscalls have side effects that are difficult to roll back or reorder.
- Error handling becomes more complex when failures are reported later.
- Dependency ordering between syscalls can become intricate.
- Legacy applications expect synchronous semantics.
As a result, modern operating systems generally make latency-heavy operations—especially I/O—efficiently asynchronous, while keeping inexpensive or state-changing operations synchronous.
Overall
The consensus from both academia and practice has largely converged on a hybrid model:
- Keep simple, fast syscalls synchronous.
- Make potentially blocking operations (especially storage and networking) asynchronous.
- Provide efficient completion mechanisms (queues, futures, or events).
- Let language runtimes present a synchronous programming model on top of asynchronous kernel facilities when that improves ergonomics.
That hybrid approach is reflected in modern systems such as Linux with io_uring, contemporary asynchronous runtimes, and ongoing research into user-space networking and storage stacks.