6.1.3 Methods for Stack Limit Checking

Because there may be accessible memory at addresses lower than those occupied by the guard region, compilers must generate code such that the stack is never extended past the guard pages into accessible memory not allocated to the thread's stack.

The general strategy is to access each page of memory down to and possibly including the page corresponding to the intended new value for the stack pointer SP. If the stack is to be extended by an amount that is larger than the size of a memory page, then a series of accesses is required that works from higher to lower addressed pages. If any access results in a memory access violation, then the code has made an invalid attempt to extend the stack of the current thread.

Note   An access can be performed using either a load or a store operation. However, care must be taken to use an instruction that is guaranteed to make an access to memory. For example, do not use a LDQ R31,* instruction because the Alpha architecture allows it to result in no memory access at all rather than a memory read access whose result is discarded as a result of the R31 destination.

There are two methods for stack limit checking: implicit and explicit.

Implicit Stack Limit Checking

Two mutually exclusive strategies for implicit stack limit checking are of interest:

The stack frame layout (see Section 3.1.2, Stack Frame Procedure) and entry code rules (see Section 3.2.6) generally do not make it feasible to guarantee access to the lowest address of a new stack region without introducing an extra access solely for that purpose. Consequently, this calling standard uses the second strategy. While the amount of implicit stack extension that can be achieved is smaller, the check is achieved at no additional cost.

This calling standard requires that the minimum guard region size is 8192 bytes, the size of the smallest memory protection granularity allowed by the Alpha architecture.

These considerations lead to the following rule:

If the stack is being extended by an amount less than or equal to 4096 and no reserve region is required, then no explicit stack limit checking is required.

However, because asynchronous interrupts and calls to other procedures may also cause stack extension without explicit stack limit checking, stack extension with implicit limit checking must follow a strict set of conventions:

These conventions ensure that the stack pointer will not be decremented such that it points to accessible storage beyond the stack limit without this error being detected (by either the guard region being accessed by the thread or an explicit stack limit check failure).

As a matter of practice, the system can provide multiple guard pages in the guard region. When a stack overflow is detected as a result of access to the guard region, one or more guard pages can be unprotected for use by the exception-handling facility, and one or more guard pages can remain protected to provide implicit stack limit checking during exception processing. However, the size of the guard region and the number of guard pages is system defined, and is not defined by this standard.

Explicit Stack Limit Checking

If the stack is being extended by an amount of unknown size or known size greater than the maximum implicit check size (4096), then a code sequence that follows the rules for implicit stack limit checking can be executed in a loop to access the new stack region incrementally in segments smaller than or equal to the minimum page size (8192 bytes). At least one access must occur in each such segment. The first access must occur between SP and SP - 4096 because, in the absence of more specific information, the previous guaranteed access relative to the current stack pointer may be as much as 4096 bytes greater than the current stack pointer address. The last access must be within 4096 bytes of the intended new value of the stack pointer. These accesses must occur in order, starting with the highest addressed segment and working toward the lowest addressed segment.

Note   A simple algorithm that is consistent with this requirement (but makes up to twice the minimum number of accesses) is to perform a sequence of accesses in a loop starting with the previous value of SP, decrementing by the minimum no check extension size (4096), to but not including the first value that is less than the new value for the stack pointer.

The stack must not be extended incrementally in procedure prologues. A procedure prologue that needs to extend the stack by an amount of unknown size or known size greater than the minimum implicit check size must test new stack segments as just described in a loop that does not modify SP, and then update the stack with one instruction that copies the new stack pointer value into SP.

Note   An explicit stack limit check may be performed either by inline code that is part of a prologue or by a run-time support routine that is specially tailored to be called from a procedure prologue.

Stack Reserve Region Checking

The size of the reserve region, if any, must be included in the increment size used for stack limit checks, after which it is not included in the amount by which the stack is actually extended. (Depending on the size of the reserve region, this may partially or even completely eliminate the ability to use implicit stack limit checking.)