Spin locks can be used in interrupt handlers, whereas semaphores cannot be used because they sleep
If a lock is used in an interrupt handler, you must also disable local interrupts (interrupt requests on the current processor) before obtaining the lock
So the pseudo code of spin lock
If used in ISR
spinlock_t mr_lock = SPIN_LOCK_UNLOCKED;
unsigned long flags;
/* critical region ... */
The fact that a contended spin lock causes threads to spin (essentially wasting processor time) while waiting for the lock to become available is important. This behavior is the point of the spin lock. It is not wise to hold a spin lock for a long time. This is the nature of the spin lock: a lightweight single-holder lock that should be held for short durations. An alternative behavior when the lock is contended is to put the current thread to sleep and wake it up when it becomes available. Then the processor can go off and execute other code. This incurs a bit of overhead most notably the two context switches required to switch out of and back into the blocking thread, which is certainly a lot more code than the handful of lines used to implement a spin lock. Therefore, it is wise to hold spin locks for less than the duration of two context switches. Because most of us have better things to do than measure context switches, just try to hold the lock as little time as possible. The semaphores provide a lock that makes the waiting thread sleep, rather than spin, when contended.
Acquires given lock
Disables local interrupts and acquires given lock
Saves current state of local interrupts, disables local interrupts, and acquires given lock
Releases given lock
Releases given lock and enables local interrupts
Releases given lock and restores local interrupts to given previous state
Dynamically initializes given spinlock_t
Tries to acquire given lock; if unavailable, returns nonzero
Returns nonzero if the given lock is currently acquired, otherwise it returns zero
certain locking precautions must be taken when working with bottom halves. The function spin_lock_bh() obtains the given lock and disables all bottom halves. The function spin_unlock_bh() performs the inverse.
Because a bottom half may preempt process context code, if data is shared between a bottom half process context, you must protect the data in process context with both a lock and the disabling of bottom halves. Likewise, because an interrupt handler may preempt a bottom half, if data is shared between an interrupt handler and a bottom half, you must both obtain the appropriate lock and disable interrupts.