Monday, December 31, 2012

Building LLVM 3.2 from source

A short guide on how to compile LLVM 3.2 a low level compiler infrastructure with Clang on Ubuntu 12.04 (64bit).



1. Create a directory for LLVM
$mkdir ~/llvm
$cd ~/llvm
Install required dependencies (Note : my system is already setup for development so I cannot find out the exact packages required, if you know them post them as comments)
$sudo apt-get install build-essential
2. Download the latest version of LLVM sources including clang (C frontend) and compiler RT from http://llvm.org/releases/download.html#3.2
$wget http://llvm.org/releases/3.2/llvm-3.2.src.tar.gz
$wget http://llvm.org/releases/3.2/clang-3.2.src.tar.gz
$wget http://llvm.org/releases/3.2/compiler-rt-3.2.src.tar.gz
3. Extract the downloaded sources
$tar zxvf ./llvm-3.2.src.tar.gz
$tar zxvf ./clang-3.2.src.tar.gz
$tar zxvf ./compiler-rt-3.2.src.tar.gz
4. Move folders to correct location. We start by renaming 'llvm-3.2.src' to 'llvm-3.2' and moving 'clang' inside the LLVM 'tools' folder and compiler-rt under the LLVM 'projects' folder. This is where LLVM expects them to be.
$mv ./llvm-3.2.src ./llvm-3.2
$mv ./clang-3.2.src ./clang
$mv ./clang ./llvm-3.2/tools/
$mv ./compiler-rt-3.2.src ./compiler-rt
$mv ./compiler-rt ./llvm-3.2/projects/
5. Once everything is in place we create a separate folder for the build process
$mkdir ./build
$cd ./build
This is how the folder structure looks like
|-- build (currently we are here)
|-- llvm-3.2
|   |-- projects
|   |   |-- compiler-rt
|   |-- tools
|   |   |-- clang
|-- clang-3.2.src.tar.gz
|-- compiler-rt-3.2.src.tar.gz
|-- llvm-3.2.src.tar.gz
6. Now we start the actual configuration and compilation of LLVM inside the 'build' folder outside of the main source directory so as to keep the main source tree clean
$../llvm-3.2/configure --enable-shared
Note : There are various configuration flags for CPU architecture, optimize builds, threads, etc. Check them with the '--help' option.
$../llvm-3.2/configure --help
If there are any missing packages required to compile LLVM it will ask you here.
7. If everything is good we can go ahead and compile it and also keep track of the time taken. After compilation all binaries are available in the 'build/Release+Asserts/bin' folder and libraries are available in the 'build/Release+Asserts/lib' folder.
$time make -j 3
.....
llvm[0]: ***** Completed Release+Asserts Build
real 31m58.051s
user 52m50.842s
sys 2m37.610s
Great job so far, few more steps to go :)

8. Its good to run some test suites that comes along with LLVM to verify everything is working.
$make check-all
9. To start using LLVM we have to include the LLVM binaries and libraries in our path.
To add the LLVM binaries
$gedit ~/.bashrc
Add this line to the end of the file
export PATH=$PATH:~/llvm/build/Release+Asserts/bin
To add the LLVM libraries
sudo gedit /etc/ld.so.conf.d/llvm.conf
Add this line to the file (replace <your_user_name> with your current username)
/home/<your_user_name>/llvm/build/Release+Asserts/lib
To apply the new settings do
$source ~/.bashrc
$sudo ldconfig
10. To check whether the LLVM binaries and libraries are correctly set
$which clang
~/llvm/build/Release+Asserts/bin/clang
$sudo ldconfig -p | grep LLVM
libLLVM-3.2svn.so (libc6,x86-64) => ~/llvm/build/Release+Asserts/lib/libLLVM-3.2svn.so
11. Test a sample program
$cd ..
$mkdir test
$cd test
$gedit test.c
Add the following lines of a simple C program and save it
#include <stdio.h>
int main(void)
{
 printf("Hello World from LLVM!\n");
 return 0;
}
Compile it using clang the C frontend to LLVM
$clang test.c -o test
Run it
$./test
Hello World from LLVM!

Wednesday, October 10, 2012

Building Linux kernel the clean way

I like to keep my kernel sources clean and have the kernel build in a separate directory. Here is how I do it.



