Limitation - Thread-Local Variables - Scope-Level 3

Under the Solaris operating system, there is a default limit on the amount of thread-local (scope-level=3) variable-space that can be declared.
(This limitation does not apply to Linux or NT.)
Specifically, threads initiated by TRIGGER_THREAD have a default stack-size-limit of 16-KBytes. This is large enough so that you do not normally need to worry about it. It is not an ultimate limitation because there are several easy alternatives. But it is good to know about it so that you avoid a potential pitfall if you are developing models which could stress the arbitrary default limit.

Local variables under a thread, declared such as:

DEFINE_THREAD: xyz
    {
        int A[100];
... are allocated from the thread's stack. Note that parameters passed into any functions or subroutines, that are called from under a thread as well as their local variables, are allocated from the thread's stack. If a thread's stack were to overflow, the result will tend to be rather confusing and catastrophic. The effect of the overflow may not be detected for some time. When the anomaly finally becomes evident, it may appear within otherwise unrelated sections and be un-repeatable.

Therefore, care must be taken when writing a model to avoid situations which may overflow a thread's stack. The thread-local variables are intended to typically hold only a few small scalar variables. Under normal cases, it is very unlikely that much of the available stack will ever be used. The possibility of stack overflow is eliminated by responsibly using the local variable sections.

However, when larger variables are needed, do one of the following three things:

  1. Declare the local variables as pointers and malloc their space.
    Example:
           Instead of declaring:
                    int A[5000];
           Replace with:
                    int *A;
                    A = (int *)malloc( 5000 * sizeof(int) );
    Malloc'd memory comes from the heap not the stack, so this is a safe way to circumvent any memory limitations. Heap is unlimited. It grows as needed.
    Or,
  2. Declare the variable(s) as Shared (scope-level=2) or Global (scope-level=1).
    Such variables are allocated from the heap not the stack. They do not affect the stack.
    Or,
  3. Use the TRIGGER_THREAD_STCKSZ variant of the TRIGGER_THREAD function to set the thread's stack size to be sufficient for the intended purpose.
    TRIGGER_THREAD_STCKSZ works just like TRIGGER_THREAD. The first three parameters are the same. The final (extra) parameter of the TRIGGER_THREAD_STCKSZ function sets the thread's stack-size in bytes.

    This enables you, the modeler, to specify the needed stack space for specific threads. For example, it often happens that most model threads are very small, but one thread will have large programs running under it, so we set that thread's stack-size to perhaps 4-MB, or 16-MB, etc.. You could even use this function to make smaller-stacks for lighter-threads, if it is consistent with what is needed.

This limitation under Solaris is due to the way the POSIX library is implemented under SOLARIS. POSIX allows threads to be implemented this way, but does not require it.

Under Linux for example, there is no such limitation for POSIX threads. Yet the threads are very memory efficient, because their stack is initialy set small but is automatically expanded (in 4kB-blocks) as needed.