When doing
kernel programming, it's often not possible to use
semaphores, the "standard" system used for locking almost everywhere else. The problem with semaphores is that they put the process to sleep until the semaphore is available. This isn't always possible - it's impossible to sleep in an
interrupt handler, for example.
Spinlocks are a different form of locking mechanism, usually used on multiprocessor systems. Spinlocks just sit in a busy loop until the lock becomes available. The rationale here is that it's quicker to just waste a few processor cycles rather than going to the overhead of putting the process to sleep and waking up later on when the lock becomes available.
So this doesn't seem like something that would be useful on a single processor system: after all, if there's only one CPU, the CPU is just going to go into an infinite loop waiting forever for another nonexistent processor to release the lock. Except, in the Linux kernel, that isn't all that spinlocks do. The first thing to realise is that on single processor machines, spinlocks do not "spin" - ie. they do not wait in a busy loop, so you won't end up in an infinite loop. Also, Linux has a function named "spin_lock_bh" (and corresponding "spin_unlock_bh"), which temporarily disables softirqs for the period of the lock. The result is that it's possible to do locking between an interrupt handler and other code, because any interrupt handler will not be able to execute while the lock is in place.
The other thing to note is that Linux 2.6 has kernel preemption, where kernel code can be preempted (previously, processes could only be preempted when executing user space code). On a kernel with preemption, spinlocks temporarily disable preemption while in the critical section. Basically, the thing to understand is that on a single processor system, while holding a spinlock, your code is never going to be interrupted*, and on a multiprocessor system, other processors will be unable to acquire the lock until you're finished. So spinlocks are a sort of universal locking mechanism that works for all configurations. The moral of this story - don't dismiss spinlocks if you're writing code for a single processor system, because they do more than they say on the tin.
* - Except by hardware interrupts - you can disable those as well using spin_lock_irq/spin_lock_irqsave.