The x86-64 ISA defines 16 general-purpose registers. These are registers the CPU provides for programmers to use for whatever they see fit. Note that programmers here include the ones that write the operating system, and they can lay additional restrictions on what registers you can use for what when you create a program to run on their operating system. In our specific example, Windows and Unix-based systems have different requirements for where to place the arguments for a function:
- Linux specifies that a function that takes two arguments should place the first argument to the function in the rdi register and the second one in the rsi register
- Windows requires that the first two arguments be passed in the registers rcx and rdx
This is just one of many ways in which a program that is written for one platform won’t work on another. Usually, these details are the concern of compiler developers, and the compiler will handle the different calling conventions when you compile for a specific platform.
So to sum it up, CPUs implement an instruction set. The instruction set defines what instructions the CPU can execute and the infrastructure it should provide to programmers (such as registers). An operating system uses this infrastructure in different ways, and it provides additional rules that a programmer must obey to run their program correctly on their platform. Most of the time, the only programmers that need to care about these details are the ones who write operating systems or compilers. However, when we write low-level code ourselves, we need to know about the ISA and the OS ABI to have our code work correctly.
Since we need to write this kind of code to implement our own fibers/green threads, we must potentially write different code for each OS ABI/ISA combination that exists. That means one for Windows/x86-64, one for Windows/ARM, one for MacOS/x86-64, one for Macos/M, etc.
As you understand, this is also one major contributor to the complexity of using fibers/green threads for handling concurrency. It has a lot of advantages once it’s correctly implemented for an ISA/OS ABI combination, but it requires a lot of work to get it right.
For the purpose of the examples in this book, we will only focus on one such combination: the System V ABI for x86-64.
Note!
In the accompanying repository, you will find a version of the main example for this chapter for Windows x86-64. The changes we have to make to make it work on Windows are explained in the README.