- Partial rewrite of CHEW

- Remove some unneeded work item usage
 - Remove an unused member of DISCONNECT_TYPE

svn path=/trunk/; revision=43076
This commit is contained in:
Cameron Gutman 2009-09-19 00:58:36 +00:00
parent 13ebb47cf4
commit 3db65819eb
6 changed files with 88 additions and 119 deletions

View file

@ -254,6 +254,8 @@ VOID LanReceiveWorker( PVOID Context ) {
Adapter = WorkItem->Adapter; Adapter = WorkItem->Adapter;
BytesTransferred = WorkItem->BytesTransferred; BytesTransferred = WorkItem->BytesTransferred;
exFreePool(WorkItem);
IPInitializePacket(&IPPacket, 0); IPInitializePacket(&IPPacket, 0);
IPPacket.NdisPacket = Packet; IPPacket.NdisPacket = Packet;
@ -303,18 +305,19 @@ VOID LanSubmitReceiveWork(
PNDIS_PACKET Packet, PNDIS_PACKET Packet,
NDIS_STATUS Status, NDIS_STATUS Status,
UINT BytesTransferred) { UINT BytesTransferred) {
LAN_WQ_ITEM WQItem; PLAN_WQ_ITEM WQItem = exAllocatePool(NonPagedPool, sizeof(LAN_WQ_ITEM));
PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext; PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext;
TI_DbgPrint(DEBUG_DATALINK,("called\n")); TI_DbgPrint(DEBUG_DATALINK,("called\n"));
WQItem.Packet = Packet; if (!WQItem) return;
WQItem.Adapter = Adapter;
WQItem.BytesTransferred = BytesTransferred;
if( !ChewCreate WQItem->Packet = Packet;
( NULL, sizeof(LAN_WQ_ITEM), LanReceiveWorker, &WQItem ) ) WQItem->Adapter = Adapter;
ASSERT(0); WQItem->BytesTransferred = BytesTransferred;
if (!ChewCreate( LanReceiveWorker, WQItem ))
exFreePool(WQItem);
} }
VOID NTAPI ProtocolTransferDataComplete( VOID NTAPI ProtocolTransferDataComplete(

View file

@ -11,7 +11,6 @@ typedef struct _DISCONNECT_TYPE {
UINT Type; UINT Type;
PVOID Context; PVOID Context;
PIRP Irp; PIRP Irp;
PFILE_OBJECT FileObject;
} DISCONNECT_TYPE, *PDISCONNECT_TYPE; } DISCONNECT_TYPE, *PDISCONNECT_TYPE;
NTSTATUS DispTdiAccept( NTSTATUS DispTdiAccept(

View file

@ -118,6 +118,8 @@ VOID DispDoDisconnect( PVOID Data ) {
TI_DbgPrint(DEBUG_IRP, ("PostCancel: DoDisconnect done\n")); TI_DbgPrint(DEBUG_IRP, ("PostCancel: DoDisconnect done\n"));
DispDataRequestComplete(DisType->Irp, STATUS_CANCELLED, 0); DispDataRequestComplete(DisType->Irp, STATUS_CANCELLED, 0);
exFreePool(DisType);
} }
VOID NTAPI DispCancelRequest( VOID NTAPI DispCancelRequest(
@ -134,9 +136,7 @@ VOID NTAPI DispCancelRequest(
PTRANSPORT_CONTEXT TranContext; PTRANSPORT_CONTEXT TranContext;
PFILE_OBJECT FileObject; PFILE_OBJECT FileObject;
UCHAR MinorFunction; UCHAR MinorFunction;
DISCONNECT_TYPE DisType; PDISCONNECT_TYPE DisType;
PVOID WorkItem;
/*NTSTATUS Status = STATUS_SUCCESS;*/
TI_DbgPrint(DEBUG_IRP, ("Called.\n")); TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
@ -159,19 +159,21 @@ VOID NTAPI DispCancelRequest(
switch(MinorFunction) { switch(MinorFunction) {
case TDI_SEND: case TDI_SEND:
case TDI_RECEIVE: case TDI_RECEIVE:
DisType.Type = TDI_DISCONNECT_RELEASE | DisType = exAllocatePool(NonPagedPool, sizeof(DISCONNECT_TYPE));
if (DisType)
{
DisType->Type = TDI_DISCONNECT_RELEASE |
((MinorFunction == TDI_RECEIVE) ? TDI_DISCONNECT_ABORT : 0); ((MinorFunction == TDI_RECEIVE) ? TDI_DISCONNECT_ABORT : 0);
DisType.Context = TranContext->Handle.ConnectionContext; DisType->Context = TranContext->Handle.ConnectionContext;
DisType.Irp = Irp; DisType->Irp = Irp;
DisType.FileObject = FileObject;
TCPRemoveIRP( TranContext->Handle.ConnectionContext, Irp ); TCPRemoveIRP( TranContext->Handle.ConnectionContext, Irp );
IoReleaseCancelSpinLock(Irp->CancelIrql); if (!ChewCreate(DispDoDisconnect, DisType))
exFreePool(DisType);
}
if( !ChewCreate( &WorkItem, sizeof(DISCONNECT_TYPE), IoReleaseCancelSpinLock(Irp->CancelIrql);
DispDoDisconnect, &DisType ) )
ASSERT(0);
return; return;
case TDI_SEND_DATAGRAM: case TDI_SEND_DATAGRAM:

View file

@ -16,25 +16,13 @@
*/ */
VOID ChewInit( PDEVICE_OBJECT DeviceObject ); VOID ChewInit( PDEVICE_OBJECT DeviceObject );
/** /**
* Shutdown CHEW, including removing remaining work items. * Shutdown CHEW, waits for remaining work items.
*/ */
VOID ChewShutdown(); VOID ChewShutdown();
/** /**
* Create a work item, or perform the work, based on IRQL. * Creates and queues a work item.
* At passive level, Worker is called directly on UserSpace.
* At greater than passive level, a work item is created with Bytes
* context area and data copied from UserSpace.
* If a work item is created, Item contains the address and the function
* returns true.
* If the work is performed immediately, Item contains NULL and the
* function returns true.
* Else, the function returns false and Item is undefined.
*/ */
BOOLEAN ChewCreate BOOLEAN ChewCreate
( PVOID *Item, SIZE_T Bytes, VOID (*Worker)(PVOID), PVOID UserSpace ); ( VOID (*Worker)(PVOID), PVOID WorkerContext );
/**
* Remove a work item, given the pointer returned to Item in ChewCreate.
*/
VOID ChewRemove( PVOID Item );
#endif/*_REACTOS_CHEW_H*/ #endif/*_REACTOS_CHEW_H*/

View file

@ -12,67 +12,56 @@
#define NDEBUG #define NDEBUG
#define FOURCC(w,x,y,z) (((w) << 24) | ((x) << 16) | ((y) << 8) | (z)) #define FOURCC(w,x,y,z) (((w) << 24) | ((x) << 16) | ((y) << 8) | (z))
#define CHEW_TAG FOURCC('C','H','E','W')
PDEVICE_OBJECT WorkQueueDevice; PDEVICE_OBJECT WorkQueueDevice;
LIST_ENTRY WorkQueue; LIST_ENTRY WorkQueue;
KSPIN_LOCK WorkQueueLock; KSPIN_LOCK WorkQueueLock;
KEVENT WorkQueueClear;
typedef struct _WORK_ITEM { typedef struct _WORK_ITEM {
LIST_ENTRY Entry; LIST_ENTRY Entry;
PIO_WORKITEM WorkItem; PIO_WORKITEM WorkItem;
VOID (*Worker)( PVOID Data ); VOID (*Worker)( PVOID WorkerContext );
CHAR UserSpace[1]; PVOID WorkerContext;
} WORK_ITEM, *PWORK_ITEM; } WORK_ITEM, *PWORK_ITEM;
VOID ChewInit( PDEVICE_OBJECT DeviceObject ) { VOID ChewInit( PDEVICE_OBJECT DeviceObject ) {
WorkQueueDevice = DeviceObject; WorkQueueDevice = DeviceObject;
InitializeListHead( &WorkQueue ); InitializeListHead( &WorkQueue );
KeInitializeSpinLock( &WorkQueueLock ); KeInitializeSpinLock( &WorkQueueLock );
KeInitializeEvent(&WorkQueueClear, NotificationEvent, TRUE);
} }
VOID ChewShutdown() { VOID ChewShutdown() {
KIRQL OldIrql; KeWaitForSingleObject(&WorkQueueClear, Executive, KernelMode, FALSE, NULL);
PLIST_ENTRY Entry;
PWORK_ITEM WorkItem;
KeAcquireSpinLock( &WorkQueueLock, &OldIrql );
while( !IsListEmpty( &WorkQueue ) ) {
Entry = RemoveHeadList( &WorkQueue );
WorkItem = CONTAINING_RECORD( Entry, WORK_ITEM, Entry );
IoFreeWorkItem( WorkItem->WorkItem );
ExFreePool( WorkItem );
}
KeReleaseSpinLock( &WorkQueueLock, OldIrql );
} }
VOID NTAPI ChewWorkItem( PDEVICE_OBJECT DeviceObject, PVOID ChewItem ) { VOID NTAPI ChewWorkItem( PDEVICE_OBJECT DeviceObject, PVOID ChewItem ) {
PWORK_ITEM WorkItem = ChewItem; PWORK_ITEM WorkItem = ChewItem;
KIRQL OldIrql;
RemoveEntryList( &WorkItem->Entry ); WorkItem->Worker( WorkItem->WorkerContext );
if( WorkItem->Worker )
WorkItem->Worker( WorkItem->UserSpace );
IoFreeWorkItem( WorkItem->WorkItem ); IoFreeWorkItem( WorkItem->WorkItem );
ExFreePool( WorkItem );
KeAcquireSpinLock(&WorkQueueLock, &OldIrql);
RemoveEntryList(&WorkItem->Entry);
if (IsListEmpty(&WorkQueue))
KeSetEvent(&WorkQueueClear, 0, FALSE);
KeReleaseSpinLock(&WorkQueueLock, OldIrql);
ExFreePoolWithTag(WorkItem, CHEW_TAG);
} }
BOOLEAN ChewCreate BOOLEAN ChewCreate
( PVOID *ItemPtr, SIZE_T Bytes, VOID (*Worker)( PVOID ), PVOID UserSpace ) { ( VOID (*Worker)( PVOID ), PVOID WorkerContext ) {
PWORK_ITEM Item; PWORK_ITEM Item;
if( KeGetCurrentIrql() == PASSIVE_LEVEL ) {
if( ItemPtr )
*ItemPtr = NULL;
Worker(UserSpace);
return TRUE;
} else {
Item = ExAllocatePoolWithTag Item = ExAllocatePoolWithTag
( NonPagedPool, ( NonPagedPool,
sizeof( WORK_ITEM ) + Bytes - 1, sizeof( WORK_ITEM ),
FOURCC('C','H','E','W') ); CHEW_TAG );
if( Item ) { if( Item ) {
Item->WorkItem = IoAllocateWorkItem( WorkQueueDevice ); Item->WorkItem = IoAllocateWorkItem( WorkQueueDevice );
@ -81,27 +70,13 @@ BOOLEAN ChewCreate
return FALSE; return FALSE;
} }
Item->Worker = Worker; Item->Worker = Worker;
if( Bytes && UserSpace ) Item->WorkerContext = WorkerContext;
RtlCopyMemory( Item->UserSpace, UserSpace, Bytes ); ExInterlockedInsertTailList( &WorkQueue, &Item->Entry, &WorkQueueLock );
KeResetEvent(&WorkQueueClear);
ExInterlockedInsertTailList IoQueueWorkItem( Item->WorkItem, ChewWorkItem, DelayedWorkQueue, Item );
( &WorkQueue, &Item->Entry, &WorkQueueLock );
IoQueueWorkItem
( Item->WorkItem, ChewWorkItem, DelayedWorkQueue, Item );
if( ItemPtr )
*ItemPtr = Item;
return TRUE; return TRUE;
} else { } else {
return FALSE; return FALSE;
} }
}
}
VOID ChewRemove( PVOID Item ) {
PWORK_ITEM WorkItem = Item;
RemoveEntryList( &WorkItem->Entry );
IoFreeWorkItem( WorkItem->WorkItem );
ExFreePool( WorkItem );
} }

View file

@ -41,39 +41,41 @@ static VOID HandleSignalledConnection( PCONNECTION_ENDPOINT Connection ) {
while ((Entry = ExInterlockedRemoveHeadList( &Connection->ReceiveRequest, while ((Entry = ExInterlockedRemoveHeadList( &Connection->ReceiveRequest,
&Connection->Lock )) != NULL) &Connection->Lock )) != NULL)
{ {
DISCONNECT_TYPE DisType;
PIO_STACK_LOCATION IrpSp;
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry ); Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject; Complete = Bucket->Request.RequestNotifyObject;
IrpSp = IoGetCurrentIrpStackLocation((PIRP)Bucket->Request.RequestContext);
/* We have to notify oskittcp of the abortion */ /* We have to notify oskittcp of the abortion */
DisType.Type = TDI_DISCONNECT_RELEASE | TDI_DISCONNECT_ABORT; TCPDisconnect
DisType.Context = Connection; ( Connection,
DisType.Irp = (PIRP)Bucket->Request.RequestContext; TDI_DISCONNECT_RELEASE | TDI_DISCONNECT_ABORT,
DisType.FileObject = IrpSp->FileObject; NULL,
NULL,
Bucket->Request.RequestNotifyObject,
(PIRP)Bucket->Request.RequestContext );
ChewCreate(NULL, sizeof(DISCONNECT_TYPE), Complete( Bucket->Request.RequestContext, STATUS_CANCELLED, 0 );
DispDoDisconnect, &DisType);
exFreePool(Bucket);
} }
while ((Entry = ExInterlockedRemoveHeadList( &Connection->SendRequest, while ((Entry = ExInterlockedRemoveHeadList( &Connection->SendRequest,
&Connection->Lock )) != NULL) &Connection->Lock )) != NULL)
{ {
DISCONNECT_TYPE DisType;
PIO_STACK_LOCATION IrpSp;
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry ); Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject; Complete = Bucket->Request.RequestNotifyObject;
IrpSp = IoGetCurrentIrpStackLocation((PIRP)Bucket->Request.RequestContext);
/* We have to notify oskittcp of the abortion */ /* We have to notify oskittcp of the abortion */
DisType.Type = TDI_DISCONNECT_RELEASE; TCPDisconnect
DisType.Context = Connection; ( Connection,
DisType.Irp = (PIRP)Bucket->Request.RequestContext; TDI_DISCONNECT_RELEASE,
DisType.FileObject = IrpSp->FileObject; NULL,
NULL,
Bucket->Request.RequestNotifyObject,
(PIRP)Bucket->Request.RequestContext );
ChewCreate(NULL, sizeof(DISCONNECT_TYPE), Complete( Bucket->Request.RequestContext, STATUS_CANCELLED, 0 );
DispDoDisconnect, &DisType);
exFreePool(Bucket);
} }
while ((Entry = ExInterlockedRemoveHeadList( &Connection->ListenRequest, while ((Entry = ExInterlockedRemoveHeadList( &Connection->ListenRequest,