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