We have covered the various synchronization mechanisms in the previous articles. One of the thing common among them was that they put the process to sleep, if the lock is not available. Also, all those are prone to deadlock, if not implemented carefully. Sometimes however, we require to protect a simple variable like integer. It can be as simple as setting a flag. Using semaphore or spinlock to protect such a variable may be overhead. So, does kernel provide any synchronization mechanism without locking? Read on to explore more on this.
Atomic Operations
Atomic operations are indivisible and uninterruptible. Each of these compile into a single machine instruction as far as possible and are guaranteed to be atomic. Kernel provides a atomic integer type atomic_t for atomic operations. Below are the operations:
#include <asm/atomic.h> void atomic_set(atomic_t *a, int i); // Set the atomic variable a to integer value i int atomic_read(atomic *a); // Return the value of atomic variable a void atomic_add(int i, atomic_t *a); // Add i to atomic variable a void atomic_sub(i, atomic_t *a); // Subtract i from atomic variable a void atomic_inc(atomic_t *a); // Increment operation void atomic_dec(atomic_t *a); // Decrement operation
Atomic Bit Operations
Many a times, the requirement is to flag some condition. For this, a single bit may serve the purpose well. However, atomic_t type variable doesn’t work well for manipulating the bits. For this, the kernel provides a set of operations as listed below:
#include <asm/bitops.h> void set_bit(int nr, void *a); // Set the bit number nr in value pointed by a void clear_bit(int nr, void *a); // Clear the bit number nr in value pointed by a void change_bit(int nr, void *a); // Toggle the bit at position nr
Conclusion
So, these are the simple, yet powerful mechanisms to provide the synchronization without locking. These can be quite useful while dealing with integer and bit operations, respectively, and involve far less overhead as compared to the usual synchronization mechanisms such as semaphore and mutex. However, these might not be useful in achieving the critical sections.
With this, we are now familiar with most of the synchronization mechanisms provided by the kernel. As you understand, synchronization mechanisms come with its own pros and cons and we need to be very careful while selecting the right one.
Pingback: Concurrency Management Part – 3 | Playing with Systems
Pingback: Waiting / Blocking in Linux Driver | Playing with Systems
Thank u you sir for providing such easy way to understand
Thanks for your appreciation.
is it possible to create a kernel program in XV6 OS without using predefined libraries
For that, I’d suggest you to refer to some XV6 related forum.