<!-- Copyright (C) 2003 Red Hat, Inc. -->
|
<!-- Copyright (C) 2003 Red Hat, Inc. -->
|
<!-- This material may be distributed only subject to the terms -->
|
<!-- This material may be distributed only subject to the terms -->
|
<!-- and conditions set forth in the Open Publication License, v1.0 -->
|
<!-- and conditions set forth in the Open Publication License, v1.0 -->
|
<!-- or later (the latest version is presently available at -->
|
<!-- or later (the latest version is presently available at -->
|
<!-- http://www.opencontent.org/openpub/). -->
|
<!-- http://www.opencontent.org/openpub/). -->
|
<!-- Distribution of the work or derivative of the work in any -->
|
<!-- Distribution of the work or derivative of the work in any -->
|
<!-- standard (paper) book form is prohibited unless prior -->
|
<!-- standard (paper) book form is prohibited unless prior -->
|
<!-- permission is obtained from the copyright holder. -->
|
<!-- permission is obtained from the copyright holder. -->
|
<HTML
|
<HTML
|
><HEAD
|
><HEAD
|
><TITLE
|
><TITLE
|
>Scheduler Control</TITLE
|
>Scheduler Control</TITLE
|
><meta name="MSSmartTagsPreventParsing" content="TRUE">
|
><meta name="MSSmartTagsPreventParsing" content="TRUE">
|
<META
|
<META
|
NAME="GENERATOR"
|
NAME="GENERATOR"
|
CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
|
CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
|
"><LINK
|
"><LINK
|
REL="HOME"
|
REL="HOME"
|
TITLE="eCos Reference Manual"
|
TITLE="eCos Reference Manual"
|
HREF="ecos-ref.html"><LINK
|
HREF="ecos-ref.html"><LINK
|
REL="UP"
|
REL="UP"
|
TITLE="The eCos Kernel"
|
TITLE="The eCos Kernel"
|
HREF="kernel.html"><LINK
|
HREF="kernel.html"><LINK
|
REL="PREVIOUS"
|
REL="PREVIOUS"
|
TITLE="Spinlocks"
|
TITLE="Spinlocks"
|
HREF="kernel-spinlocks.html"><LINK
|
HREF="kernel-spinlocks.html"><LINK
|
REL="NEXT"
|
REL="NEXT"
|
TITLE="Interrupt Handling"
|
TITLE="Interrupt Handling"
|
HREF="kernel-interrupts.html"></HEAD
|
HREF="kernel-interrupts.html"></HEAD
|
><BODY
|
><BODY
|
CLASS="REFENTRY"
|
CLASS="REFENTRY"
|
BGCOLOR="#FFFFFF"
|
BGCOLOR="#FFFFFF"
|
TEXT="#000000"
|
TEXT="#000000"
|
LINK="#0000FF"
|
LINK="#0000FF"
|
VLINK="#840084"
|
VLINK="#840084"
|
ALINK="#0000FF"
|
ALINK="#0000FF"
|
><DIV
|
><DIV
|
CLASS="NAVHEADER"
|
CLASS="NAVHEADER"
|
><TABLE
|
><TABLE
|
SUMMARY="Header navigation table"
|
SUMMARY="Header navigation table"
|
WIDTH="100%"
|
WIDTH="100%"
|
BORDER="0"
|
BORDER="0"
|
CELLPADDING="0"
|
CELLPADDING="0"
|
CELLSPACING="0"
|
CELLSPACING="0"
|
><TR
|
><TR
|
><TH
|
><TH
|
COLSPAN="3"
|
COLSPAN="3"
|
ALIGN="center"
|
ALIGN="center"
|
>eCos Reference Manual</TH
|
>eCos Reference Manual</TH
|
></TR
|
></TR
|
><TR
|
><TR
|
><TD
|
><TD
|
WIDTH="10%"
|
WIDTH="10%"
|
ALIGN="left"
|
ALIGN="left"
|
VALIGN="bottom"
|
VALIGN="bottom"
|
><A
|
><A
|
HREF="kernel-spinlocks.html"
|
HREF="kernel-spinlocks.html"
|
ACCESSKEY="P"
|
ACCESSKEY="P"
|
>Prev</A
|
>Prev</A
|
></TD
|
></TD
|
><TD
|
><TD
|
WIDTH="80%"
|
WIDTH="80%"
|
ALIGN="center"
|
ALIGN="center"
|
VALIGN="bottom"
|
VALIGN="bottom"
|
></TD
|
></TD
|
><TD
|
><TD
|
WIDTH="10%"
|
WIDTH="10%"
|
ALIGN="right"
|
ALIGN="right"
|
VALIGN="bottom"
|
VALIGN="bottom"
|
><A
|
><A
|
HREF="kernel-interrupts.html"
|
HREF="kernel-interrupts.html"
|
ACCESSKEY="N"
|
ACCESSKEY="N"
|
>Next</A
|
>Next</A
|
></TD
|
></TD
|
></TR
|
></TR
|
></TABLE
|
></TABLE
|
><HR
|
><HR
|
ALIGN="LEFT"
|
ALIGN="LEFT"
|
WIDTH="100%"></DIV
|
WIDTH="100%"></DIV
|
><H1
|
><H1
|
><A
|
><A
|
NAME="KERNEL-SCHEDCONTROL">Scheduler Control</H1
|
NAME="KERNEL-SCHEDCONTROL">Scheduler Control</H1
|
><DIV
|
><DIV
|
CLASS="REFNAMEDIV"
|
CLASS="REFNAMEDIV"
|
><A
|
><A
|
NAME="AEN1784"
|
NAME="AEN1784"
|
></A
|
></A
|
><H2
|
><H2
|
>Name</H2
|
>Name</H2
|
>cyg_scheduler_start, cyg_scheduler_lock, cyg_scheduler_unlock, cyg_scheduler_safe_lock, cyg_scheduler_read_lock -- Control the state of the scheduler</DIV
|
>cyg_scheduler_start, cyg_scheduler_lock, cyg_scheduler_unlock, cyg_scheduler_safe_lock, cyg_scheduler_read_lock -- Control the state of the scheduler</DIV
|
><DIV
|
><DIV
|
CLASS="REFSYNOPSISDIV"
|
CLASS="REFSYNOPSISDIV"
|
><A
|
><A
|
NAME="AEN1791"><H2
|
NAME="AEN1791"><H2
|
>Synopsis</H2
|
>Synopsis</H2
|
><DIV
|
><DIV
|
CLASS="FUNCSYNOPSIS"
|
CLASS="FUNCSYNOPSIS"
|
><A
|
><A
|
NAME="AEN1792"><P
|
NAME="AEN1792"><P
|
></P
|
></P
|
><TABLE
|
><TABLE
|
BORDER="5"
|
BORDER="5"
|
BGCOLOR="#E0E0F0"
|
BGCOLOR="#E0E0F0"
|
WIDTH="70%"
|
WIDTH="70%"
|
><TR
|
><TR
|
><TD
|
><TD
|
><PRE
|
><PRE
|
CLASS="FUNCSYNOPSISINFO"
|
CLASS="FUNCSYNOPSISINFO"
|
>#include <cyg/kernel/kapi.h>
|
>#include <cyg/kernel/kapi.h>
|
</PRE
|
</PRE
|
></TD
|
></TD
|
></TR
|
></TR
|
></TABLE
|
></TABLE
|
><P
|
><P
|
><CODE
|
><CODE
|
><CODE
|
><CODE
|
CLASS="FUNCDEF"
|
CLASS="FUNCDEF"
|
>void cyg_scheduler_start</CODE
|
>void cyg_scheduler_start</CODE
|
>(void);</CODE
|
>(void);</CODE
|
></P
|
></P
|
><P
|
><P
|
><CODE
|
><CODE
|
><CODE
|
><CODE
|
CLASS="FUNCDEF"
|
CLASS="FUNCDEF"
|
>void cyg_scheduler_lock</CODE
|
>void cyg_scheduler_lock</CODE
|
>(void);</CODE
|
>(void);</CODE
|
></P
|
></P
|
><P
|
><P
|
><CODE
|
><CODE
|
><CODE
|
><CODE
|
CLASS="FUNCDEF"
|
CLASS="FUNCDEF"
|
>void cyg_scheduler_unlock</CODE
|
>void cyg_scheduler_unlock</CODE
|
>(void);</CODE
|
>(void);</CODE
|
></P
|
></P
|
><P
|
><P
|
><CODE
|
><CODE
|
><CODE
|
><CODE
|
CLASS="FUNCDEF"
|
CLASS="FUNCDEF"
|
>cyg_ucount32 cyg_scheduler_read_lock</CODE
|
>cyg_ucount32 cyg_scheduler_read_lock</CODE
|
>(void);</CODE
|
>(void);</CODE
|
></P
|
></P
|
><P
|
><P
|
></P
|
></P
|
></DIV
|
></DIV
|
></DIV
|
></DIV
|
><DIV
|
><DIV
|
CLASS="REFSECT1"
|
CLASS="REFSECT1"
|
><A
|
><A
|
NAME="KERNEL-SCHEDCONTROL-DESCRIPTION"
|
NAME="KERNEL-SCHEDCONTROL-DESCRIPTION"
|
></A
|
></A
|
><H2
|
><H2
|
>Description</H2
|
>Description</H2
|
><P
|
><P
|
><TT
|
><TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_scheduler_start</TT
|
>cyg_scheduler_start</TT
|
> should only be called once,
|
> should only be called once,
|
to mark the end of system initialization. In typical configurations it
|
to mark the end of system initialization. In typical configurations it
|
is called automatically by the system startup, but some applications
|
is called automatically by the system startup, but some applications
|
may bypass the standard startup in which case
|
may bypass the standard startup in which case
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_scheduler_start</TT
|
>cyg_scheduler_start</TT
|
> will have to be called
|
> will have to be called
|
explicitly. The call will enable system interrupts, allowing I/O
|
explicitly. The call will enable system interrupts, allowing I/O
|
operations to commence. Then the scheduler will be invoked and control
|
operations to commence. Then the scheduler will be invoked and control
|
will be transferred to the highest priority runnable thread. The call
|
will be transferred to the highest priority runnable thread. The call
|
will never return.
|
will never return.
|
</P
|
</P
|
><P
|
><P
|
>The various data structures inside the eCos kernel must be protected
|
>The various data structures inside the eCos kernel must be protected
|
against concurrent updates. Consider a call to
|
against concurrent updates. Consider a call to
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_semaphore_post</TT
|
>cyg_semaphore_post</TT
|
> which causes a thread to be
|
> which causes a thread to be
|
woken up: the semaphore data structure must be updated to remove the
|
woken up: the semaphore data structure must be updated to remove the
|
thread from its queue; the scheduler data structure must also be
|
thread from its queue; the scheduler data structure must also be
|
updated to mark the thread as runnable; it is possible that the newly
|
updated to mark the thread as runnable; it is possible that the newly
|
runnable thread has a higher priority than the current one, in which
|
runnable thread has a higher priority than the current one, in which
|
case preemption is required. If in the middle of the semaphore post
|
case preemption is required. If in the middle of the semaphore post
|
call an interrupt occurred and the interrupt handler tried to
|
call an interrupt occurred and the interrupt handler tried to
|
manipulate the same data structures, for example by making another
|
manipulate the same data structures, for example by making another
|
thread runnable, then it is likely that the structures will be left in
|
thread runnable, then it is likely that the structures will be left in
|
an inconsistent state and the system will fail.
|
an inconsistent state and the system will fail.
|
</P
|
</P
|
><P
|
><P
|
>To prevent such problems the kernel contains a special lock known as
|
>To prevent such problems the kernel contains a special lock known as
|
the scheduler lock. A typical kernel function such as
|
the scheduler lock. A typical kernel function such as
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_semaphore_post</TT
|
>cyg_semaphore_post</TT
|
> will claim the scheduler lock,
|
> will claim the scheduler lock,
|
do all its manipulation of kernel data structures, and then release
|
do all its manipulation of kernel data structures, and then release
|
the scheduler lock. The current thread cannot be preempted while it
|
the scheduler lock. The current thread cannot be preempted while it
|
holds the scheduler lock. If an interrupt occurs and a DSR is supposed
|
holds the scheduler lock. If an interrupt occurs and a DSR is supposed
|
to run to signal that some event has occurred, that DSR is postponed
|
to run to signal that some event has occurred, that DSR is postponed
|
until the scheduler unlock operation. This prevents concurrent updates
|
until the scheduler unlock operation. This prevents concurrent updates
|
of kernel data structures.
|
of kernel data structures.
|
</P
|
</P
|
><P
|
><P
|
>The kernel exports three routines for manipulating the scheduler lock.
|
>The kernel exports three routines for manipulating the scheduler lock.
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_scheduler_lock</TT
|
>cyg_scheduler_lock</TT
|
> can be called to claim the
|
> can be called to claim the
|
lock. On return it is guaranteed that the current thread will not be
|
lock. On return it is guaranteed that the current thread will not be
|
preempted, and that no other code is manipulating any kernel data
|
preempted, and that no other code is manipulating any kernel data
|
structures. <TT
|
structures. <TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_scheduler_unlock</TT
|
>cyg_scheduler_unlock</TT
|
> can be used to
|
> can be used to
|
release the lock, which may cause the current thread to be preempted.
|
release the lock, which may cause the current thread to be preempted.
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_scheduler_read_lock</TT
|
>cyg_scheduler_read_lock</TT
|
> can be used to query the
|
> can be used to query the
|
current state of the scheduler lock. This function should never be
|
current state of the scheduler lock. This function should never be
|
needed because well-written code should always know whether or not the
|
needed because well-written code should always know whether or not the
|
scheduler is currently locked, but may prove useful during debugging.
|
scheduler is currently locked, but may prove useful during debugging.
|
</P
|
</P
|
><P
|
><P
|
>The implementation of the scheduler lock involves a simple counter.
|
>The implementation of the scheduler lock involves a simple counter.
|
Code can call <TT
|
Code can call <TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_scheduler_lock</TT
|
>cyg_scheduler_lock</TT
|
> multiple times,
|
> multiple times,
|
causing the counter to be incremented each time, as long as
|
causing the counter to be incremented each time, as long as
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_scheduler_unlock</TT
|
>cyg_scheduler_unlock</TT
|
> is called the same number of
|
> is called the same number of
|
times. This behaviour is different from mutexes where an attempt by a
|
times. This behaviour is different from mutexes where an attempt by a
|
thread to lock a mutex multiple times will result in deadlock or an
|
thread to lock a mutex multiple times will result in deadlock or an
|
assertion failure.
|
assertion failure.
|
</P
|
</P
|
><P
|
><P
|
>Typical application code should not use the scheduler lock. Instead
|
>Typical application code should not use the scheduler lock. Instead
|
other synchronization primitives such as mutexes and semaphores should
|
other synchronization primitives such as mutexes and semaphores should
|
be used. While the scheduler is locked the current thread cannot be
|
be used. While the scheduler is locked the current thread cannot be
|
preempted, so any higher priority threads will not be able to run.
|
preempted, so any higher priority threads will not be able to run.
|
Also no DSRs can run, so device drivers may not be able to service
|
Also no DSRs can run, so device drivers may not be able to service
|
I/O requests. However there is one situation where locking the
|
I/O requests. However there is one situation where locking the
|
scheduler is appropriate: if some data structure needs to be shared
|
scheduler is appropriate: if some data structure needs to be shared
|
between an application thread and a DSR associated with some interrupt
|
between an application thread and a DSR associated with some interrupt
|
source, the thread can use the scheduler lock to prevent concurrent
|
source, the thread can use the scheduler lock to prevent concurrent
|
invocations of the DSR and then safely manipulate the structure. It is
|
invocations of the DSR and then safely manipulate the structure. It is
|
desirable that the scheduler lock is held for only a short period of
|
desirable that the scheduler lock is held for only a short period of
|
time, typically some tens of instructions. In exceptional cases there
|
time, typically some tens of instructions. In exceptional cases there
|
may also be some performance-critical code where it is more
|
may also be some performance-critical code where it is more
|
appropriate to use the scheduler lock rather than a mutex, because the
|
appropriate to use the scheduler lock rather than a mutex, because the
|
former is more efficient.
|
former is more efficient.
|
</P
|
</P
|
></DIV
|
></DIV
|
><DIV
|
><DIV
|
CLASS="REFSECT1"
|
CLASS="REFSECT1"
|
><A
|
><A
|
NAME="KERNEL-SCHEDCONTROL-CONTEXT"
|
NAME="KERNEL-SCHEDCONTROL-CONTEXT"
|
></A
|
></A
|
><H2
|
><H2
|
>Valid contexts</H2
|
>Valid contexts</H2
|
><P
|
><P
|
><TT
|
><TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_scheduler_start</TT
|
>cyg_scheduler_start</TT
|
> can only be called during
|
> can only be called during
|
system initialization, since it marks the end of that phase. The
|
system initialization, since it marks the end of that phase. The
|
remaining functions may be called from thread or DSR context. Locking
|
remaining functions may be called from thread or DSR context. Locking
|
the scheduler from inside the DSR has no practical effect because the
|
the scheduler from inside the DSR has no practical effect because the
|
lock is claimed automatically by the interrupt subsystem before
|
lock is claimed automatically by the interrupt subsystem before
|
running DSRs, but allows functions to be shared between normal thread
|
running DSRs, but allows functions to be shared between normal thread
|
code and DSRs.
|
code and DSRs.
|
</P
|
</P
|
></DIV
|
></DIV
|
><DIV
|
><DIV
|
CLASS="NAVFOOTER"
|
CLASS="NAVFOOTER"
|
><HR
|
><HR
|
ALIGN="LEFT"
|
ALIGN="LEFT"
|
WIDTH="100%"><TABLE
|
WIDTH="100%"><TABLE
|
SUMMARY="Footer navigation table"
|
SUMMARY="Footer navigation table"
|
WIDTH="100%"
|
WIDTH="100%"
|
BORDER="0"
|
BORDER="0"
|
CELLPADDING="0"
|
CELLPADDING="0"
|
CELLSPACING="0"
|
CELLSPACING="0"
|
><TR
|
><TR
|
><TD
|
><TD
|
WIDTH="33%"
|
WIDTH="33%"
|
ALIGN="left"
|
ALIGN="left"
|
VALIGN="top"
|
VALIGN="top"
|
><A
|
><A
|
HREF="kernel-spinlocks.html"
|
HREF="kernel-spinlocks.html"
|
ACCESSKEY="P"
|
ACCESSKEY="P"
|
>Prev</A
|
>Prev</A
|
></TD
|
></TD
|
><TD
|
><TD
|
WIDTH="34%"
|
WIDTH="34%"
|
ALIGN="center"
|
ALIGN="center"
|
VALIGN="top"
|
VALIGN="top"
|
><A
|
><A
|
HREF="ecos-ref.html"
|
HREF="ecos-ref.html"
|
ACCESSKEY="H"
|
ACCESSKEY="H"
|
>Home</A
|
>Home</A
|
></TD
|
></TD
|
><TD
|
><TD
|
WIDTH="33%"
|
WIDTH="33%"
|
ALIGN="right"
|
ALIGN="right"
|
VALIGN="top"
|
VALIGN="top"
|
><A
|
><A
|
HREF="kernel-interrupts.html"
|
HREF="kernel-interrupts.html"
|
ACCESSKEY="N"
|
ACCESSKEY="N"
|
>Next</A
|
>Next</A
|
></TD
|
></TD
|
></TR
|
></TR
|
><TR
|
><TR
|
><TD
|
><TD
|
WIDTH="33%"
|
WIDTH="33%"
|
ALIGN="left"
|
ALIGN="left"
|
VALIGN="top"
|
VALIGN="top"
|
>Spinlocks</TD
|
>Spinlocks</TD
|
><TD
|
><TD
|
WIDTH="34%"
|
WIDTH="34%"
|
ALIGN="center"
|
ALIGN="center"
|
VALIGN="top"
|
VALIGN="top"
|
><A
|
><A
|
HREF="kernel.html"
|
HREF="kernel.html"
|
ACCESSKEY="U"
|
ACCESSKEY="U"
|
>Up</A
|
>Up</A
|
></TD
|
></TD
|
><TD
|
><TD
|
WIDTH="33%"
|
WIDTH="33%"
|
ALIGN="right"
|
ALIGN="right"
|
VALIGN="top"
|
VALIGN="top"
|
>Interrupt Handling</TD
|
>Interrupt Handling</TD
|
></TR
|
></TR
|
></TABLE
|
></TABLE
|
></DIV
|
></DIV
|
></BODY
|
></BODY
|
></HTML
|
></HTML
|
|
|