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 19namespace sw 20{ 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 = allocateZero(bytes); 30 } 31 32 Resource::~Resource() 33 { 34 deallocate(buffer); 35 } 36 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 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 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 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 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 177 const void *Resource::data() const 178 { 179 return buffer; 180 } 181} 182