USB: Use BReferenceable for USB objects.

The "busy" counter functionally amounted to a reference count.
So just turn it into a real one, instead.
This commit is contained in:
Augustin Cavalier 2024-10-11 10:46:18 -04:00
parent 50496cd3da
commit f7325a93db
7 changed files with 43 additions and 88 deletions

View File

@ -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;
}

View File

@ -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)

View File

@ -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!");
}

View File

@ -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);

View File

@ -183,7 +183,7 @@ Stack::GetObject(usb_id id)
Object *result = fObjectArray[id];
if (result != NULL)
result->SetBusy(true);
result->AcquireReference();
Unlock();
return result;

View File

@ -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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> object(gUSBStack->GetObject(_hub), true);
if (!object.IsSet() || (object->Type() & USB_OBJECT_HUB) == 0)
return B_DEV_INVALID_PIPE;

View File

@ -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;
};