SAM Example 5
From SoOS
Contents |
[edit] Description
This example shows how to use multiple protected memory regions within the same SAM context.
[edit] Code
#include <stdio.h>#include <stdlib.h>#include <sam.h>#define N 2#define ARRAY_SIZE 64struct datast{int *A;
};
void * worker_routine(void *args)
{SAM_t sam_context; /* Declare a SAM context variable */
void *myargs; /* Pointer to where the arguments are stored */
int *myArray; /* Pointer to the Array of the data */
struct datast *data_arg; /* Pointer to the arguments of the function */
int total; /* Store the variable of the calculation */
int *result; /* Pointer to the result (total) of the calculation */
SAM_pdif_t dif; /* The differential for the __SAM_ADDR__() macro*/
int i;
/* Start the execution of this worker thread *//* Extract the SAM context and the arguments */SAM_Execution_start(args, &sam_context, &myargs);
/* Print the SAM worker ID of this worker thread */printf("SAM worker id: %d\n", (int)SAM_My_workid(sam_context));
/* Extract the arguments of the function */data_arg = (struct datast *) myargs;
myArray = data_arg->A;
total = 0;
/* Declare the region as read by the worker thread */SAM_Memory_speculative_read(sam_context, SAM_My_workid(sam_context), myArray);
/* Prepare the memory region for speculative write and obtain the differential parameter */dif = SAM_Memory_speculative_write_prepare(sam_context, myArray);
/* Make some calculations... */for(i=0; i<ARRAY_SIZE; i++)
{/* Example on how to use the __SAM_ADDR__() for reading */total += __SAM_ADDR__(myArray[i], dif);
/* Example on how to use the __SAM_ADDR__() for writing */__SAM_ADDR__(myArray[i], dif) = __SAM_ADDR__(myArray[i], dif) *2;
}total = total * (int)SAM_My_workid(sam_context);
/* Print the total, but this value might not be valid */printf("Calculated %d: %d\n", (int)SAM_My_workid(sam_context), total);
/* Finish the execution of this worker trhead */SAM_Execution_finish(sam_context);
/* Reserve memory for the result and return it */result = (int *) malloc(sizeof(int));
*result = total;
return result;
}int main(void)
{SAM_t sam_context; /* Declare a SAM context variable */
SAM_Workerid_t th1[N]; /* For storing the worker threads ID's of memory region 1*/
SAM_Workerid_t th2[N]; /* For storing the worker threads ID's of memory region 2*/
int *result; /* Gets the result of the worker thread */
int *myArray1; /* Pointer to the array 1 of the data */
int *myArray2; /* Pointer to the array 2 of the data */
struct datast *data_arg1; /* Pointer to the worker threads arguments */
struct datast *data_arg2; /* Pointer to the worker threads arguments */
int i;
myArray1 = (int *) malloc(ARRAY_SIZE *sizeof(int));
myArray2 = (int *) malloc(ARRAY_SIZE *sizeof(int));
data_arg1 = (struct datast *) malloc(sizeof(struct datast));
data_arg2 = (struct datast *) malloc(sizeof(struct datast));
/* Set some data into the Array */for(i=0; i<ARRAY_SIZE; i++)
{myArray1[i] = i + 1000;
myArray2[i] = i + 2000;
}/* Initialize the SAM context */SAM_Init(&sam_context);
/* Setup the arguments we are going to send to the worker threads */data_arg1->A = myArray1;
data_arg2->A = myArray2;
/* Register two regions and protect them */SAM_Memory_region_register(sam_context, myArray1, ARRAY_SIZE * sizeof(int));
SAM_Memory_region_protect(sam_context, myArray1);
SAM_Memory_region_register(sam_context, myArray2, ARRAY_SIZE * sizeof(int));
SAM_Memory_region_protect(sam_context, myArray2);
for(i=0;i<N;i++)
{/* Create the worker threads running worker_routine */th1[i] = SAM_Execution_create(sam_context, *worker_routine, (void *)data_arg1);
th2[i] = SAM_Execution_create(sam_context, *worker_routine, (void *)data_arg2);
}/* ---------------------------------------- *//* Prepare the region to write, this flashes back all the worker threads *//* that already accesed to this region of memory */SAM_Memory_write_prepare(sam_context, myArray1);
for(i=0; i<ARRAY_SIZE; i++)
{/* Create a delay to allow some context switches */usleep(20*1000);
/* Set a new value in the array elements*/myArray1[i] = i;
}/* Declare the region as written */SAM_Memory_write(sam_context, myArray1);
/* Prepare the region to write, this flashes back all the worker threads *//* that already accesed to this region of memory */SAM_Memory_write_prepare(sam_context, myArray2);
for(i=0; i<ARRAY_SIZE; i++)
{/* Create a delay to allow some context switches */usleep(20*1000);
/* Set a new value in the array elements*/myArray2[i] = i;
}/* Declare the region as written */SAM_Memory_write(sam_context, myArray2);
/* ---------------------------------------- */for(i=0;i<N;i++)
{/* Join the worker threads and get the result */result = (int *)SAM_Execution_join(sam_context, th1[i]);
/* Print the result */printf("RES %d: %d\n", i, *result);
/* Do not forget to free the memory reserved to store the result */free(result);
}for(i=0;i<N;i++)
{/* Join the worker threads and get the result */result = (int *)SAM_Execution_join(sam_context, th2[i]);
/* Print the result */printf("RES %d: %d\n", i, *result);
/* Do not forget to free the memory reserved to store the result */free(result);
}/* Release and unregister the memory regions*/SAM_Memory_region_release(sam_context, myArray1);
SAM_Memory_region_unregister(sam_context, myArray1);
SAM_Memory_region_release(sam_context, myArray2);
SAM_Memory_region_unregister(sam_context, myArray2);
/* Destroy the SAM context */SAM_Destroy(&sam_context);
/* Show the array after memory speculative writing */for(i=0; i<ARRAY_SIZE; i++)
{printf("1: %d - %d\n", i, myArray1[i]);
printf("2: %d - %d\n", i, myArray2[i]);
}/* Free the memory */free(myArray1);
free(myArray2);
free(data_arg1);
free(data_arg2);
return 0;
}
[edit] Explanation
[edit] Compile Command
gcc example5.c -lsam -lpthread -o example5