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
20namespace 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