LCOV - code coverage report
Current view: top level - dynamics/se/dycore - gbarrier.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 31 45 68.9 %
Date: 2025-03-13 18:42:46 Functions: 4 6 66.7 %

          Line data    Source code
       1             : //: multi-level barrier code; predefined to a max of 64 threads, as below
       2             : 
       3             : // We need to define the Log2 of the maximum number of threads:
       4             : #define LOG2MAX 6
       5             : #define NTHREADS 64
       6             : 
       7             : #include <sched.h>
       8             : #include <math.h>
       9             : #include <stdlib.h>
      10             : #include <time.h>
      11             : #include <stdio.h>
      12             : #include <omp.h>
      13             : #include <stdbool.h>
      14             : #include <stdint.h>
      15             : 
      16             : // utility functions:
      17           0 : int ipow2 (int val) {
      18           0 :   int result = 1;
      19           0 :   while (val > 0) {
      20           0 :     result *= 2;
      21           0 :     --val;
      22             :   }
      23           0 :   return result;
      24             : }
      25             : 
      26             : // Define the data associated with a global barrier:
      27             : typedef struct gbt {
      28             :   volatile bool LocalFlags    [2][LOG2MAX];
      29             :   volatile bool *PartnerFlags [2][LOG2MAX];
      30             :   bool sense;
      31             :   int  parity;
      32             :   int  id;
      33             : } GBarrier_Type;
      34             : 
      35             : // Define a singular type for the global barrier:
      36             : typedef struct gb {
      37             :   GBarrier_Type threadData[NTHREADS];
      38             :   int numThreads;
      39             :   int log2Threads;
      40             : } GBarrier;
      41             : 
      42       31488 : void initializeThread(GBarrier_Type *threadData, int thread, int numThreads) {
      43             :   // Local loop variables: (p)arity, (r)ound and (x) [temporary]
      44       31488 :   int p, r;
      45       31488 :   unsigned int x;
      46             : 
      47             :   // local log2 threads:
      48       31488 :   int log2Threads = ceil(log2(numThreads));
      49             : 
      50       31488 :   threadData[thread].id = thread;
      51       31488 :   threadData[thread].sense = true;
      52       31488 :   threadData[thread].parity = 0;
      53             : 
      54       94464 :   for (p = 0; p < 2; p++) {
      55       62976 :     for (r = 0; r < log2Threads; r++) {
      56           0 :       x = (threadData[thread].id + ipow2(r)) % numThreads;
      57           0 :       threadData[thread].LocalFlags[p][r] = 0;
      58           0 :       threadData[thread].PartnerFlags[p][r] = &threadData[x].LocalFlags[p][r];
      59             :     }
      60             :   }
      61       31488 : }
      62             : 
      63     2981376 : void gbarrier_synchronize(GBarrier* b, int thread)
      64             : {
      65             :   // Local:
      66     2981376 :   int i;
      67             : 
      68             :   // Get the pointer to our thread's data:
      69     2981376 :   GBarrier_Type *my = &b->threadData[thread];
      70             : 
      71             :   // Loop through the log2 rounds:
      72     2981376 :   for (i = 0; i < b->log2Threads; i++) {
      73           0 :     *my->PartnerFlags[my->parity][i] = my->sense;
      74             : 
      75           0 :     while (my->LocalFlags[my->parity][i] != my->sense) { sched_yield(); }
      76             :   }
      77             : 
      78             :   // Reverse the sense for reuse on parity=1
      79     2981376 :   if (my->parity == 1) { my->sense = !my->sense; }
      80             : 
      81             :   // Swap our parity between 0 & 1:
      82     2981376 :   my->parity = 1 - my->parity;
      83     2981376 : }
      84             : 
      85       31488 : void gbarrier_initialize(GBarrier **ptb, int numThreads) {
      86             :   // Local variables:
      87       31488 :   int t;
      88             : 
      89       31488 :   GBarrier *b;
      90       31488 :   (*ptb) = malloc(sizeof(GBarrier));
      91       31488 :   b = (*ptb);
      92             : 
      93       31488 :   b->numThreads = numThreads;
      94       31488 :   b->log2Threads = ceil(log2(b->numThreads));
      95             : 
      96       62976 :   for (t = 0; t < b->numThreads; t++) {
      97       31488 :     initializeThread(b->threadData, t, b->numThreads);
      98             :   }
      99       31488 : }
     100             : 
     101           0 : void gbarrier_print(GBarrier *b) {
     102           0 :   printf("GBarrier Info: %d threads \n", b->numThreads);
     103           0 : }
     104             : 
     105        8448 : void gbarrier_free(GBarrier **ptb) {
     106        8448 :   GBarrier *b = (*ptb);
     107        8448 :   free(b);
     108        8448 : }
     109             : 

Generated by: LCOV version 1.14