1. Lets create a "~/kernel" directory for holding everything
$cd ~
$mkdir ~/kernel
$cd ~/kernel
2. Download and extract the kernel source
$wget http://www.kernel.org/pub/linux/kernel/v3.0/linux-3.6.tar.bz2
$tar jxvf linux-3.6.tar.bz2
3. Create a build directory
$mkdir ~/kernel/build
Now our directory structure looks like:
~/
~/kernel/
~/kernel/build/
~/kernel/linux-3.6.tar.bz2
~/kernel/linux-3.6/
4. We will create a bash function that will automatically create the build folder for us based on the folder name of the kernel source. Add the following to the ~/.bashrc file. Once this is done open a new bash terminal so that the function is available for use.
function kb {
    mkdir -p ~/kernel/build/$(basename $(pwd))
    echo ~/kernel/build/$(basename $(pwd))
}
Running $kb in your shell will create the build folder and return the path of the build folder which we will pass it to "make" in the next step.

5. To build the kernel in the "build" folder follow your normal step except...
$cd linux-3.6
$make distclean
$make defconfig O=`kb`
$make O=`kb`
You can see that a folder called "~/kernel/build/linux-3.6" has been created and all the object files are created in the build folder and our original kernel source folder is kept clean. After the compiling is done the kernel is available in the ~/kernel/build/arch/x86/boot/bzImage or whatever is your architecture folder.

Note :
The keys surrounding the `kb` in the above steps are the backtick keys which are located along with the "~" key on your keyboard.

Extra :
If you download and extract the linux-3.5.tar.bz2 and repeat the above 5th step it will create a ~/kernel/build/linux-3.5 folder and build everything there.

Next time I am going to post how you can fully automate the build with git.

Sunday, October 7, 2012

Using ketchup to manage kernel releases

We are going to use ketchup to download Linux kernel releases. Its a great tool written in python to automate a lot of stuff.

1. Install ketchup
$sudo apt-get install ketchup
$mkdir linux
$cd linux
2. Lets check the latest version of Linux kernel for the 3.x series
$ketchup -s 3
3.6
3. Lets download the 3.6 kernel release
$ketchup -r 3.6
.....
gpg: Signature made Monday 01 October 2012 05:25:16 AM IST using RSA key ID 00411886
gpg: Can't check signature: public key not found

ketchup: The GPG key seems not to be in the keyring. Please fix this and try again.
In the case potential malicious kernel code is not a problem,
you can skip the verifying by using --no-gpg.
ketchup: Tarball download failed
4. Oops ! You need to add the GPG key to your keyring for verification since each release is signed (Note that the RSA key ID 00411886 is mentioned in the message itself). Lets do that...
$gpg --recv-keys 00411886
gpg: requesting key 00411886 from hkp server keys.gnupg.net
gpg: key 00411886: public key "Linus Torvalds " imported
gpg: no ultimately trusted keys found
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
6. This looks good. Lets try downloading again.
$ketchup -r 3.6
....
Downloading linux-3.6.tar.sign
--2012-10-07 17:47:06--  http://www.kernel.org/pub/linux/kernel/v3.0/linux-3.6.tar.sign
....
Downloading linux-3.6.tar.xz
--2012-10-07 17:47:06--  http://www.kernel.org/pub/linux/kernel/v3.0/linux-3.6.tar.xz
....
7. It will download, verify, extract the kernel sources and it will also rename the directory to "linux-3.6" to match the kernel version downloaded. Great !

8. Since our original "linux" folder has been renamed to "linux-3.6" we need to back down to parent folder and go back to the renamed "linux-3.6" folder
$cd ..
$cd linux-3.6
9. Now lets try something different. Lets download Linux kernel version 3.5
$ketchup -r 3.5
Note that it only downloads the patch file that it needs to apply/revert to 3.6 that is already downloaded to roll back to 3.5 ! Also it will rename the directory to "linux-3.5". Remember to repeat the above step 8 to go to the renamed "linux-3.5" folder.

Sunday, September 23, 2012

Do a git checkout of Dragonfly BSD Hammer2 File System

