"Well, after them!" said Gimli. "Dwarves too can go swiftly, and they do not tire sooner than Orcs. But it will be a long chase: they have a long start."
"Yes," said Aragorn, "we shall all need the endurance of Dwarves. But come! With hope or without hope we will follow the trail of our enemies. And woe to them, if we prove the swifter! We will make such a chase as shall be accounted a marvel among the Three Kindreds; Elves, Dwarves, and Men. Forth the Three Hunters!"
—The Two Towers, Chapter 1, Book III
Like many userspace programs, the Linux kernel is designed to run concurrently with itself. In this case, kernel code must be careful not to create race conditions and concurrency bugs by accessing shared data without protection.
In this studio, you will:
Please complete the required exercises below, as well as any optional enrichment exercises that you wish to complete.
As you work through these exercises, please record your answers, and when finished email your results to dferry@email.wustl.edu with the phrase Kernel Synchronization in the subject line.
Make sure that the name of each person who worked on these exercises is listed in the first answer, and make sure you number each of your responses so it is easy to match your responses with each exercise.
int
called race
with the
volatile
qualifier, as so:
volatile int race = 0;
The volatile
qualifier tells the compiler that this variable
will be modified outside of the current execution context, and has the effect
of disabling certain optimizations.
Within the thread function for each of your threads, write a for loop that
increments the variable race
one million (1,000,000) times, as
so:
#define iters 1000000
for( i=0; i<iters; i++){
race++;
}
In your module's exit function, print out the value of race
.
Leave the answer to this exercise blank.
volatile
and that your
threads are executing simultaneously.
atomic_t
type,
which is defined in include/linux/types.h
. This is an opaque type that
is only accessed through special mutators and accessors. Initialize this new
type with the function atomic_set()
, increment it with the function
atomic_add()
, and access it's value with the function
atomic_read()
. The function prototypes are found in
include/asm-generic/atomic.h
for
loop and when they finish. Use this as a crude timestamp
to determine how long it takes your code to execute. How long does it take?
DEFINE_MUTEX(mutex_name)
to statically
declare a mutex at the global scope and use the functions
mutex_lock(&mutex_name)
and mutex_unlock(&mutex_name)
to protect access to the
race
variable.