📄 kernel-spinlocks.html
字号:
<!-- Copyright (C) 2003 Red Hat, Inc. --><!-- This material may be distributed only subject to the terms --><!-- and conditions set forth in the Open Publication License, v1.0 --><!-- or later (the latest version is presently available at --><!-- http://www.opencontent.org/openpub/). --><!-- Distribution of the work or derivative of the work in any --><!-- standard (paper) book form is prohibited unless prior --><!-- permission is obtained from the copyright holder. --><HTML><HEAD><TITLE>Spinlocks</TITLE><meta name="MSSmartTagsPreventParsing" content="TRUE"><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+"><LINKREL="HOME"TITLE="eCos Reference Manual"HREF="ecos-ref.html"><LINKREL="UP"TITLE="The eCos Kernel"HREF="kernel.html"><LINKREL="PREVIOUS"TITLE="Event Flags"HREF="kernel-flags.html"><LINKREL="NEXT"TITLE="Scheduler Control"HREF="kernel-schedcontrol.html"></HEAD><BODYCLASS="REFENTRY"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#0000FF"VLINK="#840084"ALINK="#0000FF"><DIVCLASS="NAVHEADER"><TABLESUMMARY="Header navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">eCos Reference Manual</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><AHREF="kernel-flags.html"ACCESSKEY="P">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom"></TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="kernel-schedcontrol.html"ACCESSKEY="N">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><H1><ANAME="KERNEL-SPINLOCKS">Spinlocks</H1><DIVCLASS="REFNAMEDIV"><ANAME="AEN1693"></A><H2>Name</H2>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><DIVCLASS="REFSYNOPSISDIV"><ANAME="AEN1702"><H2>Synopsis</H2><DIVCLASS="FUNCSYNOPSIS"><ANAME="AEN1703"><P></P><TABLEBORDER="5"BGCOLOR="#E0E0F0"WIDTH="70%"><TR><TD><PRECLASS="FUNCSYNOPSISINFO">#include <cyg/kernel/kapi.h> </PRE></TD></TR></TABLE><P><CODE><CODECLASS="FUNCDEF">void cyg_spinlock_init</CODE>(cyg_spinlock_t* lock, cyg_bool_t locked);</CODE></P><P><CODE><CODECLASS="FUNCDEF">void cyg_spinlock_destroy</CODE>(cyg_spinlock_t* lock);</CODE></P><P><CODE><CODECLASS="FUNCDEF">void cyg_spinlock_spin</CODE>(cyg_spinlock_t* lock);</CODE></P><P><CODE><CODECLASS="FUNCDEF">void cyg_spinlock_clear</CODE>(cyg_spinlock_t* lock);</CODE></P><P><CODE><CODECLASS="FUNCDEF">cyg_bool_t cyg_spinlock_try</CODE>(cyg_spinlock_t* lock);</CODE></P><P><CODE><CODECLASS="FUNCDEF">cyg_bool_t cyg_spinlock_test</CODE>(cyg_spinlock_t* lock);</CODE></P><P><CODE><CODECLASS="FUNCDEF">void cyg_spinlock_spin_intsave</CODE>(cyg_spinlock_t* lock, cyg_addrword_t* istate);</CODE></P><P><CODE><CODECLASS="FUNCDEF">void cyg_spinlock_clear_intsave</CODE>(cyg_spinlock_t* lock, cyg_addrword_t istate);</CODE></P><P></P></DIV></DIV><DIVCLASS="REFSECT1"><ANAME="KERNEL-SPINLOCKS-DESCRIPTION"></A><H2>Description</H2><P>Spinlocks provide an additional synchronization primitive forapplications running on SMP systems. They operate at a lower levelthan the other primitives such as mutexes, and for most purposes thehigher-level primitives should be preferred. However there are somecircumstances where a spinlock is appropriate, especially wheninterrupt handlers and threads need to share access to hardware, andon SMP systems the kernel implementation itself depends on spinlocks. </P><P>Essentially a spinlock is just a simple flag. When code tries to claima spinlock it checks whether or not the flag is already set. If notthen the flag is set and the operation succeeds immediately. The exactimplementation of this is hardware-specific, for example it may use atest-and-set instruction to guarantee the desired behaviour even ifseveral processors try to access the spinlock at the exact same time.If it is not possible to claim a spinlock then the current thead spinsin a tight loop, repeatedly checking the flag until it is clear. Thisbehaviour is very different from other synchronization primitives suchas mutexes, where contention would cause a thread to be suspended. Theassumption is that a spinlock will only be held for a very short time.If claiming a spinlock could cause the current thread to be suspendedthen spinlocks could not be used inside interrupt handlers, which isnot acceptable. </P><P>This does impose a constraint on any code which uses spinlocks.Specifically it is important that spinlocks are held only for a shortperiod of time, typically just some dozens of instructions. Otherwiseanother processor could be blocked on the spinlock for a long time,unable to do any useful work. It is also important that a thread whichowns a spinlock does not get preempted because that might causeanother processor to spin for a whole timeslice period, or longer. Oneway of achieving this is to disable interrupts on the currentprocessor, and the function<TTCLASS="FUNCTION">cyg_spinlock_spin_intsave</TT> is provided tofacilitate this. </P><P>Spinlocks should not be used on single-processor systems. Consider ahigh priority thread which attempts to claim a spinlock already heldby a lower priority thread: it will just loop forever and the lowerpriority thread will never get another chance to run and release thespinlock. Even if the two threads were running at the same priority,the one attempting to claim the spinlock would spin until it wastimesliced and a lot of cpu time would be wasted. If an interrupthandler tried to claim a spinlock owned by a thread, the interrupthandler would loop forever. Therefore spinlocks are only appropriatefor SMP systems where the current owner of a spinlock can continuerunning on a different processor. </P><P>Before a spinlock can be used it must be initialized by a call to<TTCLASS="FUNCTION">cyg_spinlock_init</TT>. This takes two arguments, apointer to a <TTCLASS="FUNCTION">cyg_spinlock_t</TT> data structure, anda flag to specify whether the spinlock starts off locked or unlocked.If a spinlock is no longer required then it can be destroyed by a callto <TTCLASS="FUNCTION">cyg_spinlock_destroy</TT>. </P><P>There are two routines for claiming a spinlock:<TTCLASS="FUNCTION">cyg_spinlock_spin</TT> and<TTCLASS="FUNCTION">cyg_spinlock_spin_intsave</TT>. The former can be usedwhen it is known the current code will not be preempted, for examplebecause it is running in an interrupt handler or because interruptsare disabled. The latter will disable interrupts in addition toclaiming the spinlock, so is safe to use in all circumstances. Theprevious interrupt state is returned via the second argument, andshould be used in a subsequent call to<TTCLASS="FUNCTION">cyg_spinlock_clear_intsave</TT>. </P><P>Similarly there are two routines for releasing a spinlock:<TTCLASS="FUNCTION">cyg_spinlock_clear</TT> and<TTCLASS="FUNCTION">cyg_spinlock_clear_intsave</TT>. Typicallythe former will be used if the spinlock was claimed by a call to<TTCLASS="FUNCTION">cyg_spinlock_spin</TT>, and the latter when<TTCLASS="FUNCTION">cyg_spinlock_intsave</TT> was used. </P><P>There are two additional routines.<TTCLASS="FUNCTION">cyg_spinlock_try</TT> is a non-blocking version of<TTCLASS="FUNCTION">cyg_spinlock_spin</TT>: if possible the lock will beclaimed and the function will return <TTCLASS="LITERAL">true</TT>; otherwise the functionwill return immediately with failure.<TTCLASS="FUNCTION">cyg_spinlock_test</TT> can be used to find out whetheror not the spinlock is currently locked. This function must be usedwith care because, especially on a multiprocessor system, the state ofthe spinlock can change at any time. </P><P>Spinlocks should only be held for a short period of time, andattempting to claim a spinlock will never cause a thread to besuspended. This means that there is no need to worry about priorityinversion problems, and concepts such as priority ceilings andinheritance do not apply. </P></DIV><DIVCLASS="REFSECT1"><ANAME="KERNEL-SPINLOCKS-CONTEXT"></A><H2>Valid contexts</H2><P>All of the spinlock functions can be called from any context,including ISR and DSR context. Typically<TTCLASS="FUNCTION">cyg_spinlock_init</TT> is only called during systeminitialization. </P></DIV><DIVCLASS="NAVFOOTER"><HRALIGN="LEFT"WIDTH="100%"><TABLESUMMARY="Footer navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top"><AHREF="kernel-flags.html"ACCESSKEY="P">Prev</A></TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="ecos-ref.html"ACCESSKEY="H">Home</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top"><AHREF="kernel-schedcontrol.html"ACCESSKEY="N">Next</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">Event Flags</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="kernel.html"ACCESSKEY="U">Up</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">Scheduler Control</TD></TR></TABLE></DIV></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -