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 { Resource(size_t bytes)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 ~Resource()33 Resource::~Resource() 34 { 35 deallocate(buffer); 36 } 37 lock(Accessor claimer)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 lock(Accessor relinquisher,Accessor claimer)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 unlock()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 unlock(Accessor relinquisher)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 destruct()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 data() const180 const void *Resource::data() const 181 { 182 return buffer; 183 } 184 } 185