The DSP/BIOS OSAL is relatively straightforward and maps relatively cleanly to the DSP/BIOS API. For instance, most mutex and semaphore operations are supported directly using the LCK and SEM API's. Specific details and exceptions are described below.
OsThreadCreate allocates a dspbiosThreadData structure that contains semaphores used for joining to a thread, cancelling a thread and the initial priority requested by the user. A pointer to this structure is stored as a TLS value.
OsThreadCreate must create threads in a suspended state. In DSP/BIOS this is done by setting the initial priority to zero. The initial priority is stored in the per thread control data. When OsThreadStart is called, it retrieves the initial priority from the control data attached to the thread and then sets the priority of the thread, which starts execution.
In order for pthread_join to wait for a thread, OsThreadWaitForEnd is called. Since DSP/BIOS doesn't have a explicit system call for this, we emulate it using a semaphore that is posted to when the thread exits. This semaphore is saved in the per thread control structure.
The PTE library calls OsThreadDelete to signal to the OSAL that the resources for a task can be freed. For DSP/BIOS, this means a call to TSK_delete (task resources are not automatically freed by DSP/BIOS when the thread exits).
OsThreadDelete will be called at a number of points. For attached threads, it will be called when pthread_join is called and returns or when pthread_detach is called for a terminated thread. For detached threads OsThreadDelete will be called when the thread exits.
The problem is that TSK_delete naturally can not be called from the same context as the thread that we're trying to free. For the first two cases (pthread_join and pthread_detach) this is not a problem as these will always be called from another thread. However, for detached threads OsThreadDelete will be called from the same context.
To work around it, the DSP/BIOS OSAL includes a low priority that will clean up detached threads. If OsThreadDelete detects that it is being called from the same context, it will post a message to a mailbox that the garbage collector thread is waiting on. The garbage collector thread will then call TSK_delete for that thread, as well as to clean up any resources that were allocated when the thread was created.
TLS is implemented using the “environment” of DSP/BIOS threads. This allows a single value to be associated with a thread. The TLS helper routines are used to provide full TLS functionality; these routines allocate a structure that holds multiple TLS keys and values. The DSP/BIOS environment is used to hold a pointer to this structure.
Since DSP/BIOS does not natively provide a way to break out of blocked operations, this functionality is emulated using a cancellation semaphore that is stored in the per thread control data. When the user requests that a thread be canceled (i.e. OsThreadCancel is called) this semaphore is posted to. In OsSemaphoreCancellablePend, the cancellation semaphore as well as the user semaphore are polled (rather than blocking) and the routine returns if the cancellation semaphore is posted to.