<!-- 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
|
>Per-thread data</TITLE
|
>Per-thread data</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="Thread priorities"
|
TITLE="Thread priorities"
|
HREF="kernel-thread-priorities.html"><LINK
|
HREF="kernel-thread-priorities.html"><LINK
|
REL="NEXT"
|
REL="NEXT"
|
TITLE="Thread destructors"
|
TITLE="Thread destructors"
|
HREF="kernel-thread-destructors.html"></HEAD
|
HREF="kernel-thread-destructors.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-thread-priorities.html"
|
HREF="kernel-thread-priorities.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-destructors.html"
|
HREF="kernel-thread-destructors.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-DATA">Per-thread data</H1
|
NAME="KERNEL-THREAD-DATA">Per-thread data</H1
|
><DIV
|
><DIV
|
CLASS="REFNAMEDIV"
|
CLASS="REFNAMEDIV"
|
><A
|
><A
|
NAME="AEN660"
|
NAME="AEN660"
|
></A
|
></A
|
><H2
|
><H2
|
>Name</H2
|
>Name</H2
|
>cyg_thread_new_data_index, cyg_thread_free_data_index, cyg_thread_get_data, cyg_thread_get_data_ptr, cyg_thread_set_data -- Manipulate per-thread data</DIV
|
>cyg_thread_new_data_index, cyg_thread_free_data_index, cyg_thread_get_data, cyg_thread_get_data_ptr, cyg_thread_set_data -- Manipulate per-thread data</DIV
|
><DIV
|
><DIV
|
CLASS="REFSYNOPSISDIV"
|
CLASS="REFSYNOPSISDIV"
|
><A
|
><A
|
NAME="AEN667"><H2
|
NAME="AEN667"><H2
|
>Synopsis</H2
|
>Synopsis</H2
|
><DIV
|
><DIV
|
CLASS="FUNCSYNOPSIS"
|
CLASS="FUNCSYNOPSIS"
|
><A
|
><A
|
NAME="AEN668"><P
|
NAME="AEN668"><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"
|
>cyg_ucount32 cyg_thread_new_data_index</CODE
|
>cyg_ucount32 cyg_thread_new_data_index</CODE
|
>(void);</CODE
|
>(void);</CODE
|
></P
|
></P
|
><P
|
><P
|
><CODE
|
><CODE
|
><CODE
|
><CODE
|
CLASS="FUNCDEF"
|
CLASS="FUNCDEF"
|
>void cyg_thread_free_data_index</CODE
|
>void cyg_thread_free_data_index</CODE
|
>(cyg_ucount32 index);</CODE
|
>(cyg_ucount32 index);</CODE
|
></P
|
></P
|
><P
|
><P
|
><CODE
|
><CODE
|
><CODE
|
><CODE
|
CLASS="FUNCDEF"
|
CLASS="FUNCDEF"
|
>cyg_addrword_t cyg_thread_get_data</CODE
|
>cyg_addrword_t cyg_thread_get_data</CODE
|
>(cyg_ucount32 index);</CODE
|
>(cyg_ucount32 index);</CODE
|
></P
|
></P
|
><P
|
><P
|
><CODE
|
><CODE
|
><CODE
|
><CODE
|
CLASS="FUNCDEF"
|
CLASS="FUNCDEF"
|
>cyg_addrword_t* cyg_thread_get_data_ptr</CODE
|
>cyg_addrword_t* cyg_thread_get_data_ptr</CODE
|
>(cyg_ucount32 index);</CODE
|
>(cyg_ucount32 index);</CODE
|
></P
|
></P
|
><P
|
><P
|
><CODE
|
><CODE
|
><CODE
|
><CODE
|
CLASS="FUNCDEF"
|
CLASS="FUNCDEF"
|
>void cyg_thread_set_data</CODE
|
>void cyg_thread_set_data</CODE
|
>(cyg_ucount32 index, cyg_addrword_t data);</CODE
|
>(cyg_ucount32 index, cyg_addrword_t data);</CODE
|
></P
|
></P
|
><P
|
><P
|
></P
|
></P
|
></DIV
|
></DIV
|
></DIV
|
></DIV
|
><DIV
|
><DIV
|
CLASS="REFSECT1"
|
CLASS="REFSECT1"
|
><A
|
><A
|
NAME="AEN696"
|
NAME="AEN696"
|
></A
|
></A
|
><H2
|
><H2
|
>Description</H2
|
>Description</H2
|
><P
|
><P
|
>In some applications and libraries it is useful to have some data that
|
>In some applications and libraries it is useful to have some data that
|
is specific to each thread. For example, many of the functions in the
|
is specific to each thread. For example, many of the functions in the
|
POSIX compatibility package return -1 to indicate an error and store
|
POSIX compatibility package return -1 to indicate an error and store
|
additional information in what appears to be a global variable
|
additional information in what appears to be a global variable
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>errno</TT
|
>errno</TT
|
>. However, if multiple threads make concurrent
|
>. However, if multiple threads make concurrent
|
calls into the POSIX library and if <TT
|
calls into the POSIX library and if <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>errno</TT
|
>errno</TT
|
> were
|
> were
|
really a global variable then a thread would have no way of knowing
|
really a global variable then a thread would have no way of knowing
|
whether the current <TT
|
whether the current <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>errno</TT
|
>errno</TT
|
> value really corresponded
|
> value really corresponded
|
to the last POSIX call it made, or whether some other thread had run
|
to the last POSIX call it made, or whether some other thread had run
|
in the meantime and made a different POSIX call which updated the
|
in the meantime and made a different POSIX call which updated the
|
variable. To avoid such confusion <TT
|
variable. To avoid such confusion <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>errno</TT
|
>errno</TT
|
> is instead
|
> is instead
|
implemented as a per-thread variable, and each thread has its own
|
implemented as a per-thread variable, and each thread has its own
|
instance.
|
instance.
|
</P
|
</P
|
><P
|
><P
|
>The support for per-thread data can be disabled via the configuration
|
>The support for per-thread data can be disabled via the configuration
|
option <TT
|
option <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>CYGVAR_KERNEL_THREADS_DATA</TT
|
>CYGVAR_KERNEL_THREADS_DATA</TT
|
>. If enabled, each
|
>. If enabled, each
|
<SPAN
|
<SPAN
|
CLASS="STRUCTNAME"
|
CLASS="STRUCTNAME"
|
>cyg_thread</SPAN
|
>cyg_thread</SPAN
|
> data structure holds a small array
|
> data structure holds a small array
|
of words. The size of this array is determined by the configuration
|
of words. The size of this array is determined by the configuration
|
option <TT
|
option <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>CYGNUM_KERNEL_THREADS_DATA_MAX</TT
|
>CYGNUM_KERNEL_THREADS_DATA_MAX</TT
|
>. When a
|
>. When a
|
thread is created the array is filled with zeroes.
|
thread is created the array is filled with zeroes.
|
</P
|
</P
|
><P
|
><P
|
>If an application needs to use per-thread data then it needs an index
|
>If an application needs to use per-thread data then it needs an index
|
into this array which has not yet been allocated to other code. This
|
into this array which has not yet been allocated to other code. This
|
index can be obtained by calling
|
index can be obtained by calling
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_new_data_index</TT
|
>cyg_thread_new_data_index</TT
|
>, and then used in
|
>, and then used in
|
subsequent calls to <TT
|
subsequent calls to <TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_get_data</TT
|
>cyg_thread_get_data</TT
|
>.
|
>.
|
Typically indices are allocated during system initialization and
|
Typically indices are allocated during system initialization and
|
stored in static variables. If for some reason a slot in the array is
|
stored in static variables. If for some reason a slot in the array is
|
no longer required and can be re-used then it can be released by calling
|
no longer required and can be re-used then it can be released by calling
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_free_data_index</TT
|
>cyg_thread_free_data_index</TT
|
>,
|
>,
|
</P
|
</P
|
><P
|
><P
|
>The current per-thread data in a given slot can be obtained using
|
>The current per-thread data in a given slot can be obtained using
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_get_data</TT
|
>cyg_thread_get_data</TT
|
>. This implicitly operates on
|
>. This implicitly operates on
|
the current thread, and its single argument should be an index as
|
the current thread, and its single argument should be an index as
|
returned by <TT
|
returned by <TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_new_data_index</TT
|
>cyg_thread_new_data_index</TT
|
>. The
|
>. The
|
per-thread data can be updated using
|
per-thread data can be updated using
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_set_data</TT
|
>cyg_thread_set_data</TT
|
>. If a particular item of
|
>. If a particular item of
|
per-thread data is needed repeatedly then
|
per-thread data is needed repeatedly then
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_get_data_ptr</TT
|
>cyg_thread_get_data_ptr</TT
|
> can be used to obtain the
|
> can be used to obtain the
|
address of the data, and indirecting through this pointer allows the
|
address of the data, and indirecting through this pointer allows the
|
data to be examined and updated efficiently.
|
data to be examined and updated efficiently.
|
</P
|
</P
|
><P
|
><P
|
>Some packages, for example the error and POSIX packages, have
|
>Some packages, for example the error and POSIX packages, have
|
pre-allocated slots in the array of per-thread data. These slots
|
pre-allocated slots in the array of per-thread data. These slots
|
should not normally be used by application code, and instead slots
|
should not normally be used by application code, and instead slots
|
should be allocated during initialization by a call to
|
should be allocated during initialization by a call to
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_new_data_index</TT
|
>cyg_thread_new_data_index</TT
|
>. If it is known that,
|
>. If it is known that,
|
for example, the configuration will never include the POSIX
|
for example, the configuration will never include the POSIX
|
compatibility package then application code may instead decide to
|
compatibility package then application code may instead decide to
|
re-use the slot allocated to that package,
|
re-use the slot allocated to that package,
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>CYGNUM_KERNEL_THREADS_DATA_POSIX</TT
|
>CYGNUM_KERNEL_THREADS_DATA_POSIX</TT
|
>, but obviously
|
>, but obviously
|
this does involve a risk of strange and subtle bugs if the
|
this does involve a risk of strange and subtle bugs if the
|
application's requirements ever change.
|
application's requirements ever change.
|
</P
|
</P
|
></DIV
|
></DIV
|
><DIV
|
><DIV
|
CLASS="REFSECT1"
|
CLASS="REFSECT1"
|
><A
|
><A
|
NAME="KERNEL-THREAD-DATA-CONTEXT"
|
NAME="KERNEL-THREAD-DATA-CONTEXT"
|
></A
|
></A
|
><H2
|
><H2
|
>Valid contexts</H2
|
>Valid contexts</H2
|
><P
|
><P
|
>Typically <TT
|
>Typically <TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_new_data_index</TT
|
>cyg_thread_new_data_index</TT
|
> is only
|
> is only
|
called during initialization, but may also be called at any time in
|
called during initialization, but may also be called at any time in
|
thread context. <TT
|
thread context. <TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_free_data_index</TT
|
>cyg_thread_free_data_index</TT
|
>, if
|
>, if
|
used at all, can also be called during initialization or from thread
|
used at all, can also be called during initialization or from thread
|
context. <TT
|
context. <TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_get_data</TT
|
>cyg_thread_get_data</TT
|
>,
|
>,
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_get_data_ptr</TT
|
>cyg_thread_get_data_ptr</TT
|
>, and
|
>, and
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_thread_set_data</TT
|
>cyg_thread_set_data</TT
|
> may only be called from
|
> may only be called from
|
thread context because they implicitly operate on the current thread.
|
thread context because they implicitly operate on the current thread.
|
</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-thread-priorities.html"
|
HREF="kernel-thread-priorities.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-destructors.html"
|
HREF="kernel-thread-destructors.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"
|
>Thread priorities</TD
|
>Thread priorities</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 destructors</TD
|
>Thread destructors</TD
|
></TR
|
></TR
|
></TABLE
|
></TABLE
|
></DIV
|
></DIV
|
></BODY
|
></BODY
|
></HTML
|
></HTML
|
|
|