17.8. Kernel Semaphores
Semaphores provide a method of synchronizing access to a
In the counter implementation, the semaphore value is
The Solaris kernel uses semaphores where appropriate, when the constraints for atomicity on lock acquisition are not as stringent as they are in the areas where mutex and RW locks are used. Also, the counting functionality that semaphores provide makes them a good fit for things like the allocation and deallocation of a fixed amount of a resource. The kernel semaphore structure maintains a sleep queue for the semaphore and a count field that reflects the value of the semaphore, shown in Figure 17.8. The figure illustrates the look of a kernel semaphore for all Solaris releases covered in this book. Figure 17.8. Kernel Semaphore
Kernel functions for semaphores include an initialization routine ( sema_init() ), a destroy function ( sema_destroy() ), the traditional P and V operations ( sema_p() and sema_v() ), and a test function (test for semaphore held, sema_held() ). There are a few other support functions, as well as some variations on the sema_p() function, which we discuss later.
The
init
function simply sets the count value in the semaphore, based on the value passed as an argument to the
sema_init()
routine. The
s_slpq
pointer is set to
NULL
, and the semaphore is initialized. The
sema_destroy()
function is used when the semaphore is an integral part of a resource that is dynamically created and
Kernel threads that must access a resource controlled by a semaphore call the
sema_p()
function, which requires that the semaphore count value be greater than 0 in order to return success. If the count is 0, then the semaphore is not available and the calling thread must block. If the count is greater than 0, then the count is decremented in the semaphore and the code returns to the caller. Otherwise, a sleep queue is located from the
Sleep queues are discussed in more detail in Section 3.10. Briefly though, sleep queues are organized as a linked list of kernel threads, and each linked list is rooted in an array referenced through a sleepq_head kernel pointer. Figure 17.9 illustrates how sleep queues are organized. Figure 17.9. Sleep Queues
A hashing function indexes the
sleepq_head
array, hashing on the address of the object. A
Inside the
sema_p()
function, if we have a semaphore count value of 0, the semaphore is not available and the calling kernel thread needs to be placed on a sleep queue. A sleep queue is located through a hash function into the
sleep_head
array, which hashes on the address of the object the thread is blocking, in this case, the address of the semaphore. The code also grabs the sleep queue lock,
sq_lock
(see Figure 17.9), to block any further
The scheduling-class-specific sleep function is called to set the thread
A semaphore is released by the
sema_v()
function, which has the exact
Semaphores are used in relatively few areas of the operating system: the buffer I/O ( bio ) module, the dynamically loadable kernel module code, and a couple of device drivers. |

Solaris Performance and Tools: DTrace and MDB Techniques for Solaris 10 and OpenSolaris

DTrace: Dynamic Tracing in Oracle Solaris, Mac OS X and FreeBSD (Oracle Solaris Series)

Solaris 10 Security Essentials

Oracle Solaris 10 System Virtualization Essentials (Oracle Solaris System Administration Series)