Skip to main content

Source: Operating Systems: Three Easy Pieces (OSTEP) — Chapter 33, Arpaci-Dusseau & Arpaci-Dusseau

Event-based Concurrency (Advanced)

Threads are not the only way to build concurrent apps. GUIs [O96], some internet servers [PDZ99], and frameworks like node.js [N13] often use event-based concurrency — roots in classic C/UNIX select/poll servers.

Crux: how to build concurrent servers without threads, keep control of scheduling, and dodge many threading bugs?

The event loop​

while (1) {
events = getEvents();
for (e in events)
processEvent(e); // one handler at a time
}

Handling an event is the only activity — so choosing which event next = scheduling. That explicit control is a main advantage.

select() / poll()​

Ask the OS which FDs are ready to read/write (or have errors). Typical loop: FD_ZERO → FD_SET interested sockets → select → FD_ISSET and processFD.

  • timeout = NULL — block until ready
  • timeout = 0 — poll and return immediately
Quiz

Rank the sequence

1 / 1

Order the steps of one pass through a select()-based event loop.

OrderDrag the handle to rearrange — top should be first.

  1. 1processFD on each ready descriptor
  2. 2FD_SET the interested sockets
  3. 3FD_ZERO to clear the descriptor set
  4. 4Call select() to find ready descriptors

Drag items into the correct order (or use ↑↓), then check.

Don’t block in event-based servers

Any blocking call stalls the entire server. Non-blocking / async I/O is mandatory.

Why simpler? No locks (on one CPU)​

One handler at a time, single-threaded → no other thread interrupts → no locks for shared state between handlers. Concurrency bugs from Ch. 32 largely vanish — until you go multicore.

The problem: blocking system calls​

A file-serving request needs open/read. Threads: one thread sleeps on I/O; others run. Events: the only loop blocks → idle waste.

Solution: asynchronous I/O​

Fill an aiocb (fd, offset, buf, nbytes), call aio_read — returns immediately. Poll completion with aio_error (or get a signal when done). Systems without good AIO often use a hybrid: events for network + thread pool for disk [PDZ99].

Quiz

Rank the sequence

1 / 1

Order the steps an event handler takes to issue and complete an asynchronous disk read.

OrderDrag the handle to rearrange — top should be first.

  1. 1Fill an aiocb with fd, offset, buffer, and nbytes
  2. 2aio_read returns immediately, handler moves on
  3. 3Call aio_read with the aiocb
  4. 4Poll aio_error (or receive a completion signal)

Drag items into the correct order (or use ↑↓), then check.

Continuations (manual stack management)​

Threads keep sd on the stack across read(fd) then write(sd,…). Events must package state when issuing async I/O — a continuation [A+02,FHK84]: e.g. hash table fd → {sd}; on completion, look up and finish the write.

What is still hard​

IssueWhy it hurts
MulticoreParallel handlers → locks return
PagingImplicit page-fault blocking stalls the loop
API driftA routine becoming blocking forces handler rewrites
Split I/O APIsOften select for net + AIO for disk — not one uniform wait

Interactive​

Try: event loop · select · don’t block · async I/O · continuations.

Check your understanding​

Quiz

Event-based concurrency

1 / 6

In a single-threaded event loop, deciding which event to handle next is equivalent to…

Pick an answer to see if you are right.

Coding challenges​

Homework lab: event server sketch​

There is no dedicated OSTEP code repo for Ch. 33 — build the homework yourself (TCP + select + file serving + optional AIO/signals).

Lab

Homework: event-based server

0/6 started

Loading lab…

Summary​

PieceRole
Event loopWait → handle one-at-a-time (= schedule)
select/pollWhich FDs are ready?
No blockingOr the whole server stalls
AIO / hybridOverlap disk without a sleeping thread
ContinuationsManual stack across async steps

Threads and events both persist — pick based on control, complexity, and platform I/O support [A+02, PDZ99, WCB01, vB+03].

Previous: Common Concurrency Problems

Next: I/O Devices — buses, interrupts, DMA, drivers.

Further Reading​