NTSTATUS CfixkrpJoinChildThreadsFilament( __in PCFIXKRP_FILAMENT Filament, __in_opt PLARGE_INTEGER Timeout ) { NTSTATUS Status; ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); ExAcquireFastMutex( &Filament->ChildThreads.Lock ); if ( Filament->ChildThreads.ThreadCount > 0 ) { KWAIT_BLOCK WaitBlocks[ CFIX_MAX_THREADS ]; Status = KeWaitForMultipleObjects( Filament->ChildThreads.ThreadCount, Filament->ChildThreads.Threads, WaitAll, Executive, KernelMode, FALSE, Timeout, WaitBlocks ); } else { Status = STATUS_SUCCESS; } ExReleaseFastMutex( &Filament->ChildThreads.Lock ); return Status; }
u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) { LARGE_INTEGER LargeTimeout, PreWaitTime, PostWaitTime; UINT64 TimeDiff; NTSTATUS Status; PVOID Message; PLWIP_MESSAGE_CONTAINER Container; PLIST_ENTRY Entry; KIRQL OldIrql; PVOID WaitObjects[] = {&mbox->Event, &TerminationEvent}; LargeTimeout.QuadPart = Int32x32To64(timeout, -10000); KeQuerySystemTime(&PreWaitTime); Status = KeWaitForMultipleObjects(2, WaitObjects, WaitAny, Executive, KernelMode, FALSE, timeout != 0 ? &LargeTimeout : NULL, NULL); if (Status == STATUS_WAIT_0) { KeAcquireSpinLock(&mbox->Lock, &OldIrql); Entry = RemoveHeadList(&mbox->ListHead); ASSERT(Entry); if (IsListEmpty(&mbox->ListHead)) KeClearEvent(&mbox->Event); KeReleaseSpinLock(&mbox->Lock, OldIrql); Container = CONTAINING_RECORD(Entry, LWIP_MESSAGE_CONTAINER, ListEntry); Message = Container->Message; ExFreePool(Container); if (msg) *msg = Message; KeQuerySystemTime(&PostWaitTime); TimeDiff = PostWaitTime.QuadPart - PreWaitTime.QuadPart; TimeDiff /= 10000; return TimeDiff; } else if (Status == STATUS_WAIT_1) { /* DON'T remove ourselves from the thread list! */ PsTerminateSystemThread(STATUS_SUCCESS); /* We should never get here! */ ASSERT(FALSE); return 0; } return SYS_ARCH_TIMEOUT; }
VOID NotificationThread(__in PDokanDCB Dcb) { PKEVENT events[5]; PKWAIT_BLOCK waitBlock; NTSTATUS status; DDbgPrint("==> NotificationThread\n"); waitBlock = ExAllocatePool(sizeof(KWAIT_BLOCK) * 5); if (waitBlock == NULL) { DDbgPrint(" Can't allocate WAIT_BLOCK\n"); return; } events[0] = &Dcb->ReleaseEvent; events[1] = &Dcb->NotifyEvent.NotEmpty; events[2] = &Dcb->PendingEvent.NotEmpty; events[3] = &Dcb->Global->PendingService.NotEmpty; events[4] = &Dcb->Global->NotifyService.NotEmpty; do { status = KeWaitForMultipleObjects(5, events, WaitAny, Executive, KernelMode, FALSE, NULL, waitBlock); if (status != STATUS_WAIT_0) { if (status == STATUS_WAIT_1 || status == STATUS_WAIT_2) { NotificationLoop(&Dcb->PendingEvent, &Dcb->NotifyEvent); } else { NotificationLoop(&Dcb->Global->PendingService, &Dcb->Global->NotifyService); } } } while (status != STATUS_WAIT_0); ExFreePool(waitBlock); DDbgPrint("<== NotificationThread\n"); }
NTSTATUS v2v_stream_recv(struct v2v_stream *stream, void *buf, size_t buf_size, size_t *_bytes_received) { NTSTATUS status = STATUS_SUCCESS; struct queued_message *qm; size_t bytes_received; size_t bytes_this_time; HANDLE handles[2]; v2v_nc2_request_fast_receive(stream->channel); handles[0] = stream->receive_event; handles[1] = stream->control_event; for (bytes_received = 0; bytes_received < buf_size; bytes_received += bytes_this_time) { if (!stream->recv_state.current_message) { while ((status = v2v_get_next_message(stream)) != STATUS_SUCCESS) { if (bytes_received != 0 || status != STATUS_NO_MORE_ENTRIES) goto out; status = KeWaitForMultipleObjects(2, handles, WaitAny, Executive, KernelMode, FALSE, NULL, NULL); if (status == STATUS_WAIT_0 + 1 && v2v_remote_disconnect(stream)) { status = STATUS_VIRTUAL_CIRCUIT_CLOSED; goto out; } } } qm = stream->recv_state.current_message; bytes_this_time = MIN(qm->size - qm->bytes_already_used, buf_size - bytes_received); RtlCopyMemory((void *)((ULONG_PTR)buf + bytes_received), (const void *)((ULONG_PTR)qm->payload + qm->bytes_already_used), bytes_this_time); qm->bytes_already_used += bytes_this_time; if (qm->bytes_already_used == qm->size) { v2v_release_queued_message(stream, qm); stream->recv_state.current_message = NULL; } } out: v2v_nc2_cancel_fast_receive(stream->channel); *_bytes_received = bytes_received; if (bytes_received == 0) return (!NT_SUCCESS(status) ? status : STATUS_UNSUCCESSFUL); else return STATUS_SUCCESS; }
NTSTATUS v2v_stream_send(struct v2v_stream *stream, const void *buf, size_t buf_len, size_t *_bytes_sent) { NTSTATUS status = STATUS_SUCCESS; unsigned bytes_sent; unsigned short bytes_this_time; unsigned bytes_avail; volatile void *msg; HANDLE handles[3]; handles[0] = stream->send_event; handles[1] = stream->control_event; handles[2] = stream->receive_event; for (bytes_sent = 0; bytes_sent < buf_len; bytes_sent += bytes_this_time){ bytes_avail = v2v_nc2_producer_bytes_available(stream->channel); if (v2v_nc2_remote_requested_fast_wakeup(stream->channel)) bytes_avail = MIN(MAX_INLINE_BYTES, bytes_avail); bytes_this_time = (unsigned short)MIN(bytes_avail, buf_len - bytes_sent); status = v2v_nc2_prep_message(stream->channel, bytes_this_time, STREAM_MSG_DATA, 0, &msg); if (!NT_SUCCESS(status)) { if (status == STATUS_RETRY) { v2v_pull_incoming_messages(stream); if (bytes_sent != 0) v2v_nc2_send_messages(stream->channel); status = KeWaitForMultipleObjects(3, handles, WaitAny, Executive, KernelMode, FALSE, NULL, NULL); if (status == STATUS_WAIT_0 + 1 && v2v_remote_disconnect(stream)) { status = STATUS_VIRTUAL_CIRCUIT_CLOSED; break; } bytes_this_time = 0; continue; } break; /* end send with error status */ } _ReadWriteBarrier(); RtlCopyMemory((void *)msg, (const void *)((ULONG_PTR)buf + bytes_sent), bytes_this_time); _ReadWriteBarrier(); } if (bytes_sent != 0) v2v_nc2_send_messages(stream->channel); *_bytes_sent = bytes_sent; return status; }
static void DDKAPI timer_thread(LPVOID arg) { while (1) { KeWaitForMultipleObjects(2, timer_wait_objs, WaitAny, Executive, KernelMode, FALSE, NULL, NULL); if (timer_done) break; lkl_trigger_irq(TIMER_IRQ); } PsTerminateSystemThread(STATUS_SUCCESS); }
BOOLEAN KTdiStreamSocket::Accept(ULONG dwTimeOut) { //KLocker locker(&m_KSynchroObject); BOOLEAN bRes = FALSE; NTSTATUS NtStatus; PVOID pkEvents[2]; LARGE_INTEGER TimeOut; PLARGE_INTEGER pTimeOut = NULL; //m_KSynchroObject.Lock(); __try { if (m_bOpen == TRUE && m_bBind == TRUE && m_bConnected == FALSE && m_bListen == TRUE) { if (dwTimeOut != 0) { pTimeOut = &TimeOut; TimeOut.QuadPart = dwTimeOut * 10000; // msec -> 100 nsec intervals TimeOut.QuadPart = -TimeOut.QuadPart; } pkEvents[0] = &m_kListenEvent; pkEvents[1] = &m_kAcceptDestroyEvent; NtStatus = KeWaitForMultipleObjects(2, pkEvents, WaitAny, Suspended, KernelMode, TRUE, pTimeOut, NULL); if (NtStatus == STATUS_WAIT_0) { if (NT_SUCCESS(m_ListenStatusBlock.Status)) { SetEventHandler(TDI_EVENT_CONNECT, (PVOID)NULL, (PVOID)NULL); m_bConnected = TRUE; bRes = TRUE; DbgPrint ("TdiAccept: OK (%08x : %04x)!!!\n", m_nRemoteAddress, m_nRemotePort); } else { DbgPrint ("TdiAccept: ERROR (%08x)!!!\n", NtStatus); } } } } __finally { } //m_KSynchroObject.UnLock(); return bRes; }
VOID DokanTimeoutThread( PDokanDCB Dcb) /*++ Routine Description: checks wheter pending IRP is timeout or not each DOKAN_CHECK_INTERVAL --*/ { NTSTATUS status; KTIMER timer; PVOID pollevents[2]; LARGE_INTEGER timeout = {0}; BOOLEAN waitObj = TRUE; DDbgPrint("==> DokanTimeoutThread\n"); KeInitializeTimerEx(&timer, SynchronizationTimer); pollevents[0] = (PVOID)&Dcb->KillEvent; pollevents[1] = (PVOID)&timer; KeSetTimerEx(&timer, timeout, DOKAN_CHECK_INTERVAL, NULL); while (waitObj) { status = KeWaitForMultipleObjects(2, pollevents, WaitAny, Executive, KernelMode, FALSE, NULL, NULL); if (!NT_SUCCESS(status) || status == STATUS_WAIT_0) { DDbgPrint(" DokanTimeoutThread catched KillEvent\n"); // KillEvent or something error is occured waitObj = FALSE; } else { ReleaseTimeoutPendingIrp(Dcb); if (Dcb->UseKeepAlive) DokanCheckKeepAlive(Dcb); } } KeCancelTimer(&timer); DDbgPrint("<== DokanTimeoutThread\n"); PsTerminateSystemThread(STATUS_SUCCESS); }
u32_t sys_arch_sem_wait(sys_sem_t* sem, u32_t timeout) { LARGE_INTEGER LargeTimeout, PreWaitTime, PostWaitTime; UINT64 TimeDiff; NTSTATUS Status; PVOID WaitObjects[] = {&sem->Event, &TerminationEvent}; LargeTimeout.QuadPart = Int32x32To64(timeout, -10000); KeQuerySystemTime(&PreWaitTime); Status = KeWaitForMultipleObjects(2, WaitObjects, WaitAny, Executive, KernelMode, FALSE, timeout != 0 ? &LargeTimeout : NULL, NULL); if (Status == STATUS_WAIT_0) { KeQuerySystemTime(&PostWaitTime); TimeDiff = PostWaitTime.QuadPart - PreWaitTime.QuadPart; TimeDiff /= 10000; return TimeDiff; } else if (Status == STATUS_WAIT_1) { /* DON'T remove ourselves from the thread list! */ PsTerminateSystemThread(STATUS_SUCCESS); /* We should never get here! */ ASSERT(FALSE); return 0; } return SYS_ARCH_TIMEOUT; }
VOID NotificationThread( __in PDEVICE_EXTENSION DeviceExtension ) { PKEVENT events[5]; NTSTATUS status; DDbgPrint("==> NotificationThread\n"); events[0] = &DeviceExtension->ReleaseEvent; events[1] = &DeviceExtension->NotifyEvent.NotEmpty; events[2] = &DeviceExtension->PendingEvent.NotEmpty; events[3] = &DeviceExtension->Global->PendingService.NotEmpty; events[4] = &DeviceExtension->Global->NotifyService.NotEmpty; while (1) { status = KeWaitForMultipleObjects( 3, events, WaitAny, Executive, KernelMode, FALSE, NULL, NULL); if (status == STATUS_WAIT_0) { ; break; } else if (status == STATUS_WAIT_1 || status == STATUS_WAIT_2) { NotificationLoop( &DeviceExtension->PendingEvent, &DeviceExtension->NotifyEvent); } else { NotificationLoop( &DeviceExtension->Global->PendingService, &DeviceExtension->Global->NotifyService); } } DDbgPrint("<== NotificationThread\n"); }
static BOOLEAN WaitForEventSafely(PRKEVENT Event) { PVOID WaitObjects[] = {Event, &TerminationEvent}; if (KeWaitForMultipleObjects(2, WaitObjects, WaitAny, Executive, KernelMode, FALSE, NULL, NULL) == STATUS_WAIT_0) { /* Signalled by the caller's event */ return TRUE; } else /* if KeWaitForMultipleObjects() == STATUS_WAIT_1 */ { /* Signalled by our termination event */ return FALSE; } }
static NTSTATUS LspConnectBindAddrList( IN OUT PLANSCSI_SESSION LSS, OUT PTA_LSTRANS_ADDRESS BoundAddr, IN PTA_LSTRANS_ADDRESS DestAddr, IN PTA_LSTRANS_ADDRESS BindAddrList, IN PLARGE_INTEGER TimeOut ){ NTSTATUS status; ULONG idx_addr, idx_cleanup_addr; TA_LSTRANS_ADDRESS bindAddr; PLSTRANS_OVERLAPPED overlapped; PKEVENT overlappedEvents; PKWAIT_BLOCK overlappedWaitBlocks; PLANSCSI_SESSION overlappedLSS; PKEVENT overlappedWait[MAXIMUM_WAIT_OBJECTS]; NDASSCSI_ASSERT( TimeOut == NULL || TimeOut->QuadPart < 0 ); // // Parameter check // if(DestAddr->TAAddressCount != 1) { return STATUS_INVALID_PARAMETER; } if(BindAddrList->TAAddressCount < 1) { return STATUS_INVALID_PARAMETER; } // Windows does not allow to wait for more than MAXIMUM_WAIT_OBJECTS // even using wait block buffer. if(BindAddrList->TAAddressCount > MAXIMUM_WAIT_OBJECTS) { return STATUS_INSUFFICIENT_RESOURCES; } if(DestAddr->Address[0].AddressType != TDI_ADDRESS_TYPE_LPX) { return STATUS_NOT_IMPLEMENTED; } bindAddr.TAAddressCount = 1; status = STATUS_UNSUCCESSFUL; // // Allocate overlapped context. // overlapped = ExAllocatePoolWithTag( NonPagedPool, sizeof(LSTRANS_OVERLAPPED) * BindAddrList->TAAddressCount, LSS_OVERLAPPED_BUFFER_POOLTAG ); if(overlapped == NULL) return STATUS_INSUFFICIENT_RESOURCES; // // Allocate completion events // overlappedEvents = ExAllocatePoolWithTag( NonPagedPool, sizeof(KEVENT) * BindAddrList->TAAddressCount, LSS_OVERLAPPED_EVENT_POOLTAG );; if(overlappedEvents == NULL) { ExFreePoolWithTag(overlapped, LSS_OVERLAPPED_BUFFER_POOLTAG); return STATUS_INSUFFICIENT_RESOURCES; } // // Allocate wait blocks. // Need this buffer to wait for more than THREAD_WAIT_OBJECTS. // overlappedWaitBlocks = ExAllocatePoolWithTag( NonPagedPool, sizeof(KWAIT_BLOCK) * BindAddrList->TAAddressCount, LSS_OVERLAPPED_WAITBLOCK_POOLTAG); if(overlappedWaitBlocks == NULL) { ExFreePoolWithTag(overlappedEvents, LSS_OVERLAPPED_EVENT_POOLTAG); ExFreePoolWithTag(overlapped, LSS_OVERLAPPED_BUFFER_POOLTAG); return STATUS_INSUFFICIENT_RESOURCES; } // // Allocate LSSes // overlappedLSS = ExAllocatePoolWithTag( NonPagedPool, sizeof(LANSCSI_SESSION) * BindAddrList->TAAddressCount, LSS_OVERLAPPED_LSS_POOLTAG); if(overlappedLSS == NULL){ ExFreePoolWithTag(overlappedWaitBlocks, LSS_OVERLAPPED_WAITBLOCK_POOLTAG); ExFreePoolWithTag(overlappedEvents, LSS_OVERLAPPED_EVENT_POOLTAG); ExFreePoolWithTag(overlapped, LSS_OVERLAPPED_BUFFER_POOLTAG); return STATUS_INSUFFICIENT_RESOURCES; } // // Connect asynchronously for each binding address // for(idx_addr = 0; idx_addr < (ULONG)BindAddrList->TAAddressCount; idx_addr++) { RtlCopyMemory( bindAddr.Address, &BindAddrList->Address[idx_addr], sizeof(struct _AddrLstrans)); KDPrintM(DBG_PROTO_ERROR, ("BindingAddr%d=%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x\n", idx_addr, bindAddr.Address[0].Address.Address[0], bindAddr.Address[0].Address.Address[1], bindAddr.Address[0].Address.Address[2], bindAddr.Address[0].Address.Address[3], bindAddr.Address[0].Address.Address[4], bindAddr.Address[0].Address.Address[5], bindAddr.Address[0].Address.Address[6], bindAddr.Address[0].Address.Address[7] )); // We do not need encryption buffer for connect operation. overlappedLSS[idx_addr].EncryptBuffer = NULL; overlappedLSS[idx_addr].EncryptBufferLength = 0; LspCopy(&overlappedLSS[idx_addr], LSS, FALSE); // // Initialize overlapped buffer // KeInitializeEvent(&overlappedEvents[idx_addr], NotificationEvent, FALSE); overlappedWait[idx_addr] = &overlappedEvents[idx_addr]; overlapped[idx_addr].IoCompleteRoutine = LstransConnectComp; overlapped[idx_addr].CompletionEvent = &overlappedEvents[idx_addr]; overlapped[idx_addr].UserContext = NULL; // // Connect asynchronously // status = LspConnect(&overlappedLSS[idx_addr], &bindAddr, DestAddr, &overlapped[idx_addr], IF_NULL_TIMEOUT_THEN_DEFAULT(LSS, TimeOut)); if(!NT_SUCCESS(status)) { // Set the completion event to continue with KeWaitForMultipleObjects() // even though this address fails. overlapped[idx_addr].IoStatusBlock.Status = status; KeSetEvent(overlapped[idx_addr].CompletionEvent, IO_NO_INCREMENT, FALSE); KDPrintM(DBG_PROTO_ERROR,("LspConnect() failed. idx=%d STATUS=%08lx\n", idx_addr, status)); } } do { // // Wait for all connect completion events // status = KeWaitForMultipleObjects( BindAddrList->TAAddressCount, overlappedWait, WaitAll, Executive, KernelMode, FALSE, NULL, overlappedWaitBlocks); if(!NT_SUCCESS(status)) { ASSERT(FALSE); break; } // // Find the first connected address // for(idx_addr = 0; idx_addr < (ULONG)BindAddrList->TAAddressCount; idx_addr++) { status = overlapped[idx_addr].IoStatusBlock.Status; if(status == STATUS_SUCCESS) { break; } } // // Clean up unsuccessful or non-selected connections. // for(idx_cleanup_addr = 0; idx_cleanup_addr < (ULONG)BindAddrList->TAAddressCount; idx_cleanup_addr++) { if(idx_cleanup_addr != idx_addr) LspDisconnect(&overlappedLSS[idx_cleanup_addr]); } // // set return value // if(status == STATUS_SUCCESS) { if(BoundAddr) { LspCopy(LSS, &overlappedLSS[idx_addr], FALSE); BoundAddr->TAAddressCount = 1; RtlCopyMemory( BoundAddr->Address, &BindAddrList->Address[idx_addr], sizeof(struct _AddrLstrans)); } } else { KDPrintM(DBG_PROTO_ERROR, ("Could not connect to the dest\n")); } } while(FALSE); ExFreePoolWithTag(overlappedLSS, LSS_OVERLAPPED_LSS_POOLTAG); ExFreePoolWithTag(overlappedWaitBlocks, LSS_OVERLAPPED_WAITBLOCK_POOLTAG); ExFreePoolWithTag(overlappedEvents, LSS_OVERLAPPED_EVENT_POOLTAG); ExFreePoolWithTag(overlapped, LSS_OVERLAPPED_BUFFER_POOLTAG); return status; }
VOID RedirDataGramSvrThreadProc ( PLFSDGRAMSVR_CTX SvrCtx ) { BOOLEAN bret; NTSTATUS status; LFSDG_Socket ServerDatagramSocket; PKEVENT Evts[3]; PLIST_ENTRY listEntry; PLFSDG_PKT pkt; SPY_LOG_PRINT( LFS_DEBUG_LIB_INFO, ("[LFS] RedirDataGramSvrThreadProc: Initializing Redirection Datagram server...\n") ); // Open server datagram port status = LfsOpenDGSocket( &ServerDatagramSocket, DEFAULT_DATAGRAM_SVRPORT ); if (status == STATUS_SUCCESS) { // register Datagram handler status = LfsRegisterDatagramRecvHandler( &ServerDatagramSocket, LfsSvrDatagramRecvHandler, SvrCtx ); } Evts[0] = &SvrCtx->ShutdownEvent; Evts[1] = &SvrCtx->DatagramRecvEvent; Evts[2] = &SvrCtx->NetworkEvent; SPY_LOG_PRINT( LFS_DEBUG_LIB_INFO, ("[LFS] RedirDataGramSvrThreadProc: Redirection Datagram server started...\n") ); // Main loop... while(1) { status = KeWaitForMultipleObjects( 3, Evts, WaitAny, Executive, KernelMode, TRUE, NULL, NULL ); SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, ("[LFS] RedirDataGramSvrThreadProc: NTSTATUS:%lu\n", status) ); if (status == 0) { SPY_LOG_PRINT( LFS_DEBUG_LIB_INFO, ("[LFS] RedirDataGramSvrThreadProc: ShutDown event received. NTSTATUS:%lu\n", status) ); break; } else if (status == 1) { // Datagram received. KeClearEvent( &SvrCtx->DatagramRecvEvent ); SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, ("[LFS] RedirDataGramSvrThreadProc: DatagramRecv event received. NTSTATUS:%lu\n", status) ); } else if (status == 2) { // Renew server datagram port SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, ("[LFS] RedirDataGramSvrThreadProc: Networking event received. NTSTATUS:%lu\n", status) ); KeClearEvent( &SvrCtx->NetworkEvent ); LfsCloseDGSocket( &ServerDatagramSocket ); status = LfsOpenDGSocket( &ServerDatagramSocket, DEFAULT_DATAGRAM_SVRPORT ); if (status == STATUS_SUCCESS) { // register Datagram handler status = LfsRegisterDatagramRecvHandler( &ServerDatagramSocket, LfsSvrDatagramRecvHandler, SvrCtx ); } continue; } else { SPY_LOG_PRINT( LFS_DEBUG_LIB_INFO, ("[LFS] RedirDataGramSvrThreadProc: KeWaitForMultipleObjects() failed. NTSTATUS:%lu\n", status) ); break; } // get packets to the dispatch routine. while (1) { listEntry = ExInterlockedRemoveHeadList( &SvrCtx->RecvDGPktQueue, &SvrCtx->RecvDGPktQSpinLock ); if (!listEntry) { SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, ("[LFS] RedirDataGramSvrThreadProc: Datagram queue empty. back to waiting mode.\n") ); break; } pkt = CONTAINING_RECORD( listEntry, LFSDG_PKT, PktListEntry ); bret = DispatchDGReqPkt( SvrCtx, pkt ); if (FALSE == bret) { SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, ( "[LFS] RedirDataGramSvrThreadProc: Don't send a reply.\n") ); } else { SPY_LOG_PRINT( LFS_DEBUG_LIB_INFO, ( "[LFS] RedirDataGramSvrThreadProc: Send a reply.\n") ); status = LfsSendDatagram( &ServerDatagramSocket, pkt, &pkt->SourceAddr ); if (status != STATUS_SUCCESS) { SPY_LOG_PRINT( LFS_DEBUG_LIB_INFO, ( "[LFS] RedirDataGramSvrThreadProc: LfsSendDatagram() failed.\n")); } } // dereference the datagram packet LfsDereferenceDGPkt( pkt ); } } LfsCloseDGSocket( &ServerDatagramSocket ); // free datagram packets. while (1) { listEntry = ExInterlockedRemoveHeadList( &SvrCtx->RecvDGPktQueue, &SvrCtx->RecvDGPktQSpinLock ); if (!listEntry) { SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, ("[LFS] RedirDataGramSvrThreadProc: Cleared datagram packets.\n") ); break; } pkt = CONTAINING_RECORD(listEntry, LFSDG_PKT, PktListEntry); LfsDereferenceDGPkt( pkt ); } SPY_LOG_PRINT( LFS_DEBUG_LIB_INFO, ( "[LFS] RedirDataGramSvrThreadProc: terminated..\n") ); PsTerminateSystemThread(0); return; }
VOID VolDoThreadProc ( IN PVOLUME_DEVICE_OBJECT VolDo ) { BOOLEAN volDoThreadTerminate = FALSE; DebugTrace( 0, Dbg2, ("VolDoThreadProc: Start VolDo = %p\n", VolDo) ); VolDo_Reference( VolDo ); VolDo->Thread.Flags = VOLDO_THREAD_FLAG_INITIALIZING; ExAcquireFastMutex( &VolDo->FastMutex ); ClearFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_INITIALIZING ); SetFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_START ); ExReleaseFastMutex( &VolDo->FastMutex ); KeSetEvent( &VolDo->ReadyEvent, IO_DISK_INCREMENT, FALSE ); volDoThreadTerminate = FALSE; while (volDoThreadTerminate == FALSE) { PKEVENT events[2]; LONG eventCount; NTSTATUS eventStatus; LARGE_INTEGER timeOut; ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); eventCount = 0; events[eventCount++] = &VolDo->RequestEvent; timeOut.QuadPart = -NDNTFS_VOLDO_THREAD_FLAG_TIME_OUT; eventStatus = KeWaitForMultipleObjects( eventCount, events, WaitAny, Executive, KernelMode, TRUE, &timeOut, NULL ); if (eventStatus == STATUS_TIMEOUT) { LARGE_INTEGER currentTime; KeQuerySystemTime( ¤tTime ); if (FlagOn(VolDo->NdasNtfsFlags, NDAS_NTFS_DEVICE_FLAG_SHUTDOWN) || !(FlagOn(VolDo->NdasNtfsFlags, NDAS_NTFS_DEVICE_FLAG_MOUNTED) /*&& !FlagOn(LfsDeviceExt->Flags, LFS_DEVICE_STOP)*/)) { continue; } if ((VolDo->NetdiskEnableMode == NETDISK_READ_ONLY && (VolDo->TryFlushOrPurgeTime.QuadPart > currentTime.QuadPart || (currentTime.QuadPart - VolDo->TryFlushOrPurgeTime.QuadPart) >= NDNTFS_TRY_PURGE_DURATION)) || (VolDo->ReceiveWriteCommand == TRUE && (VolDo->TryFlushOrPurgeTime.QuadPart > currentTime.QuadPart || (currentTime.QuadPart - VolDo->TryFlushOrPurgeTime.QuadPart) >= NDNTFS_TRY_FLUSH_DURATION))) { if (VolDo->NetdiskEnableMode != NETDISK_READ_ONLY && (currentTime.QuadPart - VolDo->CommandReceiveTime.QuadPart) <= NDNTFS_TRY_FLUSH_DURATION /*&& (currentTime.QuadPart - VolDo->TryFlushOrPurgeTime.QuadPart) <= (100*NDNTFS_TRY_FLUSH_OR_PURGE_DURATION)*/) { continue; } do { HANDLE eventHandle = NULL; HANDLE fileHandle = NULL; ACCESS_MASK desiredAccess; ULONG attributes; OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK ioStatusBlock; LARGE_INTEGER allocationSize; ULONG fileAttributes; ULONG shareAccess; ULONG createDisposition; ULONG createOptions; PVOID eaBuffer; ULONG eaLength; NTSTATUS createStatus; NTSTATUS fileSystemControlStatus; PIRP topLevelIrp; PRIMARY_REQUEST_INFO primaryRequestInfo; ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); if (VolDo->NetdiskEnableMode == NETDISK_SECONDARY) { break; } DebugTrace( 0, Dbg2, ("VolDoThreadProc: VolDo = %p, VolDo->NetdiskPartitionInformation.VolumeName = %wZ\n", VolDo, &VolDo->NetdiskPartitionInformation.VolumeName) ); desiredAccess = SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_WRITE_EA | FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_READ_EA; ASSERT( desiredAccess == 0x0012019F ); attributes = OBJ_KERNEL_HANDLE; attributes |= OBJ_CASE_INSENSITIVE; InitializeObjectAttributes( &objectAttributes, &VolDo->NetdiskPartitionInformation.VolumeName, attributes, NULL, NULL ); allocationSize.LowPart = 0; allocationSize.HighPart = 0; fileAttributes = 0; shareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE; createDisposition = FILE_OPEN; createOptions = FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE; eaBuffer = NULL; eaLength = 0; RtlZeroMemory( &ioStatusBlock, sizeof(ioStatusBlock) ); createStatus = ZwCreateFile( &fileHandle, desiredAccess, &objectAttributes, &ioStatusBlock, &allocationSize, fileAttributes, shareAccess, createDisposition, createOptions, eaBuffer, eaLength ); if (createStatus != STATUS_SUCCESS) break; ASSERT( ioStatusBlock.Information == FILE_OPENED); createStatus = ZwCreateEvent( &eventHandle, GENERIC_READ, NULL, SynchronizationEvent, FALSE ); if (createStatus != STATUS_SUCCESS) { ASSERT( NDASNTFS_UNEXPECTED ); ZwClose( fileHandle ); break; } primaryRequestInfo.PrimaryTag = 0xe2027482; primaryRequestInfo.PrimarySessionId = NDASNTFS_LOCAL_PRMARY_SESSION_ID; primaryRequestInfo.PrimarySession = NULL; primaryRequestInfo.NdfsWinxpRequestHeader = NULL; topLevelIrp = IoGetTopLevelIrp(); ASSERT( topLevelIrp == NULL ); IoSetTopLevelIrp( (PIRP)&primaryRequestInfo ); RtlZeroMemory( &ioStatusBlock, sizeof(ioStatusBlock) ); fileSystemControlStatus = ZwFsControlFile( fileHandle, NULL, //&eventHandle, NULL, NULL, &ioStatusBlock, (VolDo->NetdiskEnableMode == NETDISK_READ_ONLY) ? FSCTL_NDAS_FS_PURGE : FSCTL_NDAS_FS_FLUSH, NULL, 0, NULL, 0 ); DebugTrace( 0, Dbg2, ("VolDoThreadProc: VolDo = %p, createStatus = %x, ioStatusBlock = %x\n", VolDo, fileSystemControlStatus, ioStatusBlock.Information) ); if (fileSystemControlStatus == STATUS_PENDING) { LARGE_INTEGER timeOut; timeOut.QuadPart = -3*NANO100_PER_SEC; ASSERT( FALSE ); //fileSystemControlStatus = ZwWaitForSingleObject( eventHandle, TRUE,NULL /*, &timeOut*/ ); } IoSetTopLevelIrp( topLevelIrp ); if (fileSystemControlStatus != STATUS_SUCCESS) DebugTrace( 0, Dbg2, ("VolDoThreadProc: VolDo = %p, fileSystemControlStatus = %x, ioStatusBlock = %x\n", VolDo, fileSystemControlStatus, ioStatusBlock.Information) ); ZwClose( eventHandle ); ZwClose( fileHandle ); break; } while (0); KeQuerySystemTime( &VolDo->TryFlushOrPurgeTime ); VolDo->ReceiveWriteCommand = FALSE; } continue; } ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); ASSERT( eventCount < THREAD_WAIT_OBJECTS ); if (!NT_SUCCESS( eventStatus ) || eventStatus >= eventCount) { ASSERT( NDASNTFS_UNEXPECTED ); SetFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_ERROR ); volDoThreadTerminate = TRUE; continue; } KeClearEvent( events[eventStatus] ); if (eventStatus == 0) { volDoThreadTerminate = TRUE; break; } else { NDAS_ASSERT( NDASNTFS_BUG ); } } ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); ExAcquireFastMutex( &VolDo->FastMutex ); SetFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_STOPED ); ExReleaseFastMutex( &VolDo->FastMutex ); DebugTrace( 0, Dbg2, ("VolDoThreadProc: PsTerminateSystemThread VolDo = %p\n", VolDo) ); ExAcquireFastMutex( &VolDo->FastMutex ); SetFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_TERMINATED ); ExReleaseFastMutex( &VolDo->FastMutex ); VolDo_Dereference( VolDo ); ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); PsTerminateSystemThread( STATUS_SUCCESS ); }
static VOID NTAPI QueueThread(PVOID Context) /* * FUNCTION: Thread that manages the queue and dispatches any queued requests * ARGUMENTS: * Context: unused */ { PIRP Irp; PIO_STACK_LOCATION Stack; PDEVICE_OBJECT DeviceObject; PVOID Objects[2]; PAGED_CODE(); UNREFERENCED_PARAMETER(Context); Objects[0] = &QueueSemaphore; Objects[1] = &QueueThreadTerminate; for(;;) { KeWaitForMultipleObjects(2, Objects, WaitAny, Executive, KernelMode, FALSE, NULL, NULL); if(KeReadStateEvent(&QueueThreadTerminate)) { INFO_(FLOPPY, "QueueThread terminating\n"); return; } INFO_(FLOPPY, "QueueThread: servicing an IRP\n"); Irp = IoCsqRemoveNextIrp(&Csq, 0); /* we won't get an irp if it was canceled */ if(!Irp) { INFO_(FLOPPY, "QueueThread: IRP queue empty\n"); continue; } DeviceObject = (PDEVICE_OBJECT)Irp->Tail.Overlay.DriverContext[0]; ASSERT(DeviceObject); Stack = IoGetCurrentIrpStackLocation(Irp); /* Decide what to do with the IRP */ switch(Stack->MajorFunction) { case IRP_MJ_READ: case IRP_MJ_WRITE: ReadWritePassive(DeviceObject->DeviceExtension, Irp); break; case IRP_MJ_DEVICE_CONTROL: DeviceIoctlPassive(DeviceObject->DeviceExtension, Irp); break; default: WARN_(FLOPPY, "QueueThread(): Unrecognized irp: mj: 0x%x\n", Stack->MajorFunction); Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); } } }
LONG NTAPI Send( __in PWSK_SOCKET WskSocket, __in PVOID Buffer, __in ULONG BufferSize, __in ULONG Flags, __in ULONG Timeout, __in KEVENT *send_buf_kill_event, __in struct drbd_transport *transport, __in enum drbd_stream stream ) { KEVENT CompletionEvent = { 0 }; PIRP Irp = NULL; WSK_BUF WskBuffer = { 0 }; LONG BytesSent = SOCKET_ERROR; // DRBC_CHECK_WSK: SOCKET_ERROR be mixed EINVAL? NTSTATUS Status = STATUS_UNSUCCESSFUL; if (g_SocketsState != INITIALIZED || !WskSocket || !Buffer || ((int) BufferSize <= 0)) return SOCKET_ERROR; Status = InitWskBuffer(Buffer, BufferSize, &WskBuffer); if (!NT_SUCCESS(Status)) { return SOCKET_ERROR; } Status = InitWskData(&Irp, &CompletionEvent); if (!NT_SUCCESS(Status)) { FreeWskBuffer(&WskBuffer); return SOCKET_ERROR; } Flags |= WSK_FLAG_NODELAY; Status = ((PWSK_PROVIDER_CONNECTION_DISPATCH) WskSocket->Dispatch)->WskSend( WskSocket, &WskBuffer, Flags, Irp); if (Status == STATUS_PENDING) { LARGE_INTEGER nWaitTime; LARGE_INTEGER *pTime; int retry_count = 0; retry: if (Timeout <= 0 || Timeout == MAX_SCHEDULE_TIMEOUT) { pTime = NULL; } else { nWaitTime = RtlConvertLongToLargeInteger(-1 * Timeout * 1000 * 10); pTime = &nWaitTime; } { struct task_struct *thread = current; PVOID waitObjects[2]; int wObjCount = 1; waitObjects[0] = (PVOID) &CompletionEvent; #ifndef _WIN32_SEND_BUFFING // in send-buffering, Netlink , call_usermodehelper are distinguished to SendLocal // KILL event is only used in send-buffering thread while send block. // WIN32_V9_REFACTO_:required to refactoring that input param, log message are simplized. #else #endif Status = KeWaitForMultipleObjects(wObjCount, &waitObjects[0], WaitAny, Executive, KernelMode, FALSE, pTime, NULL); switch (Status) { case STATUS_TIMEOUT: #ifdef _WIN32_SEND_BUFFING if (wObjCount == 1) { retry_count++; WDRBD_WARN("(%s) sent timeout=%d sz=%d retry_count=%d WskSocket=%p IRP=%p\n", current->comm, Timeout, BufferSize, retry_count,WskSocket, Irp); // required to refactroing about retrying method. goto retry; } #endif if (transport != NULL) { if (!drbd_stream_send_timed_out(transport, stream)) { goto retry; } } IoCancelIrp(Irp); KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); BytesSent = -EAGAIN; break; case STATUS_WAIT_0: if (NT_SUCCESS(Irp->IoStatus.Status)) { BytesSent = (LONG)Irp->IoStatus.Information; } else { WDRBD_WARN("tx error(%s) wsk(0x%p)\n", GetSockErrorString(Irp->IoStatus.Status), WskSocket); switch (Irp->IoStatus.Status) { case STATUS_IO_TIMEOUT: BytesSent = -EAGAIN; break; case STATUS_INVALID_DEVICE_STATE: BytesSent = -EAGAIN; break; default: BytesSent = -ECONNRESET; break; } } break; //case STATUS_WAIT_1: // common: sender or send_bufferinf thread's kill signal // IoCancelIrp(Irp); // KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); // BytesSent = -EINTR; // break; default: WDRBD_ERROR("Wait failed. status 0x%x\n", Status); BytesSent = SOCKET_ERROR; } } } else { if (Status == STATUS_SUCCESS) { BytesSent = (LONG) Irp->IoStatus.Information; WDRBD_WARN("(%s) WskSend No pending: but sent(%d)!\n", current->comm, BytesSent); } else { WDRBD_WARN("(%s) WskSend error(0x%x)\n", current->comm, Status); BytesSent = SOCKET_ERROR; } } IoFreeIrp(Irp); FreeWskBuffer(&WskBuffer); return BytesSent; }
// Worker thread for processing all tunnel events _Use_decl_annotations_ VOID otLwfTunWorkerThread( PVOID Context ) { PMS_FILTER pFilter = (PMS_FILTER)Context; NT_ASSERT(pFilter); LogFuncEntry(DRIVER_DEFAULT); PKEVENT WaitEvents[] = { &pFilter->TunWorkerThreadStopEvent, &pFilter->TunWorkerThreadAddressChangedEvent }; LogFuncExit(DRIVER_DEFAULT); while (true) { // Wait for event to stop or process event to fire NTSTATUS status = KeWaitForMultipleObjects( ARRAYSIZE(WaitEvents), (PVOID*)WaitEvents, WaitAny, Executive, KernelMode, FALSE, NULL, NULL); // If it is the first event, then we are shutting down. Exit loop and terminate thread if (status == STATUS_WAIT_0) { LogInfo(DRIVER_DEFAULT, "Received tunnel worker thread shutdown event."); break; } else if (status == STATUS_WAIT_0 + 1) // TunWorkerThreadAddressChangedEvent fired { PVOID DataBuffer = NULL; const uint8_t* value_data_ptr = NULL; spinel_size_t value_data_len = 0; // Query the current addresses status = otLwfCmdGetProp( pFilter, &DataBuffer, SPINEL_PROP_IPV6_ADDRESS_TABLE, SPINEL_DATATYPE_DATA_S, &value_data_ptr, &value_data_len); if (NT_SUCCESS(status)) { uint32_t aNotifFlags = 0; otLwfTunAddressesUpdated(pFilter, value_data_ptr, value_data_len, &aNotifFlags); // Send notification if (aNotifFlags != 0) { PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter); if (NotifEntry) { RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY)); NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid; NotifEntry->Notif.NotifType = OTLWF_NOTIF_STATE_CHANGE; NotifEntry->Notif.StateChangePayload.Flags = aNotifFlags; otLwfIndicateNotification(NotifEntry); } } } else { LogWarning(DRIVER_DEFAULT, "Failed to query addresses, %!STATUS!", status); } if (DataBuffer) FILTER_FREE_MEM(DataBuffer); } else { LogWarning(DRIVER_DEFAULT, "Unexpected wait result, %!STATUS!", status); } } PsTerminateSystemThread(STATUS_SUCCESS); }
VOID PrimaryAgentThreadProc( IN PPRIMARY Primary ) { BOOLEAN primaryAgentThreadExit = FALSE; ULONG listenSocketIndex; PKWAIT_BLOCK waitBlocks; SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, ("PrimaryAgentThreadProc: Start\n")); Primary->Agent.Flags |= PRIMARY_AGENT_INITIALIZING; // // Allocate wait block // waitBlocks = ExAllocatePool(NonPagedPool, sizeof(KWAIT_BLOCK) * MAXIMUM_WAIT_OBJECTS); if(waitBlocks == NULL) { ASSERT(LFS_REQUIRED); PsTerminateSystemThread(STATUS_INSUFFICIENT_RESOURCES); } for(listenSocketIndex=0; listenSocketIndex<MAX_SOCKETLPX_INTERFACE; listenSocketIndex++) KeInitializeEvent( &Primary->Agent.ListenSocket[listenSocketIndex].TdiListenContext.CompletionEvent, NotificationEvent, FALSE ); BindListenSockets( Primary ); Primary->Agent.Flags |= PRIMARY_AGENT_START; KeSetEvent(&Primary->Agent.ReadyEvent, IO_DISK_INCREMENT, FALSE); while(primaryAgentThreadExit == FALSE) { PKEVENT events[MAXIMUM_WAIT_OBJECTS]; LONG eventCnt; ULONG i; LARGE_INTEGER timeOut; NTSTATUS ntStatus; PLIST_ENTRY primaryAgentRequestEntry; ASSERT(MAX_SOCKETLPX_INTERFACE + 1 <= MAXIMUM_WAIT_OBJECTS); eventCnt = 0; events[eventCnt++] = &Primary->Agent.RequestEvent; if(!BooleanFlagOn(Primary->Agent.Flags, PRIMARY_AGENT_SHUTDOWN)) { for(i=0; i<MAX_SOCKETLPX_INTERFACE; i++) { if(Primary->Agent.ListenSocket[i].TdiListenContext.Irp && Primary->Agent.ListenSocket[i].Active) { events[eventCnt++] = &Primary->Agent.ListenSocket[i].TdiListenContext.CompletionEvent; } else { // events[eventCnt++] = NULL; // I wanna set NULL, But It's not Work events[eventCnt++] = &Primary->Agent.ListenSocket[i].TdiListenContext.CompletionEvent; } } ASSERT(eventCnt == MAX_SOCKETLPX_INTERFACE + 1); } timeOut.QuadPart = - 5 * HZ; ntStatus = KeWaitForMultipleObjects( eventCnt, events, WaitAny, Executive, KernelMode, TRUE, &timeOut, waitBlocks ); if(ntStatus == STATUS_TIMEOUT) { continue; } SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("PrimaryAgentThreadProc: NTSTATUS:%lu\n", ntStatus)); if(!NT_SUCCESS(ntStatus) || ntStatus >= eventCnt) { ASSERT(LFS_UNEXPECTED); SetFlag(Primary->Agent.Flags, PRIMARY_AGENT_ERROR); primaryAgentThreadExit = TRUE; continue; } KeClearEvent(events[ntStatus]); if(0 == ntStatus) { SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("PrimaryAgentThreadProc: RequestEvent received\n")); while(primaryAgentRequestEntry = ExInterlockedRemoveHeadList( &Primary->Agent.RequestQueue, &Primary->Agent.RequestQSpinLock ) ) { PPRIMARY_AGENT_REQUEST primaryAgentRequest; primaryAgentRequest = CONTAINING_RECORD( primaryAgentRequestEntry, PRIMARY_AGENT_REQUEST, ListEntry ); switch(primaryAgentRequest->RequestType) { case PRIMARY_AGENT_REQ_DISCONNECT: { CloseListenSockets( Primary, FALSE ); break; } case PRIMARY_AGENT_REQ_SHUTDOWN: { CloseListenSockets( Primary, TRUE ); SetFlag(Primary->Agent.Flags, PRIMARY_AGENT_SHUTDOWN); break; } case PRIMARY_AGENT_REQ_DOWN: primaryAgentThreadExit = TRUE; break; // // added to adapt network card changes. // case PRIMARY_AGENT_REQ_NIC_DISABLED: SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, ("PrimaryAgentThreadProc: PRIMARY_AGENT_REQ_NIC_DISABLED\n")); PrimaryAgentNICDisabled(Primary, &primaryAgentRequest->AddressList); break; case PRIMARY_AGENT_REQ_NIC_ENABLED: SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("PrimaryAgentThreadProc: PRIMARY_AGENT_REQ_NIC_ENABLED\n")); PrimaryAgentNICEnabled(Primary, &primaryAgentRequest->AddressList); break; default: ASSERT(LFS_BUG); SetFlag(Primary->Agent.Flags, PRIMARY_AGENT_ERROR); break; } if(primaryAgentRequest->Synchronous == TRUE) KeSetEvent(&primaryAgentRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE); else DereferencePrimaryAgentRequest( primaryAgentRequest ); } continue; } ASSERT(1 <= ntStatus && ntStatus < eventCnt); // LpxEvent if( 1 <= ntStatus && ntStatus <= MAX_SOCKETLPX_INTERFACE ) // Connected { NTSTATUS tdiStatus; HANDLE listenFileHandle; PFILE_OBJECT listenFileObject; HANDLE connFileHandle; PFILE_OBJECT connFileObject; PPRIMARY_LISTEN_SOCKET listenSocket; LPX_ADDRESS remoteAddress; listenSocket = &Primary->Agent.ListenSocket[ntStatus-1]; // // retreive a connection file and remote address. // connFileHandle = listenSocket->ListenFileHandle; connFileObject = listenSocket->ListenFileObject; RtlCopyMemory(&remoteAddress, &listenSocket->TdiListenContext.RemoteAddress, sizeof(LPX_ADDRESS)); listenSocket->TdiListenContext.Irp = NULL; listenSocket->ListenFileHandle = NULL; listenSocket->ListenFileObject = NULL; KeClearEvent(&listenSocket->TdiListenContext.CompletionEvent); if(!listenSocket->Active) { SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, ("ListenSocket is not active. Maybe a NIC disabled.\n")); continue; } else if(listenSocket->TdiListenContext.Status != STATUS_SUCCESS) { LpxTdiCloseAddress ( listenSocket->AddressFileHandle, listenSocket->AddressFileObject ); listenSocket->Active = FALSE; Primary->Agent.ActiveListenSocketCount --; SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, ("Listen IRP #%d failed.\n", ntStatus)); continue; } SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, ("PrimaryAgentThreadProc: Connect from %02X:%02X:%02X:%02X:%02X:%02X 0x%4X\n", listenSocket->TdiListenContext.RemoteAddress.Node[0], listenSocket->TdiListenContext.RemoteAddress.Node[1], listenSocket->TdiListenContext.RemoteAddress.Node[2], listenSocket->TdiListenContext.RemoteAddress.Node[3], listenSocket->TdiListenContext.RemoteAddress.Node[4], listenSocket->TdiListenContext.RemoteAddress.Node[5], NTOHS(listenSocket->TdiListenContext.RemoteAddress.Port) )); // // Make a new listen connection first of all to get another connection. // It must be earlier than start a session that takes long time. // Primary cannot accept a connection before it creates a new listen object. // tdiStatus = MakeConnectionObject( listenSocket->AddressFileHandle, listenSocket->AddressFileObject, &listenFileHandle, &listenFileObject ); if(!NT_SUCCESS(tdiStatus)) { ASSERT(LPX_BUG); LpxTdiCloseAddress ( listenSocket->AddressFileHandle, listenSocket->AddressFileObject ); listenSocket->Active = FALSE; Primary->Agent.ActiveListenSocketCount --; goto start_session; } listenSocket->ListenFileHandle = listenFileHandle; listenSocket->ListenFileObject = listenFileObject; listenSocket->Flags = TDI_QUERY_ACCEPT; tdiStatus = LpxTdiListenWithCompletionEvent( listenSocket->ListenFileObject, &listenSocket->TdiListenContext, &listenSocket->Flags ); if(!NT_SUCCESS(tdiStatus)) { ASSERT(LPX_BUG); LpxTdiDisassociateAddress(listenFileObject); LpxTdiCloseConnection(listenFileHandle, listenFileObject); LpxTdiCloseAddress ( listenSocket->AddressFileHandle, listenSocket->AddressFileObject ); listenSocket->Active = FALSE; Primary->Agent.ActiveListenSocketCount --; } start_session: // // start a session. // Primary_AcceptConnection(Primary, connFileHandle, connFileObject, ntStatus-1, &remoteAddress); continue; } } for(listenSocketIndex=0; listenSocketIndex<MAX_SOCKETLPX_INTERFACE; listenSocketIndex++) KeClearEvent(&Primary->Agent.ListenSocket[listenSocketIndex].TdiListenContext.CompletionEvent); // // Free wait blocks // ExFreePool(waitBlocks); SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, ("PrimaryAgentThreadProc: PsTerminateSystemThread\n")); Primary->Agent.Flags |= PRIMARY_AGENT_TERMINATED; PsTerminateSystemThread(STATUS_SUCCESS); }
VOID HvlCtxSWorkItem( PVOID Context, NDIS_HANDLE NdisIoWorkItemHandle ) { NTSTATUS ntStatus = STATUS_SUCCESS; PHVL pHvl = NULL; LARGE_INTEGER waitTime = {0}; #define NUM_EVENTS 3 PVOID EventArray[NUM_EVENTS]; BOOLEAN fTerminating = FALSE; UNREFERENCED_PARAMETER(NdisIoWorkItemHandle); if (NULL == Context) { MPASSERT(Context != NULL); return; } pHvl = (PHVL) Context; EventArray[0] = &pHvl->TerminatingEvent; EventArray[1] = &pHvl->CtxSEvent; EventArray[2] = &pHvl->ExAccessEvent; /* The waitTime should ideally be a function of the beacon period. For now assume a constant */ waitTime.QuadPart = HVL_DEFAULT_CONTEXT_SWITCH_PARK_TIME_MSEC * -1; do { ntStatus = KeWaitForMultipleObjects(NUM_EVENTS, EventArray, WaitAny, Executive, KernelMode, FALSE, &waitTime, NULL); switch (ntStatus) { case STATUS_TIMEOUT: // timed context switch processing. HvlProcessTimedCtxSwitch(pHvl); // optionally set a different waitTime for the next wait break; case STATUS_WAIT_0: // we are terminating. Time to get rid of this work item processing HvlLock(pHvl); pHvl->ulNumThreadsPending--; HvlUnlock(pHvl); fTerminating = TRUE; break; case STATUS_WAIT_1: // we are asked to do context switch processing HvlProcessTimedCtxSwitch(pHvl); break; case STATUS_WAIT_2: // we have a new request for exclusive access HvlProcessExAccessReq(pHvl); break; default: MpTrace(COMP_HVL, DBG_SERIOUS, ("KeWaitForMultipleObjects returned error 0x%x", ntStatus)); break; } } while (!fTerminating); }
VOID IOThread(IN PVOID Context) { KIRQL currentIrql, oldIrql; LARGE_INTEGER timeout, maxTimeout; NTSTATUS status = STATUS_SUCCESS; PRING_BUFFER pRb; const PCHAR pMsg = "messahe1"; ULONG size = 8; INT_PTR state; PKTIMER pTimer; LONG interval; PVOID pObjects[3]; // wait for KeSetEvent(&StartEvent, 0, FALSE); timeout.QuadPart = -6000 * 10000; // 10 sec interval = 20000; // 5 sec maxTimeout.QuadPart = -20000 * 10000; InitRingBuffer(&pRb); state = (INT_PTR) ExAllocatePool(NonPagedPool, sizeof(INT)); // Set timer for periodic flush pTimer=(PKTIMER) ExAllocatePool(NonPagedPool, sizeof(KTIMER)); KeInitializeTimerEx(pTimer, SynchronizationTimer); KeSetTimerEx(pTimer, timeout, interval, NULL); pObjects[0] = pTimer; // periodic timer pObjects[1] = &StopEvent; // stop flush loop pObjects[2] = &FlushEvent; // do flush, buffer is full // Flush loop while (status != STATUS_WAIT_1) { status = KeWaitForMultipleObjects( 3, pObjects, WaitAny, Executive, KernelMode, FALSE, &maxTimeout, NULL); if (status == STATUS_WAIT_0) { DbgPrint("Timer flush\n"); } else if (status == STATUS_WAIT_2) { DbgPrint("RB flush\n"); } else if (status == STATUS_TIMEOUT) { DbgPrint("Timeout delay\n"); break; } //Klog("Msg from klog %d\s", 123); KloggerWriteToFile(); //DbgPrint("State: %d\n", state); } DbgPrint("klogger.sys: IOThread get stop signal\n"); // Free resources KeCancelTimer(pTimer); ExFreePool(pTimer); FreeRingBuffer(pRb); PsTerminateSystemThread(status); }
VOID ReadonlyThreadProc ( IN PREADONLY Readonly ) { BOOLEAN readonlyThreadTerminate = FALSE; PLIST_ENTRY readonlyRequestEntry; SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE, ("ReadonlyThreadProc: Start Readonly = %p\n", Readonly) ); Readonly_Reference( Readonly ); Readonly->Thread.Flags = READONLY_THREAD_FLAG_INITIALIZING; ExAcquireFastMutex( &Readonly->FastMutex ); SetFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_START ); ClearFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_INITIALIZING ); ExReleaseFastMutex( &Readonly->FastMutex ); KeSetEvent( &Readonly->ReadyEvent, IO_DISK_INCREMENT, FALSE ); readonlyThreadTerminate = FALSE; while (readonlyThreadTerminate == FALSE) { PKEVENT events[2]; LONG eventCount; NTSTATUS eventStatus; LARGE_INTEGER timeOut; ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); eventCount = 0; events[eventCount++] = &Readonly->RequestEvent; timeOut.QuadPart = -LFS_READONLY_THREAD_FLAG_TIME_OUT; eventStatus = KeWaitForMultipleObjects( eventCount, events, WaitAny, Executive, KernelMode, TRUE, &timeOut, NULL ); if (eventStatus == STATUS_TIMEOUT) { ReadonlyTryCloseCcb( Readonly ); ReadonlyDismountVolumeStart( Readonly ); continue; } ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); ASSERT( eventCount < THREAD_WAIT_OBJECTS ); if (!NT_SUCCESS( eventStatus ) || eventStatus >= eventCount) { ASSERT( LFS_UNEXPECTED ); SetFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_ERROR ); readonlyThreadTerminate = TRUE; continue; } KeClearEvent( events[eventStatus] ); if (eventStatus == 0) { while (!FlagOn(Readonly->Thread.Flags, READONLY_THREAD_FLAG_STOPED) && (readonlyRequestEntry = ExInterlockedRemoveHeadList(&Readonly->RequestQueue, &Readonly->RequestQSpinLock))) { PREADONLY_REQUEST readonlyRequest; InitializeListHead( readonlyRequestEntry ); readonlyRequest = CONTAINING_RECORD( readonlyRequestEntry, READONLY_REQUEST, ListEntry ); if (!(readonlyRequest->RequestType == READONLY_REQ_DISCONNECT || readonlyRequest->RequestType == READONLY_REQ_DOWN || readonlyRequest->RequestType == READONLY_REQ_SEND_MESSAGE)) { ASSERT( FALSE ); ExAcquireFastMutex( &Readonly->FastMutex ); SetFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_STOPED | READONLY_THREAD_FLAG_ERROR ); ExReleaseFastMutex( &Readonly->FastMutex ); ExInterlockedInsertHeadList( &Readonly->RequestQueue, &readonlyRequest->ListEntry, &Readonly->RequestQSpinLock ); readonlyThreadTerminate = TRUE; break; } if (readonlyRequest->RequestType == READONLY_REQ_DISCONNECT) { if (readonlyRequest->Synchronous == TRUE) KeSetEvent(&readonlyRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE); else DereferenceReadonlyRequest( readonlyRequest ); continue; } if (readonlyRequest->RequestType == READONLY_REQ_DOWN) { SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE, ("ReadonlyThread READONLY_REQ_DOWN Readonly = %p\n", Readonly) ); ExAcquireFastMutex( &Readonly->FastMutex ); SetFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_STOPED ); ExReleaseFastMutex( &Readonly->FastMutex ); ASSERT( IsListEmpty(&Readonly->RequestQueue) ); if (readonlyRequest->Synchronous == TRUE) KeSetEvent( &readonlyRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE ); else DereferenceReadonlyRequest( readonlyRequest ); readonlyThreadTerminate = TRUE; break; } ASSERT( readonlyRequest->RequestType == READONLY_REQ_SEND_MESSAGE ); ASSERT( readonlyRequest->Synchronous == TRUE ); } // while } else { NDAS_ASSERT( FALSE ); } } ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); ExAcquireFastMutex( &Readonly->FastMutex ); SetFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_STOPED ); while (readonlyRequestEntry = ExInterlockedRemoveHeadList(&Readonly->RequestQueue, &Readonly->RequestQSpinLock)) { PREADONLY_REQUEST readonlyRequest; InitializeListHead( readonlyRequestEntry ); readonlyRequest = CONTAINING_RECORD( readonlyRequestEntry, READONLY_REQUEST, ListEntry ); readonlyRequest->ExecuteStatus = STATUS_IO_DEVICE_ERROR; if (readonlyRequest->Synchronous == TRUE) KeSetEvent( &readonlyRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE ); else DereferenceReadonlyRequest( readonlyRequest ); } ExReleaseFastMutex( &Readonly->FastMutex ); SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE, ("ReadonlyThreadProc: PsTerminateSystemThread Readonly = %p, IsListEmpty(&Readonly->RequestQueue) = %d\n", Readonly, IsListEmpty(&Readonly->RequestQueue)) ); ExAcquireFastMutex( &Readonly->FastMutex ); SetFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_TERMINATED ); ExReleaseFastMutex( &Readonly->FastMutex ); Readonly_Dereference( Readonly ); ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); PsTerminateSystemThread( STATUS_SUCCESS ); }
VOID NTAPI MiBalancerThread(PVOID Unused) { PVOID WaitObjects[2]; NTSTATUS Status; ULONG i; ULONG NrFreedPages; ULONG NrPagesUsed; ULONG Target; BOOLEAN ShouldRun; WaitObjects[0] = &MiBalancerEvent; WaitObjects[1] = &MiBalancerTimer; while (1) { Status = KeWaitForMultipleObjects(2, WaitObjects, WaitAny, Executive, KernelMode, FALSE, NULL, NULL); if (Status == STATUS_SUCCESS) { /* MiBalancerEvent */ while (MmAvailablePages < MiMinimumAvailablePages + 5) { for (i = 0; i < MC_MAXIMUM; i++) { if (MiMemoryConsumers[i].Trim != NULL) { NrFreedPages = 0; Status = MiMemoryConsumers[i].Trim(MiMinimumPagesPerRun, 0, &NrFreedPages); if (!NT_SUCCESS(Status)) { KeBugCheck(MEMORY_MANAGEMENT); } } } } InterlockedExchange(&MiBalancerWork, 0); } else if (Status == STATUS_SUCCESS + 1) { /* MiBalancerTimer */ ShouldRun = MmAvailablePages < MiMinimumAvailablePages + 5 ? TRUE : FALSE; for (i = 0; i < MC_MAXIMUM; i++) { if (MiMemoryConsumers[i].Trim != NULL) { NrPagesUsed = MiMemoryConsumers[i].PagesUsed; if (NrPagesUsed > MiMemoryConsumers[i].PagesTarget || ShouldRun) { if (NrPagesUsed > MiMemoryConsumers[i].PagesTarget) { Target = max (NrPagesUsed - MiMemoryConsumers[i].PagesTarget, MiMinimumPagesPerRun); } else { Target = MiMinimumPagesPerRun; } NrFreedPages = 0; Status = MiMemoryConsumers[i].Trim(Target, 0, &NrFreedPages); if (!NT_SUCCESS(Status)) { KeBugCheck(MEMORY_MANAGEMENT); } } } } } else { DPRINT1("KeWaitForMultipleObjects failed, status = %x\n", Status); KeBugCheck(MEMORY_MANAGEMENT); } } }
PWSK_SOCKET NTAPI Accept( __in PWSK_SOCKET WskSocket, __out_opt PSOCKADDR LocalAddress, __out_opt PSOCKADDR RemoteAddress, __out_opt NTSTATUS *RetStaus, __in int timeout ) { KEVENT CompletionEvent = { 0 }; PIRP Irp = NULL; NTSTATUS Status = STATUS_UNSUCCESSFUL; PWSK_SOCKET AcceptedSocket = NULL; struct task_struct *thread = current; PVOID waitObjects[2]; int wObjCount = 1; if (g_SocketsState != INITIALIZED || !WskSocket) { *RetStaus = SOCKET_ERROR; return NULL; } Status = InitWskData(&Irp, &CompletionEvent); if (!NT_SUCCESS(Status)) { *RetStaus = Status; return NULL; } Status = ((PWSK_PROVIDER_LISTEN_DISPATCH) WskSocket->Dispatch)->WskAccept( WskSocket, 0, NULL, NULL, LocalAddress, RemoteAddress, Irp); if (Status == STATUS_PENDING) { LARGE_INTEGER nWaitTime; LARGE_INTEGER *pTime; if (timeout <= 0 || timeout == MAX_SCHEDULE_TIMEOUT) { pTime = 0; } else { nWaitTime = RtlConvertLongToLargeInteger(-1 * timeout * 10000000); pTime = &nWaitTime; } waitObjects[0] = (PVOID) &CompletionEvent; if (thread->has_sig_event) { waitObjects[1] = (PVOID) &thread->sig_event; wObjCount = 2; } Status = KeWaitForMultipleObjects(wObjCount, &waitObjects[0], WaitAny, Executive, KernelMode, FALSE, pTime, NULL); switch (Status) { case STATUS_WAIT_0: break; case STATUS_WAIT_0 + 1: IoCancelIrp(Irp); KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); *RetStaus = -EINTR; break; case STATUS_TIMEOUT: IoCancelIrp(Irp); KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); *RetStaus = STATUS_TIMEOUT; break; default: WDRBD_ERROR("Unexpected Error Status=0x%x\n", Status); break; } } else { if (Status != STATUS_SUCCESS) { WDRBD_TRACE("Accept Error Status=0x%x\n", Status); } } AcceptedSocket = (Status == STATUS_SUCCESS) ? (PWSK_SOCKET) Irp->IoStatus.Information : NULL; IoFreeIrp(Irp); return AcceptedSocket; }
VOID NTAPI MmZeroPageThread(VOID) { PKTHREAD Thread = KeGetCurrentThread(); PVOID StartAddress, EndAddress; PVOID WaitObjects[2]; KIRQL OldIrql; PVOID ZeroAddress; PFN_NUMBER PageIndex, FreePage; PMMPFN Pfn1; /* Get the discardable sections to free them */ MiFindInitializationCode(&StartAddress, &EndAddress); if (StartAddress) MiFreeInitializationCode(StartAddress, EndAddress); DPRINT("Free non-cache pages: %lx\n", MmAvailablePages + MiMemoryConsumers[MC_CACHE].PagesUsed); /* Set our priority to 0 */ Thread->BasePriority = 0; KeSetPriorityThread(Thread, 0); /* Setup the wait objects */ WaitObjects[0] = &MmZeroingPageEvent; // WaitObjects[1] = &PoSystemIdleTimer; FIXME: Implement idle timer while (TRUE) { KeWaitForMultipleObjects(1, // 2 WaitObjects, WaitAny, WrFreePage, KernelMode, FALSE, NULL, NULL); OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); while (TRUE) { if (!MmFreePageListHead.Total) { MmZeroingPageThreadActive = FALSE; KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); break; } PageIndex = MmFreePageListHead.Flink; ASSERT(PageIndex != LIST_HEAD); Pfn1 = MiGetPfnEntry(PageIndex); MI_SET_USAGE(MI_USAGE_ZERO_LOOP); MI_SET_PROCESS2("Kernel 0 Loop"); FreePage = MiRemoveAnyPage(MI_GET_PAGE_COLOR(PageIndex)); /* The first global free page should also be the first on its own list */ if (FreePage != PageIndex) { KeBugCheckEx(PFN_LIST_CORRUPT, 0x8F, FreePage, PageIndex, 0); } Pfn1->u1.Flink = LIST_HEAD; KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); ZeroAddress = MiMapPagesInZeroSpace(Pfn1, 1); ASSERT(ZeroAddress); RtlZeroMemory(ZeroAddress, PAGE_SIZE); MiUnmapPagesInZeroSpace(ZeroAddress, 1); OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); MiInsertPageInList(&MmZeroedPageListHead, PageIndex); } } }
LONG NTAPI Receive( __in PWSK_SOCKET WskSocket, __out PVOID Buffer, __in ULONG BufferSize, __in ULONG Flags, __in ULONG Timeout ) { KEVENT CompletionEvent = { 0 }; PIRP Irp = NULL; WSK_BUF WskBuffer = { 0 }; LONG BytesReceived = SOCKET_ERROR; NTSTATUS Status = STATUS_UNSUCCESSFUL; struct task_struct *thread = current; PVOID waitObjects[2]; int wObjCount = 1; if (g_SocketsState != INITIALIZED || !WskSocket || !Buffer || !BufferSize) return SOCKET_ERROR; if ((int) BufferSize <= 0) { return SOCKET_ERROR; } Status = InitWskBuffer(Buffer, BufferSize, &WskBuffer); if (!NT_SUCCESS(Status)) { return SOCKET_ERROR; } Status = InitWskData(&Irp, &CompletionEvent); if (!NT_SUCCESS(Status)) { FreeWskBuffer(&WskBuffer); return SOCKET_ERROR; } Status = ((PWSK_PROVIDER_CONNECTION_DISPATCH) WskSocket->Dispatch)->WskReceive( WskSocket, &WskBuffer, Flags, Irp); if (Status == STATUS_PENDING) { LARGE_INTEGER nWaitTime; LARGE_INTEGER *pTime; if (Timeout <= 0 || Timeout == MAX_SCHEDULE_TIMEOUT) { pTime = 0; } else { nWaitTime = RtlConvertLongToLargeInteger(-1 * Timeout * 1000 * 10); pTime = &nWaitTime; } waitObjects[0] = (PVOID) &CompletionEvent; if (thread->has_sig_event) { waitObjects[1] = (PVOID) &thread->sig_event; wObjCount = 2; } Status = KeWaitForMultipleObjects(wObjCount, &waitObjects[0], WaitAny, Executive, KernelMode, FALSE, pTime, NULL); switch (Status) { case STATUS_WAIT_0: // waitObjects[0] CompletionEvent if (Irp->IoStatus.Status == STATUS_SUCCESS) { BytesReceived = (LONG) Irp->IoStatus.Information; } else { #ifdef _WIN32_LOGLINK DbgPrint("RECV(%s) wsk(0x%p) multiWait err(0x%x:%s)\n", thread->comm, WskSocket, Irp->IoStatus.Status, GetSockErrorString(Irp->IoStatus.Status)); #else WDRBD_INFO("RECV(%s) wsk(0x%p) multiWait err(0x%x:%s)\n", thread->comm, WskSocket, Irp->IoStatus.Status, GetSockErrorString(Irp->IoStatus.Status)); #endif if(Irp->IoStatus.Status) { BytesReceived = -ECONNRESET; } } break; case STATUS_WAIT_1: BytesReceived = -EINTR; break; case STATUS_TIMEOUT: BytesReceived = -EAGAIN; break; default: BytesReceived = SOCKET_ERROR; break; } } else { if (Status == STATUS_SUCCESS) { BytesReceived = (LONG) Irp->IoStatus.Information; #ifdef _WIN32_LOGLINK DbgPrint("(%s) Rx No pending and data(%d) is avail\n", current->comm, BytesReceived); #else WDRBD_INFO("(%s) Rx No pending and data(%d) is avail\n", current->comm, BytesReceived); #endif } else { #ifdef _WIN32_LOGLINK DbgPrint("WskReceive Error Status=0x%x\n", Status); // EVENT_LOG! #else WDRBD_TRACE("WskReceive Error Status=0x%x\n", Status); // EVENT_LOG! #endif } } if (BytesReceived == -EINTR || BytesReceived == -EAGAIN) { // cancel irp in wsk subsystem IoCancelIrp(Irp); KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); if (Irp->IoStatus.Information > 0) { //WDRBD_INFO("rx canceled but rx data(%d) avaliable.\n", Irp->IoStatus.Information); BytesReceived = Irp->IoStatus.Information; } } IoFreeIrp(Irp); FreeWskBuffer(&WskBuffer); return BytesReceived; }
static NTSTATUS VifMonitor( IN PXENVIF_THREAD Self, IN PVOID _Context ) { PXENVIF_VIF_CONTEXT Context = _Context; PXENVIF_FRONTEND Frontend = PdoGetFrontend(Context->Pdo); PKEVENT Event[EVENT_COUNT]; Trace("====>\n"); Event[THREAD_EVENT] = ThreadGetEvent(Self); Event[MAC_EVENT] = MacGetEvent(FrontendGetMac(Frontend)); for (;;) { NTSTATUS status; Trace("waiting...\n"); status = KeWaitForMultipleObjects(EVENT_COUNT, Event, WaitAny, Executive, KernelMode, FALSE, NULL, NULL); Trace("awake\n"); if (status >= STATUS_WAIT_0 && status < STATUS_WAIT_0 + EVENT_COUNT) { switch (status & STATUS_MASK) { case MAC_EVENT: { KeClearEvent(Event[MAC_EVENT]); Trace("MAC_EVENT\n"); if (Context->Enabled) { PVIF_CALLBACK Callback = &Context->Callback; Callback->Function(Callback->Argument, XENVIF_CALLBACK_MEDIA_STATE_CHANGE); } break; } case THREAD_EVENT: KeClearEvent(Event[THREAD_EVENT]); Trace("THREAD_EVENT\n"); if (ThreadIsAlerted(Self)) goto done; KeSetEvent(&Context->MonitorEvent, IO_NO_INCREMENT, FALSE); break; default: ASSERT(FALSE); break; } } } done: KeSetEvent(&Context->MonitorEvent, IO_NO_INCREMENT, FALSE); Trace("<====\n"); return STATUS_SUCCESS; }
/*++ * @name ExpWorkerThreadBalanceManager * * The ExpWorkerThreadBalanceManager routine is the entrypoint for the * worker thread balance set manager. * * @param Context * Unused. * * @return None. * * @remarks The worker thread balance set manager listens every second, but can * also be woken up by an event when a new thread is needed, or by the * special shutdown event. This thread runs at priority 7. * * This routine must run at IRQL == PASSIVE_LEVEL. * *--*/ VOID NTAPI ExpWorkerThreadBalanceManager(IN PVOID Context) { KTIMER Timer; LARGE_INTEGER Timeout; NTSTATUS Status; PVOID WaitEvents[3]; PAGED_CODE(); UNREFERENCED_PARAMETER(Context); /* Raise our priority above all other worker threads */ KeSetBasePriorityThread(KeGetCurrentThread(), EX_CRITICAL_QUEUE_PRIORITY_INCREMENT + 1); /* Setup the timer */ KeInitializeTimer(&Timer); Timeout.QuadPart = Int32x32To64(-1, 10000000); /* We'll wait on the periodic timer and also the emergency event */ WaitEvents[0] = &Timer; WaitEvents[1] = &ExpThreadSetManagerEvent; WaitEvents[2] = &ExpThreadSetManagerShutdownEvent; /* Start wait loop */ for (;;) { /* Wait for the timer */ KeSetTimer(&Timer, Timeout, NULL); Status = KeWaitForMultipleObjects(3, WaitEvents, WaitAny, Executive, KernelMode, FALSE, NULL, NULL); if (Status == 0) { /* Our timer expired. Check for deadlocks */ ExpDetectWorkerThreadDeadlock(); } else if (Status == 1) { /* Someone notified us, verify if we should create a new thread */ ExpCheckDynamicThreadCount(); } else if (Status == 2) { /* We are shutting down. Cancel the timer */ DPRINT1("System shutdown\n"); KeCancelTimer(&Timer); /* Make sure we have a final thread */ ASSERT(ExpLastWorkerThread); /* Wait for it */ KeWaitForSingleObject(ExpLastWorkerThread, Executive, KernelMode, FALSE, NULL); /* Dereference it and kill us */ ObDereferenceObject(ExpLastWorkerThread); PsTerminateSystemThread(STATUS_SYSTEM_SHUTDOWN); } } }
static VOID TestEventConcurrent( IN PKEVENT Event, IN EVENT_TYPE Type, IN KIRQL OriginalIrql, PSET_EVENT_FUNCTION SetEvent, KPRIORITY PriorityIncrement, LONG ExpectedState, BOOLEAN SatisfiesAll) { NTSTATUS Status; THREAD_DATA Threads[5]; const INT ThreadCount = sizeof Threads / sizeof Threads[0]; KPRIORITY Priority; LARGE_INTEGER LongTimeout, ShortTimeout; INT i; KWAIT_BLOCK WaitBlock[MAXIMUM_WAIT_OBJECTS]; PVOID ThreadObjects[MAXIMUM_WAIT_OBJECTS]; LONG State; PKTHREAD Thread = KeGetCurrentThread(); LongTimeout.QuadPart = -100 * MILLISECOND; ShortTimeout.QuadPart = -1 * MILLISECOND; KeInitializeEvent(Event, Type, FALSE); for (i = 0; i < ThreadCount; ++i) { Threads[i].Event = Event; Threads[i].Signal = FALSE; Status = PsCreateSystemThread(&Threads[i].Handle, GENERIC_ALL, NULL, NULL, NULL, WaitForEventThread, &Threads[i]); ok_eq_hex(Status, STATUS_SUCCESS); Status = ObReferenceObjectByHandle(Threads[i].Handle, SYNCHRONIZE, PsThreadType, KernelMode, (PVOID *)&Threads[i].Thread, NULL); ok_eq_hex(Status, STATUS_SUCCESS); ThreadObjects[i] = Threads[i].Thread; Priority = KeQueryPriorityThread(Threads[i].Thread); ok_eq_long(Priority, 8L); while (!Threads[i].Signal) { Status = KeDelayExecutionThread(KernelMode, FALSE, &ShortTimeout); ok_eq_hex(Status, STATUS_SUCCESS); } CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, ThreadObjects, i + 1); } /* the threads shouldn't wake up on their own */ Status = KeDelayExecutionThread(KernelMode, FALSE, &ShortTimeout); ok_eq_hex(Status, STATUS_SUCCESS); for (i = 0; i < ThreadCount; ++i) { CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, ThreadObjects + i, ThreadCount - i); State = SetEvent(Event, PriorityIncrement + i, FALSE); ok_eq_long(State, 0L); CheckEvent(Event, Type, ExpectedState, FALSE, OriginalIrql, ThreadObjects + i + 1, SatisfiesAll ? 0 : ThreadCount - i - 1); Status = KeWaitForMultipleObjects(ThreadCount, ThreadObjects, SatisfiesAll ? WaitAll : WaitAny, Executive, KernelMode, FALSE, &LongTimeout, WaitBlock); ok_eq_hex(Status, STATUS_WAIT_0 + i); if (SatisfiesAll) { for (; i < ThreadCount; ++i) { Priority = KeQueryPriorityThread(Threads[i].Thread); ok_eq_long(Priority, max(min(8L + PriorityIncrement, 15L), 8L)); } break; } Priority = KeQueryPriorityThread(Threads[i].Thread); ok_eq_long(Priority, max(min(8L + PriorityIncrement + i, 15L), 8L)); /* replace the thread with the current thread - which will never signal */ if (!skip((Status & 0x3F) < ThreadCount, "Index out of bounds")) ThreadObjects[Status & 0x3F] = Thread; Status = KeWaitForMultipleObjects(ThreadCount, ThreadObjects, WaitAny, Executive, KernelMode, FALSE, &ShortTimeout, WaitBlock); ok_eq_hex(Status, STATUS_TIMEOUT); } for (i = 0; i < ThreadCount; ++i) { ObDereferenceObject(Threads[i].Thread); Status = ZwClose(Threads[i].Handle); ok_eq_hex(Status, STATUS_SUCCESS); } }
VOID PrimarySessionThreadProc ( IN PPRIMARY_SESSION PrimarySession ) { BOOLEAN primarySessionTerminate = FALSE; NTSTATUS status; UINT16 slotIndex; PLIST_ENTRY primarySessionRequestEntry; ASSERT( SESSION_SLOT_COUNT == 1 ); ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, ("PrimarySessionThreadProc: Start PrimarySession = %p\n", PrimarySession) ); PrimarySession_Reference( PrimarySession ); SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_INITIALIZING ); InitializeListHead( &PrimarySession->Thread.OpenedFileQueue ); KeInitializeSpinLock( &PrimarySession->Thread.OpenedFileQSpinLock ); KeInitializeEvent( &PrimarySession->Thread.WorkCompletionEvent, NotificationEvent, FALSE ); PrimarySession->SessionContext.SessionSlotCount = SESSION_SLOT_COUNT; for (slotIndex = 0; slotIndex < PrimarySession->SessionContext.SessionSlotCount; slotIndex ++) { PrimarySession->Thread.SessionSlot[slotIndex].State = SLOT_WAIT; PrimarySession->Thread.IdleSlotCount ++; } ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_INITIALIZING ); SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_START ); SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED ); KeSetEvent( &PrimarySession->ReadyEvent, IO_DISK_INCREMENT, FALSE ); status = LpxTdiV2Recv( PrimarySession->ConnectionFileObject, (PUCHAR)&PrimarySession->Thread.NdfsRequestHeader, sizeof(NDFS_REQUEST_HEADER), 0, NULL, &PrimarySession->ReceiveOverlapped, 0, NULL ); if (!NT_SUCCESS(status)) { LpxTdiV2CompleteRequest( &PrimarySession->ReceiveOverlapped, 0 ); ASSERT( LFS_BUG ); SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR ); primarySessionTerminate = TRUE; } while (primarySessionTerminate == FALSE) { PKEVENT events[3]; LONG eventCount; NTSTATUS eventStatus; LARGE_INTEGER timeOut; NDAS_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); eventCount = 0; events[eventCount++] = &PrimarySession->RequestEvent; if (!FlagOn(PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOPPING)) { events[eventCount++] = &PrimarySession->Thread.WorkCompletionEvent; if (FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN)) { if (PrimarySession->Thread.IdleSlotCount == PrimarySession->SessionContext.SessionSlotCount) { CloseOpenFiles( PrimarySession, TRUE ); KeSetEvent( &PrimarySession->Thread.ShutdownPrimarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE ); SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN_WAIT ); ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN ); } } if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN_WAIT)) { if (LpxTdiV2IsRequestPending(&PrimarySession->ReceiveOverlapped, 0)) { ASSERT( PrimarySession->Thread.IdleSlotCount != 0 ); events[eventCount++] = &PrimarySession->ReceiveOverlapped.Request[0].CompletionEvent; } } ASSERT( eventCount <= THREAD_WAIT_OBJECTS ); } timeOut.QuadPart = -5*NANO100_PER_SEC; eventStatus = KeWaitForMultipleObjects( eventCount, events, WaitAny, Executive, KernelMode, TRUE, &timeOut, NULL ); if (!FlagOn(PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOPPING)) { if (eventStatus == STATUS_TIMEOUT || eventStatus == 2) { if (PrimarySession->Thread.SessionState == SESSION_TREE_CONNECT) { ASSERT( PrimarySession->NetdiskPartition ); if (!(PrimarySession->NetdiskPartition->NetdiskVolume[NETDISK_PRIMARY].VolumeState == VolumeMounted || PrimarySession->NetdiskPartition->NetdiskVolume[NETDISK_SECONDARY2PRIMARY].VolumeState == VolumeMounted)) { SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, ("Netdisk Volume is unmounted\n") ); if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN_WAIT)) primarySessionTerminate = TRUE; continue; } } } } if (eventStatus == STATUS_TIMEOUT) { continue; } if (!NT_SUCCESS(eventStatus) || eventStatus >= eventCount) { NDAS_ASSERT( FALSE ); SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR ); primarySessionTerminate = TRUE; continue; } if (eventStatus == 0) { KeClearEvent( events[eventStatus] ); while (primarySessionRequestEntry = ExInterlockedRemoveHeadList( &PrimarySession->RequestQueue, &PrimarySession->RequestQSpinLock)) { PPRIMARY_SESSION_REQUEST primarySessionRequest; primarySessionRequest = CONTAINING_RECORD( primarySessionRequestEntry, PRIMARY_SESSION_REQUEST, ListEntry ); if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DISCONNECT || primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DISCONNECT_AND_TERMINATE) { SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, ((primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DISCONNECT) ? ("PRIMARY_SESSION_REQ_DISCONNECT: DisconnectFromSecondary\n") : ("PRIMARY_SESSION_REQ_DISCONNECT_AND_TERMINATE: DisconnectFromSecondary\n")) ); if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED)) { DisconnectFromSecondary( PrimarySession ); ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED ); SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED ); } if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DISCONNECT_AND_TERMINATE) primarySessionTerminate = TRUE; if (primarySessionRequest->Synchronous == TRUE) KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE ); else DereferencePrimarySessionRequest( primarySessionRequest ); } else if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DOWN) { SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_STOPED ); primarySessionTerminate = TRUE; if (primarySessionRequest->Synchronous == TRUE) KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE ); else DereferencePrimarySessionRequest( primarySessionRequest ); } else if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_SHUTDOWN) { SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("PrimarySessionThreadProc: PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN\n") ); SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN ); ASSERT (primarySessionRequest->Synchronous == TRUE); PrimarySession->Thread.ShutdownPrimarySessionRequest = primarySessionRequest; if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED)) { DisconnectFromSecondary( PrimarySession ); ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED ); SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED ); } } else if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_STOPPING) { SetFlag( PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOPPING ); if (PrimarySession->IsLocalAddress == FALSE) { #if __NDAS_FS_PRIMARY_DISMOUNT__ CloseOpenFiles( PrimarySession, FALSE ); #endif } ExAcquireFastMutexUnsafe( &PrimarySession->FastMutex ); if (primarySessionRequest->Synchronous == TRUE) { primarySessionRequest->ExecuteStatus = STATUS_SUCCESS; KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE ); } else { DereferencePrimarySessionRequest( primarySessionRequest ); } ExReleaseFastMutexUnsafe( &PrimarySession->FastMutex ); } else if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_CANCEL_STOPPING) { ClearFlag( PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOPPING ); if (primarySessionRequest->Synchronous == TRUE) KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE ); else DereferencePrimarySessionRequest( primarySessionRequest ); } else { ASSERT( LFS_BUG ); SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR ); } } continue; } else if (eventStatus == 1) { KeClearEvent( events[eventStatus] ); while (TRUE) { for (slotIndex = 0; slotIndex < PrimarySession->SessionContext.SessionSlotCount; slotIndex ++) { if (PrimarySession->Thread.SessionSlot[slotIndex].State == SLOT_FINISH) break; } if (slotIndex == PrimarySession->SessionContext.SessionSlotCount) break; PrimarySession->Thread.SessionSlot[slotIndex].State = SLOT_WAIT; PrimarySession->Thread.IdleSlotCount ++; if (PrimarySession->Thread.SessionSlot[slotIndex].Status == STATUS_SUCCESS) { PNDFS_REPLY_HEADER ndfsReplyHeader; ndfsReplyHeader = (PNDFS_REPLY_HEADER)PrimarySession->Thread.SessionSlot[slotIndex].ReplyMessageBuffer; PrimarySession->Thread.SessionSlot[slotIndex].Status = SendNdfsWinxpMessage( PrimarySession, ndfsReplyHeader, PrimarySession->Thread.SessionSlot[slotIndex].NdfsWinxpReplyHeader, PrimarySession->Thread.SessionSlot[slotIndex].ReplyDataSize, slotIndex ); } if (PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool) { ExFreePool(PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool); PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool = NULL; PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePoolLength = 0; } if (PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool) { ExFreePool(PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool); PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool = NULL; PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePoolLength = 0; } if (!(PrimarySession->Thread.SessionSlot[slotIndex].Status == STATUS_SUCCESS || PrimarySession->Thread.SessionSlot[slotIndex].Status == STATUS_PENDING)) { SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR ); if (PrimarySession->NetdiskPartition) { NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager, PrimarySession, PrimarySession->NetdiskPartition, PrimarySession->IsLocalAddress ); PrimarySession->NetdiskPartition = NULL; } primarySessionTerminate = TRUE; break; } if (PrimarySession->Thread.SessionState == SESSION_CLOSED) { if (PrimarySession->NetdiskPartition) { NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager, PrimarySession, PrimarySession->NetdiskPartition, PrimarySession->IsLocalAddress ); PrimarySession->NetdiskPartition = NULL; } primarySessionTerminate = TRUE; break; } if (PrimarySession->Thread.SessionSlot[slotIndex].Status == STATUS_SUCCESS) { if (!LpxTdiV2IsRequestPending(&PrimarySession->ReceiveOverlapped, 0)) { status = LpxTdiV2Recv( PrimarySession->ConnectionFileObject, (PUCHAR)&PrimarySession->Thread.NdfsRequestHeader, sizeof(NDFS_REQUEST_HEADER), 0, NULL, &PrimarySession->ReceiveOverlapped, 0, NULL ); if (!NT_SUCCESS(status)) { ASSERT( LFS_BUG ); LpxTdiV2CompleteRequest( &PrimarySession->ReceiveOverlapped, 0 ); SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR ); primarySessionTerminate = TRUE; break; } } } } continue; } else { NDAS_ASSERT( eventStatus == 2 ); // Receive Event ASSERT( !FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN_WAIT) && !FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN) ); LpxTdiV2CompleteRequest( &PrimarySession->ReceiveOverlapped, 0 ); if (PrimarySession->ReceiveOverlapped.Request[0].IoStatusBlock.Status != STATUS_SUCCESS || PrimarySession->ReceiveOverlapped.Request[0].IoStatusBlock.Information != sizeof(NDFS_REQUEST_HEADER)) { SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("DispatchRequest: Disconnected, PrimarySession = Data received:%d\n", PrimarySession->ReceiveOverlapped.Request[0].IoStatusBlock.Information) ); SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED ); primarySessionTerminate = TRUE; continue; } #if 0 if (PrimarySession->NetdiskPartition) { PENABLED_NETDISK EnabledNetdisk = PrimarySession->NetdiskPartition->EnabledNetdisk; ASSERT( EnabledNetdisk ); if (NetdiskManager_IsStoppedNetdisk(GlobalLfs.NetdiskManager, EnabledNetdisk)) { SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_ERROR, ("PrimarySessionThread: %p Netdisk is stopped\n", PrimarySession) ); SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_ERROR, ("DispatchWinXpRequest: Netdisk is stopped.\n") ); if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED)) { // no other way to notify secondary about unmount without break backward compatability. SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, ("IsStoppedNetdisk: DisconnectFromSecondary\n") ); DisconnectFromSecondary( PrimarySession ); ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED ); SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED ); } primarySessionTerminate = TRUE; continue; } } #endif status = DispatchRequest( PrimarySession ); if (!(status == STATUS_SUCCESS || status == STATUS_PENDING)) { primarySessionTerminate = TRUE; continue; } if (PrimarySession->Thread.SessionState == SESSION_CLOSED) { primarySessionTerminate = TRUE; continue; } if (status == STATUS_SUCCESS) { if (!LpxTdiV2IsRequestPending(&PrimarySession->ReceiveOverlapped, 0)) { status = LpxTdiV2Recv( PrimarySession->ConnectionFileObject, (PUCHAR)&PrimarySession->Thread.NdfsRequestHeader, sizeof(NDFS_REQUEST_HEADER), 0, NULL, &PrimarySession->ReceiveOverlapped, 0, NULL ); if (!NT_SUCCESS(status)) { LpxTdiV2CompleteRequest( &PrimarySession->ReceiveOverlapped, 0 ); SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR ); primarySessionTerminate = TRUE; } } } continue; } } ExAcquireFastMutexUnsafe( &PrimarySession->FastMutex ); SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_STOPED ); ExReleaseFastMutexUnsafe( &PrimarySession->FastMutex ); while (TRUE) { LARGE_INTEGER timeOut; NTSTATUS eventStatus; if (PrimarySession->Thread.IdleSlotCount == PrimarySession->SessionContext.SessionSlotCount) break; timeOut.QuadPart = -10*NANO100_PER_SEC; eventStatus = KeWaitForSingleObject( &PrimarySession->Thread.WorkCompletionEvent, Executive, KernelMode, FALSE, &timeOut ); KeClearEvent( &PrimarySession->Thread.WorkCompletionEvent ); if (eventStatus == STATUS_TIMEOUT) { ASSERT( LFS_UNEXPECTED ); continue; } while (TRUE) { for (slotIndex = 0; slotIndex < PrimarySession->SessionContext.SessionSlotCount; slotIndex++) { if (PrimarySession->Thread.SessionSlot[slotIndex].State == SLOT_FINISH) break; } if (slotIndex == PrimarySession->SessionContext.SessionSlotCount) break; SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("PrimarySessionThreadProc: eventStatus = %d\n", eventStatus) ); PrimarySession->Thread.SessionSlot[slotIndex].State = SLOT_WAIT; PrimarySession->Thread.IdleSlotCount++; if (PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool) { ExFreePool( PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool ); PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool = NULL; PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePoolLength = 0; } if (PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool) { ExFreePool( PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool ); PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool = NULL; PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePoolLength = 0; } } } if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED)) { SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, ("PsTerminateSystemThread: DisconnectFromSecondary\n") ); DisconnectFromSecondary( PrimarySession ); ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED ); SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED ); } CloseOpenFiles( PrimarySession, TRUE ); while (primarySessionRequestEntry = ExInterlockedRemoveHeadList( &PrimarySession->RequestQueue, &PrimarySession->RequestQSpinLock)) { PPRIMARY_SESSION_REQUEST primarySessionRequest; primarySessionRequest = CONTAINING_RECORD( primarySessionRequestEntry, PRIMARY_SESSION_REQUEST, ListEntry ); if (primarySessionRequest->Synchronous == TRUE) KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE ); else DereferencePrimarySessionRequest( primarySessionRequest ); } if (PrimarySession->NetdiskPartition) { NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager, PrimarySession, PrimarySession->NetdiskPartition, PrimarySession->IsLocalAddress ); PrimarySession->NetdiskPartition = NULL; } SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, ("PrimarySessionThreadProc: PsTerminateSystemThread PrimarySession = %p\n", PrimarySession) ); SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_TERMINATED ); PrimarySession_Dereference ( PrimarySession ); NDAS_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); PsTerminateSystemThread( STATUS_SUCCESS ); }
VOID ExpWorkerThreadBalanceManager ( IN PVOID StartContext ) /*++ Routine Description: This function is the startup code for the worker thread manager thread. The worker thread manager thread is created during system initialization and begins execution in this function. This thread is responsible for detecting and breaking circular deadlocks in the system worker thread queues. It will also create and destroy additional worker threads as needed based on loading. Arguments: Context - Supplies a pointer to an arbitrary data structure (NULL). Return Value: None. --*/ { KTIMER PeriodTimer; LARGE_INTEGER DueTime; PVOID WaitObjects[MaximumBalanceObject]; NTSTATUS Status; PAGED_CODE(); UNREFERENCED_PARAMETER (StartContext); // // Raise the thread priority to just higher than the priority of the // critical work queue. // KeSetBasePriorityThread (KeGetCurrentThread(), CRITICAL_WORK_QUEUE_PRIORITY + 1); // // Initialize the periodic timer and set the manager period. // KeInitializeTimer (&PeriodTimer); DueTime.QuadPart = - THREAD_SET_INTERVAL; // // Initialize the wait object array. // WaitObjects[TimerExpiration] = (PVOID)&PeriodTimer; WaitObjects[ThreadSetManagerEvent] = (PVOID)&ExpThreadSetManagerEvent; WaitObjects[ShutdownEvent] = (PVOID)&ExpThreadSetManagerShutdownEvent; // // Loop forever processing events. // while (TRUE) { // // Set the timer to expire at the next periodic interval. // KeSetTimer (&PeriodTimer, DueTime, NULL); // // Wake up when the timer expires or the set manager event is // signaled. // Status = KeWaitForMultipleObjects (MaximumBalanceObject, WaitObjects, WaitAny, Executive, KernelMode, FALSE, NULL, NULL); switch (Status) { case TimerExpiration: // // Periodic timer expiration - go see if any work queues // are deadlocked. // ExpDetectWorkerThreadDeadlock (); break; case ThreadSetManagerEvent: // // Someone has asked us to check some metrics to determine // whether we should create another worker thread. // ExpCheckDynamicThreadCount (); break; case ShutdownEvent: // // Time to exit... // KeCancelTimer (&PeriodTimer); ASSERT (ExpLastWorkerThread); // // Wait for the last worker thread to terminate // KeWaitForSingleObject (ExpLastWorkerThread, Executive, KernelMode, FALSE, NULL); ObDereferenceObject (ExpLastWorkerThread); PsTerminateSystemThread(STATUS_SYSTEM_SHUTDOWN); break; } // // Special debugger support. // // This checks if special debugging routines need to be run on the // behalf of the debugger. // if (ExpDebuggerWork == 1) { ExInitializeWorkItem(&ExpDebuggerWorkItem, ExpDebuggerWorker, NULL); ExpDebuggerWork = 2; ExQueueWorkItem(&ExpDebuggerWorkItem, DelayedWorkQueue); } } }