1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <atomic>
8 #include <threads.h>
9 #include <zircon/thread_annotations.h>
10 
11 namespace devmgr {
12 
13 // locking and lock debugging
14 
15 namespace internal {
16 extern mtx_t devhost_api_lock;
17 extern std::atomic<thrd_t> devhost_api_lock_owner;
18 } // namespace internal
19 
20 #define REQ_DM_LOCK TA_REQ(&::devmgr::internal::devhost_api_lock)
21 #define USE_DM_LOCK TA_GUARDED(&::devmgr::internal::devhost_api_lock)
22 
DM_LOCK()23 static inline void DM_LOCK() TA_ACQ(&::devmgr::internal::devhost_api_lock) {
24     mtx_lock(&internal::devhost_api_lock);
25     internal::devhost_api_lock_owner.store(thrd_current());
26 }
27 
DM_UNLOCK()28 static inline void DM_UNLOCK() TA_REL(&::devmgr::internal::devhost_api_lock) {
29     internal::devhost_api_lock_owner.store(0);
30     mtx_unlock(&internal::devhost_api_lock);
31 }
32 
DM_LOCK_HELD()33 static inline bool DM_LOCK_HELD() {
34     return thrd_equal(internal::devhost_api_lock_owner.load(), thrd_current());
35 }
36 
37 class ApiAutoLock {
38 public:
ApiAutoLock()39     ApiAutoLock() TA_ACQ(&::devmgr::internal::devhost_api_lock) {
40         DM_LOCK();
41     }
42     ~ApiAutoLock() TA_REL(&::devmgr::internal::devhost_api_lock) {
43         DM_UNLOCK();
44     }
45 };
46 
47 class ApiAutoRelock {
48 public:
ApiAutoRelock()49     ApiAutoRelock() TA_REL(&::devmgr::internal::devhost_api_lock) {
50         DM_UNLOCK();
51     }
52     ~ApiAutoRelock() TA_ACQ(&::devmgr::internal::devhost_api_lock) {
53         DM_LOCK();
54     }
55 };
56 
57 } // namespace devmgr
58