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 #include "device-internal.h"
6 
7 #include "devhost.h"
8 #include <fbl/auto_call.h>
9 
Create(fbl::RefPtr<zx_device> * out_dev)10 zx_status_t zx_device::Create(fbl::RefPtr<zx_device>* out_dev) {
11     *out_dev = fbl::AdoptRef(new zx_device());
12     return ZX_OK;
13 }
14 
15 // We must disable thread-safety analysis due to not being able to statically
16 // guarantee the lock holding invariant.  Instead, we acquire the lock if
17 // it's not already being held by the current thread.
fbl_recycle()18 void zx_device::fbl_recycle() TA_NO_THREAD_SAFETY_ANALYSIS {
19     bool acq_lock = !devmgr::DM_LOCK_HELD();
20     if (acq_lock) {
21         devmgr::DM_LOCK();
22     }
23     auto unlock = fbl::MakeAutoCall([acq_lock]() TA_NO_THREAD_SAFETY_ANALYSIS {
24         if (acq_lock) {
25             devmgr::DM_UNLOCK();
26         }
27     });
28 
29     if (this->flags & DEV_FLAG_INSTANCE) {
30         // these don't get removed, so mark dead state here
31         this->flags |= DEV_FLAG_DEAD | DEV_FLAG_VERY_DEAD;
32     }
33     if (this->flags & DEV_FLAG_BUSY) {
34         // this can happen if creation fails
35         // the caller to device_add() will free it
36         printf("device: %p(%s): ref=0, busy, not releasing\n", this, this->name);
37         return;
38     }
39 #if TRACE_ADD_REMOVE
40     printf("device: %p(%s): ref=0. releasing.\n", this, this->name);
41 #endif
42 
43     if (!(this->flags & DEV_FLAG_VERY_DEAD)) {
44         printf("device: %p(%s): only mostly dead (this is bad)\n", this, this->name);
45     }
46     if (!this->children.is_empty()) {
47         printf("device: %p(%s): still has children! not good.\n", this, this->name);
48     }
49 
50     this->event.reset();
51     this->local_event.reset();
52 
53     // Put on the defered work list for finalization
54     devmgr::defer_device_list.push_back(this);
55 
56     // Immediately finalize if there's not an active enumerator
57     if (devmgr::devhost_enumerators == 0) {
58         devmgr::devhost_finalize();
59     }
60 }
61