OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [doc/] [html/] [ref/] [kernel-thread-create.html] - Diff between revs 28 and 174

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 28 Rev 174
<!-- 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&nbsp;--&nbsp;Create a new thread</DIV
>cyg_thread_create&nbsp;--&nbsp;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 &lt;cyg/kernel/kapi.h&gt;
>#include &lt;cyg/kernel/kapi.h&gt;
        </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)
{
{
    &#8230;
    &#8230;
}
}
      </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 &lt;cyg/hal/hal_arch.h&gt;
>#include &lt;cyg/hal/hal_arch.h&gt;
#include &lt;cyg/kernel/kapi.h&gt;
#include &lt;cyg/kernel/kapi.h&gt;
 
 
// 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)
{
{
    &#8230;
    &#8230;
}
}
 
 
static void
static void
worker(cyg_addrword_t data)
worker(cyg_addrword_t data)
{
{
    &#8230;
    &#8230;
}
}
 
 
void
void
cyg_user_start(void)
cyg_user_start(void)
{
{
    int i;
    int i;
 
 
    cyg_thread_create(PRODUCER_PRIORITY, &amp;producer, 0, "producer",
    cyg_thread_create(PRODUCER_PRIORITY, &amp;producer, 0, "producer",
                      producer_stack, PRODUCER_STACKSIZE,
                      producer_stack, PRODUCER_STACKSIZE,
                      &amp;producer_handle, &amp;producer_thread);
                      &amp;producer_handle, &amp;producer_thread);
    cyg_thread_resume(producer_handle);
    cyg_thread_resume(producer_handle);
    for (i = 0; i &#60; NUMBER_OF_WORKERS; i++) {
    for (i = 0; i &#60; NUMBER_OF_WORKERS; i++) {
        cyg_thread_create(WORKER_PRIORITY, &amp;worker, i, "worker",
        cyg_thread_create(WORKER_PRIORITY, &amp;worker, i, "worker",
                          worker_stacks[i], WORKER_STACKSIZE,
                          worker_stacks[i], WORKER_STACKSIZE,
                          &amp;(worker_handles[i]), &amp;(worker_threads[i]));
                          &amp;(worker_handles[i]), &amp;(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&lt;fred*&gt;(objptr);
    fred* object = static_cast&lt;fred*&gt;(objptr);
    object-&gt;thread_function();
    object-&gt;thread_function();
}
}
 
 
static fred instance;
static fred instance;
 
 
extern "C" void
extern "C" void
cyg_start( void )
cyg_start( void )
{
{
    &#8230;
    &#8230;
    cyg_thread_create( &#8230;,
    cyg_thread_create( &#8230;,
                      &amp;fred::static_thread_aux,
                      &amp;fred::static_thread_aux,
                      static_cast&lt;cyg_addrword_t&gt;(&amp;instance),
                      static_cast&lt;cyg_addrword_t&gt;(&amp;instance),
                      &#8230;);
                      &#8230;);
    &#8230;
    &#8230;
}
}
      </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
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.