Assignment 2: POSIX Threads, Linux kernel modules

Files

Lab materials

A Linux PC (or virtual machine). You can use a VirtualBox guest machine that can be downloaded from the course book's website, or your own Linux machine, or one of the Linux machines in T002 (the same kernel as in the 10th Edition of the book).

Some of these programming assignments are described in the course book.

In the 9th Edition (the paper version), kernel modules are described in "Programming Projects" in chapter 2 (pages 94-98) and in project 2 in "Programming Projects" in chapter 3 (pages 156-158).

In the 10th Edition (the electronic version), kernel modules are described in "Programming Projects" in chapter 2 (there are no page numbers) and in project 2 and 3 in "Programming Projects" in chapter 3.

The 10th Edition of the book, and the accompanying virtual machine, uses Linux kernel version 4.4. (The machines in T002 have this kernel.) The 9th Edition of the book, and its virtual machine, uses an older kernel version, 3.16.

Task 1

The thread performance test program "thread-performance-test-2020.c" starts one or more threads that run in parallel, and measures how many flops (floating point operations per second) it performs, both in total and per thread.

Here is a graph showing its performance on a computer with an Intel Core i7-6850K CPU from 2016. It has 6 cores and hyperthreading. As you can see, performance increases linearly with the number of threads up to 12 threads, but with 13 or more threads the increase stops. Question: Why is that?

A graph showing thread performance

(Click the graph see a larger version.)

Here is another graph, showing the program's performance on the university's ThinLinc server, which runs on an Intel Xeon Gold 6136 CPU from 2017. According to its specifications, this processor type has 12 cores and hyperthreading. Question: Can you explain these results?

Another graph showing thread performance

(Click the graph see a larger version.)

Run the same thread performance test program on your computer. Question: What results do you get? Explain your results!

Task 2

Modify the single-threaded monster world program ("single-threaded-monster-world.c") so it starts one thread for each monster, and all the fighting (the function "one_monster_fights") is done in those threads.

You can start without locking, and see if you get incorrect results. Start without locking, and see if you get incorrect results.

See also the "MONSTER-WORLD-README" file.

Possibly useful command: "gcc -Wall -Wextra -std=c11 -O3 multi-threaded-monster-world.c -lpthread -o multi-threaded-monster-world". With the following Makefile you can just type "make multi-threaded-monster-world":

CC = gcc
CFLAGS += -Wall -Wextra -std=c11 -O3
LDLIBS += -lpthread

Question: Is the multi-threaded version faster? Why, or why not? What about the same multi-threaded version but with no locks?

Questions: Which results do you get? What are the times for the single-threaded version, the multi-threaded version without locking, and the multi-threaded version with locking? Are the multi-threaded versions faster? Explain the results!

Task 3

Create a kernel module that just prints some distinctive messages to the system log when it is loaded and when it is unloaded. Verify with "dmesg" that it works.

If you are running this in a modern Linux (kernel version 4.4.0-20 or later) on a computer where Secure Boot is enabled, it will fail with the error message "Operation not permitted", and in the kernel messages (dmesg) it will print "insmod: Loading of unsigned module is restricted; see man kernel_lockdown.7". This is beacause kernel modules have to be signed. Either turn off Secure Boot (not recommended), run in a virtual machine without Secure Boot, or sign your module (after each recompilation). Here is a Stack Overflow answer that explains how to sign your kernel modues:

https://askubuntu.com/questions/760671/could-not-load-vboxdrv-after-upgrade-to-ubuntu-16-04-and-i-want-to-keep-secur/768310#768310

(They are signing a module called vboxdrv, so you need to replace that with the name of your module.)

Task 4

Create a kernel module that, when it is loaded, prints a list of all processes to the system log. Verify with "dmesg" that it works.

There are macros to loop through processes, and they might be different between kernel 3 and 4.

An update: Note that in later kernels, the macro for_each_process has been moved to the #include file <linux/sched/signal.h>

Task 5 (Optional, counts toward a higher grade than 3)

Modify the kernel module from task 3 so that, when it is loaded, it prints a list of all processes, and for each process lists all threads in that process.

Run the threaded program from task 1 or task 2 to verify that your module works.

Report

Write down and hand in a short summary (2-4 pages) of what you have done. Don't forget to answer the questions above. Mail it (as a PDF or text file) to the teacher. All source code for your programs must be attached. It is good if you can also demonstrate your results at one of the scheduled lab times.


Thomas Padron-McCarthy (thomas.padron-mccarthy@oru.se), 17 juni 2020