- Use ExInterlockedList * functions for speed and stability

- Increment reference count on the correct miniport adapter from IPortDMus

svn path=/trunk/; revision=40886
This commit is contained in:
Johannes Anderwald 2009-05-11 17:22:27 +00:00
parent 1635685bdf
commit 173cb6b1d0
4 changed files with 147 additions and 188 deletions

View file

@ -231,6 +231,7 @@ DECLARE_INTERFACE_(IIrpQueue, IUnknown)
IN PVOID Tag); IN PVOID Tag);
STDMETHOD_(BOOL, HasLastMappingFailed)(THIS); STDMETHOD_(BOOL, HasLastMappingFailed)(THIS);
STDMETHOD_(VOID, PrintQueueStatus)(THIS);
}; };

View file

@ -11,12 +11,13 @@
typedef struct _IRP_MAPPING_ typedef struct _IRP_MAPPING_
{ {
LIST_ENTRY Entry; LIST_ENTRY Entry;
KSSTREAM_HEADER *Header; PVOID Buffer;
ULONG BufferSize;
ULONG OriginalBufferSize;
PVOID OriginalBuffer;
PIRP Irp; PIRP Irp;
ULONG References; PVOID Tag;
ULONG NumTags;
PVOID * Tag;
}IRP_MAPPING, *PIRP_MAPPING; }IRP_MAPPING, *PIRP_MAPPING;
typedef struct typedef struct
@ -34,6 +35,7 @@ typedef struct
KSPIN_LOCK Lock; KSPIN_LOCK Lock;
LIST_ENTRY ListHead; LIST_ENTRY ListHead;
LIST_ENTRY FreeHead;
ULONG OutOfMapping; ULONG OutOfMapping;
ULONG MaxFrameSize; ULONG MaxFrameSize;
@ -49,19 +51,16 @@ FreeMappingRoutine(
if (CurMapping->Irp) if (CurMapping->Irp)
{ {
CurMapping->Irp->IoStatus.Information = CurMapping->Header->FrameExtent; CurMapping->Irp->IoStatus.Information = CurMapping->OriginalBufferSize;
CurMapping->Irp->IoStatus.Status = STATUS_SUCCESS; CurMapping->Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(CurMapping->Irp, IO_SOUND_INCREMENT); IoCompleteRequest(CurMapping->Irp, IO_SOUND_INCREMENT);
} }
if (CurMapping->Tag) if (CurMapping->OriginalBuffer)
{ {
FreeItem(CurMapping->Tag, TAG_PORTCLASS); ExFreePool(CurMapping->OriginalBuffer);
} }
ExFreePool(CurMapping->Header->Data);
ExFreePool(CurMapping->Header);
ExFreePool(CurMapping); ExFreePool(CurMapping);
} }
@ -128,6 +127,7 @@ IIrpQueue_fnInit(
This->MaxFrameSize = FrameSize; This->MaxFrameSize = FrameSize;
InitializeListHead(&This->ListHead); InitializeListHead(&This->ListHead);
InitializeListHead(&This->FreeHead);
KeInitializeSpinLock(&This->Lock); KeInitializeSpinLock(&This->Lock);
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -141,59 +141,77 @@ IIrpQueue_fnAddMapping(
IN ULONG BufferSize, IN ULONG BufferSize,
IN PIRP Irp) IN PIRP Irp)
{ {
PIRP_MAPPING Mapping; PIRP_MAPPING Mapping = NULL;
KSSTREAM_HEADER * Header = (KSSTREAM_HEADER*)Buffer;
ULONG Index, NumMappings, Offset;
IIrpQueueImpl * This = (IIrpQueueImpl*)iface; IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
Mapping = AllocateItem(NonPagedPool, sizeof(IRP_MAPPING), TAG_PORTCLASS);
if (!Mapping)
return STATUS_UNSUCCESSFUL;
Mapping->Header = (KSSTREAM_HEADER*)Buffer;
Mapping->Irp = Irp;
if (This->MaxFrameSize) if (This->MaxFrameSize)
{ {
if (This->MaxFrameSize > Mapping->Header->DataUsed) if (This->MaxFrameSize > Header->DataUsed)
{ {
/* small mapping */ /* small mapping */
Mapping->NumTags = 1; NumMappings = 1;
} }
else else
{ {
ULONG Rest = Mapping->Header->DataUsed % This->MaxFrameSize; ULONG Rest = Header->DataUsed % This->MaxFrameSize;
Mapping->NumTags = Mapping->Header->DataUsed / This->MaxFrameSize; NumMappings = Header->DataUsed / This->MaxFrameSize;
if (Rest) if (Rest)
{ {
Mapping->NumTags++; NumMappings++;
} }
} }
} }
else else
{ {
/* no framesize restriction */ /* no framesize restriction */
Mapping->NumTags = 1; NumMappings = 1;
} }
Mapping->Tag = AllocateItem(NonPagedPool, sizeof(PVOID) * Mapping->NumTags, TAG_PORTCLASS); for(Index = 0; Index < NumMappings; Index++)
if (!Mapping->Tag)
{ {
FreeItem(Mapping, TAG_PORTCLASS); Mapping = AllocateItem(NonPagedPool, sizeof(IRP_MAPPING), TAG_PORTCLASS);
if (!Mapping)
{
DPRINT("OutOfMemory\n");
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
ASSERT(Mapping->NumTags < 32);
Mapping->References = (1 << Mapping->NumTags) - 1;
This->NumDataAvailable += Mapping->Header->DataUsed; if (Index)
Offset = Index * This->MaxFrameSize;
else
Offset = 0;
DPRINT("IIrpQueue_fnAddMapping NumMappings %u SizeOfMapping %lu NumDataAvailable %lu Mapping %p NumTags %u References %x FrameSize %u\n", This->NumMappings, Mapping->Header->DataUsed, This->NumDataAvailable, Mapping, Mapping->NumTags, Mapping->References, This->MaxFrameSize); Mapping->Buffer = (PVOID)UlongToPtr(PtrToUlong(Header->Data) + Offset);
KeAcquireSpinLockAtDpcLevel(&This->Lock); if (This->MaxFrameSize)
InsertTailList(&This->ListHead, &Mapping->Entry); Mapping->BufferSize = min(Header->DataUsed - Offset, This->MaxFrameSize);
KeReleaseSpinLockFromDpcLevel(&This->Lock); else
Mapping->BufferSize = Header->DataUsed;
Mapping->OriginalBufferSize = Header->FrameExtent;
Mapping->OriginalBuffer = NULL;
Mapping->Irp = NULL;
Mapping->Tag = NULL;
This->NumDataAvailable += Mapping->BufferSize;
if (Index == NumMappings - 1)
{
/* last mapping should free the irp if provided */
Mapping->OriginalBuffer = Header->Data;
Mapping->Irp = Irp;
}
ExInterlockedInsertTailList(&This->ListHead, &Mapping->Entry, &This->Lock);
(void)InterlockedIncrement((volatile long*)&This->NumMappings); (void)InterlockedIncrement((volatile long*)&This->NumMappings);
DPRINT("IIrpQueue_fnAddMapping NumMappings %u SizeOfMapping %lu NumDataAvailable %lu Mapping %p FrameSize %u\n", This->NumMappings, Mapping->BufferSize, This->NumDataAvailable, Mapping, This->MaxFrameSize);
}
if (Irp) if (Irp)
{ {
Irp->IoStatus.Status = STATUS_PENDING; Irp->IoStatus.Status = STATUS_PENDING;
@ -216,23 +234,20 @@ IIrpQueue_fnGetMapping(
IIrpQueueImpl * This = (IIrpQueueImpl*)iface; IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
PLIST_ENTRY CurEntry; PLIST_ENTRY CurEntry;
KeAcquireSpinLockAtDpcLevel(&This->Lock); CurEntry = ExInterlockedRemoveHeadList(&This->ListHead, &This->Lock);
if (!CurEntry)
CurEntry = This->ListHead.Flink;
CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
if (CurEntry == &This->ListHead)
{ {
KeReleaseSpinLockFromDpcLevel(&This->Lock); This->StartStream = FALSE;
This->OutOfMapping = TRUE; This->OutOfMapping = TRUE;
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
*Buffer = (PUCHAR)CurMapping->Header->Data + This->CurrentOffset; CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
*BufferSize = CurMapping->Header->DataUsed - This->CurrentOffset; *Buffer = (PUCHAR)CurMapping->Buffer + This->CurrentOffset;
*BufferSize = CurMapping->BufferSize - This->CurrentOffset;
ExInterlockedInsertHeadList(&This->ListHead, &CurMapping->Entry, &This->Lock);
This->OutOfMapping = FALSE; This->OutOfMapping = FALSE;
KeReleaseSpinLockFromDpcLevel(&This->Lock);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -248,24 +263,22 @@ IIrpQueue_fnUpdateMapping(
PIRP_MAPPING CurMapping; PIRP_MAPPING CurMapping;
IIrpQueueImpl * This = (IIrpQueueImpl*)iface; IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
CurEntry = ExInterlockedRemoveHeadList(&This->ListHead, &This->Lock);
CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
This->CurrentOffset += BytesWritten; This->CurrentOffset += BytesWritten;
This->NumDataAvailable -= BytesWritten; This->NumDataAvailable -= BytesWritten;
CurEntry = This->ListHead.Flink; if (CurMapping->BufferSize <= This->CurrentOffset)
CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
if (CurMapping->Header->DataUsed <= This->CurrentOffset)
{ {
This->CurrentOffset = 0; This->CurrentOffset = 0;
KeAcquireSpinLockAtDpcLevel(&This->Lock);
RemoveHeadList(&This->ListHead);
KeReleaseSpinLockFromDpcLevel(&This->Lock);
InterlockedDecrement(&This->NumMappings); InterlockedDecrement(&This->NumMappings);
FreeMappingRoutine(CurMapping); FreeMappingRoutine(CurMapping);
} }
else
{
ExInterlockedInsertHeadList(&This->ListHead, &CurMapping->Entry, &This->Lock);
}
} }
ULONG ULONG
@ -332,51 +345,6 @@ IIrpQueue_fnUpdateFormat(
} }
VOID
GetMapping(
IIrpQueueImpl * This,
IN ULONG Index,
IN PVOID Tag,
IN PIRP_MAPPING CurMapping,
OUT PPHYSICAL_ADDRESS PhysicalAddress,
OUT PVOID *VirtualAddress,
OUT PULONG ByteCount,
OUT PULONG Flags)
{
ULONG Offset;
/* calculate the offset */
if (Index)
Offset = Index * This->MaxFrameSize;
else
Offset = 0;
ASSERT(CurMapping->Header->DataUsed > Offset);
*VirtualAddress = (PUCHAR)CurMapping->Header->Data + Offset;
*PhysicalAddress = MmGetPhysicalAddress(*VirtualAddress);
/* FIXME alignment */
*ByteCount = min(CurMapping->Header->DataUsed - Offset, This->MaxFrameSize);
/* reset out of mapping indicator */
This->OutOfMapping = FALSE;
/* decrement available byte counter */
This->NumDataAvailable -= *ByteCount;
/* store the tag */
CurMapping->Tag[Index] = Tag;
if (Index + 1 == CurMapping->NumTags)
{
/* indicate end of packet */
*Flags = 1;
}
DPRINT("IIrpQueue_fnGetMappingWithTag Tag %p Mapping %p Index %u NumTags %u\n", Tag, CurMapping, Index, CurMapping->NumTags);
}
NTSTATUS NTSTATUS
NTAPI NTAPI
IIrpQueue_fnGetMappingWithTag( IIrpQueue_fnGetMappingWithTag(
@ -389,45 +357,47 @@ IIrpQueue_fnGetMappingWithTag(
{ {
PIRP_MAPPING CurMapping; PIRP_MAPPING CurMapping;
PLIST_ENTRY CurEntry; PLIST_ENTRY CurEntry;
ULONG Index;
ULONG Value;
IIrpQueueImpl * This = (IIrpQueueImpl*)iface; IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
*Flags = 0; *Flags = 0;
ASSERT(Tag != NULL); ASSERT(Tag != NULL);
KeAcquireSpinLockAtDpcLevel(&This->Lock);
CurEntry = This->ListHead.Flink; CurEntry = ExInterlockedRemoveHeadList(&This->ListHead, &This->Lock);
if (CurEntry == &This->ListHead) if (!CurEntry)
{ {
KeReleaseSpinLockFromDpcLevel(&This->Lock);
This->OutOfMapping = TRUE; This->OutOfMapping = TRUE;
This->StartStream = FALSE; This->StartStream = FALSE;
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
while (CurEntry != &This->ListHead)
{
CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry); CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
for(Index = 0; Index < CurMapping->NumTags; Index++)
*PhysicalAddress = MmGetPhysicalAddress(CurMapping->Buffer);
*VirtualAddress = CurMapping->Buffer;
*ByteCount = CurMapping->BufferSize;
InterlockedDecrement(&This->NumMappings);
This->NumDataAvailable -= CurMapping->BufferSize;
if (CurMapping->OriginalBuffer)
{ {
Value = CurMapping->References & ( 1 << Index); /* last partial buffer */
if (CurMapping->Tag[Index] == NULL && Value) *Flags = 1;
/* store tag */
CurMapping->Tag = Tag;
/* insert into list to free later */
ExInterlockedInsertTailList(&This->FreeHead, &CurMapping->Entry, &This->Lock);
}
else
{ {
/* found a free mapping within audio irp */ /* we can free this entry now */
GetMapping(This, Index, Tag, CurMapping, PhysicalAddress, VirtualAddress, ByteCount, Flags); FreeItem(CurMapping, TAG_PORTCLASS);
KeReleaseSpinLockFromDpcLevel(&This->Lock); }
DPRINT("IIrpQueue_fnGetMappingWithTag Tag %p\n", Tag);
return STATUS_SUCCESS; return STATUS_SUCCESS;
}
}
CurEntry = CurEntry->Flink;
}
KeReleaseSpinLockFromDpcLevel(&This->Lock);
This->OutOfMapping = TRUE;
This->StartStream = FALSE;
DPRINT("No Mapping available\n");
return STATUS_UNSUCCESSFUL;
} }
NTSTATUS NTSTATUS
@ -438,62 +408,28 @@ IIrpQueue_fnReleaseMappingWithTag(
{ {
PIRP_MAPPING CurMapping = NULL; PIRP_MAPPING CurMapping = NULL;
PLIST_ENTRY CurEntry; PLIST_ENTRY CurEntry;
ULONG Index = 0;
ULONG Found;
IIrpQueueImpl * This = (IIrpQueueImpl*)iface; IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
KeAcquireSpinLockAtDpcLevel(&This->Lock); DPRINT("IIrpQueue_fnReleaseMappingWithTag Tag %p\n", Tag);
CurEntry = This->ListHead.Flink; CurEntry = ExInterlockedRemoveHeadList(&This->FreeHead, &This->Lock);
if (CurEntry == &This->ListHead) if (!CurMapping)
{ {
KeReleaseSpinLockFromDpcLevel(&This->Lock);
return STATUS_UNSUCCESSFUL;
}
Found = FALSE;
while (CurEntry != &This->ListHead)
{
CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
for(Index = 0; Index < CurMapping->NumTags; Index++)
{
if (CurMapping->Tag[Index] == Tag)
{
Found = TRUE;
CurMapping->Tag[Index] = NULL;
break;
}
}
if (Found)
break;
CurEntry = CurEntry->Flink;
}
if (!Found)
{
DPRINT1("Tag %p not found\n", Tag);
ASSERT(Found);
}
DPRINT("References %x\n", CurMapping->References);
CurMapping->References &= ~(1 << Index);
if (CurMapping->References)
{
/* released mapping is not the last mapping of the irp */
DPRINT1("IIrpQueue_fnReleaseMappingWithTag Tag %p Index %u NumTags %u Refs %x\n", Tag, Index, CurMapping->NumTags, CurMapping->References);
KeReleaseSpinLockFromDpcLevel(&This->Lock);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
RemoveEntryList(&CurMapping->Entry); CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
if (CurMapping->Tag != Tag)
{
/* the released mapping is not the last one */
ExInterlockedInsertHeadList(&This->FreeHead, &CurMapping->Entry, &This->Lock);
return STATUS_SUCCESS;
}
/* last mapping of the irp, free irp */ /* last mapping of the irp, free irp */
DPRINT("Freeing mapping %p\n", CurMapping); DPRINT("IIrpQueue_fnReleaseMappingWithTag Tag %p Mapping %p FREED\n", Tag, CurMapping);
InterlockedDecrement(&This->NumMappings);
FreeMappingRoutine(CurMapping);
KeReleaseSpinLockFromDpcLevel(&This->Lock);
FreeMappingRoutine(CurMapping);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -506,6 +442,32 @@ IIrpQueue_fnHasLastMappingFailed(
return This->OutOfMapping; return This->OutOfMapping;
} }
VOID
NTAPI
IIrpQueue_fnPrintQueueStatus(
IN IIrpQueue *iface)
{
PIRP_MAPPING CurMapping = NULL;
PLIST_ENTRY CurEntry;
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
KeAcquireSpinLockAtDpcLevel(&This->Lock);
CurEntry = This->ListHead.Flink;
DPRINT("IIrpQueue_fnPrintQueueStatus % u ===============\n", This->NumMappings);
while (CurEntry != &This->ListHead)
{
CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
DPRINT("Mapping %p Size %u Original %p\n", CurMapping, CurMapping->BufferSize, CurMapping->OriginalBuffer);
CurEntry = CurEntry->Flink;
}
KeReleaseSpinLockFromDpcLevel(&This->Lock);
DPRINT("IIrpQueue_fnPrintQueueStatus ===============\n");
}
static IIrpQueueVtbl vt_IIrpQueue = static IIrpQueueVtbl vt_IIrpQueue =
{ {
IIrpQueue_fnQueryInterface, IIrpQueue_fnQueryInterface,
@ -522,7 +484,8 @@ static IIrpQueueVtbl vt_IIrpQueue =
IIrpQueue_fnUpdateFormat, IIrpQueue_fnUpdateFormat,
IIrpQueue_fnGetMappingWithTag, IIrpQueue_fnGetMappingWithTag,
IIrpQueue_fnReleaseMappingWithTag, IIrpQueue_fnReleaseMappingWithTag,
IIrpQueue_fnHasLastMappingFailed IIrpQueue_fnHasLastMappingFailed,
IIrpQueue_fnPrintQueueStatus
}; };

View file

@ -207,6 +207,10 @@ IPortDMus_fnInit(
Miniport->lpVtbl->Release(Miniport); Miniport->lpVtbl->Release(Miniport);
return Status; return Status;
} }
/* increment reference on miniport adapter */
Miniport->lpVtbl->AddRef(Miniport);
} }
else else
{ {
@ -226,6 +230,9 @@ IPortDMus_fnInit(
MidiMiniport->lpVtbl->Release(MidiMiniport); MidiMiniport->lpVtbl->Release(MidiMiniport);
return Status; return Status;
} }
/* increment reference on miniport adapter */
MidiMiniport->lpVtbl->AddRef(MidiMiniport);
} }
/* create the subdevice descriptor */ /* create the subdevice descriptor */
@ -265,10 +272,6 @@ IPortDMus_fnInit(
This->pDeviceObject = DeviceObject; This->pDeviceObject = DeviceObject;
This->bInitialized = TRUE; This->bInitialized = TRUE;
/* increment reference on miniport adapter */
Miniport->lpVtbl->AddRef(Miniport);
/* check if it supports IPinCount interface */ /* check if it supports IPinCount interface */
Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IPinCount, (PVOID*)&PinCount); Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IPinCount, (PVOID*)&PinCount);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))

View file

@ -504,7 +504,6 @@ PcCreateItemDispatch(
PIO_STACK_LOCATION IoStack; PIO_STACK_LOCATION IoStack;
ISubdevice * SubDevice; ISubdevice * SubDevice;
PPCLASS_DEVICE_EXTENSION DeviceExt; PPCLASS_DEVICE_EXTENSION DeviceExt;
SUBDEVICE_ENTRY * Entry;
IIrpTarget *Filter; IIrpTarget *Filter;
PKSOBJECT_CREATE_ITEM CreateItem; PKSOBJECT_CREATE_ITEM CreateItem;
PPIN_WORKER_CONTEXT Context; PPIN_WORKER_CONTEXT Context;
@ -528,13 +527,6 @@ PcCreateItemDispatch(
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
Entry = AllocateItem(NonPagedPool, sizeof(SUBDEVICE_ENTRY), TAG_PORTCLASS);
if (!Entry)
{
DPRINT1("PcCreateItemDispatch no memory\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
#if KS_IMPLEMENTED #if KS_IMPLEMENTED
Status = KsReferenceSoftwareBusObject(DeviceExt->KsDeviceHeader); Status = KsReferenceSoftwareBusObject(DeviceExt->KsDeviceHeader);
if (!NT_SUCCESS(Status) && Status != STATUS_NOT_IMPLEMENTED) if (!NT_SUCCESS(Status) && Status != STATUS_NOT_IMPLEMENTED)