www.ti.com
Threads and Reentrancy
2.2.2 Preemptive vs. Non-Preemptive Multitasking
Non-preemptive multitasking relies on each thread to voluntarily relinquish control to the operating system before letting another thread execute. This is usually done by requiring threads to periodically call an operating system function, say yield(), to allow another thread to take control of the CPU or by simply requiring all threads to complete within a specified short period. In a non-preemptive multi-threading environment, the amount of time a thread is allowed to run is determined by the thread, whereas in a preemptive environment, the time is determined by the operating system and the entire set of tasks that are ready to run.
Note that the difference between those two flavors of multi-threading can be a very big one; for example, under a non-preemptive system, you can safely assume that no other thread executes while a particular algorithm processes data using on-chip data memory. Under preemptive execution, this is not true; a thread may be preempted while it is in the middle of processing. Thus, if your application relies on the assumption that things do not change in the middle of processing some data, it might break under a preemptive execution scheme.
Since preemptive systems are designed to preserve the state of a preempted thread and restore it when its execution continues, threads can safely assume that most registers and all of the thread'sdata memory remain unchanged. What would cause an application to fail? Any assumptions related to the maximum amount of time that can elapse between any two instructions, the state of any global system resource such as a data cache, or the state of a global variable accessed by multiple threads, can cause an application to fail in a preemptive environment.
Non-preemptive environments incur less overhead and often result in higher performance systems; for example, data caches are much more effective in non-preemptive systems since each thread can control when preemption (and therefore, cache flushing) will occur.
On the other hand, non-preemptive environments require that either each thread complete within a specified maximum amount of time, or explicitly relinquish control of the CPU to the framework (or operating system) at some minimum periodic rate. By itself, this is not a problem since most DSP threads are periodic with real-time deadlines. However, this minimum rate is a function of the other threads in the system and, consequently, non-preemptive threads are not completely independent of one another; they must be sensitive to the scheduling requirements of the other threads in the system. Thus, systems that are by their nature multirate and multichannel often require preemption; otherwise, all of the algorithms used would have to be rewritten whenever a new algorithm is added to the system.
If we want all algorithms to be framework-independent, we must either define a framework-neutral way for algorithms to relinquish control, or assume that algorithms used in a non-preemptive environment always complete in less than the required maximum scheduling latency time. Since we require documentation of worst-case execution times, it is possible for system integrators to quickly determine if an algorithm will cause a non-preemptive system to violate its scheduling latency requirements. Thus, the TMS320 DSP Algorithm Standard does not define a framework-neutral "yield" operation for algorithms.
Since algorithms can be used in both preemptive and non-preemptive environments, it is important that all algorithms be designed to support both. This means that algorithms should minimize the maximum time that they can delay other algorithms in a non-preemptive system.
2.2.3 Reentrancy
Reentrancy is the attribute of a program or routine that allows the same copy of the program or routine to be used concurrently by two or more threads.
Reentrancy is an extremely valuable property for functions. In multichannel systems, for example, any function that can be invoked as part of one channel'sprocessing must be reentrant ; otherwise, that function would not be usable for other channels. In single channel multirate systems, any function that must be used at two different rates must be reentrant; for example, a general digital filter function used for both echo cancellation and pre-emphasis for a vocoder. Unfortunately, it is not always easy to determine if a function is reentrant.
SPRU352G –June 2005 –Revised February 2007 | General Programming Guidelines | 17 |