diff --git a/zircon/system/core/devmgr/devhost/core.cpp b/zircon/system/core/devmgr/devhost/core.cpp index 35da4be746cff1b06129ec6523f5be3f5fc1a4e4..98edd56b45d33909bb45f7d6b0ed4e13c051c4f8 100644 --- a/zircon/system/core/devmgr/devhost/core.cpp +++ b/zircon/system/core/devmgr/devhost/core.cpp @@ -46,12 +46,18 @@ __LOCAL mtx_t devhost_api_lock = MTX_INIT; __LOCAL std::atomic<thrd_t> devhost_api_lock_owner(0); } // namespace internal +static thread_local BindContext* g_bind_context; static thread_local CreationContext* g_creation_context; -// The creation context is setup before the bind() or create() ops are -// invoked to provide the ability to sanity check the required device_add() -// operations these hooks should be making. +// The bind and creation contexts is setup before the bind() or +// create() ops are invoked to provide the ability to sanity check the +// required device_add() operations these hooks should be making. +void devhost_set_bind_context(BindContext* ctx) { + g_bind_context = ctx; +} + void devhost_set_creation_context(CreationContext* ctx) { + ZX_DEBUG_ASSERT(!ctx || ctx->rpc->is_valid()); g_creation_context = ctx; } @@ -360,21 +366,22 @@ zx_status_t devhost_device_add(const fbl::RefPtr<zx_device_t>& dev, return fail(ZX_ERR_BAD_STATE); } - CreationContext* ctx = nullptr; + BindContext* bind_ctx = nullptr; + CreationContext* creation_ctx = nullptr; - // if creation ctx (thread local) is set, we are in a thread - // that is handling a bind() or create() callback and if that - // ctx's parent matches the one provided to add we need to do + // If the bind or creation ctx (thread locals) are set, we are in + // a thread that is handling a bind() or create() callback and if + // that ctx's parent matches the one provided to add we need to do // some additional checking... + if ((g_bind_context != nullptr) && (g_bind_context->parent == parent)) { + bind_ctx = g_bind_context; + } if ((g_creation_context != nullptr) && (g_creation_context->parent == parent)) { - ctx = g_creation_context; - // If the RPC channel exists, this is for create rather than bind. - if (ctx->rpc->is_valid()) { - // create() must create only one child - if (ctx->child != nullptr) { - printf("devhost: driver attempted to create multiple proxy devices!\n"); - return ZX_ERR_BAD_STATE; - } + creation_ctx = g_creation_context; + // create() must create only one child + if (creation_ctx->child != nullptr) { + printf("devhost: driver attempted to create multiple proxy devices!\n"); + return ZX_ERR_BAD_STATE; } } @@ -393,15 +400,15 @@ zx_status_t devhost_device_add(const fbl::RefPtr<zx_device_t>& dev, dev->flags |= DEV_FLAG_BUSY; // proxy devices are created through this handshake process - if (ctx && (ctx->rpc->is_valid())) { + if (creation_ctx) { if (dev->flags & DEV_FLAG_INVISIBLE) { printf("devhost: driver attempted to create invisible device in create()\n"); return ZX_ERR_INVALID_ARGS; } dev->flags |= DEV_FLAG_ADDED; dev->flags &= (~DEV_FLAG_BUSY); - dev->rpc = zx::unowned_channel(ctx->rpc); - ctx->child = dev; + dev->rpc = zx::unowned_channel(creation_ctx->rpc); + creation_ctx->child = dev; return ZX_OK; } @@ -428,9 +435,9 @@ zx_status_t devhost_device_add(const fbl::RefPtr<zx_device_t>& dev, dev->flags |= DEV_FLAG_ADDED; dev->flags &= (~DEV_FLAG_BUSY); - // record this device in the creation context if there is one - if (ctx && (ctx->child == nullptr)) { - ctx->child = dev; + // record this device in the bind context if there is one + if (bind_ctx && (bind_ctx->child == nullptr)) { + bind_ctx->child = dev; } return ZX_OK; } diff --git a/zircon/system/core/devmgr/devhost/devhost.cpp b/zircon/system/core/devmgr/devhost/devhost.cpp index fe94cb76356ff245d093c777114743b1aca2d308..c678c11eb491ae253bab53e0e1e18719f4fcccf6 100644 --- a/zircon/system/core/devmgr/devhost/devhost.cpp +++ b/zircon/system/core/devmgr/devhost/devhost.cpp @@ -492,14 +492,13 @@ static zx_status_t fidl_BindDriver(void* raw_ctx, const char* driver_path_data, } if (drv->has_bind_op()) { - CreationContext creation_ctx = { + BindContext bind_ctx = { .parent = ctx->conn->dev, .child = nullptr, - .rpc = zx::unowned_channel(), }; - r = drv->BindOp(&creation_ctx, ctx->conn->dev); + r = drv->BindOp(&bind_ctx, ctx->conn->dev); - if ((r == ZX_OK) && (creation_ctx.child == nullptr)) { + if ((r == ZX_OK) && (bind_ctx.child == nullptr)) { printf("devhost: WARNING: driver '%.*s' did not add device in bind()\n", static_cast<int>(driver_path_size), driver_path_data); } diff --git a/zircon/system/core/devmgr/devhost/devhost.h b/zircon/system/core/devmgr/devhost/devhost.h index f8fec592b775e22218f9c1195e9dcb3db43bf475..0277aee0365c33944cdda2125e7fde0bacf5467d 100644 --- a/zircon/system/core/devmgr/devhost/devhost.h +++ b/zircon/system/core/devmgr/devhost/devhost.h @@ -29,12 +29,18 @@ namespace devmgr { +struct BindContext { + fbl::RefPtr<zx_device_t> parent; + fbl::RefPtr<zx_device_t> child; +}; + struct CreationContext { fbl::RefPtr<zx_device_t> parent; fbl::RefPtr<zx_device_t> child; zx::unowned_channel rpc; }; +void devhost_set_bind_context(BindContext* ctx); void devhost_set_creation_context(CreationContext* ctx); } // namespace devmgr @@ -78,11 +84,11 @@ struct zx_driver : fbl::DoublyLinkedListable<fbl::RefPtr<zx_driver>>, fbl::RefCo zx_status_t InitOp() { return ops_->init(&ctx_); } - zx_status_t BindOp(devmgr::CreationContext* creation_context, + zx_status_t BindOp(devmgr::BindContext* bind_context, const fbl::RefPtr<zx_device_t>& device) const { - devmgr::devhost_set_creation_context(creation_context); + devmgr::devhost_set_bind_context(bind_context); auto status = ops_->bind(ctx_, device.get()); - devmgr::devhost_set_creation_context(nullptr); + devmgr::devhost_set_bind_context(nullptr); return status; }