Difference between revisions of "reentrant"

From SEGGER Wiki
Jump to: navigation, search
m
m
Line 3: Line 3:
 
This can happen in different ways:
 
This can happen in different ways:
 
* From an other [[thread of execution]] (an other task)
 
* From an other [[thread of execution]] (an other task)
* From an [[Interrupt service routine]]
+
* From an [[Interrupt Service Routine]]
 
* From another CPU-core sharing memory space.
 
* From another CPU-core sharing memory space.
 
Typically, this means that the routine does not use any static variables. Routines which use only parameters and local variables are reentrant.
 
Typically, this means that the routine does not use any static variables. Routines which use only parameters and local variables are reentrant.

Revision as of 22:26, 5 June 2019

A subroutine is called reentrant if can be safely be called again ("re-entered") before the previous invocation has completed execution. This can happen in different ways:

Typically, this means that the routine does not use any static variables. Routines which use only parameters and local variables are reentrant. Note that re-entrancy is not the same as recursive calling. If a function is recursive, it calls itself, either directly (FuncA calls FuncA) or indirectly (FuncA calls FuncB calls FuncA).

Calling conventions of most modern processors store parameters in registers and on the stack, which is basically required for a routine to be reentrant. Some compilers for older architectures (especially for 8-bit architectures such as 8051 and 6502) do not produce reentrant code and use a static overlay scheme instead.

Bad example

The example below is a bad example, as it uses static variable data. If the code executes multiple times, both instances use the same table. Unfortunately, if the Polynomial parameter for the 2 instances is different, they require different tables. One or both invocations will produce an incorrect result.

unsigned CalcCRC(unsigned crc, const unsigned char* pData, unsigned NumBytes, unsigned Polynomial) {
  static unsigned _Poly;
  static unsigned _aCRC[256];

  //
  // Build CRC table if it has not already been built for this polynomial
  //
  if (Polynomial != _Poly) {
    _Poly = Polynomial;
    // ... More code to compute the static table. Code can be in subroutine.
  }
  while (NumBytes--) {
    // Use table to compute the actual crc
  }
  return crc;  
}