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