SAM Example 3A

From SoOS

Jump to: navigation, search

Contents

[edit] Description

This example shows how to execute speculatively and flash back a worker thread (inefficient version).

[edit] Code

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sam.h>
  4.  
  5. #define N 4
  6. #define ARRAY_SIZE 64
  7.  
  8. struct datast
  9. {
  10.   int *A;
  11. };
  12.  
  13. void * worker_routine(void *args)
  14. {
  15.   SAM_t sam_context; /* Declare a SAM context variable */
  16.   void *myargs; /* Pointer to where the arguments are stored */
  17.   int *myArray; /* Pointer to the Array of the data */
  18.   struct datast *data_arg; /* Pointer to the arguments of the function */
  19.   int total; /* Store the variable of the calculation */
  20.   int *result; /* Pointer to the result (total) of the calculation */
  21.   int i;
  22.  
  23.  
  24.   /* Start the execution of this worker thread */
  25.   /* Extract the SAM context and the arguments */
  26.   SAM_Execution_start(args, &sam_context, &myargs);
  27.  
  28.   /* Print the SAM worker ID of this worker thread  */
  29.   printf("SAM worker id: %d\n", (int)SAM_My_workid(sam_context));
  30.  
  31.   /* Extract the arguments of the function */
  32.   data_arg = (struct datast *) myargs;
  33.   myArray = data_arg->A;
  34.  
  35.   total = 0;
  36.  
  37.   /* Declare the region as read by the worker thread */
  38.   SAM_Memory_speculative_read(sam_context, SAM_My_workid(sam_context), myArray);
  39.  
  40.   /* Make some calculations... */
  41.   for(i=0; i<ARRAY_SIZE; i++)
  42.     {
  43.       total += myArray[i];
  44.     }
  45.  
  46.   total = total * (int)SAM_My_workid(sam_context);
  47.  
  48.   /* Print the total, but this value might not be valid */
  49.   printf("Calculated %d: %d\n", (int)SAM_My_workid(sam_context), total);
  50.  
  51.   /* Finish the execution of this worker trhead */
  52.   SAM_Execution_finish(sam_context);
  53.  
  54.   /* Reserve memory for the result and return it */
  55.   result = (int *) malloc(sizeof(int));
  56.   *result = total;
  57.  
  58.   return result;
  59. }
  60.  
  61. int main(void)
  62. {
  63.   SAM_t sam_context; /* Declare a SAM context variable */
  64.   SAM_Workerid_t th[N]; /* For storing the worker threads ID's  */
  65.   int *result; /* Gets the result of the worker thread */
  66.   int *myArray; /* Pointer to the array of the data */
  67.   struct datast *data_arg; /* Pointer to the worker threads arguments */
  68.   int i;
  69.  
  70.  
  71.   myArray = (int *) malloc(ARRAY_SIZE *sizeof(int));
  72.   data_arg = (struct datast *) malloc(sizeof(struct datast));
  73.  
  74.  
  75.   /* Set some data into the Array */
  76.   for(i=0; i<ARRAY_SIZE; i++)
  77.     {
  78.       myArray[i] = i + 1000;
  79.     }
  80.  
  81.  
  82.   /* Initialize the SAM context */
  83.   SAM_Init(&sam_context);
  84.  
  85.   /* Setup the arguments we are going to send to the worker threads */
  86.   data_arg->A = myArray;
  87.  
  88.  
  89.   /* Register a region and protect it */
  90.   SAM_Memory_region_register(sam_context, myArray, ARRAY_SIZE * sizeof(int));
  91.   SAM_Memory_region_protect(sam_context, myArray);
  92.  
  93.  
  94.   for(i=0;i<N;i++)
  95.     {
  96.       /* Create the worker threads running worker_routine  */
  97.       th[i] = SAM_Execution_create(sam_context, *worker_routine, (void *)data_arg);
  98.     }
  99.  
  100.   /* ---------------------------------------- */
  101.   for(i=0; i<ARRAY_SIZE; i++)
  102.     {
  103.       /* Create a delay to allow some context switches */
  104.       usleep(20*1000);
  105.       /* Set a new value in the array elements*/
  106.       myArray[i] = i;
  107.  
  108.       /* Declare the region as written */
  109.       SAM_Memory_write(sam_context, myArray);
  110.     }
  111.   /* ---------------------------------------- */
  112.  
  113.  
  114.   for(i=0;i<N;i++)
  115.     {
  116.       /* Join the worker threads and get the result */
  117.       result = (int *)SAM_Execution_join(sam_context, th[i]);
  118.  
  119.       /* Print the result */
  120.       printf("RES %d: %d\n", i, *result);
  121.  
  122.       /* Do not forget to free the memory reserved to store the result */
  123.       free(result);
  124.     }
  125.  
  126.   /* Release and unregister the memory region*/
  127.   SAM_Memory_region_release(sam_context, myArray);
  128.   SAM_Memory_region_unregister(sam_context, myArray);
  129.  
  130.  
  131.   /* Destroy the SAM context */
  132.   SAM_Destroy(&sam_context);
  133.  
  134.  
  135.   /* Free the memory */
  136.   free(myArray);
  137.   free(data_arg);
  138.  
  139.   return 0;
  140. }

[edit] Explanation

This example shows how to register a region, protect it, read from it speculatively and flash back a worker thread when needed.

In the main thread, first the memory region (in this case the integer array myArray) has to be registered and protected (calls to SAM_Memory_region_register() in the line 90 and SAM_Memory_region_protect() in the line 91). As shown in the line 109, after writing to memory the function SAM_Memory_write() must be called. After finishing the speculative access to the region of memory, it should be released and unregistered with the functions SAM_Memory_region_release() and SAM_Memory_region_unregister() as shown in the lines 127 and 128.

As for the speculative worker thread, the function SAM_Memory_speculative_read() must be called before the access to memory (see line 38).

[edit] Compile Command

gcc example3a.c -lsam -lpthread -o example3a

[edit] Download