[syscalls][usb][xhci] Introduce scheduler profile to devhost
... and use to remove zx_thread_set_priority() call from usb-xhci.
devhost connects to scheduler.ProfileProvider, and allows drivers to
request a profile. This is an intermediate state until we decide if/how
we want to allow drivers to consume fidl services.
ZX-3703 #comment [syscalls][usb][xhci] Introduce scheduler profile to devhost
ZX-2914 #comment [syscalls][usb][xhci] Introduce scheduler profile to devhost
Test: CQ, manual instrumentation/logging
Change-Id: I23359f2062b77cf84e3bccef72682668817618ad
diff --git a/zircon/system/core/devmgr/devhost/BUILD.gn b/zircon/system/core/devmgr/devhost/BUILD.gn
index a328c7e..e04dc35 100644
--- a/zircon/system/core/devmgr/devhost/BUILD.gn
+++ b/zircon/system/core/devmgr/devhost/BUILD.gn
@@ -23,6 +23,7 @@
"core.cpp",
"devhost.cpp",
"rpc-server.cpp",
+ "scheduler_profile.cpp",
"tracing.cpp",
"zx-device.cpp",
]
@@ -32,6 +33,7 @@
"$zx/system/fidl/fuchsia-device:c",
"$zx/system/fidl/fuchsia-device-manager:c",
"$zx/system/fidl/fuchsia-io:c",
+ "$zx/system/fidl/fuchsia-scheduler:c",
"$zx/system/ulib/async:async-cpp.static",
"$zx/system/ulib/async:async-default.static",
"$zx/system/ulib/async:static",
diff --git a/zircon/system/core/devmgr/devhost/api.cpp b/zircon/system/core/devmgr/devhost/api.cpp
index ad882b8..6317813 100644
--- a/zircon/system/core/devmgr/devhost/api.cpp
+++ b/zircon/system/core/devmgr/devhost/api.cpp
@@ -5,6 +5,7 @@
#include <zircon/compiler.h>
#include "devhost.h"
+#include "scheduler_profile.h"
#include <ddk/debug.h>
#include <ddk/device.h>
#include <zircon/device/vfs.h>
@@ -140,6 +141,11 @@
devhost_make_visible(dev_ref);
}
+__EXPORT zx_status_t device_get_profile(zx_device_t* dev, uint32_t priority, const char* name,
+ zx_handle_t* out_profile) {
+ return devhost_get_scheduler_profile(priority, name, out_profile);
+}
+
__EXPORT const char* device_get_name(zx_device_t* dev) {
return dev->name;
}
diff --git a/zircon/system/core/devmgr/devhost/devhost.cpp b/zircon/system/core/devmgr/devhost/devhost.cpp
index 9fc0440..d2379ce 100644
--- a/zircon/system/core/devmgr/devhost/devhost.cpp
+++ b/zircon/system/core/devmgr/devhost/devhost.cpp
@@ -46,6 +46,7 @@
#include "../shared/log.h"
#include "composite-device.h"
#include "main.h"
+#include "scheduler_profile.h"
#include "tracing.h"
zx_status_t zx_driver::Create(fbl::RefPtr<zx_driver>* out_driver) {
@@ -1350,6 +1351,12 @@
}
}
+ r = devhost_connect_scheduler_profile_provider();
+ if (r != ZX_OK) {
+ log(INFO, "devhost: error connecting to profile provider: %d\n", r);
+ return -1;
+ }
+
if ((r = SetupRootDevcoordinatorConnection(std::move(root_conn_channel))) != ZX_OK) {
log(ERROR, "devhost: could not watch rpc channel: %d\n", r);
return -1;
diff --git a/zircon/system/core/devmgr/devhost/scheduler_profile.cpp b/zircon/system/core/devmgr/devhost/scheduler_profile.cpp
new file mode 100644
index 0000000..67f3f41
--- /dev/null
+++ b/zircon/system/core/devmgr/devhost/scheduler_profile.cpp
@@ -0,0 +1,49 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "scheduler_profile.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <lib/fdio/directory.h>
+#include <lib/zx/channel.h>
+#include <lib/zx/profile.h>
+
+#include <fuchsia/scheduler/c/fidl.h>
+
+namespace devmgr {
+
+zx_handle_t scheduler_profile_provider;
+
+zx_status_t devhost_connect_scheduler_profile_provider() {
+ zx::channel registry_client;
+ zx::channel registry_service;
+ zx_status_t status = zx::channel::create(0u, ®istry_client, ®istry_service);
+ if (status != ZX_OK)
+ return status;
+
+ status = fdio_service_connect("/svc/" fuchsia_scheduler_ProfileProvider_Name,
+ registry_service.release());
+ if (status != ZX_OK)
+ return status;
+
+ scheduler_profile_provider = registry_client.release();
+ return ZX_OK;
+}
+
+zx_status_t devhost_get_scheduler_profile(uint32_t priority, const char* name,
+ zx_handle_t* profile) {
+ zx_status_t fidl_status = ZX_ERR_INTERNAL;
+ zx_status_t status = fuchsia_scheduler_ProfileProviderGetProfile(
+ scheduler_profile_provider, priority, name, strlen(name), &fidl_status, profile);
+ if (status != ZX_OK) {
+ return status;
+ }
+ if (fidl_status != ZX_OK) {
+ return fidl_status;
+ }
+ return ZX_OK;
+}
+
+} // namespace devmgr
diff --git a/zircon/system/core/devmgr/devhost/scheduler_profile.h b/zircon/system/core/devmgr/devhost/scheduler_profile.h
new file mode 100644
index 0000000..26cb61f
--- /dev/null
+++ b/zircon/system/core/devmgr/devhost/scheduler_profile.h
@@ -0,0 +1,15 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include <zircon/types.h>
+
+namespace devmgr {
+
+zx_status_t devhost_connect_scheduler_profile_provider();
+zx_status_t devhost_get_scheduler_profile(uint32_t priority, const char* name,
+ zx_handle_t* profile);
+
+} // namespace devmgr
diff --git a/zircon/system/dev/usb/xhci/usb-xhci.cpp b/zircon/system/dev/usb/xhci/usb-xhci.cpp
index 9d2b53b..4daf1b0 100644
--- a/zircon/system/dev/usb/xhci/usb-xhci.cpp
+++ b/zircon/system/dev/usb/xhci/usb-xhci.cpp
@@ -36,9 +36,6 @@
#define MAX_SLOTS 255
-#define DEFAULT_PRIORITY 16
-#define HIGH_PRIORITY 24
-
#define PDEV_MMIO_INDEX 0
#define PDEV_IRQ_INDEX 0
@@ -217,7 +214,9 @@
// TODO(johngro): See ZX-940. Get rid of this. For now we need thread
// priorities so that realtime transactions use the completer which ends
// up getting realtime latency guarantees.
- zx_thread_set_priority(completer->priority);
+ if (completer->high_priority) {
+ zx_object_set_profile(zx_thread_self(), xhci->profile_handle.get(), 0);
+ }
while (1) {
zx_status_t wait_res;
@@ -252,7 +251,7 @@
if (!ac.check()) {
return ZX_ERR_NO_MEMORY;
}
-
+
for (uint32_t i = 0; i < xhci_->num_interrupts; i++) {
auto* completer = &completers_[i];
completer->xhci = xhci_.get();
@@ -260,8 +259,7 @@
// We need a high priority thread for isochronous transfers.
// If there is only one interrupt available, that thread will need
// to be high priority.
- completer->priority = (i == ISOCH_INTERRUPTER || xhci_->num_interrupts == 1) ?
- HIGH_PRIORITY : DEFAULT_PRIORITY;
+ completer->high_priority = i == ISOCH_INTERRUPTER || xhci_->num_interrupts == 1;
}
// xhci_start will block, so do this part here instead of in usb_xhci_bind
@@ -297,6 +295,12 @@
return status;
}
+ status = device_get_profile(zxdev_, /*HIGH_PRIORITY*/ 24, "zircon/system/dev/usb/xhci/usb-xhci",
+ xhci_->profile_handle.reset_and_get_address());
+ if (status != ZX_OK) {
+ return status;
+ }
+
thrd_t thread;
thrd_create_with_name(&thread,
[](void* arg) -> int {
diff --git a/zircon/system/dev/usb/xhci/usb-xhci.h b/zircon/system/dev/usb/xhci/usb-xhci.h
index e0070f5..72da710 100644
--- a/zircon/system/dev/usb/xhci/usb-xhci.h
+++ b/zircon/system/dev/usb/xhci/usb-xhci.h
@@ -58,7 +58,7 @@
struct Completer {
xhci_t *xhci;
uint32_t interrupter;
- uint32_t priority;
+ bool high_priority;
};
int StartThread();
diff --git a/zircon/system/dev/usb/xhci/xhci.h b/zircon/system/dev/usb/xhci/xhci.h
index acdb616..e8024791 100644
--- a/zircon/system/dev/usb/xhci/xhci.h
+++ b/zircon/system/dev/usb/xhci/xhci.h
@@ -14,6 +14,7 @@
#include <lib/sync/completion.h>
#include <lib/zx/bti.h>
#include <lib/zx/interrupt.h>
+#include <lib/zx/profile.h>
#include <usb/usb-request.h>
#include <zircon/hw/usb.h>
#include <zircon/listnode.h>
@@ -209,6 +210,7 @@
ddk::IoBuffer scratch_pad_index_buffer;
zx::bti bti_handle;
+ zx::profile profile_handle;
// pool of control requests that can be reused
usb_request_pool_t free_reqs = {};
diff --git a/zircon/system/ulib/ddk/include/ddk/driver.h b/zircon/system/ulib/ddk/include/ddk/driver.h
index 832a6c4..b25f5867 100644
--- a/zircon/system/ulib/ddk/include/ddk/driver.h
+++ b/zircon/system/ulib/ddk/include/ddk/driver.h
@@ -142,6 +142,17 @@
zx_status_t device_rebind(zx_device_t* device);
void device_make_visible(zx_device_t* device);
+// Retrieves a profile handle into |out_profile| from the scheduler for the
+// given |priority| and |name|. Ownership of |out_profile| is given to the
+// caller. See fuchsia.scheduler.ProfileProvider for more detail.
+//
+// The profile handle can be used with zx_object_set_profile() to control thread
+// priority.
+//
+// The current arguments are transitional, and will likely change in the future.
+zx_status_t device_get_profile(zx_device_t* device, uint32_t priority, const char* name,
+ zx_handle_t* out_profile);
+
// A description of a part of a device component. It provides a bind program
// that will match a device on the path from the root of the device tree to the
// target device.