1. Clone the main Dragonfly BSD git repo (approx. 750MB)
$git clone git://git.dragonflybsd.org/dragonfly.git dragonfly
$cd dragonfly
2. List all branches
$git branch -a
* master
  remotes/origin/DragonFly_RELEASE_1_10
  remotes/origin/DragonFly_RELEASE_1_12
  remotes/origin/DragonFly_RELEASE_1_2
  remotes/origin/DragonFly_RELEASE_1_4
  remotes/origin/DragonFly_RELEASE_1_6
  ....
  remotes/origin/HEAD -> origin/master
  remotes/origin/doc
  remotes/origin/hammer2   <======================== HAMMER2
  remotes/origin/master
  remotes/origin/netmp
  ....
3. Checkout the Hammer2 branch
$git checkout hammer2
cd sys/vfs/hammer2

Friday, September 21, 2012

Compiling LLVM on Ubuntu

A short guide on how to compile latest version of LLVM a low level compiler infrastructure with Clang on Ubuntu 12.04 (64bit).

1. Create a directory for LLVM
$mkdir ~/llvm
$cd ~/llvm
Install required dependencies (Note : my system is already setup for development so I cannot find out the exact packages required, if you know them post them as comments)
$sudo apt-get install build-essential
2. Download the latest version of LLVM sources including clang (C frontend) and compiler RT from http://llvm.org/releases/download.html#3.1
$wget http://llvm.org/releases/3.1/llvm-3.1.src.tar.gz
$wget http://llvm.org/releases/3.1/clang-3.1.src.tar.gz
$wget http://llvm.org/releases/3.1/compiler-rt-3.1.src.tar.gz
$wget http://llvm.org/releases/3.1/test-suite-3.1.src.tar.gz
3. Extract the downloaded sources
$tar zxvf ./llvm-3.1.src.tar.gz
$tar zxvf ./clang-3.1.src.tar.gz
$tar zxvf ./compiler-rt-3.1.src.tar.gz
4. Move folders to correct location. We start by renaming 'llvm-3.1.src' to 'llvm-3.1' and moving 'clang' inside the LLVM 'tools' folder and compiler-rt under the LLVM 'projects' folder. This is where LLVM expects them to be.
$mv ./llvm-3.1.src ./llvm-3.1
$mv ./clang-3.1.src ./clang
$mv ./clang ./llvm-3.1/tools/
$mv ./compiler-rt-3.1.src ./compiler-rt
$mv ./compiler-rt ./llvm-3.1/projects/
5. Once everything is in place we create a separate folder for the build process
$mkdir ./build
$cd ./build
6. Now we start the actual configuration and compilation of LLVM inside the 'build' folder
$../llvm-3.1/configure
If there are any missing packages required to compile LLVM it will ask you here. If everything is ok we can go ahead and compile it and also keep track of the time taken. Note that all binaries are available in the 'build/Release+Asserts/bin' folder including llvm, clang, clang++
$time make
.....
llvm[0]: ***** Completed Release+Asserts Build
real 44m17.244s
user 41m42.572s
sys 2m5.592s
That's it ! We are done :)

7. To start using LLVM we have to include the binaries in our path. Add the following lines to your bash profile
$gedit ~/.bashrc
Add this line to the end of the file
export PATH=$PATH:~/llvm/build/Release+Asserts/bin
To apply the new settings close the terminal and start a new one or you can do
$source ~/.bashrc
8. Test a sample program
$cd ..
$mkdir test
$cd test
$gedit test.c
Add the following lines of a simple C program and save it
#include <stdio.h>
int main(void)
{
 printf("Hello World from LLVM!\n");
 return 0;
}
Compile it using clang the C frontend to LLVM
$clang test.c -o test
Run it
$./test
Hello World from LLVM!

Saturday, May 5, 2012

Using ccache to speed up kernel compilation

We are going to use "ccache" to speed up our Linux kernel compilation. This neat tool caches the output of C/C++ compilation so the next time the results can be taken from the cache. It can result in 5-10 times speed improvements.


Update : Recorded a short video on it !

1. First we need to install ccache which is already available in Ubuntu repositories
$sudo apt-get install ccache
2. Now let us configure our system to use ccache. Edit your ~/.bashrc
$vim ~/.bashrc
And add the following lines to the end of the file
# ccache
export CCACHE_DIR="/home/prashants/.ccache"
export CC="ccache gcc"
export CXX="ccache g++"
export PATH="/usr/lib/ccache:$PATH"
Replace the /home/prashant/.ccache folder to your own home folder. It is a empty folder that ccache will use to store the result of the compilation. You can use any other folder name of your choice.

