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 64
struct 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