1 | // Copyright 2016 The SwiftShader Authors. All Rights Reserved. |
---|---|
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | #include "Resource.hpp" |
16 | |
17 | #include "Memory.hpp" |
18 | #include "Debug.hpp" |
19 | |
20 | namespace sw |
21 | { |
22 | Resource::Resource(size_t bytes) : size(bytes) |
23 | { |
24 | blocked = 0; |
25 | |
26 | accessor = PUBLIC; |
27 | count = 0; |
28 | orphaned = false; |
29 | |
30 | buffer = allocate(bytes); |
31 | } |
32 | |
33 | Resource::~Resource() |
34 | { |
35 | deallocate(buffer); |
36 | } |
37 | |
38 | void *Resource::lock(Accessor claimer) |
39 | { |
40 | criticalSection.lock(); |
41 | |
42 | while(count > 0 && accessor != claimer) |
43 | { |
44 | blocked++; |
45 | criticalSection.unlock(); |
46 | |
47 | unblock.wait(); |
48 | |
49 | criticalSection.lock(); |
50 | blocked--; |
51 | } |
52 | |
53 | accessor = claimer; |
54 | count++; |
55 | |
56 | criticalSection.unlock(); |
57 | |
58 | return buffer; |
59 | } |
60 | |
61 | void *Resource::lock(Accessor relinquisher, Accessor claimer) |
62 | { |
63 | criticalSection.lock(); |
64 | |
65 | // Release |
66 | while(count > 0 && accessor == relinquisher) |
67 | { |
68 | count--; |
69 | |
70 | if(count == 0) |
71 | { |
72 | if(blocked) |
73 | { |
74 | unblock.signal(); |
75 | } |
76 | else if(orphaned) |
77 | { |
78 | criticalSection.unlock(); |
79 | |
80 | delete this; |
81 | |
82 | return 0; |
83 | } |
84 | } |
85 | } |
86 | |
87 | // Acquire |
88 | while(count > 0 && accessor != claimer) |
89 | { |
90 | blocked++; |
91 | criticalSection.unlock(); |
92 | |
93 | unblock.wait(); |
94 | |
95 | criticalSection.lock(); |
96 | blocked--; |
97 | } |
98 | |
99 | accessor = claimer; |
100 | count++; |
101 | |
102 | criticalSection.unlock(); |
103 | |
104 | return buffer; |
105 | } |
106 | |
107 | void Resource::unlock() |
108 | { |
109 | criticalSection.lock(); |
110 | ASSERT(count > 0); |
111 | |
112 | count--; |
113 | |
114 | if(count == 0) |
115 | { |
116 | if(blocked) |
117 | { |
118 | unblock.signal(); |
119 | } |
120 | else if(orphaned) |
121 | { |
122 | criticalSection.unlock(); |
123 | |
124 | delete this; |
125 | |
126 | return; |
127 | } |
128 | } |
129 | |
130 | criticalSection.unlock(); |
131 | } |
132 | |
133 | void Resource::unlock(Accessor relinquisher) |
134 | { |
135 | criticalSection.lock(); |
136 | ASSERT(count > 0); |
137 | |
138 | while(count > 0 && accessor == relinquisher) |
139 | { |
140 | count--; |
141 | |
142 | if(count == 0) |
143 | { |
144 | if(blocked) |
145 | { |
146 | unblock.signal(); |
147 | } |
148 | else if(orphaned) |
149 | { |
150 | criticalSection.unlock(); |
151 | |
152 | delete this; |
153 | |
154 | return; |
155 | } |
156 | } |
157 | } |
158 | |
159 | criticalSection.unlock(); |
160 | } |
161 | |
162 | void Resource::destruct() |
163 | { |
164 | criticalSection.lock(); |
165 | |
166 | if(count == 0 && !blocked) |
167 | { |
168 | criticalSection.unlock(); |
169 | |
170 | delete this; |
171 | |
172 | return; |
173 | } |
174 | |
175 | orphaned = true; |
176 | |
177 | criticalSection.unlock(); |
178 | } |
179 | |
180 | const void *Resource::data() const |
181 | { |
182 | return buffer; |
183 | } |
184 | } |
185 |