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: |
41 | BarrierActive () |
42 | : cntr(0) {} |
43 | |
44 | void reset() { |
45 | cntr.store(i: 0); |
46 | } |
47 | |
48 | 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: |
63 | BarrierActiveAutoReset () |
64 | : cntr0(0), cntr1(0) {} |
65 | |
66 | void wait (size_t threadCount) |
67 | { |
68 | cntr0.fetch_add(i: 1); |
69 | while (cntr0 != threadCount) pause_cpu(); |
70 | cntr1.fetch_add(i: 1); |
71 | while (cntr1 != threadCount) pause_cpu(); |
72 | cntr0.fetch_add(i: -1); |
73 | while (cntr0 != 0) pause_cpu(); |
74 | cntr1.fetch_add(i: -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 | |