1 <!-- Copyright (C) 2003 Red Hat, Inc. -->
2 <!-- This material may be distributed only subject to the terms -->
3 <!-- and conditions set forth in the Open Publication License, v1.0 -->
4 <!-- or later (the latest version is presently available at -->
5 <!-- http://www.opencontent.org/openpub/). -->
6 <!-- Distribution of the work or derivative of the work in any -->
7 <!-- standard (paper) book form is prohibited unless prior -->
8 <!-- permission is obtained from the copyright holder. -->
13 ><meta name="MSSmartTagsPreventParsing" content="TRUE">
16 CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
19 TITLE="eCos Reference Manual"
20 HREF="ecos-ref.html"><LINK
22 TITLE="The eCos Kernel"
23 HREF="kernel.html"><LINK
26 HREF="kernel-flags.html"><LINK
28 TITLE="Scheduler Control"
29 HREF="kernel-schedcontrol.html"></HEAD
40 SUMMARY="Header navigation table"
49 >eCos Reference Manual</TH
57 HREF="kernel-flags.html"
71 HREF="kernel-schedcontrol.html"
82 NAME="KERNEL-SPINLOCKS">Spinlocks</H1
90 >cyg_spinlock_create, cyg_spinlock_destroy, cyg_spinlock_spin, cyg_spinlock_clear, cyg_spinlock_test, cyg_spinlock_spin_intsave, cyg_spinlock_clear_intsave -- Low-level Synchronization Primitive</DIV
92 CLASS="REFSYNOPSISDIV"
108 CLASS="FUNCSYNOPSISINFO"
109 >#include <cyg/kernel/kapi.h>
118 >void cyg_spinlock_init</CODE
119 >(cyg_spinlock_t* lock, cyg_bool_t locked);</CODE
125 >void cyg_spinlock_destroy</CODE
126 >(cyg_spinlock_t* lock);</CODE
132 >void cyg_spinlock_spin</CODE
133 >(cyg_spinlock_t* lock);</CODE
139 >void cyg_spinlock_clear</CODE
140 >(cyg_spinlock_t* lock);</CODE
146 >cyg_bool_t cyg_spinlock_try</CODE
147 >(cyg_spinlock_t* lock);</CODE
153 >cyg_bool_t cyg_spinlock_test</CODE
154 >(cyg_spinlock_t* lock);</CODE
160 >void cyg_spinlock_spin_intsave</CODE
161 >(cyg_spinlock_t* lock, cyg_addrword_t* istate);</CODE
167 >void cyg_spinlock_clear_intsave</CODE
168 >(cyg_spinlock_t* lock, cyg_addrword_t istate);</CODE
177 NAME="KERNEL-SPINLOCKS-DESCRIPTION"
182 >Spinlocks provide an additional synchronization primitive for
183 applications running on SMP systems. They operate at a lower level
184 than the other primitives such as mutexes, and for most purposes the
185 higher-level primitives should be preferred. However there are some
186 circumstances where a spinlock is appropriate, especially when
187 interrupt handlers and threads need to share access to hardware, and
188 on SMP systems the kernel implementation itself depends on spinlocks.
191 >Essentially a spinlock is just a simple flag. When code tries to claim
192 a spinlock it checks whether or not the flag is already set. If not
193 then the flag is set and the operation succeeds immediately. The exact
194 implementation of this is hardware-specific, for example it may use a
195 test-and-set instruction to guarantee the desired behaviour even if
196 several processors try to access the spinlock at the exact same time.
197 If it is not possible to claim a spinlock then the current thead spins
198 in a tight loop, repeatedly checking the flag until it is clear. This
199 behaviour is very different from other synchronization primitives such
200 as mutexes, where contention would cause a thread to be suspended. The
201 assumption is that a spinlock will only be held for a very short time.
202 If claiming a spinlock could cause the current thread to be suspended
203 then spinlocks could not be used inside interrupt handlers, which is
207 >This does impose a constraint on any code which uses spinlocks.
208 Specifically it is important that spinlocks are held only for a short
209 period of time, typically just some dozens of instructions. Otherwise
210 another processor could be blocked on the spinlock for a long time,
211 unable to do any useful work. It is also important that a thread which
212 owns a spinlock does not get preempted because that might cause
213 another processor to spin for a whole timeslice period, or longer. One
214 way of achieving this is to disable interrupts on the current
215 processor, and the function
218 >cyg_spinlock_spin_intsave</TT
223 >Spinlocks should not be used on single-processor systems. Consider a
224 high priority thread which attempts to claim a spinlock already held
225 by a lower priority thread: it will just loop forever and the lower
226 priority thread will never get another chance to run and release the
227 spinlock. Even if the two threads were running at the same priority,
228 the one attempting to claim the spinlock would spin until it was
229 timesliced and a lot of cpu time would be wasted. If an interrupt
230 handler tried to claim a spinlock owned by a thread, the interrupt
231 handler would loop forever. Therefore spinlocks are only appropriate
232 for SMP systems where the current owner of a spinlock can continue
233 running on a different processor.
236 >Before a spinlock can be used it must be initialized by a call to
239 >cyg_spinlock_init</TT
240 >. This takes two arguments, a
244 > data structure, and
245 a flag to specify whether the spinlock starts off locked or unlocked.
246 If a spinlock is no longer required then it can be destroyed by a call
249 >cyg_spinlock_destroy</TT
253 >There are two routines for claiming a spinlock:
256 >cyg_spinlock_spin</TT
260 >cyg_spinlock_spin_intsave</TT
261 >. The former can be used
262 when it is known the current code will not be preempted, for example
263 because it is running in an interrupt handler or because interrupts
264 are disabled. The latter will disable interrupts in addition to
265 claiming the spinlock, so is safe to use in all circumstances. The
266 previous interrupt state is returned via the second argument, and
267 should be used in a subsequent call to
270 >cyg_spinlock_clear_intsave</TT
274 >Similarly there are two routines for releasing a spinlock:
277 >cyg_spinlock_clear</TT
281 >cyg_spinlock_clear_intsave</TT
283 the former will be used if the spinlock was claimed by a call to
286 >cyg_spinlock_spin</TT
287 >, and the latter when
290 >cyg_spinlock_intsave</TT
294 >There are two additional routines.
297 >cyg_spinlock_try</TT
298 > is a non-blocking version of
301 >cyg_spinlock_spin</TT
302 >: if possible the lock will be
303 claimed and the function will return <TT
306 >; otherwise the function
307 will return immediately with failure.
310 >cyg_spinlock_test</TT
311 > can be used to find out whether
312 or not the spinlock is currently locked. This function must be used
313 with care because, especially on a multiprocessor system, the state of
314 the spinlock can change at any time.
317 >Spinlocks should only be held for a short period of time, and
318 attempting to claim a spinlock will never cause a thread to be
319 suspended. This means that there is no need to worry about priority
320 inversion problems, and concepts such as priority ceilings and
321 inheritance do not apply.
327 NAME="KERNEL-SPINLOCKS-CONTEXT"
332 >All of the spinlock functions can be called from any context,
333 including ISR and DSR context. Typically
336 >cyg_spinlock_init</TT
337 > is only called during system
346 SUMMARY="Footer navigation table"
357 HREF="kernel-flags.html"
375 HREF="kernel-schedcontrol.html"
399 >Scheduler Control</TD