https://git.reactos.org/?p=reactos.git;a=commitdiff;h=27fcfe66a2a7a8beb4b29e...
commit 27fcfe66a2a7a8beb4b29eee18bb251a3a9aae22 Author: Jérôme Gardou jerome.gardou@reactos.org AuthorDate: Fri May 21 09:36:27 2021 +0200 Commit: Jérôme Gardou zefklop@users.noreply.github.com CommitDate: Mon Jun 21 11:42:01 2021 +0200
[TCPIP][IP] Use an ERESOURCE as mutex for address files & connection end points
Spinlocks are not reentrant (and this is done a lot), using them forces us to have an horrible hack in the kernel, which unschedules threads which are at DISPATCH_LEVEL thus allowing another thread to take ownership of the spinlock while the unscheduled thread should already hold it.
CORE-6473 --- drivers/network/tcpip/include/tcp.h | 6 +- drivers/network/tcpip/include/titypes.h | 52 ++---- drivers/network/tcpip/tcpip/ainfo.c | 18 +-- drivers/network/tcpip/tcpip/dispatch.c | 33 ++-- drivers/network/tcpip/tcpip/fileobjs.c | 32 ++-- drivers/network/tcpip/tcpip/icmp.c | 15 +- sdk/lib/drivers/ip/transport/datagram/datagram.c | 27 ++-- sdk/lib/drivers/ip/transport/rawip/rawip.c | 11 +- sdk/lib/drivers/ip/transport/tcp/accept.c | 15 +- sdk/lib/drivers/ip/transport/tcp/event.c | 194 ++++++++-------------- sdk/lib/drivers/ip/transport/tcp/tcp.c | 197 ++++++++++++++--------- sdk/lib/drivers/ip/transport/udp/udp.c | 11 +- sdk/lib/drivers/lwip/src/include/rosip.h | 4 + sdk/lib/drivers/lwip/src/rostcp.c | 40 ++++- 14 files changed, 319 insertions(+), 336 deletions(-)
diff --git a/drivers/network/tcpip/include/tcp.h b/drivers/network/tcpip/include/tcp.h index 6bb8280d5a1..65a5d11b355 100644 --- a/drivers/network/tcpip/include/tcp.h +++ b/drivers/network/tcpip/include/tcp.h @@ -201,13 +201,13 @@ VOID FlushConnectQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status);
VOID -FlushReceiveQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked); +FlushReceiveQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status);
VOID -FlushSendQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked); +FlushSendQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status);
VOID -FlushShutdownQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked); +FlushShutdownQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status);
VOID FlushAllQueues(PCONNECTION_ENDPOINT Connection, NTSTATUS Status); diff --git a/drivers/network/tcpip/include/titypes.h b/drivers/network/tcpip/include/titypes.h index 14541a24a65..0290c2dd54d 100644 --- a/drivers/network/tcpip/include/titypes.h +++ b/drivers/network/tcpip/include/titypes.h @@ -29,44 +29,26 @@ }
/* - * VOID LockObject(PVOID Object, PKIRQL OldIrql) + * VOID LockObject(PVOID Object) */ -#define LockObject(Object, Irql) \ -{ \ - ReferenceObject(Object); \ - KeAcquireSpinLock(&((Object)->Lock), Irql); \ - memcpy(&(Object)->OldIrql, Irql, sizeof(KIRQL)); \ -} - -/* - * VOID LockObjectAtDpcLevel(PVOID Object) - */ -#define LockObjectAtDpcLevel(Object) \ -{ \ - ReferenceObject(Object); \ - KeAcquireSpinLockAtDpcLevel(&((Object)->Lock)); \ - (Object)->OldIrql = DISPATCH_LEVEL; \ -} - -/* - * VOID UnlockObject(PVOID Object, KIRQL OldIrql) - */ -#define UnlockObject(Object, OldIrql) \ -{ \ - KeReleaseSpinLock(&((Object)->Lock), OldIrql); \ - DereferenceObject(Object); \ -} +#define LockObject(Object) do \ +{ \ + ReferenceObject(Object); \ + KeEnterCriticalRegion(); \ + ExAcquireResourceExclusiveLite(&(Object)->Resource, TRUE); \ +} while(0)
/* - * VOID UnlockObjectFromDpcLevel(PVOID Object) + * VOID UnlockObject(PVOID Object) */ -#define UnlockObjectFromDpcLevel(Object) \ +#define UnlockObject(Object) do \ { \ - KeReleaseSpinLockFromDpcLevel(&((Object)->Lock)); \ + ExReleaseResourceLite(&(Object)->Resource); \ + KeLeaveCriticalRegion(); \ DereferenceObject(Object); \ -} - +} while(0)
+#define ASSERT_TCPIP_OBJECT_LOCKED(Object) ASSERT(ExIsResourceAcquiredExclusiveLite(&(Object)->Resource))
#include <ip.h>
@@ -131,8 +113,7 @@ typedef struct _ADDRESS_FILE { LIST_ENTRY ListEntry; /* Entry on list */ LONG RefCount; /* Reference count */ OBJECT_FREE_ROUTINE Free; /* Routine to use to free resources for the object */ - KSPIN_LOCK Lock; /* Spin lock to manipulate this structure */ - KIRQL OldIrql; /* Currently not used */ + ERESOURCE Resource; /* Resource to manipulate this structure */ IP_ADDRESS Address; /* Address of this address file */ USHORT Family; /* Address family */ USHORT Protocol; /* Protocol number */ @@ -142,7 +123,6 @@ typedef struct _ADDRESS_FILE { UINT DF; /* Don't fragment */ UINT BCast; /* Receive broadcast packets */ UINT HeaderIncl; /* Include header in RawIP packets */ - WORK_QUEUE_ITEM WorkItem; /* Work queue item handle */ DATAGRAM_COMPLETION_ROUTINE Complete; /* Completion routine for delete request */ PVOID Context; /* Delete request context */ DATAGRAM_SEND_ROUTINE Send; /* Routine to send a datagram */ @@ -262,8 +242,7 @@ typedef struct _CONNECTION_ENDPOINT { LIST_ENTRY ListEntry; /* Entry on list */ LONG RefCount; /* Reference count */ OBJECT_FREE_ROUTINE Free; /* Routine to use to free resources for the object */ - KSPIN_LOCK Lock; /* Spin lock to protect this structure */ - KIRQL OldIrql; /* The old irql is stored here for use in HandleSignalledConnection */ + ERESOURCE Resource; /* The lock protecting this structure */ PVOID ClientContext; /* Pointer to client context information */ PADDRESS_FILE AddressFile; /* Associated address file object (NULL if none) */
@@ -279,6 +258,7 @@ typedef struct _CONNECTION_ENDPOINT { /* Disconnect Timer */ KTIMER DisconnectTimer; KDPC DisconnectDpc; + PIO_WORKITEM DisconnectWorkItem;
/* Socket state */ BOOLEAN SendShutdown; diff --git a/drivers/network/tcpip/tcpip/ainfo.c b/drivers/network/tcpip/tcpip/ainfo.c index bba0affc1bc..1553149dc1e 100644 --- a/drivers/network/tcpip/tcpip/ainfo.c +++ b/drivers/network/tcpip/tcpip/ainfo.c @@ -13,17 +13,15 @@ TDI_STATUS SetAddressFileInfo(TDIObjectID *ID, PVOID Buffer, UINT BufferSize) { - KIRQL OldIrql; - switch (ID->toi_id) { case AO_OPTION_TTL: if (BufferSize < sizeof(UINT)) return TDI_INVALID_PARAMETER;
- LockObject(AddrFile, &OldIrql); + LockObject(AddrFile); AddrFile->TTL = *((PUCHAR)Buffer); - UnlockObject(AddrFile, OldIrql); + UnlockObject(AddrFile);
return TDI_SUCCESS;
@@ -31,9 +29,9 @@ TDI_STATUS SetAddressFileInfo(TDIObjectID *ID, if (BufferSize < sizeof(UINT)) return TDI_INVALID_PARAMETER;
- LockObject(AddrFile, &OldIrql); + LockObject(AddrFile); AddrFile->DF = *((PUINT)Buffer); - UnlockObject(AddrFile, OldIrql); + UnlockObject(AddrFile);
return TDI_SUCCESS;
@@ -41,9 +39,9 @@ TDI_STATUS SetAddressFileInfo(TDIObjectID *ID, if (BufferSize < sizeof(UINT)) return TDI_INVALID_PARAMETER;
- LockObject(AddrFile, &OldIrql); + LockObject(AddrFile); AddrFile->BCast = *((PUINT)Buffer); - UnlockObject(AddrFile, OldIrql); + UnlockObject(AddrFile);
return TDI_SUCCESS;
@@ -51,9 +49,9 @@ TDI_STATUS SetAddressFileInfo(TDIObjectID *ID, if (BufferSize < sizeof(UINT)) return TDI_INVALID_PARAMETER;
- LockObject(AddrFile, &OldIrql); + LockObject(AddrFile); AddrFile->HeaderIncl = *((PUINT)Buffer); - UnlockObject(AddrFile, OldIrql); + UnlockObject(AddrFile);
return TDI_SUCCESS;
diff --git a/drivers/network/tcpip/tcpip/dispatch.c b/drivers/network/tcpip/tcpip/dispatch.c index da2a00ba5bd..375c0bc5fd5 100644 --- a/drivers/network/tcpip/tcpip/dispatch.c +++ b/drivers/network/tcpip/tcpip/dispatch.c @@ -284,7 +284,6 @@ NTSTATUS DispTdiAssociateAddress( PFILE_OBJECT FileObject; PADDRESS_FILE AddrFile = NULL; NTSTATUS Status; - KIRQL OldIrql;
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
@@ -319,18 +318,18 @@ NTSTATUS DispTdiAssociateAddress( return STATUS_INVALID_PARAMETER; }
- LockObject(Connection, &OldIrql); + LockObject(Connection);
if (Connection->AddressFile) { ObDereferenceObject(FileObject); - UnlockObject(Connection, OldIrql); + UnlockObject(Connection); TI_DbgPrint(MID_TRACE, ("An address file is already associated.\n")); return STATUS_INVALID_PARAMETER; }
if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) { ObDereferenceObject(FileObject); - UnlockObject(Connection, OldIrql); + UnlockObject(Connection); TI_DbgPrint(MID_TRACE, ("Bad address file object. Magic (0x%X).\n", FileObject->FsContext2)); return STATUS_INVALID_PARAMETER; @@ -341,20 +340,20 @@ NTSTATUS DispTdiAssociateAddress( TranContext = FileObject->FsContext; if (!TranContext) { ObDereferenceObject(FileObject); - UnlockObject(Connection, OldIrql); + UnlockObject(Connection); TI_DbgPrint(MID_TRACE, ("Bad transport context.\n")); return STATUS_INVALID_PARAMETER; }
AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle; if (!AddrFile) { - UnlockObject(Connection, OldIrql); + UnlockObject(Connection); ObDereferenceObject(FileObject); TI_DbgPrint(MID_TRACE, ("No address file object.\n")); return STATUS_INVALID_PARAMETER; }
- LockObjectAtDpcLevel(AddrFile); + LockObject(AddrFile);
ReferenceObject(AddrFile); Connection->AddressFile = AddrFile; @@ -373,8 +372,8 @@ NTSTATUS DispTdiAssociateAddress(
ObDereferenceObject(FileObject);
- UnlockObjectFromDpcLevel(AddrFile); - UnlockObject(Connection, OldIrql); + UnlockObject(AddrFile); + UnlockObject(Connection);
return STATUS_SUCCESS; } @@ -563,7 +562,6 @@ NTSTATUS DispTdiListen( PTRANSPORT_CONTEXT TranContext; PIO_STACK_LOCATION IrpSp; NTSTATUS Status = STATUS_SUCCESS; - KIRQL OldIrql;
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
@@ -596,17 +594,17 @@ NTSTATUS DispTdiListen( Irp, (PDRIVER_CANCEL)DispCancelListenRequest);
- LockObject(Connection, &OldIrql); + LockObject(Connection);
if (Connection->AddressFile == NULL) { TI_DbgPrint(MID_TRACE, ("No associated address file\n")); - UnlockObject(Connection, OldIrql); + UnlockObject(Connection); Status = STATUS_INVALID_PARAMETER; goto done; }
- LockObjectAtDpcLevel(Connection->AddressFile); + LockObject(Connection->AddressFile);
/* Listening will require us to create a listening socket and store it in * the address file. It will be signalled, and attempt to complete an irp @@ -647,8 +645,8 @@ NTSTATUS DispTdiListen( Irp ); }
- UnlockObjectFromDpcLevel(Connection->AddressFile); - UnlockObject(Connection, OldIrql); + UnlockObject(Connection->AddressFile); + UnlockObject(Connection);
done: if (Status != STATUS_PENDING) { @@ -1116,7 +1114,6 @@ NTSTATUS DispTdiSetEventHandler(PIRP Irp) PIO_STACK_LOCATION IrpSp; PADDRESS_FILE AddrFile; NTSTATUS Status; - KIRQL OldIrql;
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
@@ -1139,7 +1136,7 @@ NTSTATUS DispTdiSetEventHandler(PIRP Irp) Parameters = (PTDI_REQUEST_KERNEL_SET_EVENT)&IrpSp->Parameters; Status = STATUS_SUCCESS;
- LockObject(AddrFile, &OldIrql); + LockObject(AddrFile);
/* Set the event handler. if an event handler is associated with a specific event, it's flag (RegisteredXxxHandler) is TRUE. @@ -1260,7 +1257,7 @@ NTSTATUS DispTdiSetEventHandler(PIRP Irp) Status = STATUS_INVALID_PARAMETER; }
- UnlockObject(AddrFile, OldIrql); + UnlockObject(AddrFile);
return Status; } diff --git a/drivers/network/tcpip/tcpip/fileobjs.c b/drivers/network/tcpip/tcpip/fileobjs.c index 6854acc7da7..d926abed97e 100644 --- a/drivers/network/tcpip/tcpip/fileobjs.c +++ b/drivers/network/tcpip/tcpip/fileobjs.c @@ -310,7 +310,7 @@ VOID AddrFileFree( PADDRESS_FILE AddrFile = Object; KIRQL OldIrql; PDATAGRAM_RECEIVE_REQUEST ReceiveRequest; - PDATAGRAM_SEND_REQUEST SendRequest; + // PDATAGRAM_SEND_REQUEST SendRequest; See WTF below PLIST_ENTRY CurrentEntry;
TI_DbgPrint(MID_TRACE, ("Called.\n")); @@ -330,20 +330,26 @@ VOID AddrFileFree( TI_DbgPrint(DEBUG_ADDRFILE, ("Aborting receive requests on AddrFile at (0x%X).\n", AddrFile));
/* Go through pending receive request list and cancel them all */ - while ((CurrentEntry = ExInterlockedRemoveHeadList(&AddrFile->ReceiveQueue, &AddrFile->Lock))) { + while (!IsListEmpty(&AddrFile->ReceiveQueue)) + { + CurrentEntry = RemoveHeadList(&AddrFile->ReceiveQueue); ReceiveRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_RECEIVE_REQUEST, ListEntry); (*ReceiveRequest->Complete)(ReceiveRequest->Context, STATUS_CANCELLED, 0); - /* ExFreePoolWithTag(ReceiveRequest, DATAGRAM_RECV_TAG); FIXME: WTF? */ + ExFreePoolWithTag(ReceiveRequest, DATAGRAM_RECV_TAG); }
TI_DbgPrint(DEBUG_ADDRFILE, ("Aborting send requests on address file at (0x%X).\n", AddrFile));
+#if 0 /* Biggest WTF. All of this was taken care of above as DATAGRAM_RECEIVE_REQUEST. */ /* Go through pending send request list and cancel them all */ - while ((CurrentEntry = ExInterlockedRemoveHeadList(&AddrFile->ReceiveQueue, &AddrFile->Lock))) { + while (!IsListEmpty(&AddrFile->ReceiveQueue)) + { + CurrentEntry = RemoveHeadList(&AddrFile->ReceiveQueue); SendRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_SEND_REQUEST, ListEntry); (*SendRequest->Complete)(SendRequest->Context, STATUS_CANCELLED, 0); ExFreePoolWithTag(SendRequest, DATAGRAM_SEND_TAG); } +#endif
/* Protocol specific handling */ switch (AddrFile->Protocol) { @@ -361,6 +367,8 @@ VOID AddrFileFree(
RemoveEntityByContext(AddrFile);
+ ExDeleteResourceLite(&AddrFile->Resource); + ExFreePoolWithTag(Object, ADDR_FILE_TAG); }
@@ -553,7 +561,7 @@ NTSTATUS FileOpenAddress( InitializeListHead(&AddrFile->TransmitQueue);
/* Initialize spin lock that protects the address file object */ - KeInitializeSpinLock(&AddrFile->Lock); + ExInitializeResourceLite(&AddrFile->Resource);
/* Return address file object */ Request->Handle.AddressHandle = AddrFile; @@ -581,27 +589,27 @@ NTSTATUS FileCloseAddress( PTDI_REQUEST Request) { PADDRESS_FILE AddrFile = Request->Handle.AddressHandle; - KIRQL OldIrql; + PCONNECTION_ENDPOINT Listener;
if (!Request->Handle.AddressHandle) return STATUS_INVALID_PARAMETER;
- LockObject(AddrFile, &OldIrql); + LockObject(AddrFile);
if (InterlockedDecrement(&AddrFile->Sharers) != 0) { /* Still other guys have open handles to this, so keep it around */ - UnlockObject(AddrFile, OldIrql); + UnlockObject(AddrFile); return STATUS_SUCCESS; }
/* We have to close this listener because we started it */ - if( AddrFile->Listener ) + Listener = AddrFile->Listener; + UnlockObject(AddrFile); + if( Listener ) { - TCPClose( AddrFile->Listener ); + TCPClose( Listener ); }
- UnlockObject(AddrFile, OldIrql); - DereferenceObject(AddrFile);
TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); diff --git a/drivers/network/tcpip/tcpip/icmp.c b/drivers/network/tcpip/tcpip/icmp.c index 7603e2551a5..67d77c14693 100644 --- a/drivers/network/tcpip/tcpip/icmp.c +++ b/drivers/network/tcpip/tcpip/icmp.c @@ -74,11 +74,9 @@ VOID ClearReceiveHandler( _In_ PADDRESS_FILE AddrFile) { - KIRQL OldIrql; - - LockObject(AddrFile, &OldIrql); + LockObject(AddrFile); AddrFile->RegisteredReceiveDatagramHandler = FALSE; - UnlockObject(AddrFile, OldIrql); + UnlockObject(AddrFile); }
IO_WORKITEM_ROUTINE EndRequestHandler; @@ -95,6 +93,8 @@ EndRequestHandler( UINT32 nReplies; KIRQL OldIrql;
+ ClearReceiveHandler((PADDRESS_FILE)Context->TdiRequest.Handle.AddressHandle); + KeWaitForSingleObject(&Context->DatagramProcessedEvent, Executive, KernelMode, FALSE, NULL);
TI_DbgPrint(DEBUG_ICMP, ("Finishing request Context: %p\n", Context)); @@ -267,8 +267,6 @@ TimeoutHandler( _In_opt_ PVOID SystemArgument2) { PICMP_PACKET_CONTEXT Context = (PICMP_PACKET_CONTEXT)_Context; - PADDRESS_FILE AddrFile = (PADDRESS_FILE)Context->TdiRequest.Handle.AddressHandle; - ClearReceiveHandler(AddrFile);
IoQueueWorkItem(Context->FinishWorker, &EndRequestHandler, DelayedWorkQueue, _Context); } @@ -290,7 +288,6 @@ DispEchoRequest( PUCHAR Buffer; UINT16 RequestSize; PICMP_PACKET_CONTEXT SendContext; - KIRQL OldIrql; LARGE_INTEGER RequestTimeout; UINT8 SavedTtl;
@@ -390,14 +387,14 @@ DispEchoRequest(
RtlZeroMemory(Irp->AssociatedIrp.SystemBuffer, OutputBufferLength);
- LockObject(AddrFile, &OldIrql); + LockObject(AddrFile);
AddrFile->TTL = SavedTtl; AddrFile->ReceiveDatagramHandlerContext = SendContext; AddrFile->ReceiveDatagramHandler = ReceiveDatagram; AddrFile->RegisteredReceiveDatagramHandler = TRUE;
- UnlockObject(AddrFile, OldIrql); + UnlockObject(AddrFile);
Status = AddrFile->Send(AddrFile, &ConnectionInfo, (PCHAR)Buffer, RequestSize, &DataUsed);
diff --git a/sdk/lib/drivers/ip/transport/datagram/datagram.c b/sdk/lib/drivers/ip/transport/datagram/datagram.c index 053a3020894..2840dc950a7 100644 --- a/sdk/lib/drivers/ip/transport/datagram/datagram.c +++ b/sdk/lib/drivers/ip/transport/datagram/datagram.c @@ -16,13 +16,12 @@ BOOLEAN DGRemoveIRP( { PLIST_ENTRY ListEntry; PDATAGRAM_RECEIVE_REQUEST ReceiveRequest; - KIRQL OldIrql; BOOLEAN Found = FALSE;
TI_DbgPrint(MAX_TRACE, ("Called (Cancel IRP %08x for file %08x).\n", Irp, AddrFile));
- LockObject(AddrFile, &OldIrql); + LockObject(AddrFile);
for( ListEntry = AddrFile->ReceiveQueue.Flink; ListEntry != &AddrFile->ReceiveQueue; @@ -42,7 +41,7 @@ BOOLEAN DGRemoveIRP( } }
- UnlockObject(AddrFile, OldIrql); + UnlockObject(AddrFile);
TI_DbgPrint(MAX_TRACE, ("Done.\n"));
@@ -73,7 +72,6 @@ DGDeliverData( * handler if it exists, otherwise we drop the packet. */ { - KIRQL OldIrql; LONG AddressLength; PVOID SourceAddress; ULONG BytesTaken; @@ -82,7 +80,7 @@ DGDeliverData(
TI_DbgPrint(MIN_TRACE, ("Called.\n"));
- LockObject(AddrFile, &OldIrql); + LockObject(AddrFile);
if (AddrFile->Protocol == IPPROTO_UDP) { @@ -145,7 +143,7 @@ DGDeliverData( SrcAddress->Address.IPv4Address, SrcPort));
ReferenceObject(AddrFile); - UnlockObject(AddrFile, OldIrql); + UnlockObject(AddrFile);
/* Complete the receive request */ if (Current->BufferSize < DataSize) @@ -153,12 +151,12 @@ DGDeliverData( else Current->Complete(Current->Context, STATUS_SUCCESS, DataSize);
- LockObject(AddrFile, &OldIrql); + LockObject(AddrFile); DereferenceObject(AddrFile); } }
- UnlockObject(AddrFile, OldIrql); + UnlockObject(AddrFile); } else if (AddrFile->RegisteredReceiveDatagramHandler) { @@ -186,7 +184,7 @@ DGDeliverData( }
ReferenceObject(AddrFile); - UnlockObject(AddrFile, OldIrql); + UnlockObject(AddrFile);
TI_DbgPrint(MIN_TRACE, ("OptionsSize %d DataSize: %u\n", OptionsSize, DataSize));
@@ -209,7 +207,7 @@ DGDeliverData( } else { - UnlockObject(AddrFile, OldIrql); + UnlockObject(AddrFile); TI_DbgPrint(MAX_TRACE, ("Discarding datagram.\n")); }
@@ -254,11 +252,10 @@ NTSTATUS DGReceiveDatagram( { NTSTATUS Status; PDATAGRAM_RECEIVE_REQUEST ReceiveRequest; - KIRQL OldIrql;
TI_DbgPrint(MAX_TRACE, ("Called.\n"));
- LockObject(AddrFile, &OldIrql); + LockObject(AddrFile);
ReceiveRequest = ExAllocatePoolWithTag(NonPagedPool, sizeof(DATAGRAM_RECEIVE_REQUEST), DATAGRAM_RECV_TAG); @@ -276,7 +273,7 @@ NTSTATUS DGReceiveDatagram( if (!NT_SUCCESS(Status)) { ExFreePoolWithTag(ReceiveRequest, DATAGRAM_RECV_TAG); - UnlockObject(AddrFile, OldIrql); + UnlockObject(AddrFile); return Status; } } @@ -304,13 +301,13 @@ NTSTATUS DGReceiveDatagram(
TI_DbgPrint(MAX_TRACE, ("Leaving (pending %08x).\n", ReceiveRequest));
- UnlockObject(AddrFile, OldIrql); + UnlockObject(AddrFile);
return STATUS_PENDING; } else { - UnlockObject(AddrFile, OldIrql); + UnlockObject(AddrFile); Status = STATUS_INSUFFICIENT_RESOURCES; }
diff --git a/sdk/lib/drivers/ip/transport/rawip/rawip.c b/sdk/lib/drivers/ip/transport/rawip/rawip.c index 7e7fb22436a..cb32d4b02e3 100644 --- a/sdk/lib/drivers/ip/transport/rawip/rawip.c +++ b/sdk/lib/drivers/ip/transport/rawip/rawip.c @@ -191,9 +191,8 @@ NTSTATUS RawIPSendDatagram( USHORT RemotePort; NTSTATUS Status; PNEIGHBOR_CACHE_ENTRY NCE; - KIRQL OldIrql;
- LockObject(AddrFile, &OldIrql); + LockObject(AddrFile);
TI_DbgPrint(MID_TRACE,("Sending Datagram(%x %x %x %d)\n", AddrFile, ConnInfo, BufferData, DataSize)); @@ -208,7 +207,7 @@ NTSTATUS RawIPSendDatagram( break;
default: - UnlockObject(AddrFile, OldIrql); + UnlockObject(AddrFile); return STATUS_UNSUCCESSFUL; }
@@ -222,7 +221,7 @@ NTSTATUS RawIPSendDatagram( * interface we're sending over */ if(!(NCE = RouteGetRouteToDestination( &RemoteAddress ))) { - UnlockObject(AddrFile, OldIrql); + UnlockObject(AddrFile); return STATUS_NETWORK_UNREACHABLE; }
@@ -231,7 +230,7 @@ NTSTATUS RawIPSendDatagram( else { if(!(NCE = NBLocateNeighbor( &LocalAddress, NULL ))) { - UnlockObject(AddrFile, OldIrql); + UnlockObject(AddrFile); return STATUS_INVALID_PARAMETER; } } @@ -245,7 +244,7 @@ NTSTATUS RawIPSendDatagram( BufferData, DataSize );
- UnlockObject(AddrFile, OldIrql); + UnlockObject(AddrFile);
if( !NT_SUCCESS(Status) ) return Status; diff --git a/sdk/lib/drivers/ip/transport/tcp/accept.c b/sdk/lib/drivers/ip/transport/tcp/accept.c index aab177a94ad..19b6d4644ca 100644 --- a/sdk/lib/drivers/ip/transport/tcp/accept.c +++ b/sdk/lib/drivers/ip/transport/tcp/accept.c @@ -48,12 +48,11 @@ NTSTATUS TCPListen(PCONNECTION_ENDPOINT Connection, UINT Backlog) { NTSTATUS Status = STATUS_SUCCESS; struct ip_addr AddressToBind; - KIRQL OldIrql; TA_IP_ADDRESS LocalAddress;
ASSERT(Connection);
- LockObject(Connection, &OldIrql); + LockObject(Connection);
ASSERT_KM_POINTER(Connection->AddressFile);
@@ -93,7 +92,7 @@ NTSTATUS TCPListen(PCONNECTION_ENDPOINT Connection, UINT Backlog) Status = STATUS_UNSUCCESSFUL; }
- UnlockObject(Connection, OldIrql); + UnlockObject(Connection);
TI_DbgPrint(DEBUG_TCP,("[IP, TCPListen] Leaving. Status = %x\n", Status));
@@ -106,10 +105,9 @@ BOOLEAN TCPAbortListenForSocket { PLIST_ENTRY ListEntry; PTDI_BUCKET Bucket; - KIRQL OldIrql; BOOLEAN Found = FALSE;
- LockObject(Listener, &OldIrql); + LockObject(Listener);
ListEntry = Listener->ListenRequest.Flink; while (ListEntry != &Listener->ListenRequest) @@ -128,7 +126,7 @@ BOOLEAN TCPAbortListenForSocket ListEntry = ListEntry->Flink; }
- UnlockObject(Listener, OldIrql); + UnlockObject(Listener);
return Found; } @@ -141,9 +139,8 @@ NTSTATUS TCPAccept ( PTDI_REQUEST Request, { NTSTATUS Status; PTDI_BUCKET Bucket; - KIRQL OldIrql;
- LockObject(Listener, &OldIrql); + LockObject(Listener);
Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList);
@@ -160,7 +157,7 @@ NTSTATUS TCPAccept ( PTDI_REQUEST Request, else Status = STATUS_NO_MEMORY;
- UnlockObject(Listener, OldIrql); + UnlockObject(Listener);
return Status; } diff --git a/sdk/lib/drivers/ip/transport/tcp/event.c b/sdk/lib/drivers/ip/transport/tcp/event.c index 02613c2af17..9294815d3d1 100644 --- a/sdk/lib/drivers/ip/transport/tcp/event.c +++ b/sdk/lib/drivers/ip/transport/tcp/event.c @@ -50,125 +50,66 @@ CompleteBucket(PCONNECTION_ENDPOINT Connection, PTDI_BUCKET Bucket, const BOOLEA }
VOID -FlushReceiveQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked) +FlushReceiveQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status) { PTDI_BUCKET Bucket; PLIST_ENTRY Entry;
- ReferenceObject(Connection); + ASSERT_TCPIP_OBJECT_LOCKED(Connection);
- if (interlocked) + while (!IsListEmpty(&Connection->ReceiveRequest)) { - while ((Entry = ExInterlockedRemoveHeadList(&Connection->ReceiveRequest, &Connection->Lock))) - { - Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry ); - - TI_DbgPrint(DEBUG_TCP, - ("Completing Receive request: %x %x\n", - Bucket->Request, Status)); + Entry = RemoveHeadList(&Connection->ReceiveRequest);
- Bucket->Status = Status; - Bucket->Information = 0; + Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
- CompleteBucket(Connection, Bucket, FALSE); - } - } - else - { - while (!IsListEmpty(&Connection->ReceiveRequest)) - { - Entry = RemoveHeadList(&Connection->ReceiveRequest); - - Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry); - - Bucket->Information = 0; - Bucket->Status = Status; + Bucket->Information = 0; + Bucket->Status = Status;
- CompleteBucket(Connection, Bucket, FALSE); - } + CompleteBucket(Connection, Bucket, FALSE); } - - DereferenceObject(Connection); }
VOID -FlushSendQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked) +FlushSendQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status) { PTDI_BUCKET Bucket; PLIST_ENTRY Entry;
- ReferenceObject(Connection); + ASSERT_TCPIP_OBJECT_LOCKED(Connection);
- if (interlocked) + while (!IsListEmpty(&Connection->SendRequest)) { - while ((Entry = ExInterlockedRemoveHeadList(&Connection->SendRequest, &Connection->Lock))) - { - Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry ); - - TI_DbgPrint(DEBUG_TCP, - ("Completing Send request: %x %x\n", - Bucket->Request, Status)); - - Bucket->Status = Status; - Bucket->Information = 0; - - CompleteBucket(Connection, Bucket, FALSE); - } - } - else - { - while (!IsListEmpty(&Connection->SendRequest)) - { - Entry = RemoveHeadList(&Connection->SendRequest); + Entry = RemoveHeadList(&Connection->SendRequest);
- Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry); + Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
- Bucket->Information = 0; - Bucket->Status = Status; + Bucket->Information = 0; + Bucket->Status = Status;
- CompleteBucket(Connection, Bucket, FALSE); - } + CompleteBucket(Connection, Bucket, FALSE); } - - DereferenceObject(Connection); }
VOID -FlushShutdownQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked) +FlushShutdownQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status) { PTDI_BUCKET Bucket; PLIST_ENTRY Entry;
- ReferenceObject(Connection); - - if (interlocked) - { - while ((Entry = ExInterlockedRemoveHeadList(&Connection->ShutdownRequest, &Connection->Lock))) - { - Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry ); - - Bucket->Status = Status; - Bucket->Information = 0; + ASSERT_TCPIP_OBJECT_LOCKED(Connection);
- CompleteBucket(Connection, Bucket, FALSE); - } - } - else + while (!IsListEmpty(&Connection->ShutdownRequest)) { - while (!IsListEmpty(&Connection->ShutdownRequest)) - { - Entry = RemoveHeadList(&Connection->ShutdownRequest); + Entry = RemoveHeadList(&Connection->ShutdownRequest);
- Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry); + Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
- Bucket->Information = 0; - Bucket->Status = Status; + Bucket->Information = 0; + Bucket->Status = Status;
- CompleteBucket(Connection, Bucket, FALSE); - } + CompleteBucket(Connection, Bucket, FALSE); } - - DereferenceObject(Connection); }
VOID @@ -177,10 +118,11 @@ FlushConnectQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status) PTDI_BUCKET Bucket; PLIST_ENTRY Entry;
- ReferenceObject(Connection); + ASSERT_TCPIP_OBJECT_LOCKED(Connection);
- while ((Entry = ExInterlockedRemoveHeadList(&Connection->ConnectRequest, &Connection->Lock))) + while (!IsListEmpty(&Connection->ConnectRequest)) { + Entry = RemoveHeadList(&Connection->ConnectRequest); Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Bucket->Status = Status; @@ -188,8 +130,6 @@ FlushConnectQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
CompleteBucket(Connection, Bucket, FALSE); } - - DereferenceObject(Connection); }
VOID @@ -198,10 +138,11 @@ FlushListenQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status) PTDI_BUCKET Bucket; PLIST_ENTRY Entry;
- ReferenceObject(Connection); + ASSERT_TCPIP_OBJECT_LOCKED(Connection);
- while ((Entry = ExInterlockedRemoveHeadList(&Connection->ListenRequest, &Connection->Lock))) + while (!IsListEmpty(&Connection->ListenRequest)) { + Entry = RemoveHeadList(&Connection->ListenRequest); Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Bucket->Status = Status; @@ -210,17 +151,13 @@ FlushListenQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status) DereferenceObject(Bucket->AssociatedEndpoint); CompleteBucket(Connection, Bucket, FALSE); } - - DereferenceObject(Connection); }
VOID FlushAllQueues(PCONNECTION_ENDPOINT Connection, NTSTATUS Status) { - ReferenceObject(Connection); - // flush receive queue - FlushReceiveQueue(Connection, Status, TRUE); + FlushReceiveQueue(Connection, Status);
/* We completed the reads successfully but we need to return failure now */ if (Status == STATUS_SUCCESS) @@ -232,15 +169,13 @@ FlushAllQueues(PCONNECTION_ENDPOINT Connection, NTSTATUS Status) FlushListenQueue(Connection, Status);
// flush send queue - FlushSendQueue(Connection, Status, TRUE); + FlushSendQueue(Connection, Status);
// flush connect queue FlushConnectQueue(Connection, Status);
// flush shutdown queue - FlushShutdownQueue(Connection, Status, TRUE); - - DereferenceObject(Connection); + FlushShutdownQueue(Connection, Status); }
VOID @@ -248,18 +183,17 @@ TCPFinEventHandler(void *arg, const err_t err) { PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)arg, LastConnection; const NTSTATUS Status = TCPTranslateError(err); - KIRQL OldIrql;
ASSERT(Connection->SocketContext == NULL); ASSERT(Connection->AddressFile); ASSERT(err != ERR_OK);
+ LockObject(Connection); + /* Complete all outstanding requests now */ FlushAllQueues(Connection, Status);
- LockObject(Connection, &OldIrql); - - LockObjectAtDpcLevel(Connection->AddressFile); + LockObject(Connection->AddressFile);
/* Unlink this connection from the address file */ if (Connection->AddressFile->Connection == Connection) @@ -284,13 +218,13 @@ TCPFinEventHandler(void *arg, const err_t err) } }
- UnlockObjectFromDpcLevel(Connection->AddressFile); + UnlockObject(Connection->AddressFile);
/* Remove the address file from this connection */ DereferenceObject(Connection->AddressFile); Connection->AddressFile = NULL;
- UnlockObject(Connection, OldIrql); + UnlockObject(Connection); }
VOID @@ -301,14 +235,15 @@ TCPAcceptEventHandler(void *arg, PTCP_PCB newpcb) PLIST_ENTRY Entry; PIRP Irp; NTSTATUS Status; - KIRQL OldIrql;
- ReferenceObject(Connection); + LockObject(Connection);
- while ((Entry = ExInterlockedRemoveHeadList(&Connection->ListenRequest, &Connection->Lock))) + while (!IsListEmpty(&Connection->ListenRequest)) { PIO_STACK_LOCATION IrpSp;
+ Entry = RemoveHeadList(&Connection->ListenRequest); + Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Irp = Bucket->Request.RequestContext; @@ -326,7 +261,7 @@ TCPAcceptEventHandler(void *arg, PTCP_PCB newpcb)
if (Status == STATUS_SUCCESS) { - LockObject(Bucket->AssociatedEndpoint, &OldIrql); + LockObject(Bucket->AssociatedEndpoint);
/* sanity assert...this should never be in anything else but a CLOSED state */ ASSERT( ((PTCP_PCB)Bucket->AssociatedEndpoint->SocketContext)->state == CLOSED ); @@ -337,9 +272,9 @@ TCPAcceptEventHandler(void *arg, PTCP_PCB newpcb) /* free previously created socket context (we don't use it, we use newpcb) */ Bucket->AssociatedEndpoint->SocketContext = newpcb;
- LibTCPAccept(newpcb, (PTCP_PCB)Connection->SocketContext, Bucket->AssociatedEndpoint); + UnlockObject(Bucket->AssociatedEndpoint);
- UnlockObject(Bucket->AssociatedEndpoint, OldIrql); + LibTCPAccept(newpcb, (PTCP_PCB)Connection->SocketContext, Bucket->AssociatedEndpoint); }
DereferenceObject(Bucket->AssociatedEndpoint); @@ -352,7 +287,7 @@ TCPAcceptEventHandler(void *arg, PTCP_PCB newpcb) } }
- DereferenceObject(Connection); + UnlockObject(Connection); }
VOID @@ -367,12 +302,17 @@ TCPSendEventHandler(void *arg, const u16_t space) ULONG BytesSent;
ReferenceObject(Connection); + LockObject(Connection);
- while ((Entry = ExInterlockedRemoveHeadList(&Connection->SendRequest, &Connection->Lock))) + while (!IsListEmpty(&Connection->SendRequest)) { UINT SendLen = 0; PVOID SendBuffer = 0;
+ Entry = RemoveHeadList(&Connection->SendRequest); + + UnlockObject(Connection); + Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Irp = Bucket->Request.RequestContext; @@ -400,9 +340,8 @@ TCPSendEventHandler(void *arg, const u16_t space)
if( Status == STATUS_PENDING ) { - ExInterlockedInsertHeadList(&Connection->SendRequest, - &Bucket->Entry, - &Connection->Lock); + LockObject(Connection); + InsertHeadList(&Connection->SendRequest, &Bucket->Entry); break; } else @@ -416,13 +355,15 @@ TCPSendEventHandler(void *arg, const u16_t space)
CompleteBucket(Connection, Bucket, FALSE); } + + LockObject(Connection); }
// If we completed all outstanding send requests then finish all pending shutdown requests, // cancel the timer and dereference the connection if (IsListEmpty(&Connection->SendRequest)) { - FlushShutdownQueue(Connection, STATUS_SUCCESS, FALSE); + FlushShutdownQueue(Connection, STATUS_SUCCESS);
if (KeCancelTimer(&Connection->DisconnectTimer)) { @@ -430,6 +371,8 @@ TCPSendEventHandler(void *arg, const u16_t space) } }
+ UnlockObject(Connection); + DereferenceObject(Connection); }
@@ -446,10 +389,11 @@ TCPRecvEventHandler(void *arg) PUCHAR RecvBuffer; NTSTATUS Status;
- ReferenceObject(Connection); + LockObject(Connection);
- while ((Entry = ExInterlockedRemoveHeadList(&Connection->ReceiveRequest, &Connection->Lock))) + while(!IsListEmpty(&Connection->ReceiveRequest)) { + Entry = RemoveHeadList(&Connection->ReceiveRequest); Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Irp = Bucket->Request.RequestContext; @@ -460,9 +404,7 @@ TCPRecvEventHandler(void *arg) Status = LibTCPGetDataFromConnectionQueue(Connection, RecvBuffer, RecvLen, &Received); if (Status == STATUS_PENDING) { - ExInterlockedInsertHeadList(&Connection->ReceiveRequest, - &Bucket->Entry, - &Connection->Lock); + InsertHeadList(&Connection->ReceiveRequest, &Bucket->Entry); break; }
@@ -471,8 +413,7 @@ TCPRecvEventHandler(void *arg)
CompleteBucket(Connection, Bucket, FALSE); } - - DereferenceObject(Connection); + UnlockObject(Connection); }
VOID @@ -482,10 +423,11 @@ TCPConnectEventHandler(void *arg, const err_t err) PTDI_BUCKET Bucket; PLIST_ENTRY Entry;
- ReferenceObject(Connection); + LockObject(Connection);
- while ((Entry = ExInterlockedRemoveHeadList(&Connection->ConnectRequest, &Connection->Lock))) + while (!IsListEmpty(&Connection->ConnectRequest)) { + Entry = RemoveHeadList(&Connection->ConnectRequest);
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
@@ -495,5 +437,5 @@ TCPConnectEventHandler(void *arg, const err_t err) CompleteBucket(Connection, Bucket, FALSE); }
- DereferenceObject(Connection); + UnlockObject(Connection); } diff --git a/sdk/lib/drivers/ip/transport/tcp/tcp.c b/sdk/lib/drivers/ip/transport/tcp/tcp.c index d18b350a967..7bdc8ab7486 100644 --- a/sdk/lib/drivers/ip/transport/tcp/tcp.c +++ b/sdk/lib/drivers/ip/transport/tcp/tcp.c @@ -25,21 +25,27 @@ PORT_SET TCPPorts;
NPAGED_LOOKASIDE_LIST TdiBucketLookasideList;
-VOID NTAPI -DisconnectTimeoutDpc(PKDPC Dpc, - PVOID DeferredContext, - PVOID SystemArgument1, - PVOID SystemArgument2) +static +IO_WORKITEM_ROUTINE +DisconnectWorker; + +_Use_decl_annotations_ +VOID +NTAPI +DisconnectWorker( + _Unreferenced_parameter_ PDEVICE_OBJECT DeviceObject, + _In_ PVOID Context +) { - PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)DeferredContext; + PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)Context; PLIST_ENTRY Entry; PTDI_BUCKET Bucket;
- LockObjectAtDpcLevel(Connection); - /* We timed out waiting for pending sends so force it to shutdown */ TCPTranslateError(LibTCPShutdown(Connection, 0, 1));
+ LockObject(Connection); + while (!IsListEmpty(&Connection->SendRequest)) { Entry = RemoveHeadList(&Connection->SendRequest); @@ -64,11 +70,23 @@ DisconnectTimeoutDpc(PKDPC Dpc, CompleteBucket(Connection, Bucket, FALSE); }
- UnlockObjectFromDpcLevel(Connection); + UnlockObject(Connection);
DereferenceObject(Connection); }
+VOID +NTAPI +DisconnectTimeoutDpc(PKDPC Dpc, + PVOID DeferredContext, + PVOID SystemArgument1, + PVOID SystemArgument2) +{ + PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)DeferredContext; + + IoQueueWorkItem(Connection->DisconnectWorkItem, DisconnectWorker, DelayedWorkQueue, Connection); +} + VOID ConnectionFree(PVOID Object) { PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)Object; @@ -80,6 +98,9 @@ VOID ConnectionFree(PVOID Object) RemoveEntryList(&Connection->ListEntry); TcpipReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
+ ExDeleteResourceLite(&Connection->Resource); + IoFreeWorkItem(Connection->DisconnectWorkItem); + ExFreePoolWithTag( Connection, CONN_ENDPT_TAG ); }
@@ -96,7 +117,7 @@ PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext ) RtlZeroMemory(Connection, sizeof(CONNECTION_ENDPOINT));
/* Initialize spin lock that protects the connection endpoint file object */ - KeInitializeSpinLock(&Connection->Lock); + ExInitializeResourceLite(&Connection->Resource); InitializeListHead(&Connection->ConnectRequest); InitializeListHead(&Connection->ListenRequest); InitializeListHead(&Connection->ReceiveRequest); @@ -107,6 +128,13 @@ PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext ) /* Initialize disconnect timer */ KeInitializeTimer(&Connection->DisconnectTimer); KeInitializeDpc(&Connection->DisconnectDpc, DisconnectTimeoutDpc, Connection); + Connection->DisconnectWorkItem = IoAllocateWorkItem(TCPDeviceObject); + if (!Connection->DisconnectWorkItem) + { + ExDeleteResourceLite(&Connection->Resource); + ExFreePoolWithTag( Connection, CONN_ENDPT_TAG ); + return NULL; + }
/* Save client context pointer */ Connection->ClientContext = ClientContext; @@ -126,9 +154,8 @@ NTSTATUS TCPSocket( PCONNECTION_ENDPOINT Connection, UINT Family, UINT Type, UINT Proto ) { NTSTATUS Status; - KIRQL OldIrql;
- LockObject(Connection, &OldIrql); + LockObject(Connection);
TI_DbgPrint(DEBUG_TCP,("[IP, TCPSocket] Called: Connection %x, Family %d, Type %d, " "Proto %d, sizeof(CONNECTION_ENDPOINT) = %d\n", @@ -140,7 +167,7 @@ NTSTATUS TCPSocket( PCONNECTION_ENDPOINT Connection, else Status = STATUS_INSUFFICIENT_RESOURCES;
- UnlockObject(Connection, OldIrql); + UnlockObject(Connection);
TI_DbgPrint(DEBUG_TCP,("[IP, TCPSocket] Leaving. Status = 0x%x\n", Status));
@@ -149,15 +176,13 @@ NTSTATUS TCPSocket( PCONNECTION_ENDPOINT Connection,
NTSTATUS TCPClose( PCONNECTION_ENDPOINT Connection ) { - KIRQL OldIrql; - - LockObject(Connection, &OldIrql); + LockObject(Connection);
FlushAllQueues(Connection, STATUS_CANCELLED);
- LibTCPClose(Connection, FALSE, TRUE); + UnlockObject(Connection);
- UnlockObject(Connection, OldIrql); + LibTCPClose(Connection, FALSE, TRUE);
DereferenceObject(Connection);
@@ -287,7 +312,6 @@ NTSTATUS TCPConnect TA_IP_ADDRESS LocalAddress; PTDI_BUCKET Bucket; PNEIGHBOR_CACHE_ENTRY NCE; - KIRQL OldIrql;
TI_DbgPrint(DEBUG_TCP,("[IP, TCPConnect] Called\n"));
@@ -308,11 +332,11 @@ NTSTATUS TCPConnect RemoteAddress.Address.IPv4Address, RemotePort));
- LockObject(Connection, &OldIrql); + LockObject(Connection);
if (!Connection->AddressFile) { - UnlockObject(Connection, OldIrql); + UnlockObject(Connection); return STATUS_INVALID_PARAMETER; }
@@ -320,7 +344,7 @@ NTSTATUS TCPConnect { if (!(NCE = RouteGetRouteToDestination(&RemoteAddress))) { - UnlockObject(Connection, OldIrql); + UnlockObject(Connection); return STATUS_NETWORK_UNREACHABLE; }
@@ -335,48 +359,51 @@ NTSTATUS TCPConnect &bindaddr, Connection->AddressFile->Port));
- if (NT_SUCCESS(Status)) + if (!NT_SUCCESS(Status)) { - /* Copy bind address into connection */ - Connection->AddressFile->Address.Address.IPv4Address = bindaddr.addr; - /* Check if we had an unspecified port */ - if (!Connection->AddressFile->Port) - { - /* We did, so we need to copy back the port */ - Status = TCPGetSockAddress(Connection, (PTRANSPORT_ADDRESS)&LocalAddress, FALSE); - if (NT_SUCCESS(Status)) - { - /* Allocate the port in the port bitmap */ - Connection->AddressFile->Port = TCPAllocatePort(LocalAddress.Address[0].Address[0].sin_port); - - /* This should never fail */ - ASSERT(Connection->AddressFile->Port != 0xFFFF); - } - } + UnlockObject(Connection); + return Status; + }
- if (NT_SUCCESS(Status)) + /* Copy bind address into connection */ + Connection->AddressFile->Address.Address.IPv4Address = bindaddr.addr; + /* Check if we had an unspecified port */ + if (!Connection->AddressFile->Port) + { + /* We did, so we need to copy back the port */ + Status = TCPGetSockAddress(Connection, (PTRANSPORT_ADDRESS)&LocalAddress, FALSE); + if (!NT_SUCCESS(Status)) { - connaddr.addr = RemoteAddress.Address.IPv4Address; + UnlockObject(Connection); + return Status; + }
- Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList); - if (!Bucket) - { - UnlockObject(Connection, OldIrql); - return STATUS_NO_MEMORY; - } + /* Allocate the port in the port bitmap */ + Connection->AddressFile->Port = TCPAllocatePort(LocalAddress.Address[0].Address[0].sin_port);
- Bucket->Request.RequestNotifyObject = (PVOID)Complete; - Bucket->Request.RequestContext = Context; + /* This should never fail */ + ASSERT(Connection->AddressFile->Port != 0xFFFF); + }
- InsertTailList( &Connection->ConnectRequest, &Bucket->Entry ); + connaddr.addr = RemoteAddress.Address.IPv4Address;
- Status = TCPTranslateError(LibTCPConnect(Connection, - &connaddr, - RemotePort)); - } + Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList); + if (!Bucket) + { + UnlockObject(Connection); + return STATUS_NO_MEMORY; }
- UnlockObject(Connection, OldIrql); + Bucket->Request.RequestNotifyObject = (PVOID)Complete; + Bucket->Request.RequestContext = Context; + + InsertTailList( &Connection->ConnectRequest, &Bucket->Entry ); + + UnlockObject(Connection); + + Status = TCPTranslateError(LibTCPConnect(Connection, + &connaddr, + RemotePort));
TI_DbgPrint(DEBUG_TCP,("[IP, TCPConnect] Leaving. Status = 0x%x\n", Status));
@@ -394,12 +421,11 @@ NTSTATUS TCPDisconnect { NTSTATUS Status = STATUS_INVALID_PARAMETER; PTDI_BUCKET Bucket; - KIRQL OldIrql; LARGE_INTEGER ActualTimeout;
TI_DbgPrint(DEBUG_TCP,("[IP, TCPDisconnect] Called\n"));
- LockObject(Connection, &OldIrql); + LockObject(Connection);
if (Connection->SocketContext) { @@ -407,12 +433,20 @@ NTSTATUS TCPDisconnect { if (IsListEmpty(&Connection->SendRequest)) { + ReferenceObject(Connection); + UnlockObject(Connection); Status = TCPTranslateError(LibTCPShutdown(Connection, 0, 1)); + LockObject(Connection); + DereferenceObject(Connection); } else if (Timeout && Timeout->QuadPart == 0) { - FlushSendQueue(Connection, STATUS_FILE_CLOSED, FALSE); - TCPTranslateError(LibTCPShutdown(Connection, 0, 1)); + FlushSendQueue(Connection, STATUS_FILE_CLOSED); + ReferenceObject(Connection); + UnlockObject(Connection); + LibTCPShutdown(Connection, 0, 1); + LockObject(Connection); + DereferenceObject(Connection); Status = STATUS_TIMEOUT; } else @@ -431,7 +465,7 @@ NTSTATUS TCPDisconnect Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList); if (!Bucket) { - UnlockObject(Connection, OldIrql); + UnlockObject(Connection); return STATUS_NO_MEMORY; }
@@ -441,11 +475,11 @@ NTSTATUS TCPDisconnect InsertTailList(&Connection->ShutdownRequest, &Bucket->Entry);
ReferenceObject(Connection); - if (KeCancelTimer(&Connection->DisconnectTimer)) + if (KeSetTimer(&Connection->DisconnectTimer, ActualTimeout, &Connection->DisconnectDpc)) { + /* Timer was already in the queue. */ DereferenceObject(Connection); } - KeSetTimer(&Connection->DisconnectTimer, ActualTimeout, &Connection->DisconnectDpc);
Status = STATUS_PENDING; } @@ -453,20 +487,26 @@ NTSTATUS TCPDisconnect
if ((Flags & TDI_DISCONNECT_ABORT) || !Flags) { - FlushReceiveQueue(Connection, STATUS_FILE_CLOSED, FALSE); - FlushSendQueue(Connection, STATUS_FILE_CLOSED, FALSE); - FlushShutdownQueue(Connection, STATUS_FILE_CLOSED, FALSE); + FlushReceiveQueue(Connection, STATUS_FILE_CLOSED); + FlushSendQueue(Connection, STATUS_FILE_CLOSED); + FlushShutdownQueue(Connection, STATUS_FILE_CLOSED); + ReferenceObject(Connection); + UnlockObject(Connection); Status = TCPTranslateError(LibTCPShutdown(Connection, 1, 1)); + DereferenceObject(Connection); + } + else + { + UnlockObject(Connection); } } else { + UnlockObject(Connection); /* We already got closed by the other side so just return success */ Status = STATUS_SUCCESS; }
- UnlockObject(Connection, OldIrql); - TI_DbgPrint(DEBUG_TCP,("[IP, TCPDisconnect] Leaving. Status = 0x%x\n", Status));
return Status; @@ -506,7 +546,9 @@ NTSTATUS TCPReceiveData Bucket->Request.RequestNotifyObject = Complete; Bucket->Request.RequestContext = Context;
- ExInterlockedInsertTailList( &Connection->ReceiveRequest, &Bucket->Entry, &Connection->Lock ); + LockObject(Connection); + InsertTailList( &Connection->ReceiveRequest, &Bucket->Entry ); + UnlockObject(Connection); TI_DbgPrint(DEBUG_TCP,("[IP, TCPReceiveData] Queued read irp\n"));
TI_DbgPrint(DEBUG_TCP,("[IP, TCPReceiveData] Leaving. Status = STATUS_PENDING\n")); @@ -532,9 +574,8 @@ NTSTATUS TCPSendData { NTSTATUS Status; PTDI_BUCKET Bucket; - KIRQL OldIrql;
- LockObject(Connection, &OldIrql); + ReferenceObject(Connection);
TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Called for %d bytes (on socket %x)\n", SendLength, Connection->SocketContext)); @@ -558,7 +599,7 @@ NTSTATUS TCPSendData Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList); if (!Bucket) { - UnlockObject(Connection, OldIrql); + DereferenceObject(Connection); TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Failed to allocate bucket\n")); return STATUS_NO_MEMORY; } @@ -566,13 +607,15 @@ NTSTATUS TCPSendData Bucket->Request.RequestNotifyObject = Complete; Bucket->Request.RequestContext = Context;
+ LockObject(Connection); InsertTailList( &Connection->SendRequest, &Bucket->Entry ); TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Queued write irp\n")); + UnlockObject(Connection); }
- UnlockObject(Connection, OldIrql);
TI_DbgPrint(DEBUG_TCP, ("[IP, TCPSendData] Leaving. Status = %x\n", Status)); + DereferenceObject(Connection);
return Status; } @@ -606,13 +649,12 @@ NTSTATUS TCPGetSockAddress PTA_IP_ADDRESS AddressIP = (PTA_IP_ADDRESS)Address; struct ip_addr ipaddr; NTSTATUS Status; - KIRQL OldIrql;
AddressIP->TAAddressCount = 1; AddressIP->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP; AddressIP->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
- LockObject(Connection, &OldIrql); + LockObject(Connection);
if (GetRemote) { @@ -627,7 +669,7 @@ NTSTATUS TCPGetSockAddress &AddressIP->Address[0].Address[0].sin_port)); }
- UnlockObject(Connection, OldIrql); + UnlockObject(Connection);
AddressIP->Address[0].Address[0].in_addr = ipaddr.addr;
@@ -641,7 +683,6 @@ BOOLEAN TCPRemoveIRP( PCONNECTION_ENDPOINT Endpoint, PIRP Irp ) { PLIST_ENTRY Entry; PLIST_ENTRY ListHead[5]; - KIRQL OldIrql; PTDI_BUCKET Bucket; UINT i = 0; BOOLEAN Found = FALSE; @@ -652,7 +693,7 @@ BOOLEAN TCPRemoveIRP( PCONNECTION_ENDPOINT Endpoint, PIRP Irp ) ListHead[3] = &Endpoint->ListenRequest; ListHead[4] = &Endpoint->ShutdownRequest;
- LockObject(Endpoint, &OldIrql); + LockObject(Endpoint);
for( i = 0; i < 5; i++ ) { @@ -671,7 +712,7 @@ BOOLEAN TCPRemoveIRP( PCONNECTION_ENDPOINT Endpoint, PIRP Irp ) } }
- UnlockObject(Endpoint, OldIrql); + UnlockObject(Endpoint);
return Found; } diff --git a/sdk/lib/drivers/ip/transport/udp/udp.c b/sdk/lib/drivers/ip/transport/udp/udp.c index 783dae988b9..0ad09fa7bf3 100644 --- a/sdk/lib/drivers/ip/transport/udp/udp.c +++ b/sdk/lib/drivers/ip/transport/udp/udp.c @@ -171,9 +171,8 @@ NTSTATUS UDPSendDatagram( USHORT RemotePort; NTSTATUS Status; PNEIGHBOR_CACHE_ENTRY NCE; - KIRQL OldIrql;
- LockObject(AddrFile, &OldIrql); + LockObject(AddrFile);
TI_DbgPrint(MID_TRACE,("Sending Datagram(%x %x %x %d)\n", AddrFile, ConnInfo, BufferData, DataSize)); @@ -188,7 +187,7 @@ NTSTATUS UDPSendDatagram( break;
default: - UnlockObject(AddrFile, OldIrql); + UnlockObject(AddrFile); return STATUS_UNSUCCESSFUL; }
@@ -200,7 +199,7 @@ NTSTATUS UDPSendDatagram( * interface we're sending over */ if(!(NCE = RouteGetRouteToDestination( &RemoteAddress ))) { - UnlockObject(AddrFile, OldIrql); + UnlockObject(AddrFile); return STATUS_NETWORK_UNREACHABLE; }
@@ -209,7 +208,7 @@ NTSTATUS UDPSendDatagram( else { if(!(NCE = NBLocateNeighbor( &LocalAddress, NULL ))) { - UnlockObject(AddrFile, OldIrql); + UnlockObject(AddrFile); return STATUS_INVALID_PARAMETER; } } @@ -223,7 +222,7 @@ NTSTATUS UDPSendDatagram( BufferData, DataSize );
- UnlockObject(AddrFile, OldIrql); + UnlockObject(AddrFile);
if( !NT_SUCCESS(Status) ) return Status; diff --git a/sdk/lib/drivers/lwip/src/include/rosip.h b/sdk/lib/drivers/lwip/src/include/rosip.h index af852910d2f..701a65614da 100644 --- a/sdk/lib/drivers/lwip/src/include/rosip.h +++ b/sdk/lib/drivers/lwip/src/include/rosip.h @@ -31,6 +31,9 @@ struct lwip_callback_msg struct { PVOID Arg; } Socket; + struct { + struct tcp_pcb* pcb; + } FreeSocket; struct { PCONNECTION_ENDPOINT Connection; struct ip_addr *IpAddress; @@ -99,6 +102,7 @@ extern void TCPRecvEventHandler(void *arg);
/* TCP functions */ PTCP_PCB LibTCPSocket(void *arg); +VOID LibTCPFreeSocket(PTCP_PCB pcb); err_t LibTCPBind(PCONNECTION_ENDPOINT Connection, struct ip_addr *const ipaddr, const u16_t port); PTCP_PCB LibTCPListen(PCONNECTION_ENDPOINT Connection, const u8_t backlog); err_t LibTCPSend(PCONNECTION_ENDPOINT Connection, void *const dataptr, const u16_t len, u32_t *sent, const int safe); diff --git a/sdk/lib/drivers/lwip/src/rostcp.c b/sdk/lib/drivers/lwip/src/rostcp.c index de5564642b8..cc0dd4bc0d6 100644 --- a/sdk/lib/drivers/lwip/src/rostcp.c +++ b/sdk/lib/drivers/lwip/src/rostcp.c @@ -81,7 +81,9 @@ void LibTCPEnqueuePacket(PCONNECTION_ENDPOINT Connection, struct pbuf *p) qp->p = p; qp->Offset = 0;
- ExInterlockedInsertTailList(&Connection->PacketQueue, &qp->ListEntry, &Connection->Lock); + LockObject(Connection); + InsertTailList(&Connection->PacketQueue, &qp->ListEntry); + UnlockObject(Connection); }
PQUEUE_ENTRY LibTCPDequeuePacket(PCONNECTION_ENDPOINT Connection) @@ -104,11 +106,10 @@ NTSTATUS LibTCPGetDataFromConnectionQueue(PCONNECTION_ENDPOINT Connection, PUCHA struct pbuf* p; NTSTATUS Status; UINT ReadLength, PayloadLength, Offset, Copied; - KIRQL OldIrql;
(*Received) = 0;
- LockObject(Connection, &OldIrql); + LockObject(Connection);
if (!IsListEmpty(&Connection->PacketQueue)) { @@ -132,13 +133,9 @@ NTSTATUS LibTCPGetDataFromConnectionQueue(PCONNECTION_ENDPOINT Connection, PUCHA qp = NULL; }
- UnlockObject(Connection, OldIrql); - Copied = pbuf_copy_partial(p, RecvBuffer, ReadLength, Offset); ASSERT(Copied == ReadLength);
- LockObject(Connection, &OldIrql); - /* Update trackers */ RecvLen -= ReadLength; RecvBuffer += ReadLength; @@ -172,7 +169,7 @@ NTSTATUS LibTCPGetDataFromConnectionQueue(PCONNECTION_ENDPOINT Connection, PUCHA Status = STATUS_PENDING; }
- UnlockObject(Connection, OldIrql); + UnlockObject(Connection);
return Status; } @@ -364,6 +361,33 @@ LibTCPSocket(void *arg) return NULL; }
+static +void +LibTCPFreeSocketCallback(void *arg) +{ + struct lwip_callback_msg *msg = arg; + + ASSERT(msg); + + /* Calling tcp_close will free it */ + tcp_close(msg->Input.FreeSocket.pcb); + + KeSetEvent(&msg->Event, IO_NO_INCREMENT, FALSE); +} + +void LibTCPFreeSocket(PTCP_PCB pcb) +{ + struct lwip_callback_msg msg; + + KeInitializeEvent(&msg.Event, NotificationEvent, FALSE); + msg.Input.FreeSocket.pcb = pcb; + + tcpip_callback_with_block(LibTCPFreeSocketCallback, &msg, 1); + + WaitForEventSafely(&msg.Event); +} + + static void LibTCPBindCallback(void *arg)