1 // Copyright 2009-2021 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 
4 #pragma once
5 
6 #include "intrinsics.h"
7 #include "sysinfo.h"
8 #include "atomic.h"
9 
10 namespace embree
11 {
12   /*! system barrier using operating system */
13   class BarrierSys
14   {
15   public:
16 
17     /*! construction / destruction */
18     BarrierSys (size_t N = 0);
19     ~BarrierSys ();
20 
21   private:
22     /*! class in non-copyable */
23     BarrierSys (const BarrierSys& other) DELETED; // do not implement
24     BarrierSys& operator= (const BarrierSys& other) DELETED; // do not implement
25 
26   public:
27     /*! intializes the barrier with some number of threads */
28     void init(size_t count);
29 
30     /*! lets calling thread wait in barrier */
31     void wait();
32 
33   private:
34     void* opaque;
35   };
36 
37   /*! fast active barrier using atomitc counter */
38   struct BarrierActive
39   {
40   public:
BarrierActiveBarrierActive41     BarrierActive ()
42       : cntr(0) {}
43 
resetBarrierActive44     void reset() {
45       cntr.store(0);
46     }
47 
waitBarrierActive48     void wait (size_t numThreads)
49     {
50       cntr++;
51       while (cntr.load() != numThreads)
52         pause_cpu();
53     }
54 
55   private:
56     std::atomic<size_t> cntr;
57   };
58 
59   /*! fast active barrier that does not require initialization to some number of threads */
60   struct BarrierActiveAutoReset
61   {
62   public:
BarrierActiveAutoResetBarrierActiveAutoReset63     BarrierActiveAutoReset ()
64       : cntr0(0), cntr1(0) {}
65 
waitBarrierActiveAutoReset66     void wait (size_t threadCount)
67     {
68       cntr0.fetch_add(1);
69       while (cntr0 != threadCount) pause_cpu();
70       cntr1.fetch_add(1);
71       while (cntr1 != threadCount) pause_cpu();
72       cntr0.fetch_add(-1);
73       while (cntr0 != 0) pause_cpu();
74       cntr1.fetch_add(-1);
75       while (cntr1 != 0) pause_cpu();
76     }
77 
78   private:
79     std::atomic<size_t> cntr0;
80     std::atomic<size_t> cntr1;
81   };
82 
83   class LinearBarrierActive
84   {
85   public:
86 
87     /*! construction and destruction */
88     LinearBarrierActive (size_t threadCount = 0);
89     ~LinearBarrierActive();
90 
91   private:
92     /*! class in non-copyable */
93     LinearBarrierActive (const LinearBarrierActive& other) DELETED; // do not implement
94     LinearBarrierActive& operator= (const LinearBarrierActive& other) DELETED; // do not implement
95 
96   public:
97     /*! intializes the barrier with some number of threads */
98     void init(size_t threadCount);
99 
100     /*! thread with threadIndex waits in the barrier */
101     void wait (const size_t threadIndex);
102 
103   private:
104     volatile unsigned char* count0;
105     volatile unsigned char* count1;
106     volatile unsigned int mode;
107     volatile unsigned int flag0;
108     volatile unsigned int flag1;
109     volatile size_t threadCount;
110   };
111 }
112 
113