|
34 | 34 | #include <level_zero/ze_intel_gpu.h> |
35 | 35 | #include <umf_pools/disjoint_pool_config_parser.hpp> |
36 | 36 |
|
| 37 | +#include "common/ur_ref_count.hpp" |
37 | 38 | #include "logger/ur_logger.hpp" |
38 | 39 | #include "ur_interface_loader.hpp" |
39 | 40 |
|
@@ -220,55 +221,9 @@ void zeParseError(ze_result_t ZeError, const char *&ErrorString); |
220 | 221 | #define ZE_CALL_NOCHECK_NAME(ZeName, ZeArgs, callName) \ |
221 | 222 | ZeCall().doCall(ZeName ZeArgs, callName, #ZeArgs, false) |
222 | 223 |
|
223 | | -// This wrapper around std::atomic is created to limit operations with reference |
224 | | -// counter and to make allowed operations more transparent in terms of |
225 | | -// thread-safety in the plugin. increment() and load() operations do not need a |
226 | | -// mutex guard around them since the underlying data is already atomic. |
227 | | -// decrementAndTest() method is used to guard a code which needs to be |
228 | | -// executed when object's ref count becomes zero after release. This method also |
229 | | -// doesn't need a mutex guard because decrement operation is atomic and only one |
230 | | -// thread can reach ref count equal to zero, i.e. only a single thread can pass |
231 | | -// through this check. |
232 | | -struct ReferenceCounter { |
233 | | - ReferenceCounter() : RefCount{1} {} |
234 | | - |
235 | | - // Reset the counter to the initial value. |
236 | | - void reset() { RefCount = 1; } |
237 | | - |
238 | | - // Used when retaining an object. |
239 | | - void increment() { RefCount++; } |
240 | | - |
241 | | - // Supposed to be used in ur*GetInfo* methods where ref count value is |
242 | | - // requested. |
243 | | - uint32_t load() { return RefCount.load(); } |
244 | | - |
245 | | - // This method allows to guard a code which needs to be executed when object's |
246 | | - // ref count becomes zero after release. It is important to notice that only a |
247 | | - // single thread can pass through this check. This is true because of several |
248 | | - // reasons: |
249 | | - // 1. Decrement operation is executed atomically. |
250 | | - // 2. It is not allowed to retain an object after its refcount reaches zero. |
251 | | - // 3. It is not allowed to release an object more times than the value of |
252 | | - // the ref count. |
253 | | - // 2. and 3. basically means that we can't use an object at all as soon as its |
254 | | - // refcount reaches zero. Using this check guarantees that code for deleting |
255 | | - // an object and releasing its resources is executed once by a single thread |
256 | | - // and we don't need to use any mutexes to guard access to this object in the |
257 | | - // scope after this check. Of course if we access another objects in this code |
258 | | - // (not the one which is being deleted) then access to these objects must be |
259 | | - // guarded, for example with a mutex. |
260 | | - bool decrementAndTest() { return --RefCount == 0; } |
261 | | - |
262 | | -private: |
263 | | - std::atomic<uint32_t> RefCount; |
264 | | -}; |
265 | | - |
266 | 224 | // Base class to store common data |
267 | 225 | struct ur_object : ur::handle_base<ur::level_zero::ddi_getter> { |
268 | | - ur_object() : handle_base(), RefCount{} {} |
269 | | - |
270 | | - // Must be atomic to prevent data race when incrementing/decrementing. |
271 | | - ReferenceCounter RefCount; |
| 226 | + ur_object() : handle_base() {} |
272 | 227 |
|
273 | 228 | // This mutex protects accesses to all the non-const member variables. |
274 | 229 | // Exclusive access is required to modify any of these members. |
@@ -303,6 +258,8 @@ struct MemAllocRecord : ur_object { |
303 | 258 | // TODO: this should go away when memory isolation issue is fixed in the Level |
304 | 259 | // Zero runtime. |
305 | 260 | ur_context_handle_t Context; |
| 261 | + |
| 262 | + ur::RefCount RefCount; |
306 | 263 | }; |
307 | 264 |
|
308 | 265 | extern usm::DisjointPoolAllConfigs DisjointPoolConfigInstance; |
|
0 commit comments