From f7325a93db585836da1ad886575ed30d93c8f2df Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Fri, 11 Oct 2024 10:46:18 -0400 Subject: [PATCH] USB: Use BReferenceable for USB objects. The "busy" counter functionally amounted to a reference count. So just turn it into a real one, instead. --- .../kernel/bus_managers/usb/Device.cpp | 6 +- src/add-ons/kernel/bus_managers/usb/Hub.cpp | 2 +- .../kernel/bus_managers/usb/Object.cpp | 18 ++-- src/add-ons/kernel/bus_managers/usb/Pipe.cpp | 2 +- src/add-ons/kernel/bus_managers/usb/Stack.cpp | 2 +- src/add-ons/kernel/bus_managers/usb/usb.cpp | 88 +++++-------------- .../kernel/bus_managers/usb/usb_private.h | 13 ++- 7 files changed, 43 insertions(+), 88 deletions(-) diff --git a/src/add-ons/kernel/bus_managers/usb/Device.cpp b/src/add-ons/kernel/bus_managers/usb/Device.cpp index 7e59844a4d..73771c927c 100644 --- a/src/add-ons/kernel/bus_managers/usb/Device.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Device.cpp @@ -334,7 +334,7 @@ Device::~Device() if (fDefaultPipe != NULL) { fDefaultPipe->PutUSBID(false); fDefaultPipe->CancelQueuedTransfers(true); - fDefaultPipe->WaitForUnbusy(); + fDefaultPipe->WaitForIdle(); } // Destroy open endpoints. Do not send a device request to unconfigure @@ -365,7 +365,7 @@ Device::~Device() Interface* interfaceObject = (Interface*)GetStack()->GetObject(interface->handle); if (interfaceObject != NULL) - interfaceObject->SetBusy(false); + interfaceObject->ReleaseReference(); delete interfaceObject; interface->handle = 0; } @@ -648,7 +648,7 @@ Device::ClearEndpoints(int32 interfaceIndex) usb_endpoint_info* endpoint = &interfaceInfo->endpoint[i]; Pipe* pipe = (Pipe*)GetStack()->GetObject(endpoint->handle); if (pipe != NULL) - pipe->SetBusy(false); + pipe->ReleaseReference(); delete pipe; endpoint->handle = 0; } diff --git a/src/add-ons/kernel/bus_managers/usb/Hub.cpp b/src/add-ons/kernel/bus_managers/usb/Hub.cpp index 370a477589..6a85ebc409 100644 --- a/src/add-ons/kernel/bus_managers/usb/Hub.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Hub.cpp @@ -76,7 +76,7 @@ Hub::Hub(Object *parent, int8 hubAddress, uint8 hubPort, } else { TRACE_ALWAYS("no interrupt pipe found\n"); } - object->SetBusy(false); + object->ReleaseReference(); // Wait some time before powering up the ports if (!isRootHub) diff --git a/src/add-ons/kernel/bus_managers/usb/Object.cpp b/src/add-ons/kernel/bus_managers/usb/Object.cpp index 595dbc03de..4f518e61c0 100644 --- a/src/add-ons/kernel/bus_managers/usb/Object.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Object.cpp @@ -13,8 +13,7 @@ Object::Object(Stack *stack, BusManager *bus) : fParent(NULL), fBusManager(bus), fStack(stack), - fUSBID(fStack->GetUSBID(this)), - fBusy(0) + fUSBID(fStack->GetUSBID(this)) { } @@ -23,8 +22,7 @@ Object::Object(Object *parent) : fParent(parent), fBusManager(parent->GetBusManager()), fStack(parent->GetStack()), - fUSBID(fStack->GetUSBID(this)), - fBusy(0) + fUSBID(fStack->GetUSBID(this)) { } @@ -36,26 +34,26 @@ Object::~Object() void -Object::PutUSBID(bool waitForUnbusy) +Object::PutUSBID(bool waitForIdle) { if (fUSBID != UINT32_MAX) { fStack->PutUSBID(this); fUSBID = UINT32_MAX; } - if (waitForUnbusy) - WaitForUnbusy(); + if (waitForIdle) + WaitForIdle(); } void -Object::WaitForUnbusy() +Object::WaitForIdle() { int32 retries = 20; - while (atomic_get(&fBusy) != 0 && retries--) + while (CountReferences() != 1 && retries--) snooze(100); if (retries <= 0) - panic("USB object did not become unbusy!"); + panic("USB object did not become idle!"); } diff --git a/src/add-ons/kernel/bus_managers/usb/Pipe.cpp b/src/add-ons/kernel/bus_managers/usb/Pipe.cpp index 70ed4af57e..3362e8bbf7 100644 --- a/src/add-ons/kernel/bus_managers/usb/Pipe.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Pipe.cpp @@ -375,7 +375,7 @@ ControlPipe::~ControlPipe() // We do this here in case a submitted request is still running. PutUSBID(false); ControlPipe::CancelQueuedTransfers(true); - WaitForUnbusy(); + WaitForIdle(); if (fNotifySem >= 0) delete_sem(fNotifySem); diff --git a/src/add-ons/kernel/bus_managers/usb/Stack.cpp b/src/add-ons/kernel/bus_managers/usb/Stack.cpp index 9dba7e9a61..c77651a2e5 100644 --- a/src/add-ons/kernel/bus_managers/usb/Stack.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Stack.cpp @@ -183,7 +183,7 @@ Stack::GetObject(usb_id id) Object *result = fObjectArray[id]; if (result != NULL) - result->SetBusy(true); + result->AcquireReference(); Unlock(); return result; diff --git a/src/add-ons/kernel/bus_managers/usb/usb.cpp b/src/add-ons/kernel/bus_managers/usb/usb.cpp index ac1a70c7c3..6078cf47a9 100644 --- a/src/add-ons/kernel/bus_managers/usb/usb.cpp +++ b/src/add-ons/kernel/bus_managers/usb/usb.cpp @@ -195,46 +195,6 @@ bus_std_ops(int32 op, ...) } -// #pragma mark - ObjectBusyReleaser - - -class ObjectBusyReleaser { -public: - ObjectBusyReleaser(Object* object) : fObject(object) {} - - ~ObjectBusyReleaser() - { - Release(); - } - - void Release() - { - if (fObject != NULL) { - fObject->SetBusy(false); - fObject = NULL; - } - } - - inline bool IsSet() const - { - return fObject != NULL; - } - - inline Object *Get() const - { - return fObject; - } - - inline Object *operator->() const - { - return fObject; - } - -private: - Object *fObject; -}; - - // #pragma mark - public methods @@ -266,7 +226,7 @@ const usb_device_descriptor * get_device_descriptor(usb_device dev) { TRACE_MODULE("get_device_descriptor(%" B_PRId32 ")\n", dev); - ObjectBusyReleaser object(gUSBStack->GetObject(dev)); + BReference object(gUSBStack->GetObject(dev), true); if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) return NULL; Device *device = (Device *)object.Get(); @@ -280,7 +240,7 @@ get_nth_configuration(usb_device dev, uint32 index) { TRACE_MODULE("get_nth_configuration(%" B_PRId32 ", %" B_PRIu32 ")\n", dev, index); - ObjectBusyReleaser object(gUSBStack->GetObject(dev)); + BReference object(gUSBStack->GetObject(dev), true); if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) return NULL; Device *device = (Device *)object.Get(); @@ -293,7 +253,7 @@ const usb_configuration_info * get_configuration(usb_device dev) { TRACE_MODULE("get_configuration(%" B_PRId32 ")\n", dev); - ObjectBusyReleaser object(gUSBStack->GetObject(dev)); + BReference object(gUSBStack->GetObject(dev), true); if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) return NULL; Device *device = (Device *)object.Get(); @@ -308,7 +268,7 @@ set_configuration(usb_device dev, { TRACE_MODULE("set_configuration(%" B_PRId32 ", %p)\n", dev, configuration); - ObjectBusyReleaser object(gUSBStack->GetObject(dev)); + BReference object(gUSBStack->GetObject(dev), true); if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) return B_DEV_INVALID_PIPE; Device *device = (Device *)object.Get(); @@ -321,7 +281,7 @@ status_t set_alt_interface(usb_device dev, const usb_interface_info *interface) { TRACE_MODULE("set_alt_interface(%" B_PRId32 ", %p)\n", dev, interface); - ObjectBusyReleaser object(gUSBStack->GetObject(dev)); + BReference object(gUSBStack->GetObject(dev), true); if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) return B_DEV_INVALID_PIPE; Device *device = (Device *)object.Get(); @@ -334,7 +294,7 @@ status_t set_feature(usb_id handle, uint16 selector) { TRACE_MODULE("set_feature(%" B_PRId32 ", %d)\n", handle, selector); - ObjectBusyReleaser object(gUSBStack->GetObject(handle)); + BReference object(gUSBStack->GetObject(handle), true); if (!object.IsSet()) return B_DEV_INVALID_PIPE; @@ -346,7 +306,7 @@ status_t clear_feature(usb_id handle, uint16 selector) { TRACE_MODULE("clear_feature(%" B_PRId32 ", %d)\n", handle, selector); - ObjectBusyReleaser object(gUSBStack->GetObject(handle)); + BReference object(gUSBStack->GetObject(handle), true); if (!object.IsSet()) return B_DEV_INVALID_PIPE; @@ -361,7 +321,7 @@ get_status(usb_id handle, uint16 *status) if (!status) return B_BAD_VALUE; - ObjectBusyReleaser object(gUSBStack->GetObject(handle)); + BReference object(gUSBStack->GetObject(handle), true); if (!object.IsSet()) return B_DEV_INVALID_PIPE; @@ -376,7 +336,7 @@ get_descriptor(usb_device dev, uint8 type, uint8 index, uint16 languageID, TRACE_MODULE("get_descriptor(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, %p, " "%" B_PRIuSIZE ", %p)\n", dev, type, index, languageID, data, dataLength, actualLength); - ObjectBusyReleaser object(gUSBStack->GetObject(dev)); + BReference object(gUSBStack->GetObject(dev), true); if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) return B_DEV_INVALID_PIPE; Device *device = (Device *)object.Get(); @@ -393,7 +353,7 @@ send_request(usb_device dev, uint8 requestType, uint8 request, TRACE_MODULE("send_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x, " "%d, %p, %p)\n", dev, requestType, request, value, index, length, data, actualLength); - ObjectBusyReleaser object(gUSBStack->GetObject(dev)); + BReference object(gUSBStack->GetObject(dev), true); if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) return B_DEV_INVALID_PIPE; Device *device = (Device *)object.Get(); @@ -411,7 +371,7 @@ queue_request(usb_device dev, uint8 requestType, uint8 request, TRACE_MODULE("queue_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x," " %u, %p, %p, %p)\n", dev, requestType, request, value, index, length, data, callback, callbackCookie); - ObjectBusyReleaser object(gUSBStack->GetObject(dev)); + BReference object(gUSBStack->GetObject(dev), true); if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) return B_DEV_INVALID_PIPE; Device *device = (Device *)object.Get(); @@ -427,7 +387,7 @@ queue_interrupt(usb_pipe pipe, void *data, size_t dataLength, { TRACE_MODULE("queue_interrupt(%" B_PRId32 ", %p, %ld, %p, %p)\n", pipe, data, dataLength, callback, callbackCookie); - ObjectBusyReleaser object(gUSBStack->GetObject(pipe)); + BReference object(gUSBStack->GetObject(pipe), true); if (!object.IsSet() || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0) return B_DEV_INVALID_PIPE; @@ -442,7 +402,7 @@ queue_bulk(usb_pipe pipe, void *data, size_t dataLength, { TRACE_MODULE("queue_bulk(%" B_PRId32 ", %p, %" B_PRIuSIZE ", %p, %p)\n", pipe, data, dataLength, callback, callbackCookie); - ObjectBusyReleaser object(gUSBStack->GetObject(pipe)); + BReference object(gUSBStack->GetObject(pipe), true); if (!object.IsSet() || (object->Type() & USB_OBJECT_BULK_PIPE) == 0) return B_DEV_INVALID_PIPE; @@ -457,7 +417,7 @@ queue_bulk_v(usb_pipe pipe, iovec *vector, size_t vectorCount, { TRACE_MODULE("queue_bulk_v(%" B_PRId32 ", %p, %" B_PRIuSIZE " %p, %p)\n", pipe, vector, vectorCount, callback, callbackCookie); - ObjectBusyReleaser object(gUSBStack->GetObject(pipe)); + BReference object(gUSBStack->GetObject(pipe), true); if (!object.IsSet() || (object->Type() & USB_OBJECT_BULK_PIPE) == 0) return B_DEV_INVALID_PIPE; @@ -472,7 +432,7 @@ queue_bulk_v_physical(usb_pipe pipe, physical_entry *vector, size_t vectorCount, { TRACE_MODULE("queue_bulk_v_physical(%" B_PRId32 ", %p, %" B_PRIuSIZE ", %p, %p)\n", pipe, vector, vectorCount, callback, callbackCookie); - ObjectBusyReleaser object(gUSBStack->GetObject(pipe)); + BReference object(gUSBStack->GetObject(pipe), true); if (!object.IsSet() || (object->Type() & USB_OBJECT_BULK_PIPE) == 0) return B_DEV_INVALID_PIPE; @@ -491,7 +451,7 @@ queue_isochronous(usb_pipe pipe, void *data, size_t dataLength, "%" B_PRId32 ", %p, 0x%08" B_PRIx32 ", %p, %p)\n", pipe, data, dataLength, packetDesc, packetCount, startingFrameNumber, flags, callback, callbackCookie); - ObjectBusyReleaser object(gUSBStack->GetObject(pipe)); + BReference object(gUSBStack->GetObject(pipe), true); if (!object.IsSet() || (object->Type() & USB_OBJECT_ISO_PIPE) == 0) return B_DEV_INVALID_PIPE; @@ -507,7 +467,7 @@ set_pipe_policy(usb_pipe pipe, uint8 maxQueuedPackets, { TRACE_MODULE("set_pipe_policy(%" B_PRId32 ", %d, %d, %d)\n", pipe, maxQueuedPackets, maxBufferDurationMS, sampleSize); - ObjectBusyReleaser object(gUSBStack->GetObject(pipe)); + BReference object(gUSBStack->GetObject(pipe), true); if (!object.IsSet() || (object->Type() & USB_OBJECT_ISO_PIPE) == 0) return B_DEV_INVALID_PIPE; @@ -520,7 +480,7 @@ status_t cancel_queued_transfers(usb_pipe pipe) { TRACE_MODULE("cancel_queued_transfers(%" B_PRId32 ")\n", pipe); - ObjectBusyReleaser object(gUSBStack->GetObject(pipe)); + BReference object(gUSBStack->GetObject(pipe), true); if (!object.IsSet() || (object->Type() & USB_OBJECT_PIPE) == 0) return B_DEV_INVALID_PIPE; @@ -532,7 +492,7 @@ status_t cancel_queued_requests(usb_device dev) { TRACE_MODULE("cancel_queued_requests(%" B_PRId32 ")\n", dev); - ObjectBusyReleaser object(gUSBStack->GetObject(dev)); + BReference object(gUSBStack->GetObject(dev), true); if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) return B_DEV_INVALID_PIPE; Device *device = (Device *)object.Get(); @@ -549,7 +509,7 @@ usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize) switch (opcode) { case 'DNAM': { - ObjectBusyReleaser object(gUSBStack->GetObject(*(usb_id *)buffer)); + BReference object(gUSBStack->GetObject(*(usb_id *)buffer), true); if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) return B_BAD_VALUE; Device *device = (Device *)object.Get(); @@ -589,7 +549,7 @@ get_nth_child(usb_device _hub, uint8 index, usb_device *childDevice) if (!childDevice) return B_BAD_VALUE; - ObjectBusyReleaser object(gUSBStack->GetObject(_hub)); + BReference object(gUSBStack->GetObject(_hub), true); if (!object.IsSet() || (object->Type() & USB_OBJECT_HUB) == 0) return B_DEV_INVALID_PIPE; @@ -615,7 +575,7 @@ get_device_parent(usb_device _device, usb_device *parentHub, uint8 *portIndex) if (!parentHub || !portIndex) return B_BAD_VALUE; - ObjectBusyReleaser object(gUSBStack->GetObject(_device)); + BReference object(gUSBStack->GetObject(_device), true); if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) return B_DEV_INVALID_PIPE; @@ -639,7 +599,7 @@ get_device_parent(usb_device _device, usb_device *parentHub, uint8 *portIndex) status_t reset_port(usb_device _hub, uint8 portIndex) { - ObjectBusyReleaser object(gUSBStack->GetObject(_hub)); + BReference object(gUSBStack->GetObject(_hub), true); if (!object.IsSet() || (object->Type() & USB_OBJECT_HUB) == 0) return B_DEV_INVALID_PIPE; @@ -651,7 +611,7 @@ reset_port(usb_device _hub, uint8 portIndex) status_t disable_port(usb_device _hub, uint8 portIndex) { - ObjectBusyReleaser object(gUSBStack->GetObject(_hub)); + BReference object(gUSBStack->GetObject(_hub), true); if (!object.IsSet() || (object->Type() & USB_OBJECT_HUB) == 0) return B_DEV_INVALID_PIPE; diff --git a/src/add-ons/kernel/bus_managers/usb/usb_private.h b/src/add-ons/kernel/bus_managers/usb/usb_private.h index 52c751a775..9e7d2ee288 100644 --- a/src/add-ons/kernel/bus_managers/usb/usb_private.h +++ b/src/add-ons/kernel/bus_managers/usb/usb_private.h @@ -137,10 +137,10 @@ public: usb_id GetUSBID(Object *object); void PutUSBID(Object *object); - // This sets the object as busy; the caller must set it un-busy. + // Acquires a reference to the object. Object * GetObject(usb_id id); - // only for the kernel debugger + // only for the kernel debugger (and doesn't acquire a reference) Object * GetObjectNoLock(usb_id id) const; void AddBusManager(BusManager *bus); @@ -270,7 +270,7 @@ private: }; -class Object { +class Object : public BReferenceable { public: Object(Stack *stack, BusManager *bus); Object(Object *parent); @@ -283,8 +283,6 @@ virtual ~Object(); Stack * GetStack() const { return fStack; } usb_id USBID() const { return fUSBID; } - void SetBusy(bool busy) - { atomic_add(&fBusy, busy ? 1 : -1); } virtual uint32 Type() const { return USB_OBJECT_NONE; } virtual const char * TypeName() const { return "object"; } @@ -295,15 +293,14 @@ virtual status_t ClearFeature(uint16 selector); virtual status_t GetStatus(uint16 *status); protected: - void PutUSBID(bool waitForUnbusy = true); - void WaitForUnbusy(); + void PutUSBID(bool waitForIdle = true); + void WaitForIdle(); private: Object * fParent; BusManager * fBusManager; Stack * fStack; usb_id fUSBID; - int32 fBusy; };