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 19 namespace sw 20 { Resource(size_t bytes)21 Resource::Resource(size_t bytes) : size(bytes) 22 { 23 blocked = 0; 24 25 accessor = PUBLIC; 26 count = 0; 27 orphaned = false; 28 29 buffer = allocate(bytes); 30 } 31 ~Resource()32 Resource::~Resource() 33 { 34 deallocate(buffer); 35 } 36 lock(Accessor claimer)37 void *Resource::lock(Accessor claimer) 38 { 39 criticalSection.lock(); 40 41 while(count > 0 && accessor != claimer) 42 { 43 blocked++; 44 criticalSection.unlock(); 45 46 unblock.wait(); 47 48 criticalSection.lock(); 49 blocked--; 50 } 51 52 accessor = claimer; 53 count++; 54 55 criticalSection.unlock(); 56 57 return buffer; 58 } 59 lock(Accessor relinquisher,Accessor claimer)60 void *Resource::lock(Accessor relinquisher, Accessor claimer) 61 { 62 criticalSection.lock(); 63 64 // Release 65 while(count > 0 && accessor == relinquisher) 66 { 67 count--; 68 69 if(count == 0) 70 { 71 if(blocked) 72 { 73 unblock.signal(); 74 } 75 else if(orphaned) 76 { 77 criticalSection.unlock(); 78 79 delete this; 80 81 return 0; 82 } 83 } 84 } 85 86 // Acquire 87 while(count > 0 && accessor != claimer) 88 { 89 blocked++; 90 criticalSection.unlock(); 91 92 unblock.wait(); 93 94 criticalSection.lock(); 95 blocked--; 96 } 97 98 accessor = claimer; 99 count++; 100 101 criticalSection.unlock(); 102 103 return buffer; 104 } 105 unlock()106 void Resource::unlock() 107 { 108 criticalSection.lock(); 109 110 count--; 111 112 if(count == 0) 113 { 114 if(blocked) 115 { 116 unblock.signal(); 117 } 118 else if(orphaned) 119 { 120 criticalSection.unlock(); 121 122 delete this; 123 124 return; 125 } 126 } 127 128 criticalSection.unlock(); 129 } 130 unlock(Accessor relinquisher)131 void Resource::unlock(Accessor relinquisher) 132 { 133 criticalSection.lock(); 134 135 while(count > 0 && accessor == relinquisher) 136 { 137 count--; 138 139 if(count == 0) 140 { 141 if(blocked) 142 { 143 unblock.signal(); 144 } 145 else if(orphaned) 146 { 147 criticalSection.unlock(); 148 149 delete this; 150 151 return; 152 } 153 } 154 } 155 156 criticalSection.unlock(); 157 } 158 destruct()159 void Resource::destruct() 160 { 161 criticalSection.lock(); 162 163 if(count == 0 && !blocked) 164 { 165 criticalSection.unlock(); 166 167 delete this; 168 169 return; 170 } 171 172 orphaned = true; 173 174 criticalSection.unlock(); 175 } 176 data() const177 const void *Resource::data() const 178 { 179 return buffer; 180 } 181 } 182