123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
- <html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="content-type"><title>PTE Porting Guide</title></head><body>
- <meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8"><title></title><meta name="GENERATOR" content="OpenOffice.org 2.3 (Linux)"><meta name="CHANGEDBY" content="Jason"><meta name="CHANGEDBY" content="Jason"><meta name="CHANGEDBY" content="Jason"><meta name="CHANGEDBY" content="Jason">
-
-
-
-
-
-
- <style type="text/css">
- <!--
- @page { size: 8.5in 11in; margin: 0.79in }
- P { margin-bottom: 0.08in }
- H1 { margin-bottom: 0.08in }
- H1.western { font-family: "Helvetica"; font-size: 16pt }
- H1.cjk { font-family: "AR PL ShanHeiSun Uni"; font-size: 16pt }
- H1.ctl { font-family: "Tahoma"; font-size: 16pt }
- H2 { margin-bottom: 0.08in }
- H3 { margin-bottom: 0.08in }
- P.code-western { font-family: "Courier New", monospace }
- -->
- </style>
- <p style="margin-bottom: 0in;"><br>
- </p>
- <h1 class="western" align="center">Pthreads-Embedded (PTE) Porting
- Guide</h1>
- <p>The PTE library consists of both a platform independent component,
- which contains the bulk of the pthreads functionality, and a platform
- specific component which connects the platform independent component
- to the underlying OS. Naturally, the platform specific layer is the
- only layer that needs to be modified when porting PTE.</p>
- <p>The OS adaptation layer (OSAL) must provide the following
- functionality:</p>
- <ol><li><p>Threads</p>
- </li><li><p>Semaphores</p>
- </li><li><p>Mutexes</p>
- </li><li><p>Atomic operations</p>
- </li><li><p>Thread local storage</p>
- </li></ol>
- <p>The underlying OS does not necessarily have to provide all of this
- functionality – it is possible for the OSAL to emulate behavior.
- For instance, mutexes can be emulated using semaphores provided by
- the OS. The sections below present a high level of the required
- functionality as well as how it fits into a “typical” embedded
- OS. Specifics such as function parameters, etc are covered in the
- OSAL API reference.</p>
- <h2 align="center">Threads</h2>
- <h3>Thread Initialization</h3>
- <p class="code-western"><b>OsThreadCreate, OsThreadStart</b></p>
- <p>Thread initialization is separated into two steps: create and
- start. When <font face="Courier New, monospace">OSThreadCreate</font>
- is called, the OS should create a new thread, but it must be started
- in a suspended state. The thread should not start executing until
- <font face="Courier New, monospace">OSThreadStart</font> is called.
- This separation in functionality is due necessary to avoid race
- condFor instance, if the target OS supports TLS but only allows a
- single TLS value, this single value could contain a pointer to a
- structure that contains multiple TLS values. The PTE distribution
- includes a helper file to implement this functionality
- (/platform/helper/tls-helper.c). See the DSP/BIOS port for an
- example of using tls-helper.c.itions in the PTE library<span style="font-style: normal;">.</span></p>
- <p><span style="font-style: normal;">Since the actual prototype of an
- thread entry point varies between OS and thus will more than likely
- </span><i>not</i> <span style="font-style: normal;">match that used by
- </span><font face="Courier New, monospace"><span style="font-style: normal;">OsThreadCreate</span></font><span style="font-style: normal;">,
- it will usually be necessary to create a stub function that matches
- your OS's entry point prototype. This stub function simply calls the
- entry point specified by </span><font face="Courier New, monospace"><span style="font-style: normal;">OsThreadCreate</span></font>
- <span style="font-style: normal;">(see DSP/BIOS and PSP-OS ports).</span></p>
- <p>Typically, OsThreadCreate will also perform other initialization;
- for instance to initialize TLS structures, allocate other control
- resources. This of course varies depending on the target OS.
- </p>
- <p>Some OS's require additional parameters to start a thread. For
- instance, DSP/BIOS requires the priority in order to start the
- thread. Rather than pass these parameters to both <font face="Courier New, monospace">OsThreadCreate</font>
- and <font face="Courier New, monospace">OsThreadStart</font>, the
- OSAL should store any necessary information as thread specific values
- during <font face="Courier New, monospace">OsThreadCreate</font> and
- then retrieve them as necessary in <font face="Courier New, monospace">OsThreadStart</font>.</p>
- <p><br><br>
- </p>
- <h3>Thread Destruction</h3>
- <p class="code-western"><b>OsThreadExit, OsThreadDelete,
- OsThreadExitAndDelete, OsThreadWaitForEnd</b></p>
- <p>Thread destruction is broken into three API calls to support the
- different use cases of the pthreads API. <font face="Courier New, monospace">OsThreadExit</font>
- should cause the currently executing thread to stop execution;
- resources should not yet be freed. This is called when a thread
- exits but the thread is not detached – resource deallocation must
- wait until the user calls <font face="Courier New, monospace">pthread_join</font>
- (or <font face="Courier New, monospace">pthread_detach</font>) at
- which point <font face="Courier New, monospace">OsThreadDelete</font>
- will be called.</p>
- <p>Alternatively, if a detached thread exits, thread resource
- deallocation and thread termination can occur simultaneously. In
- this case, <font face="Courier New, monospace">OsThreadExitAndDelete</font>
- will be called.</p>
- <p><font face="Courier New, monospace">OsThreadWaitForEnd</font>
- should block until the specified thread exists. For OS's that do not
- directly support this functionality, a semaphore can be used to
- emulate this behavior (see DSP/BIOS port). Note that this call
- should be cancellable – that is, it should return (even if the
- target thread has not exited) if <font face="Courier New, monospace">OsThreadCancel</font>
- is called.</p>
- <h3>Thread Priority</h3>
- <p class="code-western"><b>OsThreadSetPriority, OsThreadGetPriority,
- OsThreadGetMaxPriority, OsThreadGetMinPriority</b></p>
- <p>The OSAL provides the upper and lower bounds of it's priority
- range when <font face="Courier New, monospace">OsThreadGetMaxPriority</font>
- and <font face="Courier New, monospace">OsThreadGetMinPriority</font>
- are called. The PTE library will ensure that all priorities passed
- to the OSAL (e.g. through <font face="Courier New, monospace">OsThreadCreate</font>)
- are within these bounds.</p>
- <h3>Thread Cancellation</h3>
- <p class="code-western"><b>OsThreadCancel, OsThreadCheckCancel</b></p>
- <p>Currently, the PTE library only supports deferred cancellation
- (see PTE notes). While the PTE library handles most of the
- complexities of cancellation, there are three hooks required from the
- OSAL. When <font face="Courier New, monospace">OsThreadCancel</font>
- is called, it must cause <font face="Courier New, monospace">OsSemaphorePendCancellable</font>
- and <font face="Courier New, monospace">OsThreadWaitForEnd </font>to
- return (this function is used by the PTE library to implement pthread
- cancellation points). Since most embedded OS's do not support this
- kind of functionality, it can be implemented using semaphores (see
- DSP/BIOS and PSP-OS ports). <font face="Courier New, monospace">OsThreadCheckCancel</font>
- simply returns whether <font face="Courier New, monospace">OsThreadCancel</font>
- has been called for this thread.</p>
- <h3>Miscellaneous Thread Functionality</h3>
- <p class="code-western"><b>OsThreadGetHandle, OsThreadSleep,
- OsThreadGetMaxPriority, OsThreadGetMinPriority,
- OsThreadGetDefaultPriority</b><br><br>
- </p>
- <h2 align="center"></h2>
- <h2 style="page-break-before: always;" align="center">Semaphores</h2>
- <p align="center"><br><br>
- </p>
- <p class="code-western"><b>OsSemaphoreCreate, OsSemaphoreDelete,
- OsSemaphorePend, OsSemaphorePort</b></p>
- <p>This basic semaphore functionality should map directly to almost
- all embedded OS's.
- </p>
- <p class="code-western"><b>OsSemaphoreCancellablePend</b></p>
- <p>In order to implement deferred cancellation, a “cancellable”
- pend (<font face="Courier New, monospace">OsSemaphorePendCancellable</font>)
- must also be supported. As discussed above,
- <font face="Courier New, monospace">OsSemaphorePendCancellable</font>
- must return when <font face="Courier New, monospace">OsThreadCancel</font>
- has been called on the thread that is currently pending, regardless
- of whether the semaphore has been posted to or not. The way that this
- is implemented in other ports (e.g. DSP/BIOS and PSP-OS) is to use an
- additional semaphore, and then poll on both semaphores, as shown in
- the pseudo-code below:</p>
- <p><font face="Courier New, monospace">loop forever:</font></p>
- <p><font face="Courier New, monospace">poll main semaphore</font></p>
- <p><font face="Courier New, monospace">if semaphore was posted to,
- return OK</font></p>
- <p><font face="Courier New, monospace">else</font></p>
- <p><font face="Courier New, monospace">check timeout</font></p>
- <p><font face="Courier New, monospace">if timeout has expired, return
- 'timed out'</font></p>
- <p><font face="Courier New, monospace">else</font></p>
- <p><font face="Courier New, monospace">poll cancellation semaphore </font>
- </p>
- <p><font face="Courier New, monospace">if cancellation semaphore has
- been posted to, return 'canceled'</font></p>
- <p><font face="Courier New, monospace">else</font></p>
- <p><font face="Courier New, monospace">sleep for small amount of time</font></p>
- <p>For instance, if the target OS supports TLS but only allows a
- single TLS value, this single value could contain a pointer to a
- structure that contains multiple TLS values. The PTE distribution
- includes a helper file to implement this functionality
- (/platform/helper/tls-helper.c). See the DSP/BIOS port for an
- example of using tls-helper.c.</p>
- <h2 align="center">Mutexes</h2>
- <p>Mutexes are only included as an optimization as some OS's mutex
- operation is much faster than semaphore operations. If the target OS
- does not support mutexes, they can easily be implemented using
- semaphores.</p>
- <p><br><br>
- </p>
- <h2 align="center">Atomic operations</h2>
- <p class="code-western"><b>OsAtomicExchange, OsAtomicCompareExchange,
- OsAtomicExchangeIncrement, OsAtomicDecrement, OsAtomicIncrement</b></p>
- <p align="left">The PTE library requires five atomic operations to be
- supplied by the OSAL. Macros are used in case the target platform
- supports direct assembly instructions to perform some or all of these
- operations. However, under most OS's these macros will simply refer
- to functions that disable interrupts and then perform the required
- operations.</p>
- <p><br><br>
- </p>
- <h2 align="center">Thread local storage</h2>
- <p class="code-western"><b>OsTlsInit, OsTlsAlloc, OsTlsFree,
- OsTlsSetValue, OsTlsGetValue</b></p>
- <p>The OSAL must be able to allocate and free TLS keys, and retrieve
- thread specific data. If the target OS does not support this level
- of TLS functionality, but does have limited TLS support, it is
- possible to emulate the behavior required by the PTE library.</p>
- <p>For instance, if the target OS supports TLS but only allows a
- single TLS value, this single value could contain a pointer to a
- structure that contains multiple TLS values. The PTE distribution
- includes a helper file to implement this functionality
- (/platform/helper/tls-helper.c). See the DSP/BIOS port for an
- example of using tls-helper.c.</p>
- <p>If the OS contains no TLS support, it might still be possible to
- emulate TLS functionality. See the PSP-OS port for an example of how
- this can be accomplished. Be warned – it is not a pretty solution,
- but it works.</p>
- <p>It is important to note that TLS functionality is <i>required </i><span style="font-style: normal;">by
- the PTE library – it is used for more than just the pthread TLS
- functions, but is used extensively throughout the library.</span></p>
- <p style="font-style: normal;">One potentially tricky issue with TLS
- is how to handle the case of when pthread TLS functions are called
- from non-pthread threads (i.e. pure native threads that were not
- created through pthread_create). Technically, according to the
- pthread spec, this should work. However, it is problematic in that
- OsTlsInit would not have been called for that thread, since it is
- called in response to pthread_create(). Different ports handle this
- differently – see the notes for a particular ports.</p>
- <h2 align="center">Miscellaneous Functionality</h2>
- <p class="code-western"><b>ftime</b></p>
- <p>Since pthreads uses absolute time for timeouts, the PTE library
- requires the OS to supply the current time. Note that this does not
- have to be the actual world time, but can be an internal timebase
- (for example, since the unit started up). However, the time source
- should be the same one that the caller to pthread would use.</p>
- <h2 align="center">Types and Constants</h2>
- <p align="left">The OSAL layer must declare a number of types and
- constants.
- </p>
- <p align="left">The following types must be defined to map to the
- appropriate OS constructs:</p>
- <p class="code-western">OsThreadHandle</p>
- <p class="code-western">OsSemaphoreHandle</p>
- <p class="code-western">OsMutexHandle<br><br><br>
- </p>
- <p>The following constants must be defined:</p>
- <p align="left"><font face="Courier New, monospace">OS_DEFAULT_PRIO</font>
- – default priority for a created thread.</p>
- <p align="left"><font face="Courier New, monospace">OS_MIN_PRIO</font>
- – minimum thread priority.</p>
- <p align="left"><font face="Courier New, monospace">OS_MAX_PRIO</font>
- – maximum thread priority.</p>
- <p align="left"><font face="Courier New, monospace">OS_MAX_SIMUL_THREADS</font>
- – maximum number of threads that may be active simultaneously.</p>
- <p align="left"><br><br>
- </p>
- <p align="left">Each port must also include a file, pte_types.h, that
- defines all of the following types. This may be done by explicitly
- typedef'ing the structure (for OS's that do not natively support the
- type) or simply by including the appropriate header file:</p>
- <p align="left"><font face="Courier New, monospace">pid_t</font></p>
- <p align="left"><font face="Courier New, monospace">struct timespec</font></p>
- <p align="left"><font face="Courier New, monospace">mode_t</font></p>
- <p align="left"><font face="Courier New, monospace">struct timeb</font></p>
- <h2 align="center">File structure</h2>
- <p align="left">The OSAL layer must include a file named pte_osal.h.
- This file must include pte_generic_osal.h as well as the platform
- specific header file (e.g. dspbios_osal.h).</p>
- </body></html>
|