#include <stdlib.h> #include <stdio.h> #include <omp.h> #include "gtmp.h" /* From the MCS Paper: A sense-reversing centralized barrier shared count: integer := P shared sense : Boolean := true processor private local_sense : Boolean := true local_sense := not local_sense // each processor if fetch_and_decrement(&count) = 1 count := P sense := local_sense else repeat until sense = local_sense */ typedef struct _node_t{ int k; int count; int locksense; struct _node_t* parent; } node_t; static int num_leaves; static node_t* nodes; void gtmp_barrier_aux(node_t* node, int sense); node_t* _gtmp_get_node(int i){ return &nodes[i]; } void gtmp_init(int num_threads){ int i, v, num_nodes; node_t* curnode; /*Setting constants */ v = 1; while( v < num_threads) v *= 2; num_nodes = v - 1; num_leaves = v/2; /* Setting up the tree */ nodes = (node_t*) malloc(num_nodes * sizeof(node_t)); for(i = 0; i < num_nodes; i++){ curnode = _gtmp_get_node(i); curnode->k = i < num_threads - 1 ? 1 : 1; curnode->count = curnode->k; curnode->locksense = 0; curnode->parent = _gtmp_get_node((i-1)/2); } curnode = _gtmp_get_node(0); curnode->parent = NULL; } void gtmp_barrier(){ node_t* mynode; int sense; mynode = _gtmp_get_node(num_leaves - 1 + (omp_get_thread_num() % num_leaves)); sense = !mynode->locksense; gtmp_barrier_aux(mynode, sense); } void gtmp_barrier_aux(node_t* node, int sense){ int test; #pragma omp critical { test = node->count; node->count--; } if( 1 == test ){ if(node->parent != NULL) gtmp_barrier_aux(node->parent, sense); node->count = node->k; node->locksense = !node->locksense; } while(node->locksense != sense); } void gtmp_finalize(){ free(nodes); }