Oracle® Solaris Studio 12.4: OpenMP API User's Guide

Exit Print View

Updated: December 2014
 
 

4.7.3 References to Stack Data

A task may reference data on the stack of the routine where the task construct appears (the host routine). Because the execution of a task may be deferred until the next implicit or explicit barrier, a task could execute after the stack of the host routine has already been popped and the stack data overwritten, thereby destroying the stack data referenced by the task.

Be sure to insert the needed synchronizations so that variables are still on the stack when the task references them, as illustrated in the two examples in this section.

In Example 4–8, i is specified to be shared in the task construct, and the task accesses the copy of i that is allocated on the stack of the work() routine.

Task execution may be deferred, so the task may be executed at the implicit barrier at the end of the parallel region in main() after the work() routine has already returned. At that point, when the task references i, it accesses some undetermined value that happens to be on the stack at that time.

For correct results, make sure that work() does not return before the task has completed. This can be accomplished by inserting a taskwait directive after the task construct, as shown in Example 4–9. Alternatively, i can be specified to be firstprivate in the task construct, instead of shared.

Example 4-8  Stack Data: Incorrect Reference
#include <stdio.h>
#include <omp.h>

void work()
 {
   int i;

   i = 10;
   #pragma omp task shared(i)
   {
     #pragma omp critical
     printf("In Task, i = %d\n",i);
   }
 }

int main(int argc, char** argv)
 {
    omp_set_num_threads(8);
    omp_set_dynamic(0);

    #pragma omp parallel 
    {
      work();
    }
 }
Example 4-9  Stack Data: Corrected Reference
#include <stdio.h>
#include <omp.h>

void work()
 {
   int i;

   i = 10;
   #pragma omp task shared(i)
   {
     #pragma omp critical
     printf("In Task, i = %d\n",i);
   }

   /* Use TASKWAIT for synchronization. */
   #pragma omp taskwait
 }

int main(int argc, char** argv)
 {
    omp_set_num_threads(8);
    omp_set_dynamic(0);

    #pragma omp parallel 
    {
      work();
    }
 }

In the following example, j in the task construct refers to the j in the sections construct. Therefore, the task accesses the firstprivate copy of j in the sections construct, which in Oracle Solaris Studio is a local variable on the stack of the outlined routine for the sections construct.

Task execution may be deferred so the task may be executed at the implicit barrier at the end of the sections region after the outlined routine for the sections construct has exited. Therefore, when the task references j, it accesses some undetermined value on the stack.

For correct results, make sure that the task is executed before the sections region reaches its implicit barrier by inserting a taskwait directive after the task construct as shown in Example 4–11. Alternatively, j can be specified to be firstprivate in the task construct, instead of shared.

Example 4-10  Sections Data: Incorrect Reference
#include <stdio.h>
#include <omp.h>

int main(int argc, char** argv)
 {
    omp_set_num_threads(2);
    omp_set_dynamic(0);
    int j=100;

    #pragma omp parallel shared(j)
    {
       #pragma omp sections firstprivate(j)
       {
          #pragma omp section
          {
             #pragma omp task shared(j)
             {
               #pragma omp critical
               printf("In Task, j = %d\n",j);
             }
          }
       } /* Implicit barrier for sections */
    } /* Implicit barrier for parallel */

    printf("After parallel, j = %d\n",j);
 }
Example 4-11  Sections Data: Corrected Reference
#include <stdio.h>
#include <omp.h>

int main(int argc, char** argv)
 {
    omp_set_num_threads(2);
    omp_set_dynamic(0);
    int j=100;

    #pragma omp parallel shared(j)
    {
       #pragma omp sections firstprivate(j)
       {
          #pragma omp section
          {
             #pragma omp task shared(j)
             {
               #pragma omp critical
               printf("In Task, j = %d\n",j);
             }

             /* Use TASKWAIT for synchronization. */
             #pragma omp taskwait
          }
       } /* Implicit barrier for sections */
    }/* Implicit barrier for parallel */

    printf("After parallel, j = %d\n",j);
 }