The /usr/lib/ccache folder is automatically created by ccache and it contains symlinks to ccache for gcc/g++ compiler names. By adding it to our PATH environment variable, ccache will be called instead of gcc compiler.
$ls /usr/lib/ccache
Now to apply the changes in the ~/.bashrc file
$source ~/.bashrc
3. Next we need to setup the maximum cache size
$ccache -M 2G
This limits the cache size to 2GB. You can change it to something more if you have enough free space.

4. You are done ! Next time you run gcc/g++/make commands it will use ccache. You can monitor the current usage of ccache by executing
$watch -n1 -d ccache -s
5. Lets try it out ! Download the latest linux kernel source from http://kernel.org and compile it. Simultaneously keep a terminal open with the above command running and you will see this


Combining ccache along with distributed kernel compilation can give really amazing results ! Read about the distributed kernel compilation in my previous article here.

Debugging Linux kernel over serial port

We are going to see how to output the kernel messages over the serial port. We need two machines for this but it can also be done with a single machine and simulating the second machine in Virtualbox.

The primary machine is called the HOST machine where we will receive the debug messages. It is running Ubuntu Linux 11.10. We will install Virtualbox Open Source Edition (OSE) on this machine and create another machine called the TARGET machine inside Virtualbox. We will install Ubuntu Linux 11.10 inside this TARGET machine. This TARGET machine is the one we will want to debug over the serial port.

In this guide I have assumed that you have install Ubuntu Linux in the Virtualbox TARGET machine.

1. Let us first configure the Virtualbox TARGET machine. We need to enable the serial port for the TARGET machine. Open the settings for this machine in Virtualbox. Go to "Serial ports". In the "Port 1" tab enable the "Enable Serial Port" option. Use the following settings :
Port Number : COM1
Port Mode : Host Pipe
Create Pipe (Enabled)
Port/File Path : /tmp/vserial


2. Now start the TARGET machine and edit the entry in the Grub2 selection menu


- Click on 'e' key to edit the entry
- Navigate to the line
linux /boot/vmlinuz...
- Press the "End" key to append to the end of this line and type the following at the end of the line :
console=tty console=ttyS0,9600
This is how it should look like
linux /boot/vmlinuz-3.0.0-12-generic root=UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx ro quiet splash vt.handoff=7 console=tty console=ttyS0,9600


Incase if you make some mistake press the "Esc" key to go back the previous menu and again click on 'e' to edit it.

Once done, wait at this screen and follow the next step. We will come back to this screen later.

3. Let us switch to our HOST machine. We are now going to setup our HOST machine to connect to the above Virtualbox TARGET machine using the serial port. We will use minicom terminal program for this
$sudo apt-get install minicom
Since we have already started the Virtualbox TARGET machine in the above step it will automatically create a /tmp/vserial file in our HOST machine. Remember the HOST machine is our main machine and the TARGET machine is running inside Virtualbox. Let us check in our host machine if this file is created.
$ls -al /tmp/vserial
srwxrwxr-x 1 prashants prashants 0 2012-05-05 19:47 /tmp/vserial
The file is created and the 's' in the first character means its a socket file. We are now going to setup minicom to use that file.
$minicom -s
Select "Serial port setup". Now, Press "A" to setup "Serial device". Delete whatever the current entry is, and type
unix#/tmp/vserial
Press "Enter" when done.

Now, press "E" and then press "C" to select 9600 baud rate. Then press "L" to select "No Parity" and then press "V" to select 8-data bit. When done press "Enter".

This is how it should look like finally


Now press "Enter" again to come out of the Serial port setup and back to the main configuration menu.


Once on this screen press "Esc" and it will connect to the socket file. This is how it should looks.


Check the status in the bottom - it says "unix-socket" and "Online". Also check the socket filename in the serial terminal it should be "unix#/tmp/vserial"

Our HOST machine is now ready to receive the kernel debugging message.

4. Let us now switch back to the TARGET machine inside the Virtualbox which is still at the screen



