<!-- 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
|
>Thread creation</TITLE
|
>Thread creation</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="SMP Support"
|
TITLE="SMP Support"
|
HREF="kernel-smp.html"><LINK
|
HREF="kernel-smp.html"><LINK
|
REL="NEXT"
|
REL="NEXT"
|
TITLE="Thread information"
|
TITLE="Thread information"
|
HREF="kernel-thread-info.html"></HEAD
|
HREF="kernel-thread-info.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-smp.html"
|
HREF="kernel-smp.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-thread-info.html"
|
HREF="kernel-thread-info.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-THREAD-CREATE">Thread creation</H1
|
NAME="KERNEL-THREAD-CREATE">Thread creation</H1
|
><DIV
|
><DIV
|
CLASS="REFNAMEDIV"
|
CLASS="REFNAMEDIV"
|
><A
|
><A
|
NAME="AEN256"
|
NAME="AEN256"
|
></A
|
></A
|
><H2
|
><H2
|
>Name</H2
|
>Name</H2
|
>cyg_thread_create -- Create a new thread</DIV
|
>cyg_thread_create -- Create a new thread</DIV
|
><DIV
|
><DIV
|
CLASS="REFSYNOPSISDIV"
|
CLASS="REFSYNOPSISDIV"
|
><A
|
><A
|
NAME="AEN259"><H2
|
NAME="AEN259"><H2
|
>Synopsis</H2
|
>Synopsis</H2
|
><DIV
|
><DIV
|
CLASS="FUNCSYNOPSIS"
|
CLASS="FUNCSYNOPSIS"
|
><A
|
><A
|
NAME="AEN260"><P
|
NAME="AEN260"><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_thread_create</CODE
|
>void cyg_thread_create</CODE
|
>(cyg_addrword_t sched_info, cyg_thread_entry_t* entry, cyg_addrword_t entry_data, char* name, void* stack_base, cyg_ucount32 stack_size, cyg_handle_t* handle, cyg_thread* thread);</CODE
|
>(cyg_addrword_t sched_info, cyg_thread_entry_t* entry, cyg_addrword_t entry_data, char* name, void* stack_base, cyg_ucount32 stack_size, cyg_handle_t* handle, cyg_thread* thread);</CODE
|
></P
|
></P
|
><P
|
><P
|
></P
|
></P
|
></DIV
|
></DIV
|
></DIV
|
></DIV
|
><DIV
|
><DIV
|
CLASS="REFSECT1"
|
CLASS="REFSECT1"
|
><A
|
><A
|
NAME="KERNEL-THREAD-CREATE-DESCRIPTION"
|
NAME="KERNEL-THREAD-CREATE-DESCRIPTION"
|
></A
|
></A
|
><H2
|
><H2
|
>Description</H2
|
>Description</H2
|
><P
|
><P
|
>The <TT
|
>The <TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_create</TT
|
>cyg_thread_create</TT
|
> function allows application
|
> function allows application
|
code and eCos packages to create new threads. In many applications
|
code and eCos packages to create new threads. In many applications
|
this only happens during system initialization and all required data
|
this only happens during system initialization and all required data
|
is allocated statically. However additional threads can be created at
|
is allocated statically. However additional threads can be created at
|
any time, if necessary. A newly created thread is always in suspended
|
any time, if necessary. A newly created thread is always in suspended
|
state and will not start running until it has been resumed via a call
|
state and will not start running until it has been resumed via a call
|
to <TT
|
to <TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_resume</TT
|
>cyg_thread_resume</TT
|
>. Also, if threads are
|
>. Also, if threads are
|
created during system initialization then they will not start running
|
created during system initialization then they will not start running
|
until the eCos scheduler has been started.
|
until the eCos scheduler has been started.
|
</P
|
</P
|
><P
|
><P
|
>The <TT
|
>The <TT
|
CLASS="PARAMETER"
|
CLASS="PARAMETER"
|
><I
|
><I
|
>name</I
|
>name</I
|
></TT
|
></TT
|
> argument is used
|
> argument is used
|
primarily for debugging purposes, making it easier to keep track of
|
primarily for debugging purposes, making it easier to keep track of
|
which <SPAN
|
which <SPAN
|
CLASS="STRUCTNAME"
|
CLASS="STRUCTNAME"
|
>cyg_thread</SPAN
|
>cyg_thread</SPAN
|
> structure is associated with
|
> structure is associated with
|
which application-level thread. The kernel configuration option
|
which application-level thread. The kernel configuration option
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>CYGVAR_KERNEL_THREADS_NAME</TT
|
>CYGVAR_KERNEL_THREADS_NAME</TT
|
> controls whether or not
|
> controls whether or not
|
this name is actually used.
|
this name is actually used.
|
</P
|
</P
|
><P
|
><P
|
>On creation each thread is assigned a unique handle, and this will be
|
>On creation each thread is assigned a unique handle, and this will be
|
stored in the location pointed at by the <TT
|
stored in the location pointed at by the <TT
|
CLASS="PARAMETER"
|
CLASS="PARAMETER"
|
><I
|
><I
|
>handle</I
|
>handle</I
|
></TT
|
></TT
|
> argument. Subsequent operations on
|
> argument. Subsequent operations on
|
this thread including the required
|
this thread including the required
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_resume</TT
|
>cyg_thread_resume</TT
|
> should use this handle to
|
> should use this handle to
|
identify the thread.
|
identify the thread.
|
</P
|
</P
|
><P
|
><P
|
>The kernel requires a small amount of space for each thread, in the
|
>The kernel requires a small amount of space for each thread, in the
|
form of a <SPAN
|
form of a <SPAN
|
CLASS="STRUCTNAME"
|
CLASS="STRUCTNAME"
|
>cyg_thread</SPAN
|
>cyg_thread</SPAN
|
> data structure, to hold
|
> data structure, to hold
|
information such as the current state of that thread. To avoid any
|
information such as the current state of that thread. To avoid any
|
need for dynamic memory allocation within the kernel this space has to
|
need for dynamic memory allocation within the kernel this space has to
|
be provided by higher-level code, typically in the form of a static
|
be provided by higher-level code, typically in the form of a static
|
variable. The <TT
|
variable. The <TT
|
CLASS="PARAMETER"
|
CLASS="PARAMETER"
|
><I
|
><I
|
>thread</I
|
>thread</I
|
></TT
|
></TT
|
> argument
|
> argument
|
provides this space.
|
provides this space.
|
</P
|
</P
|
></DIV
|
></DIV
|
><DIV
|
><DIV
|
CLASS="REFSECT1"
|
CLASS="REFSECT1"
|
><A
|
><A
|
NAME="KERNEL-THREAD-CREATE-ENTRY"
|
NAME="KERNEL-THREAD-CREATE-ENTRY"
|
></A
|
></A
|
><H2
|
><H2
|
>Thread Entry Point</H2
|
>Thread Entry Point</H2
|
><P
|
><P
|
>The entry point for a thread takes the form:
|
>The entry point for a thread takes the form:
|
</P
|
</P
|
><TABLE
|
><TABLE
|
BORDER="5"
|
BORDER="5"
|
BGCOLOR="#E0E0F0"
|
BGCOLOR="#E0E0F0"
|
WIDTH="70%"
|
WIDTH="70%"
|
><TR
|
><TR
|
><TD
|
><TD
|
><PRE
|
><PRE
|
CLASS="PROGRAMLISTING"
|
CLASS="PROGRAMLISTING"
|
>void
|
>void
|
thread_entry_function(cyg_addrword_t data)
|
thread_entry_function(cyg_addrword_t data)
|
{
|
{
|
…
|
…
|
}
|
}
|
</PRE
|
</PRE
|
></TD
|
></TD
|
></TR
|
></TR
|
></TABLE
|
></TABLE
|
><P
|
><P
|
>The second argument to <TT
|
>The second argument to <TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_create</TT
|
>cyg_thread_create</TT
|
> is a
|
> is a
|
pointer to such a function. The third argument <TT
|
pointer to such a function. The third argument <TT
|
CLASS="PARAMETER"
|
CLASS="PARAMETER"
|
><I
|
><I
|
>entry_data</I
|
>entry_data</I
|
></TT
|
></TT
|
> is used to pass additional
|
> is used to pass additional
|
data to the function. Typically this takes the form of a pointer to
|
data to the function. Typically this takes the form of a pointer to
|
some static data, or a small integer, or <TT
|
some static data, or a small integer, or <TT
|
CLASS="LITERAL"
|
CLASS="LITERAL"
|
>0</TT
|
>0</TT
|
> if the
|
> if the
|
thread does not require any additional data.
|
thread does not require any additional data.
|
</P
|
</P
|
><P
|
><P
|
>If the thread entry function ever returns then this is equivalent to
|
>If the thread entry function ever returns then this is equivalent to
|
the thread calling <TT
|
the thread calling <TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_exit</TT
|
>cyg_thread_exit</TT
|
>. Even though
|
>. Even though
|
the thread will no longer run again, it remains registered with the
|
the thread will no longer run again, it remains registered with the
|
scheduler. If the application needs to re-use the
|
scheduler. If the application needs to re-use the
|
<SPAN
|
<SPAN
|
CLASS="STRUCTNAME"
|
CLASS="STRUCTNAME"
|
>cyg_thread</SPAN
|
>cyg_thread</SPAN
|
> data structure then a call to
|
> data structure then a call to
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_delete</TT
|
>cyg_thread_delete</TT
|
> is required first.
|
> is required first.
|
</P
|
</P
|
></DIV
|
></DIV
|
><DIV
|
><DIV
|
CLASS="REFSECT1"
|
CLASS="REFSECT1"
|
><A
|
><A
|
NAME="KERNEL-THREAD-CREATE-PRIORITIES"
|
NAME="KERNEL-THREAD-CREATE-PRIORITIES"
|
></A
|
></A
|
><H2
|
><H2
|
>Thread Priorities</H2
|
>Thread Priorities</H2
|
><P
|
><P
|
>The <TT
|
>The <TT
|
CLASS="PARAMETER"
|
CLASS="PARAMETER"
|
><I
|
><I
|
>sched_info</I
|
>sched_info</I
|
></TT
|
></TT
|
> argument
|
> argument
|
provides additional information to the scheduler. The exact details
|
provides additional information to the scheduler. The exact details
|
depend on the scheduler being used. For the bitmap and mlqueue
|
depend on the scheduler being used. For the bitmap and mlqueue
|
schedulers it is a small integer, typically in the range 0 to 31, with
|
schedulers it is a small integer, typically in the range 0 to 31, with
|
0 being the highest priority. The lowest priority is normally used
|
0 being the highest priority. The lowest priority is normally used
|
only by the system's idle thread. The exact number of priorities is
|
only by the system's idle thread. The exact number of priorities is
|
controlled by the kernel configuration option
|
controlled by the kernel configuration option
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>CYGNUM_KERNEL_SCHED_PRIORITIES</TT
|
>CYGNUM_KERNEL_SCHED_PRIORITIES</TT
|
>.
|
>.
|
</P
|
</P
|
><P
|
><P
|
>It is the responsibility of the application developer to be aware of
|
>It is the responsibility of the application developer to be aware of
|
the various threads in the system, including those created by eCos
|
the various threads in the system, including those created by eCos
|
packages, and to ensure that all threads run at suitable priorities.
|
packages, and to ensure that all threads run at suitable priorities.
|
For threads created by other packages the documentation provided by
|
For threads created by other packages the documentation provided by
|
those packages should indicate any requirements.
|
those packages should indicate any requirements.
|
</P
|
</P
|
><P
|
><P
|
>The functions <TT
|
>The functions <TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_set_priority</TT
|
>cyg_thread_set_priority</TT
|
>,
|
>,
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_get_priority</TT
|
>cyg_thread_get_priority</TT
|
>, and
|
>, and
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_get_current_priority</TT
|
>cyg_thread_get_current_priority</TT
|
> can be used to
|
> can be used to
|
manipulate a thread's priority.
|
manipulate a thread's priority.
|
</P
|
</P
|
></DIV
|
></DIV
|
><DIV
|
><DIV
|
CLASS="REFSECT1"
|
CLASS="REFSECT1"
|
><A
|
><A
|
NAME="KERNEL-THREAD-CREATE-STACK"
|
NAME="KERNEL-THREAD-CREATE-STACK"
|
></A
|
></A
|
><H2
|
><H2
|
>Stacks and Stack Sizes</H2
|
>Stacks and Stack Sizes</H2
|
><P
|
><P
|
>Each thread needs its own stack for local variables and to keep track
|
>Each thread needs its own stack for local variables and to keep track
|
of function calls and returns. Again it is expected that this stack is
|
of function calls and returns. Again it is expected that this stack is
|
provided by the calling code, usually in the form of static data, so
|
provided by the calling code, usually in the form of static data, so
|
that the kernel does not need any dynamic memory allocation
|
that the kernel does not need any dynamic memory allocation
|
facilities. <TT
|
facilities. <TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_create</TT
|
>cyg_thread_create</TT
|
> takes two arguments
|
> takes two arguments
|
related to the stack, a pointer to the base of the stack and the total
|
related to the stack, a pointer to the base of the stack and the total
|
size of this stack. On many processors stacks actually descend from the
|
size of this stack. On many processors stacks actually descend from the
|
top down, so the kernel will add the stack size to the base address to
|
top down, so the kernel will add the stack size to the base address to
|
determine the starting location.
|
determine the starting location.
|
</P
|
</P
|
><P
|
><P
|
>The exact stack size requirements for any given thread depend on a
|
>The exact stack size requirements for any given thread depend on a
|
number of factors. The most important is of course the code that will
|
number of factors. The most important is of course the code that will
|
be executed in the context of this code: if this involves significant
|
be executed in the context of this code: if this involves significant
|
nesting of function calls, recursion, or large local arrays, then the
|
nesting of function calls, recursion, or large local arrays, then the
|
stack size needs to be set to a suitably high value. There are some
|
stack size needs to be set to a suitably high value. There are some
|
architectural issues, for example the number of cpu registers and the
|
architectural issues, for example the number of cpu registers and the
|
calling conventions will have some effect on stack usage. Also,
|
calling conventions will have some effect on stack usage. Also,
|
depending on the configuration, it is possible that some other code
|
depending on the configuration, it is possible that some other code
|
such as interrupt handlers will occasionally run on the current
|
such as interrupt handlers will occasionally run on the current
|
thread's stack. This depends in part on configuration options such as
|
thread's stack. This depends in part on configuration options such as
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK</TT
|
>CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK</TT
|
>
|
>
|
and <TT
|
and <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING</TT
|
>CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING</TT
|
>.
|
>.
|
</P
|
</P
|
><P
|
><P
|
>Determining an application's actual stack size requirements is the
|
>Determining an application's actual stack size requirements is the
|
responsibility of the application developer, since the kernel cannot
|
responsibility of the application developer, since the kernel cannot
|
know in advance what code a given thread will run. However, the system
|
know in advance what code a given thread will run. However, the system
|
does provide some hints about reasonable stack sizes in the form of
|
does provide some hints about reasonable stack sizes in the form of
|
two constants: <TT
|
two constants: <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>CYGNUM_HAL_STACK_SIZE_MINIMUM</TT
|
>CYGNUM_HAL_STACK_SIZE_MINIMUM</TT
|
> and
|
> and
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>CYGNUM_HAL_STACK_SIZE_TYPICAL</TT
|
>CYGNUM_HAL_STACK_SIZE_TYPICAL</TT
|
>. These are defined by
|
>. These are defined by
|
the appropriate HAL package. The <TT
|
the appropriate HAL package. The <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>MINIMUM</TT
|
>MINIMUM</TT
|
> value is
|
> value is
|
appropriate for a thread that just runs a single function and makes
|
appropriate for a thread that just runs a single function and makes
|
very simple system calls. Trying to create a thread with a smaller
|
very simple system calls. Trying to create a thread with a smaller
|
stack than this is illegal. The <TT
|
stack than this is illegal. The <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>TYPICAL</TT
|
>TYPICAL</TT
|
> value is
|
> value is
|
appropriate for applications where application calls are nested no
|
appropriate for applications where application calls are nested no
|
more than half a dozen or so levels, and there are no large arrays on
|
more than half a dozen or so levels, and there are no large arrays on
|
the stack.
|
the stack.
|
</P
|
</P
|
><P
|
><P
|
>If the stack sizes are not estimated correctly and a stack overflow
|
>If the stack sizes are not estimated correctly and a stack overflow
|
occurs, the probably result is some form of memory corruption. This
|
occurs, the probably result is some form of memory corruption. This
|
can be very hard to track down. The kernel does contain some code to
|
can be very hard to track down. The kernel does contain some code to
|
help detect stack overflows, controlled by the configuration option
|
help detect stack overflows, controlled by the configuration option
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>CYGFUN_KERNEL_THREADS_STACK_CHECKING</TT
|
>CYGFUN_KERNEL_THREADS_STACK_CHECKING</TT
|
>: a small
|
>: a small
|
amount of space is reserved at the stack limit and filled with a
|
amount of space is reserved at the stack limit and filled with a
|
special signature: every time a thread context switch occurs this
|
special signature: every time a thread context switch occurs this
|
signature is checked, and if invalid that is a good indication (but
|
signature is checked, and if invalid that is a good indication (but
|
not absolute proof) that a stack overflow has occurred. This form of
|
not absolute proof) that a stack overflow has occurred. This form of
|
stack checking is enabled by default when the system is built with
|
stack checking is enabled by default when the system is built with
|
debugging enabled. A related configuration option is
|
debugging enabled. A related configuration option is
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>CYGFUN_KERNEL_THREADS_STACK_MEASUREMENT</TT
|
>CYGFUN_KERNEL_THREADS_STACK_MEASUREMENT</TT
|
>: enabling
|
>: enabling
|
this option means that a thread can call the function
|
this option means that a thread can call the function
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_measure_stack_usage</TT
|
>cyg_thread_measure_stack_usage</TT
|
> to find out the
|
> to find out the
|
maximum stack usage to date. Note that this is not necessarily the
|
maximum stack usage to date. Note that this is not necessarily the
|
true maximum because, for example, it is possible that in the current
|
true maximum because, for example, it is possible that in the current
|
run no interrupt occurred at the worst possible moment.
|
run no interrupt occurred at the worst possible moment.
|
</P
|
</P
|
></DIV
|
></DIV
|
><DIV
|
><DIV
|
CLASS="REFSECT1"
|
CLASS="REFSECT1"
|
><A
|
><A
|
NAME="KERNEL-THREAD-CREATE-CONTEXT"
|
NAME="KERNEL-THREAD-CREATE-CONTEXT"
|
></A
|
></A
|
><H2
|
><H2
|
>Valid contexts</H2
|
>Valid contexts</H2
|
><P
|
><P
|
><TT
|
><TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_create</TT
|
>cyg_thread_create</TT
|
> may be called during
|
> may be called during
|
initialization and from within thread context. It may not be called
|
initialization and from within thread context. It may not be called
|
from inside a DSR.
|
from inside a DSR.
|
</P
|
</P
|
></DIV
|
></DIV
|
><DIV
|
><DIV
|
CLASS="REFSECT1"
|
CLASS="REFSECT1"
|
><A
|
><A
|
NAME="KERNEL-THREAD-CREATE-EXAMPLE"
|
NAME="KERNEL-THREAD-CREATE-EXAMPLE"
|
></A
|
></A
|
><H2
|
><H2
|
>Example</H2
|
>Example</H2
|
><P
|
><P
|
>A simple example of thread creation is shown below. This involves
|
>A simple example of thread creation is shown below. This involves
|
creating five threads, one producer and four consumers or workers. The
|
creating five threads, one producer and four consumers or workers. The
|
threads are created in the system's
|
threads are created in the system's
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_user_start</TT
|
>cyg_user_start</TT
|
>: depending on the configuration it
|
>: depending on the configuration it
|
might be more appropriate to do this elsewhere, for example inside
|
might be more appropriate to do this elsewhere, for example inside
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>main</TT
|
>main</TT
|
>.
|
>.
|
</P
|
</P
|
><TABLE
|
><TABLE
|
BORDER="5"
|
BORDER="5"
|
BGCOLOR="#E0E0F0"
|
BGCOLOR="#E0E0F0"
|
WIDTH="70%"
|
WIDTH="70%"
|
><TR
|
><TR
|
><TD
|
><TD
|
><PRE
|
><PRE
|
CLASS="PROGRAMLISTING"
|
CLASS="PROGRAMLISTING"
|
>#include <cyg/hal/hal_arch.h>
|
>#include <cyg/hal/hal_arch.h>
|
#include <cyg/kernel/kapi.h>
|
#include <cyg/kernel/kapi.h>
|
|
|
// These numbers depend entirely on your application
|
// These numbers depend entirely on your application
|
#define NUMBER_OF_WORKERS 4
|
#define NUMBER_OF_WORKERS 4
|
#define PRODUCER_PRIORITY 10
|
#define PRODUCER_PRIORITY 10
|
#define WORKER_PRIORITY 11
|
#define WORKER_PRIORITY 11
|
#define PRODUCER_STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
|
#define PRODUCER_STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
|
#define WORKER_STACKSIZE (CYGNUM_HAL_STACK_SIZE_MINIMUM + 1024)
|
#define WORKER_STACKSIZE (CYGNUM_HAL_STACK_SIZE_MINIMUM + 1024)
|
|
|
static unsigned char producer_stack[PRODUCER_STACKSIZE];
|
static unsigned char producer_stack[PRODUCER_STACKSIZE];
|
static unsigned char worker_stacks[NUMBER_OF_WORKERS][WORKER_STACKSIZE];
|
static unsigned char worker_stacks[NUMBER_OF_WORKERS][WORKER_STACKSIZE];
|
static cyg_handle_t producer_handle, worker_handles[NUMBER_OF_WORKERS];
|
static cyg_handle_t producer_handle, worker_handles[NUMBER_OF_WORKERS];
|
static cyg_thread_t producer_thread, worker_threads[NUMBER_OF_WORKERS];
|
static cyg_thread_t producer_thread, worker_threads[NUMBER_OF_WORKERS];
|
|
|
static void
|
static void
|
producer(cyg_addrword_t data)
|
producer(cyg_addrword_t data)
|
{
|
{
|
…
|
…
|
}
|
}
|
|
|
static void
|
static void
|
worker(cyg_addrword_t data)
|
worker(cyg_addrword_t data)
|
{
|
{
|
…
|
…
|
}
|
}
|
|
|
void
|
void
|
cyg_user_start(void)
|
cyg_user_start(void)
|
{
|
{
|
int i;
|
int i;
|
|
|
cyg_thread_create(PRODUCER_PRIORITY, &producer, 0, "producer",
|
cyg_thread_create(PRODUCER_PRIORITY, &producer, 0, "producer",
|
producer_stack, PRODUCER_STACKSIZE,
|
producer_stack, PRODUCER_STACKSIZE,
|
&producer_handle, &producer_thread);
|
&producer_handle, &producer_thread);
|
cyg_thread_resume(producer_handle);
|
cyg_thread_resume(producer_handle);
|
for (i = 0; i < NUMBER_OF_WORKERS; i++) {
|
for (i = 0; i < NUMBER_OF_WORKERS; i++) {
|
cyg_thread_create(WORKER_PRIORITY, &worker, i, "worker",
|
cyg_thread_create(WORKER_PRIORITY, &worker, i, "worker",
|
worker_stacks[i], WORKER_STACKSIZE,
|
worker_stacks[i], WORKER_STACKSIZE,
|
&(worker_handles[i]), &(worker_threads[i]));
|
&(worker_handles[i]), &(worker_threads[i]));
|
cyg_thread_resume(worker_handles[i]);
|
cyg_thread_resume(worker_handles[i]);
|
}
|
}
|
}
|
}
|
</PRE
|
</PRE
|
></TD
|
></TD
|
></TR
|
></TR
|
></TABLE
|
></TABLE
|
></DIV
|
></DIV
|
><DIV
|
><DIV
|
CLASS="REFSECT1"
|
CLASS="REFSECT1"
|
><A
|
><A
|
NAME="KERNEL-THREAD-CREATE-CXX"
|
NAME="KERNEL-THREAD-CREATE-CXX"
|
></A
|
></A
|
><H2
|
><H2
|
>Thread Entry Points and C++</H2
|
>Thread Entry Points and C++</H2
|
><P
|
><P
|
>For code written in C++ the thread entry function must be either a
|
>For code written in C++ the thread entry function must be either a
|
static member function of a class or an ordinary function outside any
|
static member function of a class or an ordinary function outside any
|
class. It cannot be a normal member function of a class because such
|
class. It cannot be a normal member function of a class because such
|
member functions take an implicit additional argument
|
member functions take an implicit additional argument
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>this</TT
|
>this</TT
|
>, and the kernel has no way of knowing what
|
>, and the kernel has no way of knowing what
|
value to use for this argument. One way around this problem is to make
|
value to use for this argument. One way around this problem is to make
|
use of a special static member function, for example:
|
use of a special static member function, for example:
|
</P
|
</P
|
><TABLE
|
><TABLE
|
BORDER="5"
|
BORDER="5"
|
BGCOLOR="#E0E0F0"
|
BGCOLOR="#E0E0F0"
|
WIDTH="70%"
|
WIDTH="70%"
|
><TR
|
><TR
|
><TD
|
><TD
|
><PRE
|
><PRE
|
CLASS="PROGRAMLISTING"
|
CLASS="PROGRAMLISTING"
|
>class fred {
|
>class fred {
|
public:
|
public:
|
void thread_function();
|
void thread_function();
|
static void static_thread_aux(cyg_addrword_t);
|
static void static_thread_aux(cyg_addrword_t);
|
};
|
};
|
|
|
void
|
void
|
fred::static_thread_aux(cyg_addrword_t objptr)
|
fred::static_thread_aux(cyg_addrword_t objptr)
|
{
|
{
|
fred* object = static_cast<fred*>(objptr);
|
fred* object = static_cast<fred*>(objptr);
|
object->thread_function();
|
object->thread_function();
|
}
|
}
|
|
|
static fred instance;
|
static fred instance;
|
|
|
extern "C" void
|
extern "C" void
|
cyg_start( void )
|
cyg_start( void )
|
{
|
{
|
…
|
…
|
cyg_thread_create( …,
|
cyg_thread_create( …,
|
&fred::static_thread_aux,
|
&fred::static_thread_aux,
|
static_cast<cyg_addrword_t>(&instance),
|
static_cast<cyg_addrword_t>(&instance),
|
…);
|
…);
|
…
|
…
|
}
|
}
|
</PRE
|
</PRE
|
></TD
|
></TD
|
></TR
|
></TR
|
></TABLE
|
></TABLE
|
><P
|
><P
|
>Effectively this uses the <TT
|
>Effectively this uses the <TT
|
CLASS="PARAMETER"
|
CLASS="PARAMETER"
|
><I
|
><I
|
>entry_data</I
|
>entry_data</I
|
></TT
|
></TT
|
> argument to
|
> argument to
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_create</TT
|
>cyg_thread_create</TT
|
> to hold the
|
> to hold the
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>this</TT
|
>this</TT
|
> pointer. Unfortunately this approach does
|
> pointer. Unfortunately this approach does
|
require the use of some C++ casts, so some of the type safety that can
|
require the use of some C++ casts, so some of the type safety that can
|
be achieved when programming in C++ is lost.
|
be achieved when programming in C++ is lost.
|
</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-smp.html"
|
HREF="kernel-smp.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-thread-info.html"
|
HREF="kernel-thread-info.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"
|
>SMP Support</TD
|
>SMP Support</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"
|
>Thread information</TD
|
>Thread information</TD
|
></TR
|
></TR
|
></TABLE
|
></TABLE
|
></DIV
|
></DIV
|
></BODY
|
></BODY
|
></HTML
|
></HTML
|
|
|