]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - doc/html/ref/kernel-spinlocks.html
Initial revision
[karo-tx-redboot.git] / doc / html / ref / kernel-spinlocks.html
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.               -->
9 <HTML
10 ><HEAD
11 ><TITLE
12 >Spinlocks</TITLE
13 ><meta name="MSSmartTagsPreventParsing" content="TRUE">
14 <META
15 NAME="GENERATOR"
16 CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
17 "><LINK
18 REL="HOME"
19 TITLE="eCos Reference Manual"
20 HREF="ecos-ref.html"><LINK
21 REL="UP"
22 TITLE="The eCos Kernel"
23 HREF="kernel.html"><LINK
24 REL="PREVIOUS"
25 TITLE="Event Flags"
26 HREF="kernel-flags.html"><LINK
27 REL="NEXT"
28 TITLE="Scheduler Control"
29 HREF="kernel-schedcontrol.html"></HEAD
30 ><BODY
31 CLASS="REFENTRY"
32 BGCOLOR="#FFFFFF"
33 TEXT="#000000"
34 LINK="#0000FF"
35 VLINK="#840084"
36 ALINK="#0000FF"
37 ><DIV
38 CLASS="NAVHEADER"
39 ><TABLE
40 SUMMARY="Header navigation table"
41 WIDTH="100%"
42 BORDER="0"
43 CELLPADDING="0"
44 CELLSPACING="0"
45 ><TR
46 ><TH
47 COLSPAN="3"
48 ALIGN="center"
49 >eCos Reference Manual</TH
50 ></TR
51 ><TR
52 ><TD
53 WIDTH="10%"
54 ALIGN="left"
55 VALIGN="bottom"
56 ><A
57 HREF="kernel-flags.html"
58 ACCESSKEY="P"
59 >Prev</A
60 ></TD
61 ><TD
62 WIDTH="80%"
63 ALIGN="center"
64 VALIGN="bottom"
65 ></TD
66 ><TD
67 WIDTH="10%"
68 ALIGN="right"
69 VALIGN="bottom"
70 ><A
71 HREF="kernel-schedcontrol.html"
72 ACCESSKEY="N"
73 >Next</A
74 ></TD
75 ></TR
76 ></TABLE
77 ><HR
78 ALIGN="LEFT"
79 WIDTH="100%"></DIV
80 ><H1
81 ><A
82 NAME="KERNEL-SPINLOCKS">Spinlocks</H1
83 ><DIV
84 CLASS="REFNAMEDIV"
85 ><A
86 NAME="AEN1693"
87 ></A
88 ><H2
89 >Name</H2
90 >cyg_spinlock_create, cyg_spinlock_destroy, cyg_spinlock_spin, cyg_spinlock_clear, cyg_spinlock_test, cyg_spinlock_spin_intsave, cyg_spinlock_clear_intsave&nbsp;--&nbsp;Low-level Synchronization Primitive</DIV
91 ><DIV
92 CLASS="REFSYNOPSISDIV"
93 ><A
94 NAME="AEN1702"><H2
95 >Synopsis</H2
96 ><DIV
97 CLASS="FUNCSYNOPSIS"
98 ><A
99 NAME="AEN1703"><P
100 ></P
101 ><TABLE
102 BORDER="5"
103 BGCOLOR="#E0E0F0"
104 WIDTH="70%"
105 ><TR
106 ><TD
107 ><PRE
108 CLASS="FUNCSYNOPSISINFO"
109 >#include &lt;cyg/kernel/kapi.h&gt;
110         </PRE
111 ></TD
112 ></TR
113 ></TABLE
114 ><P
115 ><CODE
116 ><CODE
117 CLASS="FUNCDEF"
118 >void cyg_spinlock_init</CODE
119 >(cyg_spinlock_t* lock, cyg_bool_t locked);</CODE
120 ></P
121 ><P
122 ><CODE
123 ><CODE
124 CLASS="FUNCDEF"
125 >void cyg_spinlock_destroy</CODE
126 >(cyg_spinlock_t* lock);</CODE
127 ></P
128 ><P
129 ><CODE
130 ><CODE
131 CLASS="FUNCDEF"
132 >void cyg_spinlock_spin</CODE
133 >(cyg_spinlock_t* lock);</CODE
134 ></P
135 ><P
136 ><CODE
137 ><CODE
138 CLASS="FUNCDEF"
139 >void cyg_spinlock_clear</CODE
140 >(cyg_spinlock_t* lock);</CODE
141 ></P
142 ><P
143 ><CODE
144 ><CODE
145 CLASS="FUNCDEF"
146 >cyg_bool_t cyg_spinlock_try</CODE
147 >(cyg_spinlock_t* lock);</CODE
148 ></P
149 ><P
150 ><CODE
151 ><CODE
152 CLASS="FUNCDEF"
153 >cyg_bool_t cyg_spinlock_test</CODE
154 >(cyg_spinlock_t* lock);</CODE
155 ></P
156 ><P
157 ><CODE
158 ><CODE
159 CLASS="FUNCDEF"
160 >void cyg_spinlock_spin_intsave</CODE
161 >(cyg_spinlock_t* lock, cyg_addrword_t* istate);</CODE
162 ></P
163 ><P
164 ><CODE
165 ><CODE
166 CLASS="FUNCDEF"
167 >void cyg_spinlock_clear_intsave</CODE
168 >(cyg_spinlock_t* lock, cyg_addrword_t istate);</CODE
169 ></P
170 ><P
171 ></P
172 ></DIV
173 ></DIV
174 ><DIV
175 CLASS="REFSECT1"
176 ><A
177 NAME="KERNEL-SPINLOCKS-DESCRIPTION"
178 ></A
179 ><H2
180 >Description</H2
181 ><P
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.
189       </P
190 ><P
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
204 not acceptable.
205       </P
206 ><P
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
216 <TT
217 CLASS="FUNCTION"
218 >cyg_spinlock_spin_intsave</TT
219 > is provided to
220 facilitate this.
221       </P
222 ><P
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.
234       </P
235 ><P
236 >Before a spinlock can be used it must be initialized by a call to
237 <TT
238 CLASS="FUNCTION"
239 >cyg_spinlock_init</TT
240 >. This takes two arguments, a
241 pointer to a <TT
242 CLASS="FUNCTION"
243 >cyg_spinlock_t</TT
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
247 to <TT
248 CLASS="FUNCTION"
249 >cyg_spinlock_destroy</TT
250 >.
251       </P
252 ><P
253 >There are two routines for claiming a spinlock:
254 <TT
255 CLASS="FUNCTION"
256 >cyg_spinlock_spin</TT
257 > and
258 <TT
259 CLASS="FUNCTION"
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
268 <TT
269 CLASS="FUNCTION"
270 >cyg_spinlock_clear_intsave</TT
271 >. 
272       </P
273 ><P
274 >Similarly there are two routines for releasing a spinlock:
275 <TT
276 CLASS="FUNCTION"
277 >cyg_spinlock_clear</TT
278 > and
279 <TT
280 CLASS="FUNCTION"
281 >cyg_spinlock_clear_intsave</TT
282 >. Typically
283 the former will be used if the spinlock was claimed by a call to
284 <TT
285 CLASS="FUNCTION"
286 >cyg_spinlock_spin</TT
287 >, and the latter when
288 <TT
289 CLASS="FUNCTION"
290 >cyg_spinlock_intsave</TT
291 > was used.
292       </P
293 ><P
294 >There are two additional routines.
295 <TT
296 CLASS="FUNCTION"
297 >cyg_spinlock_try</TT
298 > is a non-blocking version of
299 <TT
300 CLASS="FUNCTION"
301 >cyg_spinlock_spin</TT
302 >: if possible the lock will be
303 claimed and the function will return <TT
304 CLASS="LITERAL"
305 >true</TT
306 >; otherwise the function
307 will return immediately with failure.
308 <TT
309 CLASS="FUNCTION"
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.
315       </P
316 ><P
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.
322       </P
323 ></DIV
324 ><DIV
325 CLASS="REFSECT1"
326 ><A
327 NAME="KERNEL-SPINLOCKS-CONTEXT"
328 ></A
329 ><H2
330 >Valid contexts</H2
331 ><P
332 >All of the spinlock functions can be called from any context,
333 including ISR and DSR context. Typically
334 <TT
335 CLASS="FUNCTION"
336 >cyg_spinlock_init</TT
337 > is only called during system
338 initialization. 
339       </P
340 ></DIV
341 ><DIV
342 CLASS="NAVFOOTER"
343 ><HR
344 ALIGN="LEFT"
345 WIDTH="100%"><TABLE
346 SUMMARY="Footer navigation table"
347 WIDTH="100%"
348 BORDER="0"
349 CELLPADDING="0"
350 CELLSPACING="0"
351 ><TR
352 ><TD
353 WIDTH="33%"
354 ALIGN="left"
355 VALIGN="top"
356 ><A
357 HREF="kernel-flags.html"
358 ACCESSKEY="P"
359 >Prev</A
360 ></TD
361 ><TD
362 WIDTH="34%"
363 ALIGN="center"
364 VALIGN="top"
365 ><A
366 HREF="ecos-ref.html"
367 ACCESSKEY="H"
368 >Home</A
369 ></TD
370 ><TD
371 WIDTH="33%"
372 ALIGN="right"
373 VALIGN="top"
374 ><A
375 HREF="kernel-schedcontrol.html"
376 ACCESSKEY="N"
377 >Next</A
378 ></TD
379 ></TR
380 ><TR
381 ><TD
382 WIDTH="33%"
383 ALIGN="left"
384 VALIGN="top"
385 >Event Flags</TD
386 ><TD
387 WIDTH="34%"
388 ALIGN="center"
389 VALIGN="top"
390 ><A
391 HREF="kernel.html"
392 ACCESSKEY="U"
393 >Up</A
394 ></TD
395 ><TD
396 WIDTH="33%"
397 ALIGN="right"
398 VALIGN="top"
399 >Scheduler Control</TD
400 ></TR
401 ></TABLE
402 ></DIV
403 ></BODY
404 ></HTML
405 >