Now, press "Ctrl-X" or F10 inside this screen to boot into this and also watch the minicom screen in the host machine and you will see the kernel messages.




5. The changes we made to the Grub2 entry in above Step 1 are temporary so you need to do this after every reboot of the Virtualbox TARGET machine. To make these entry in Grub2 permanent you need to update the Grub2 configuration files for the TARGET machine which is beyond the scope of this tutorial. One short-cut method is to directly edit the "/boot/grub/grub.cfg" file but this method is not recommended - do it at your own risk. An invalid entry can render the system unbootable.

Also in some cases you might not see the Grub2 menu during boot - You can either press the "Shift" key during boot or else edit the "/etc/default/grub" file and change the following entry
GRUB_HIDDEN_TIMEOUT_QUIET=true
GRUB_TIMEOUT=10
Also you need to update Grub2 after changing the "/etc/default/grub" file
$sudo update-grub

Sunday, April 15, 2012

Perf tool

Perf is a performance monitoring tool for Linux kernel available under "tools/perf". Install it on ubuntu :

$sudo apt-get install linux-tools-common linux-tools

More information is available at :

https://perf.wiki.kernel.org/
https://perf.wiki.kernel.org/articles/t/u/t/Tutorial.html
http://vger.kernel.org/~acme/perf/lk2010-perf-paper.pdf

Thursday, March 22, 2012

Distributed Kernel Compilation in Ubuntu

We are going to use "distcc" which is a distributed C/C++ compiler.

1. We have one host machine (Machine A) on which we have downloaded the latest linux kernel sources. The IP address of this machine is 10.1.1.1

We have one more machine (Machine B) which we are going to run the distributed compiler. The IP address of this machine is 10.1.1.2

Both the machines are running Ubuntu.

2. On Machine A do the following :

Install distcc :
$sudo apt-get install distcc

Add entry for Machine B in the '/etc/distcc/hosts' file. Comment out '+zeroconf' as given below since we are not going to use it :
# Add a list of hostnames in one line, seperated by spaces, here.
# +zeroconf
10.1.1.2

Check if the host is added :
$distcc --show-hosts

3. On Machine B do the following :

Install distcc :
$sudo apt-get install distcc

Edit the '/etc/default/distcc' file and set the following parameters :
STARTDISTCC="true"
ALLOWEDNETS="127.0.0.1 10.1.1.1/24"
LISTENER="10.1.1.2"
ZEROCONF="false"

Start the "distcc" service :
$sudo service distcc start

Now we are ready to start the distributed kernel compilation.

4. Download the latest linux kernel source from http://kernel.org and extract it on Machine A. Setup the kernel .config file (refer this guide for more information). Now to start the distributed compilation and even time it :
$time make -j8 CC=distcc
This will start 8 threads and distribute the compilation between Machine A and Machine B

5. Test results :
kernel compilation using single machine :
real 50m55.498s
user 71m4.967s
sys 6m55.030s

kernel compilation using three machines:
real 28m21.146s
user 17m32.862s
sys 4m35.537s

Monday, February 20, 2012

Kernel Error Codes

All error codes for the kernel are available in the following files in the kernel source tree :

include/asm-generic/errno-base.h
include/asm-generic/errno.h

----------------------include/asm-generic/errno-base.h----------------------

#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */

-------------------------include/asm-generic/errno.h----------------------

