Based on "Understanding the Linux Kernel", p. 190: each process descriptor has a lock_depth field, set to -1 when the bkl isn't taken, and lock_kernel() and unlock_kernel() are equivalent to if (++current->lock_depth == 0) spin_lock(&kernel_flag); and if (--current->lock_depth < 0) spin_unlock(&kernel_flag); respectively. What happens when we schedule()? Examination of the code for schedule() shows that we release the kernel lock if the old task had it, and then reacquire it if necessary if the new task has it (we determine this by looking at the new and previous tasks' lock_depth fields). So it's a recursive spinlock that's dropped while we sleep. Or, at least that's how it used to work; recent proposals would, for example, make it preemptible. But the above should be roughly correct for understanding how to use it.