• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef sw_MutexLock_hpp
16 #define sw_MutexLock_hpp
17 
18 #include "Thread.hpp"
19 
20 #ifdef __ANDROID__
21 /* Use an actual mutex on android. Since many processes may use switchshader
22    at the same time it's best to just have the scheduler overhead. */
23 #include <pthread.h>
24 
25 namespace sw
26 {
27 	class BackoffLock
28 	{
29 	public:
BackoffLock()30 		BackoffLock()
31 		{
32 			pthread_mutex_init(&mutex, NULL);
33 		}
~BackoffLock()34 		~BackoffLock()
35 		{
36 			pthread_mutex_destroy(&mutex);
37 		}
38 
attemptLock()39 		bool attemptLock()
40 		{
41                 	if (pthread_mutex_trylock(&mutex) == 0)
42                         {
43                         	return true;
44                         }
45 			return false;
46 		}
47 
lock()48 		void lock()
49 		{
50 			pthread_mutex_lock(&mutex);
51 		}
52 
unlock()53 		void unlock()
54 		{
55 			pthread_mutex_unlock(&mutex);
56 		}
57 
58 	private:
59 		struct
60 		{
61 			// Ensure that the mutex variable is on its own 64-byte cache line to avoid false sharing
62 			// Padding must be public to avoid compiler warnings
63 			volatile int padding1[16];
64 			pthread_mutex_t mutex;
65 			volatile int padding2[15];
66 		};
67 	};
68 }
69 
70 #else
71 
72 namespace sw
73 {
74 	class BackoffLock
75 	{
76 	public:
BackoffLock()77 		BackoffLock()
78 		{
79 			mutex = 0;
80 		}
81 
attemptLock()82 		bool attemptLock()
83 		{
84 			if(!isLocked())
85 			{
86 				if(atomicExchange(&mutex, 1) == 0)
87 				{
88 					return true;
89 				}
90 			}
91 
92 			return false;
93 		}
94 
lock()95 		void lock()
96 		{
97 			int backoff = 1;
98 
99 			while(!attemptLock())
100 			{
101 				if(backoff <= 64)
102 				{
103 					for(int i = 0; i < backoff; i++)
104 					{
105 						nop();
106 						nop();
107 						nop();
108 						nop();
109 						nop();
110 
111 						nop();
112 						nop();
113 						nop();
114 						nop();
115 						nop();
116 
117 						nop();
118 						nop();
119 						nop();
120 						nop();
121 						nop();
122 
123 						nop();
124 						nop();
125 						nop();
126 						nop();
127 						nop();
128 
129 						nop();
130 						nop();
131 						nop();
132 						nop();
133 						nop();
134 
135 						nop();
136 						nop();
137 						nop();
138 						nop();
139 						nop();
140 
141 						nop();
142 						nop();
143 						nop();
144 						nop();
145 						nop();
146 					}
147 
148 					backoff *= 2;
149 				}
150 				else
151 				{
152 					Thread::yield();
153 
154 					backoff = 1;
155 				}
156 			};
157 		}
158 
unlock()159 		void unlock()
160 		{
161 			mutex = 0;
162 		}
163 
isLocked()164 		bool isLocked()
165 		{
166 			return mutex != 0;
167 		}
168 
169 	private:
170 		struct
171 		{
172 			// Ensure that the mutex variable is on its own 64-byte cache line to avoid false sharing
173 			// Padding must be public to avoid compiler warnings
174 			volatile int padding1[16];
175 			volatile int mutex;
176 			volatile int padding2[15];
177 		};
178 	};
179 }
180 #endif   // __android
181 
182 #endif   // sw_MutexLock_hpp
183