#define EDEADLK 35 /* Resource deadlock would occur */
#define ENAMETOOLONG 36 /* File name too long */
#define ENOLCK 37 /* No record locks available */
#define ENOSYS 38 /* Function not implemented */
#define ENOTEMPTY 39 /* Directory not empty */
#define ELOOP 40 /* Too many symbolic links encountered */
#define EWOULDBLOCK EAGAIN /* Operation would block */
#define ENOMSG 42 /* No message of desired type */
#define EIDRM 43 /* Identifier removed */
#define ECHRNG 44 /* Channel number out of range */
#define EL2NSYNC 45 /* Level 2 not synchronized */
#define EL3HLT 46 /* Level 3 halted */
#define EL3RST 47 /* Level 3 reset */
#define ELNRNG 48 /* Link number out of range */
#define EUNATCH 49 /* Protocol driver not attached */
#define ENOCSI 50 /* No CSI structure available */
#define EL2HLT 51 /* Level 2 halted */
#define EBADE 52 /* Invalid exchange */
#define EBADR 53 /* Invalid request descriptor */
#define EXFULL 54 /* Exchange full */
#define ENOANO 55 /* No anode */
#define EBADRQC 56 /* Invalid request code */
#define EBADSLT 57 /* Invalid slot */
#define EDEADLOCK EDEADLK
#define EBFONT 59 /* Bad font file format */
#define ENOSTR 60 /* Device not a stream */
#define ENODATA 61 /* No data available */
#define ETIME 62 /* Timer expired */
#define ENOSR 63 /* Out of streams resources */
#define ENONET 64 /* Machine is not on the network */
#define ENOPKG 65 /* Package not installed */
#define EREMOTE 66 /* Object is remote */
#define ENOLINK 67 /* Link has been severed */
#define EADV 68 /* Advertise error */
#define ESRMNT 69 /* Srmount error */
#define ECOMM 70 /* Communication error on send */
#define EPROTO 71 /* Protocol error */
#define EMULTIHOP 72 /* Multihop attempted */
#define EDOTDOT 73 /* RFS specific error */
#define EBADMSG 74 /* Not a data message */
#define EOVERFLOW 75 /* Value too large for defined data type */
#define ENOTUNIQ 76 /* Name not unique on network */
#define EBADFD 77 /* File descriptor in bad state */
#define EREMCHG 78 /* Remote address changed */
#define ELIBACC 79 /* Can not access a needed shared library */
#define ELIBBAD 80 /* Accessing a corrupted shared library */
#define ELIBSCN 81 /* .lib section in a.out corrupted */
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
#define EILSEQ 84 /* Illegal byte sequence */
#define ERESTART 85 /* Interrupted system call should be restarted */
#define ESTRPIPE 86 /* Streams pipe error */
#define EUSERS 87 /* Too many users */
#define ENOTSOCK 88 /* Socket operation on non-socket */
#define EDESTADDRREQ 89 /* Destination address required */
#define EMSGSIZE 90 /* Message too long */
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
#define ENOPROTOOPT 92 /* Protocol not available */
#define EPROTONOSUPPORT 93 /* Protocol not supported */
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
#define EPFNOSUPPORT 96 /* Protocol family not supported */
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
#define EADDRINUSE 98 /* Address already in use */
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
#define ENETDOWN 100 /* Network is down */
#define ENETUNREACH 101 /* Network is unreachable */
#define ENETRESET 102 /* Network dropped connection because of reset */
#define ECONNABORTED 103 /* Software caused connection abort */
#define ECONNRESET 104 /* Connection reset by peer */
#define ENOBUFS 105 /* No buffer space available */
#define EISCONN 106 /* Transport endpoint is already connected */
#define ENOTCONN 107 /* Transport endpoint is not connected */
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
#define ETIMEDOUT 110 /* Connection timed out */
#define ECONNREFUSED 111 /* Connection refused */
#define EHOSTDOWN 112 /* Host is down */
#define EHOSTUNREACH 113 /* No route to host */
#define EALREADY 114 /* Operation already in progress */
#define EINPROGRESS 115 /* Operation now in progress */
#define ESTALE 116 /* Stale NFS file handle */
#define EUCLEAN 117 /* Structure needs cleaning */
#define ENOTNAM 118 /* Not a XENIX named type file */
#define ENAVAIL 119 /* No XENIX semaphores available */
#define EISNAM 120 /* Is a named type file */
#define EREMOTEIO 121 /* Remote I/O error */
#define EDQUOT 122 /* Quota exceeded */
#define ENOMEDIUM 123 /* No medium found */
#define EMEDIUMTYPE 124 /* Wrong medium type */
#define ECANCELED 125 /* Operation Canceled */
#define ENOKEY 126 /* Required key not available */
#define EKEYEXPIRED 127 /* Key has expired */
#define EKEYREVOKED 128 /* Key has been revoked */
#define EKEYREJECTED 129 /* Key was rejected by service */
/* for robust mutexes */
#define EOWNERDEAD 130 /* Owner died */
#define ENOTRECOVERABLE 131 /* State not recoverable */
#define ERFKILL 132 /* Operation not possible due to RF-kill */
#define EHWPOISON 133 /* Memory page has hardware error */