views:

928

answers:

5

I am confused by the function of spin lock.

The spin lock is used to stop the process from re-scheduling. However, in a machine with just one core, is it useful to use spin lock to prevent context switching?

A: 

Yes and no; depending on what operating system is present, if any is present at all, and what you are trying to achieve.

If you have the luxury of a full multi-tasking and multi-threading operating system available, then you must pick your primitives from the collection it provides you, or you risk inefficiencies at best and non-working synchronization at worst. Each OS has its idioms and preferred mechanisms, and failing to follow those conventions can also have costs.

The further you get from a full kernel (or the deeper into the kernel and device drivers you get), you will find that the best idioms involve lower level synchronization primitives.

Even a single core CPU has interrupt handlers that can execute (in principle) between any pair of instructions, or even during certain multiple-cycle instructions in some architectures. This is effectively a kind of concurrency, albeit weaker than a second core, so synchronization primitives are required when communicating between the foreground thread(s) and any interrupt handlers in the background. In a single core, synchronization between foreground threads must involve a context switch, of course.

Waiting on a condition set in an interrupt handler or on a condition set in a hardware register are both cases where a single foreground thread in single core might have no better choice than to spin on the flag or register.

Edit: I've tried to clarify this answer to make it clear that I'm talking about synchronization in general more than any specific OS's implementation of a spinlock. The question isn't specific about what OS (if any) and isn't tagged for any specific OS either.

RBerteig
"This is effectively a kind of concurrency" No, it's really not; nothing ever actually happens *concurrently*. On all but the most pathological systems, unless you're directly mucking about with the same things as an interrupt vector, you do not need to worry about them.
kquinn
"you do not need to worry": False. The concurrency issues from an interrupt between any pair instructions are similar to those from a second core. DMA is another kind of concurrency that doesn't itself require a second core. If data structures are shared with an I/O device, a DMA buffer, or an interrupt routine, you MUST worry about concurrency. Spinlocks can be a useful way to model a thread that is waiting for an interrupt to occur before proceeding.
RBerteig
It seems to me that if any data structures are shared between your code and an interrupt handler, that counts as either an extremely pathological system, or low-level code where you're mucking about with the same things as an interrupt handler.
kquinn
The ring buffers that implement a FIFO between your UART hardware and your serial port driver are an example of a buffer shared between code and an IRQ handler (and possibly with DMA involved as well, depending on the system). Synchronize it incorrectly, and characters arrive out of order, get lost, or get repeated. A lot of embedded systems work is in a delicate balance between conflicting requirements of hardware and software.
RBerteig
+5  A: 

Short answer: no.

According to http://docsrv.sco.com/cgi-bin/man/man?Intro+3synch

Spin locks must not be used on a single processor system. In the best case, a spin lock on a single processor system will waste resources, slowing down the owner of the lock; in the worst case, it will deadlock the processor.

From: http://blogs.microsoft.co.il/blogs/sasha/archive/2008/08/10/practical-concurrency-patterns-spinlock.aspx

On single-processor systems, spinlocks are not needed because spinlock synchronization is required on high IRQLs only. On high IRQLs (above dispatch IRQL) a context switch cannot occur, so instead of spinning the acquiring thread can simply request an interrupt on the relevant IRQL and return; the interrupt will be masked until the releasing thread lowers the IRQL below the requested IRQL.

For single processor systems, the kernel will ignore the spin count value, and treat it as zero - essentially making a spinlock a no-op.

Yes, spin locks can be useful, and improve efficiency of some operations. However, generally you should start with a mutex, and if profiling show it to be a bottleneck, you may want to consider a spinlock.

brianegge
+3  A: 

Your observation is good: on a uniprocessor system, there is no point in spinning to wait for a resource, because you will may as well switch threads sooner rather than later. Mutexes and semaphores do exactly this.

On a multiprocessor system, a thread on another processor may release the lock without you context-switching. Spinlocks can be useful, then, if you don't expect to be waiting long, because it may be faster just to hang around until the other thread unlocks the thing. If you go to sleep on a mutex, you're basically assured some significant dead time before you will get rescheduled.

In kernel code, however, the situation changes: Interrupt handlers need to access shared resources with the rest of the kernel, but they cannot sleep. Mutexes will put the kernel to sleep, so you can't use them, but spinlocks aren't useful either because nothing will interrupt an interrupt handler on a uniprocessor (well, maybe another interrupt, but that's scary).

In a kernel, then, spinlocks within an interrupt handler compile to a no-op. They are completely elided, just like you might think. At the same time, to prevent races, spinlocks in the rest of the kernel disable interrupts just before they actually spin on something (because kernel tasks can be scheduled). These codes only need spinlocks (as opposed to mutexes) if they share code with an interrupt handler.

In general, you're right: spinlocks really don't make much sense on a uniprocessor if you have mutexes, because mutexes waste less time.

Andres Jaan Tack
A: 

The reason to use a spin lock instead of some other locking mechanism is that the time you will probably hold the lock will be relatively short compared to one or two context switches. In this case, it is better to do a spin lock even on a single core processort, because you can avoid the cost of a context switch.

They usually have to be used with great care and only in very low level code where you can reliably estimate how many context switches could occur.

Simon Lehmann
A: 

No.

For a much more detailed answer, see "How Do Locks Lock?" along with the comments.

Jeff Moser