This article is a personal take on the ["What Happens When..."](https://github.com/alex/what-happens-when) question, answered from the perspective of ToaruOS. As of 2 October 2015, ToaruOS does not have a graphical web browser ported, so we will answer the question "What happens when I run `fetch http://www.toaruos.org/` in my terminal?" instead, substituting the challenges of HTML, CSS, DOMs, etc. with the added task of loading a binary (`fetch`). Each step of the process will include a reference to a source file in ToaruOS (kernel, userspace, C library glue...). It should be noted before we begin that ToaruOS's network stack is very new and still missing many critical features, and we'll be skipping over anything that ToaruOS is incapable of doing at the moment. Note also that many of the steps in this process are repeated several times throughout - we will only explain them in detail the first time. You can watch a presentation of this [on YouTube](https://www.youtube.com/watch?v=Wp5kl-NfpM8). ## Initial State Before we begin, let's establish the current state of things: [![](http://i.imgur.com/a6yWL2cm.png)](http://i.imgur.com/a6yWL2c.png) ## We're at a terminal. Our shell is in the middle of a [`read` system call](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/sys/syscall.c#L702) instigated by [a call to `fgetc(stdin)`](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/lib/rline.c#L48) in the `rline` library that provides line editing. The [file descriptor](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/include/process.h#L55) for `stdin` points to a [`pty` slave device](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/fs/tty.c#L306), which was created when the terminal application called [`syscall_openpty`](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/terminal/terminal.c#L1364). Thus, [`sys_read`](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/sys/syscall.c#L58) will call the [`read` method of the `pty` slave](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/fs/tty.c#L228). Normally, a PTY device would be in [canonical input mode](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/fs/tty.c#L363) by default, but [before we called `rline`](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/core/sh.c#L482) in the shell, we [disabled canonical input and input echoing](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/core/sh.c#L130-L133). `VMIN` is still set to `1`, its default value, so we'll [read precisely one character](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/fs/tty.c#L237) from the PTY's ring buffer. As there is nothing available to read in the ring buffer, we will [sleep until a writer wakes us up](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/ds/ringbuffer.c#L63). Meanwhile, our terminal application is doing several things: It is blinking a cursor in [a thread that sleeps at regular intervals](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/terminal/terminal.c#L1215-L1227). Another thread is [reading from the PTY master](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/terminal/terminal.c#L1419) waiting for new terminal output to process and render. A third thread is [waiting for events from the window compositor](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/terminal/terminal.c#L1123). We don't quite care about the first two threads at the moment, but we'll get to both of them later. The third thread, however, will be critical to the first step in our walkthrough, so we should talk about its current state: Waiting for events from the window compositor means a call to [`yutani_poll`](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/lib/yutani.c#L41) which ends up as [a `read` system call](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/lib/pex.c#L38-L41) on a "PEX" (Packet EXchange, a ToaruOS-specific packet datagram IPC mechanism) endpoint. PEX is implemented internally through an older form of pipes, and [that `read`](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/modules/packetfs.c#L171) boils down to another sleeping ring buffer. Next, our compositor's keyboard driver is also blocked on [a `read`](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/compositor/compositor.c#L562), this time from the keyboard device, which is actually the same kind of pipe PEX uses, and thus also a sleeping ring buffer. The compositor itself is also processing commands from other running applications (the terminal's blinking cursor, the clock that updates every second...) as the server side of a PEX endpoint which - you guessed it - also involves a ring buffer. So that's a bunch of ring buffers waiting for writers and some background noise. Now what happens when we... ## Press the `f` key We go to type `fetch`, and as soon as we hit the first key, our PS/2 keyboard fires off an interrupt. When we first booted, our PS/2 keyboard driver [installed an interrupt handler](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/modules/ps2kbd.c#L63) for this interrupt, and our base interrupt handler will [locate and call that handler](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/cpu/irq.c#L155-L156). As ToaruOS leaves a lot of the finer details of keyboard mappings to a userspace library, not much more happens in the kernel driver; we read in the scancode from the keyboard and then [append it to the ring buffer](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/modules/ps2kbd.c#L43). [Writing to a ring buffer](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/ds/ringbuffer.c#L73) will [wake up the sleeping readers](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/ds/ringbuffer.c#L85), which in this case means the compositor's keyboard thread, which will finish its ring buffer read of one character, return to userspace, and then [add that scancode to a state machine](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/compositor/compositor.c#L564) which will [convert it into a generic scancode and modifier status](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/lib/kbd.c#L219). The encoded scancode and modifier status are then [turned into a message for the window compositor](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/compositor/compositor.c#L565) and [sent to the event queue](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/compositor/compositor.c#L566) where they will be processed like any other request to the window compositor. This will awaken the [event handling thread](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/compositor/compositor.c#L2014) in the compositor, which will then [process the key event](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/compositor/compositor.c#L2083-L2089), determining whether it should [perform some general window management task](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/compositor/compositor.c#L1429-L1437), pass the key event to a [globally bound application](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/compositor/compositor.c#L1566-L1578) or [send it to the focused window](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/compositor/compositor.c#L1581-L1587). Since we've typed `f` with no modifiers and have nothing bound to steal our `f` key presses, we send an event to the owner of the focused window: the terminal. The terminal receives the event from the window compositor, [recognizes it as a key event](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/terminal/terminal.c#L1126-L1132) and then [converts the key press into the appropriate string](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/terminal/terminal.c#L832) to send to the PTY. Many keys require special sequences, such as the arrow keys or function keys, but our `f` requires nothing special, and we can [simply send it on its way](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/terminal/terminal.c#L842) by [writing it to the PTY master](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/terminal/terminal.c#L827). Writing to a [PTY master](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/fs/tty.c#L211-L220) may involve [extra processing](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/fs/tty.c#L72) depending on the mode of the PTY - especially in the case of `ICANON` [or `ECHO`](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/fs/tty.c#L146), but neither of those flags are set in our mode, so we simply append the `f` [to our ring buffer](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/fs/tty.c#L47), which will wake up the sleeping PTY slave. Reading one character, the PTY slave will [immediately return](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/fs/tty.c#L235), putting us back into userspace in shell - or more specifically, [in the `rline` library](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/lib/rline.c#L48). `rline` needs to process our input to check it for special actions like arrow keys and function keys, which we would represent as special escape sequences. To do that, it uses a [state machine](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/lib/kbd.c#L129) which converts terminal escape sequences into the same scancodes and modifier statuses that the compositor uses. Since `f` requires no special treatment, we can skip over the details of the state machine as well as the handlers for various control key combinations and [add the character to our input buffer](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/lib/rline.c#L221-L245). Since `rline` handles complex editing tasks such as insertion, it needs to be able to handle cases where the "cursor" isn't at the end of the input. It also needs to perform its own input echoing, as we have disabled this on the PTY, so we'll then [print `f` and flush `stdout`](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/lib/rline.c#L238-L244), which will write to the PTY slave, awakening the PTY master, awakening the terminal thread that was handling terminal output. The terminal will process the output it has read from the PTY (the character `f`) through a [state machine of its own](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/terminal/terminal.c#L1420-L1425), which processes [terminal escape sequences](https://en.wikipedia.org/wiki/ANSI_escape_code). That state machine lives in the [`termemu` library](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/terminal/lib/termemu.c) and supports coloring output, moving the cursor, and several other things. The dialect of escape sequences that ToaruOS's terminal implements is based on Xterm, with a few additions from Konsole. The state machine will eventually [call a callback](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/terminal/lib/termemu.c#L121) in the terminal to write the character `f`, where [additional processing will happen](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/terminal/terminal.c#L626) to handle line feeds, bells, UTF-8 codepoint reconstruction, and more. Eventually, the terminal [sets a cell to the character `f`](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/terminal/terminal.c#L690), with appropriate foreground, background, emboldening, and so on, and [draws that cell](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/terminal/terminal.c#L404-L412). Actually [drawing a cell](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/terminal/terminal.c#L410) involves calling into Freetype to [render the glyph for the character](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/terminal/terminal.c#L196-L208) in the cell as pixels in a canvas (a mapped region of memory shared with the compositor containing the texture of the window). Once the character is drawn, a [partial display flip event](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/terminal/terminal.c#L117-L125) is sent to the window compositor to repaint the modified (or "damaged") display regions. The compositor's event handler thread receives the display flip event and [appends the damaged region to a list of damaged regions](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/compositor/compositor.c#L2074-L2082) for processing in the next pass of the rendering thread. The [render thread](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/compositor/compositor.c#L1210) attempts to run 60 times each second, and only performs work [when necessary](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/compositor/compositor.c#L1090) - such as [when display regions have been marked as damaged](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/compositor/compositor.c#L1077-L1086). The compositor uses Cairo to [render window canvases](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/compositor/compositor.c#L1102), restricting rendering to affected regions to avoid unnecessary work. The compositor can perform various transformations to the window when drawing it, such as [rotation](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/compositor/compositor.c#L852-L862) or [animation effects](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/compositor/compositor.c#L881-L897). When compositing is done, the results will be [copied to the framebuffer](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/gui/compositor/compositor.c#L1154-L1157), writing 32-bit RGB values directly into graphics memory that was mapped in the compositor, updating the display. [![](http://i.imgur.com/lKo1DABm.png)](http://i.imgur.com/lKo1DAB.png) ## `fetch http://www.toaruos.org` The process for the `f` key repeats for all the other keys until we hit Enter and the shell's [call to `rline()`](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/core/sh.c#L483) returns, our buffer now filled with "fetch http://www.toaruos.org". At this point, the shell needs to [parse the buffer](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/core/sh.c#L526) to figure out what we want to do. The shell supports complex quoting, variables, and pipes, the last of which means forking off multiple child processes and linking their inputs and outputs appropriately. Luckily, we've entered a fairly simple command and all the shell needs to do is split it into two tokens (`fetch` and `http://www.toaruos.org`), [fork a child and run the command](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/core/sh.c#L779). [![](http://i.imgur.com/jnhNCk9m.png)](http://i.imgur.com/jnhNCk9.png) ## Forking and execing _TODO: This section could use more details._ Forking is the traditional Unix method of starting a new process. Forking involves building a new copy of the current process, including its file descriptors, memory, CPU state, and so on. Our entry point into this process is the [`fork` system call](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/sys/task.c#L187), which will [do all of those things](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/sys/task.c#L194-L206) and then [add this new process to the scheduler's "ready" queue](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/sys/task.c#L227). Our old process will receive the PID of the new process as its return value from the system call, while the new process will receive `0`, allowing us to track the new child process. The original shell process will [`wait`](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/core/sh.c#L784-L794) on "all" of its "children" (one child process in this case), and - finding none of them to be finished - will [sleep](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/sys/process.c#L786) on an [event](https://en.wikipedia.org/wiki/Event_%28synchronization_primitive%29) to be raised when a child finishes later. Meanwhile, the new shell process will call `execvp` to replace itself with the `fetch` binary. `execvp` evaluates the `PATH` environment variable, searching the filesystem with [`open`](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/fs/vfs.c#L942-L946), [`readdir`](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/modules/ext2.c#L1238-L1256), and [`fstat`](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/sys/syscall.c#L256-L293) to find a binary named `fetch`. All of those filesystem operations call down into the EXT2 filesystem module, which will [read inodes](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/modules/ext2.c#L1093-L1112), which means [reading blocks](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/modules/ext2.c#L121) which means [reading sectors from the disk](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/modules/ata.c#L382) or memory in a [ramdisk](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/fs/ramdisk.c#L22-L36). Once `execvp` has found an appropriate binary, it then calls [`execve` system call](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/sys/syscall.c#L186) which will [load and parse the executable](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/misc/elf.c#L257-L262) to determine whether it's an ELF binary, shell script with `#!` line, or something else it can execute. Finding `fetch` to be an ELF binary, it will then continue [loading the rest of the binary](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/misc/elf.c#L16) and [copy it into memory](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/misc/elf.c#L73). [Arguments](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/misc/elf.c#L112-L121), environment variables, and ELF auxiliary variables will also be copied into place. Eventually we will [jump back to userspace](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/kernel/misc/elf.c#L156) at the binary's requested start address, which will bring us to [the crt0](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/toolchain/patches/newlib/toaru/crt0.s) startup code, which then jump to [`pre_main`](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/toolchain/patches/newlib/toaru/syscalls.c#L421-L439) which reads the environment variables, calls `init` functions, and then calls `main`. ## `fetch` Now we're at the point where we can look at the code for `fetch` itself. We're at [`main()`](https://github.com/klange/toaruos/blob/e195298e5ba99956ee05a1ce91c0024ea95321db/userspace/net/fetch.c#L76). _TODO: This is still a work in progress_