#include #include #include #include #include #include #include /* For mode constants */ #include /* For O_* constants */ #include #include #include #include "stencil.h" double *cur_step; /* pointer to the current matrix */ double *next_step; /* pointer to the next step matrix */ int next_thread_id = 0; pthread_mutex_t thread_id_mutex; int shm_id; struct shared_memory_t *p_shm = NULL; sem_t upper_border[NB_THREADS]; sem_t lower_border[NB_THREADS]; /* initialize matrixes */ void init() { int i, j; /* A COMPLETER */ for(i=0;i=0); /* set the size of the shared memory segment */ assert(ftruncate(shm_id, SHM_SIZE) >= 0); /* map the shared memory segment in the current address space */ p_shm = mmap(NULL, SHM_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, shm_id, 0); assert(p_shm>=0); sem_init(&p_shm->step_produced, 1, 0); sem_init(&p_shm->step_consumed, 1, 0); /* initialize the matrixes */ cur_step = p_shm->cur_step; next_step = p_shm->next_step; srand(time(NULL)); for(i=0; istep_produced); } void finalize() { /* A COMPLETER */ int retour; /* wait until the visualizer ends */ sem_wait(&p_shm->step_consumed); /* destroy the shared memory segment */ retour = munmap(p_shm, SHM_SIZE); assert(retour >= 0); retour = close(shm_id); assert(retour == 0); retour = shm_unlink(KEY); assert(retour >= 0); } void compute(int i_min, int i_max, int j_min, int j_max, double *src, double *dest) { int i, j; /* compute the next matrix */ for(i=i_min; i< i_max; i++) { for(j=j_min; j< j_max; j++) { GET(dest, i, j) = (GET(src, i-1, j) + GET(src, i+1, j) + GET(src, i, j-1) + GET(src, i, j+1) + GET(src, i, j)) / 5; } } } void* thread_func(void* arg) { int i; pthread_mutex_lock(&thread_id_mutex); int my_id = next_thread_id; next_thread_id ++; pthread_mutex_unlock(&thread_id_mutex); double *m1, *m2; m1 = cur_step; m2 = next_step; int i_min, i_max, j_min, j_max; compute_boundaries(&i_min, &i_max, &j_min, &j_max, NB_THREADS, my_id); printf("Thread %d starts (%d, %d)\n", my_id, i_min, i_max); for(i=0; i< NB_STEPS; i++) { if(my_id > 0) sem_wait(&upper_border[my_id]); if(my_id < NB_THREADS-1) sem_wait(&lower_border[my_id]); if(my_id == 0) printf("STEP %d...\n", i); /* wait until the visualizer process consumed the data */ sem_wait(&p_shm->step_consumed); compute(i_min, i_max, j_min, j_max, m1, m2); /* when all the threads have finished, notify the visualizer */ sem_post(&p_shm->step_produced); double *tmp = m1; m1 = m2; m2 = tmp; if(my_id < NB_THREADS-1) sem_post(&upper_border[my_id+1]); if(my_id > 0) sem_post(&lower_border[my_id-1]); } printf("Thread %d ends\n", my_id); return NULL; } int main(int argc, char**argv) { struct timeval t1, t2; unsigned int i; printf("Initialization (problem size: %d)\n", N); init(); printf("Start computing (%d steps)\n", NB_STEPS); GET_TIME(t1); pthread_t tids[NB_THREADS]; for(i=0;i