X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=reactos%2Fdrivers%2Flib%2Fip%2Ftransport%2Ftcp%2Ftcp.c;h=1f7961660e639c3cb72e8a6a6a67f3f5937325e8;hp=fcaa415b42d01993a4943fd8b173ae4f0afcac80;hb=9851ee0b334ad1159aa893a39e59e2813c8ccf44;hpb=d108d4822a78790e08d761c2919153aee8c3eee3 diff --git a/reactos/drivers/lib/ip/transport/tcp/tcp.c b/reactos/drivers/lib/ip/transport/tcp/tcp.c index fcaa415b42d..1f7961660e6 100644 --- a/reactos/drivers/lib/ip/transport/tcp/tcp.c +++ b/reactos/drivers/lib/ip/transport/tcp/tcp.c @@ -307,6 +307,68 @@ OSKITTCP_EVENT_HANDLERS EventHandlers = { TCPWakeup /* Wakeup */ }; +static KEVENT TimerLoopEvent; +static HANDLE TimerThreadHandle; + +/* + * We are running 2 timers here, one with a 200ms interval (fast) and the other + * with a 500ms interval (slow). So we need to time out at 200, 400, 500, 600, + * 800, 1000 and process the "fast" events at 200, 400, 600, 800, 1000 and the + * "slow" events at 500 and 1000. + */ +static VOID DDKAPI +TimerThread(PVOID Context) +{ + LARGE_INTEGER Timeout; + NTSTATUS Status; + unsigned Current, NextFast, NextSlow, Next; + + Current = 0; + Next = 0; + NextFast = 0; + NextSlow = 0; + while ( 1 ) { + if (Next == NextFast) { + NextFast += 2; + } + if (Next == NextSlow) { + NextSlow += 5; + } + Next = min(NextFast, NextSlow); + Timeout.QuadPart = (LONGLONG) (Next - Current) * -1000000; /* 100 ms */ + Status = KeWaitForSingleObject(&TimerLoopEvent, Executive, KernelMode, + FALSE, &Timeout); + if (STATUS_SUCCESS == Status) { + PsTerminateSystemThread(STATUS_SUCCESS); + } + ASSERT(STATUS_TIMEOUT == Status); + + TcpipRecursiveMutexEnter( &TCPLock, TRUE ); + TimerOskitTCP( Next == NextFast, Next == NextSlow ); + if (Next == NextSlow) { + DrainSignals(); + } + TcpipRecursiveMutexLeave( &TCPLock ); + + Current = Next; + if (10 <= Current) { + Current = 0; + Next = 0; + NextFast = 0; + NextSlow = 0; + } + } +} + +static VOID +StartTimer(VOID) +{ + KeInitializeEvent(&TimerLoopEvent, NotificationEvent, FALSE); + PsCreateSystemThread(&TimerThreadHandle, THREAD_ALL_ACCESS, 0, 0, 0, + TimerThread, NULL); +} + + NTSTATUS TCPStartup(VOID) /* * FUNCTION: Initializes the TCP subsystem @@ -336,6 +398,8 @@ NTSTATUS TCPStartup(VOID) TAG('T','C','P','S'), /* Tag */ 0); /* Depth */ + StartTimer(); + TCPInitialized = TRUE; return STATUS_SUCCESS; @@ -349,9 +413,16 @@ NTSTATUS TCPShutdown(VOID) * Status of operation */ { + LARGE_INTEGER WaitForThread; + if (!TCPInitialized) return STATUS_SUCCESS; + WaitForThread.QuadPart = -2500000; /* 250 ms */ + KeSetEvent(&TimerLoopEvent, IO_NO_INCREMENT, TRUE); + KeWaitForSingleObject(&TimerThreadHandle, Executive, KernelMode, + FALSE, &WaitForThread); + /* Deregister this protocol with IP layer */ IPRegisterProtocol(IPPROTO_TCP, NULL); @@ -598,13 +669,7 @@ NTSTATUS TCPSendData } VOID TCPTimeout(VOID) { - static int Times = 0; - TcpipRecursiveMutexEnter( &TCPLock, TRUE ); - if( (Times++ % 5) == 0 ) { - TimerOskitTCP(); - } - DrainSignals(); - TcpipRecursiveMutexLeave( &TCPLock ); + /* Now handled by TimerThread */ } UINT TCPAllocatePort( UINT HintPort ) { @@ -647,4 +712,34 @@ NTSTATUS TCPGetPeerAddress return STATUS_SUCCESS; } +VOID TCPRemoveIRP( PCONNECTION_ENDPOINT Endpoint, PIRP Irp ) { + PLIST_ENTRY Entry; + PLIST_ENTRY ListHead[4]; + KIRQL OldIrql; + PTDI_BUCKET Bucket; + UINT i = 0; + + ListHead[0] = &Endpoint->ReceiveRequest; + ListHead[1] = &Endpoint->ConnectRequest; + ListHead[2] = &Endpoint->ListenRequest; + ListHead[3] = 0; + + TcpipAcquireSpinLock( &Endpoint->Lock, &OldIrql ); + + for( i = 0; ListHead[i]; i++ ) { + for( Entry = ListHead[i]->Flink; + Entry != ListHead[i]; + Entry = Entry->Flink ) { + Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry ); + + if( Bucket->Request.RequestContext == Irp ) { + RemoveEntryList( &Bucket->Entry ); + break; + } + } + } + + TcpipReleaseSpinLock( &Endpoint->Lock, OldIrql ); +} + /* EOF */