/********************************************************** NDIS-required procedure for DPC handling Parameters: PVOID MiniportInterruptContext (Adapter context) ***********************************************************/ static VOID MiniportInterruptDPC( IN NDIS_HANDLE MiniportInterruptContext, IN PVOID MiniportDpcContext, IN PVOID ReceiveThrottleParameters, IN PVOID NdisReserved2 ) { PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER *)MiniportInterruptContext; ULONG requiresProcessing; #if NDIS_SUPPORT_NDIS620 PNDIS_RECEIVE_THROTTLE_PARAMETERS RxThrottleParameters = (PNDIS_RECEIVE_THROTTLE_PARAMETERS)ReceiveThrottleParameters; DEBUG_ENTRY(5); RxThrottleParameters->MoreNblsPending = 0; requiresProcessing = ParaNdis_DPCWorkBody(pContext, RxThrottleParameters->MaxNblsToIndicate); if(requiresProcessing) { BOOLEAN bSpawnNextDpc = FALSE; DPrintf(4, ("[%s] Queued additional DPC for %d\n", __FUNCTION__, requiresProcessing)); InterlockedOr(&pContext->InterruptStatus, requiresProcessing); if(requiresProcessing & isReceive) { if (NDIS_INDICATE_ALL_NBLS != RxThrottleParameters->MaxNblsToIndicate) RxThrottleParameters->MoreNblsPending = 1; else bSpawnNextDpc = TRUE; } if(requiresProcessing & isTransmit) bSpawnNextDpc = TRUE; if (bSpawnNextDpc) { GROUP_AFFINITY Affinity; GetAffinityForCurrentCpu(&Affinity); NdisMQueueDpcEx(pContext->InterruptHandle, 0, &Affinity, MiniportDpcContext); } } #else /* NDIS 6.0*/ DEBUG_ENTRY(5); UNREFERENCED_PARAMETER(ReceiveThrottleParameters); requiresProcessing = ParaNdis_DPCWorkBody(pContext, PARANDIS_UNLIMITED_PACKETS_TO_INDICATE); if (requiresProcessing) { DPrintf(4, ("[%s] Queued additional DPC for %d\n", __FUNCTION__, requiresProcessing)); InterlockedOr(&pContext->InterruptStatus, requiresProcessing); NdisMQueueDpc(pContext->InterruptHandle, 0, 1 << KeGetCurrentProcessorNumber(), MiniportDpcContext); } #endif /* NDIS_SUPPORT_NDIS620 */ UNREFERENCED_PARAMETER(NdisReserved2); }
static void condSignal( os_cond *cond, long mask) { HANDLE hQueue; DWORD result; long oldState; assert(cond != NULL); if (cond->scope == OS_SCOPE_SHARED) { hQueue = get_semaphore_handle(cond); } else { hQueue = (HANDLE)cond->qId; } oldState = InterlockedOr(&cond->state, mask); if (oldState == 0) { /* no waiters */ InterlockedAnd(&cond->state, ~mask); return; } if (mask == BROADCAST_BIT_MASK) { result = ReleaseSemaphore(hQueue, oldState, 0); } else { result = ReleaseSemaphore(hQueue, 1, 0); } InterlockedAnd(&cond->state, ~mask); }
/* Reports current ready state * If one event in error_report_events has potential error code, the last WSA error code is set to that */ static int socket_update_events_unsafe(struct socket_file *f, int error_report_events) { WSANETWORKEVENTS events; WSAEnumNetworkEvents(f->socket, f->event_handle, &events); int e = 0; if (events.lNetworkEvents & FD_READ) e |= FD_READ; if (events.lNetworkEvents & FD_WRITE) e |= FD_WRITE; if (events.lNetworkEvents & FD_CONNECT) { e |= FD_CONNECT; f->shared->connect_error = events.iErrorCode[FD_CONNECT_BIT]; } if (events.lNetworkEvents & FD_ACCEPT) e |= FD_ACCEPT; if (events.lNetworkEvents & FD_CLOSE) e |= FD_CLOSE; int original = InterlockedOr(&f->shared->events, e); if (error_report_events & f->shared->events & FD_CONNECT) { WSASetLastError(f->shared->connect_error); f->shared->connect_error = 0; InterlockedAnd(&f->shared->events, ~FD_CONNECT); } return original | e; }
static __inline uintptr_t __atomic_load_n(void *ptr, unsigned type) { assert(type == __ATOMIC_ACQUIRE); // These return the previous value - but since we do an OR with 0, // it's equivalent to a plain load. #ifdef _WIN64 return InterlockedOr64(ptr, 0); #else return InterlockedOr(ptr, 0); #endif }
gsize (g_atomic_pointer_or) (volatile void *atomic, gsize val) { #if GLIB_SIZEOF_VOID_P == 8 return InterlockedOr64 (atomic, val); #else return InterlockedOr (atomic, val); #endif }
inline void CMyDevice::EnterShutdown() { Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Entry"); // // Begin shutdown. Spin if control handler is in progress. // while (((InterlockedOr (&m_dwShutdownControlFlags, SHUTDOWN_IN_PROGRESS) & PROCESSING_IN_PROGRESS) != 0)) { Yield(); } }
static os_result condSignal( os_cond *cond, long mask) { char name[OS_SERVICE_ENTITY_NAME_MAX]; HANDLE hQueue; DWORD result; long oldState; os_result osr; assert(cond != NULL); osr = os_resultSuccess; if (cond->scope == OS_SCOPE_SHARED) { _snprintf(name, sizeof(name), "%s%s%d%d", (os_sharedMemIsGlobal() ? OS_SERVICE_GLOBAL_NAME_PREFIX : ""), OS_SERVICE_SEM_NAME_PREFIX, cond->qId, os_getShmBaseAddressFromPointer(cond)); hQueue = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, name); if (hQueue == NULL) { OS_DEBUG_1("condSignal", "OpenSemaphore failed %d", (int)GetLastError()); assert(0); return os_resultFail; } } else { hQueue = (HANDLE)cond->qId; } oldState = InterlockedOr(&cond->state, mask); if (oldState == 0) { /* no waiters */ InterlockedAnd(&cond->state, ~mask); return osr; } if (mask == BROADCAST_BIT_MASK) { result = ReleaseSemaphore(hQueue, oldState, 0); } else { result = ReleaseSemaphore(hQueue, 1, 0); } InterlockedAnd(&cond->state, ~mask); if (cond->scope == OS_SCOPE_SHARED) { CloseHandle(hQueue); } return osr; }
inline HRESULT CMyDevice::EnterProcessing(DWORD64 dwControlFlag) { //Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Entry"); HRESULT hr = S_OK; if ((InterlockedOr (&m_dwShutdownControlFlags, dwControlFlag) & SHUTDOWN_IN_PROGRESS) != 0) { hr = HRESULT_FROM_WIN32(ERROR_SHUTDOWN_IN_PROGRESS); } return hr; }
__checkReturn FLT_POSTOP_CALLBACK_STATUS FLTAPI PostWrite ( __inout PFLT_CALLBACK_DATA Data, __in PCFLT_RELATED_OBJECTS FltObjects, __in PVOID CompletionContext, __in FLT_POST_OPERATION_FLAGS Flags ) { FLT_POSTOP_CALLBACK_STATUS fltStatus = FLT_POSTOP_FINISHED_PROCESSING; PStreamContext pStreamContext = (PStreamContext) CompletionContext; ASSERT( pStreamContext ); __try { if ( FlagOn( Flags, FLTFL_POST_OPERATION_DRAINING ) ) { __leave; } if ( !NT_SUCCESS( Data->IoStatus.Status ) ) { __leave; } if ( !Data->IoStatus.Information ) { __leave; } if ( FlagOn( Data->Iopb->IrpFlags, IRP_PAGING_IO ) ) { //! \todo обработка MM файлов __leave; } InterlockedIncrement( &pStreamContext->m_WriteCount ); InterlockedAnd( &pStreamContext->m_Flags, ~_STREAM_FLAGS_CASHE1 ); InterlockedOr( &pStreamContext->m_Flags, _STREAM_FLAGS_MODIFIED ); } __finally { ReleaseContext( (PFLT_CONTEXT*) &pStreamContext ); } return fltStatus; }
NTSTATUS FltpStartingToDrainObject(_Inout_ PFLT_OBJECT Object) { /* * Set the draining flag for the filter. This let's us force * a post op callback for minifilters currently awaiting one. */ if (InterlockedOr((PLONG)&Object->Flags, FLT_OBFL_DRAINING) & 1) { /* We've been called once, we're already being deleted */ return STATUS_FLT_DELETING_OBJECT; } return STATUS_SUCCESS; }
bool SetCOWPageBits(BYTE* pStart, size_t len, bool value) { _ASSERTE(len > 0); // we don't need a barrier here, since: // a) all supported hardware maintains ordering of dependent reads // b) it's ok if additional reads happen, because this never changes // once initialized. LONG* pCOWPageMap = g_pCOWPageMap; // // Write the bits in 32-bit chunks, to avoid doing one interlocked instruction for each bit. // size_t page = (size_t)pStart / PAGE_SIZE; size_t lastPage = (size_t)(pStart+len-1) / PAGE_SIZE; size_t elem = page / 32; LONG bits = 0; do { bits |= 1 << (page % 32); ++page; // // if we've moved to a new element of the map, or we've covered every page, // we need to write out the already-accumulated element. // size_t newElem = page / 32; if (page > lastPage || newElem != elem) { LONG* pElem = &pCOWPageMap[elem]; if (!EnsureCOWPageMapElementAllocated(pElem)) return false; if (value) InterlockedOr(&pCOWPageMap[elem], bits); else InterlockedAnd(&pCOWPageMap[elem], ~bits); elem = newElem; bits = 0; } } while (page <= lastPage); return true; }
int aio_socket_sendto_v(aio_socket_t socket, const struct sockaddr *addr, socklen_t addrlen, socket_bufvec_t* vec, int n, aio_onsend proc, void* param) { struct aio_context *ctx = (struct aio_context*)socket; struct aio_context_action *aio; aio = util_alloc(ctx); aio->action = iocp_send; aio->send.proc = proc; aio->send.param = param; assert(0 == (AIO_WRITE & InterlockedOr(&ctx->flags, AIO_WRITE))); if(SOCKET_ERROR == WSASendTo(ctx->socket, vec, (DWORD)n, NULL/*&dwBytes*/, 0, addr, addrlen, &aio->overlapped, NULL)) { return aio_socket_result(aio, AIO_WRITE); } return 0; }
NTSTATUS NTAPI PspTerminateProcess(IN PEPROCESS Process, IN NTSTATUS ExitStatus) { PETHREAD Thread; NTSTATUS Status = STATUS_NOTHING_TO_TERMINATE; PAGED_CODE(); PSTRACE(PS_KILL_DEBUG, "Process: %p ExitStatus: %d\n", Process, ExitStatus); PSREFTRACE(Process); /* Check if this is a Critical Process */ if (Process->BreakOnTermination) { /* Break to debugger */ PspCatchCriticalBreak("Terminating critical process 0x%p (%s)\n", Process, Process->ImageFileName); } /* Set the delete flag */ InterlockedOr((PLONG)&Process->Flags, PSF_PROCESS_DELETE_BIT); /* Get the first thread */ Thread = PsGetNextProcessThread(Process, NULL); while (Thread) { /* Kill it */ PspTerminateThreadByPointer(Thread, ExitStatus, FALSE); Thread = PsGetNextProcessThread(Process, Thread); /* We had at least one thread, so termination is OK */ Status = STATUS_SUCCESS; } /* Check if there was nothing to terminate or if we have a debug port */ if ((Status == STATUS_NOTHING_TO_TERMINATE) || (Process->DebugPort)) { /* Clear the handle table anyway */ ObClearProcessHandleTable(Process); } /* Return status */ return Status; }
int aio_socket_connect(aio_socket_t socket, const struct sockaddr *addr, socklen_t addrlen, aio_onconnect proc, void* param) { struct aio_context *ctx = (struct aio_context*)socket; struct aio_context_action *aio; aio = util_alloc(ctx); aio->action = iocp_connect; aio->connect.proc = proc; aio->connect.param = param; assert(0 == (AIO_WRITE & InterlockedOr(&ctx->flags, AIO_WRITE))); if (!ConnectEx(ctx->socket, addr, addrlen, NULL, 0, NULL, &aio->overlapped)) { return aio_socket_result(aio, AIO_WRITE); } return 0; }
int aio_socket_recv_v(aio_socket_t socket, socket_bufvec_t* vec, int n, aio_onrecv proc, void* param) { DWORD flags = 0; struct aio_context *ctx = (struct aio_context*)socket; struct aio_context_action *aio; aio = util_alloc(ctx); aio->action = iocp_recv; aio->recv.proc = proc; aio->recv.param = param; assert(0 == (AIO_READ & InterlockedOr(&ctx->flags, AIO_READ))); if(SOCKET_ERROR == WSARecv(ctx->socket, vec, n, NULL/*&dwBytes*/, &flags, &aio->overlapped, NULL)) { return aio_socket_result(aio, AIO_READ); } return 0; }
EXPORT void hal_signal(struct THALBase *hal, struct THALObject *thread, TUINT signals) { struct HALThread *wth = THALGetObject(thread, struct HALThread); #ifndef HAL_USE_ATOMICS EnterCriticalSection(&wth->hth_SigLock); if (signals & ~wth->hth_SigState) { wth->hth_SigState |= signals; SetEvent(wth->hth_SigEvent); } LeaveCriticalSection(&wth->hth_SigLock); #else if (signals & ~(TUINT) InterlockedOr(&wth->hth_SigState, signals)) SetEvent(wth->hth_SigEvent); #endif }
__host__ __device__ typename enable_if< sizeof(Integer32) == 4, Integer32 >::type atomic_fetch_xor(Integer32 *x, Integer32 y) { #if defined(__CUDA_ARCH__) return atomicXor(x, y); #elif defined(__GNUC__) return __atomic_fetch_xor(x, y, __ATOMIC_SEQ_CST); #elif defined(_MSC_VER) return InterlockedOr(x, y); #elif defined(__clang__) return __c11_atomic_fetch_xor(x, y) #else #error "No atomic_fetch_xor implementation." #endif }
bool EnsureCOWPageMapElementAllocated(LONG* elem) { _ASSERTE(elem > g_pCOWPageMap); _ASSERTE(g_pCOWPageMap != NULL); size_t offset = (size_t)elem - (size_t)g_pCOWPageMap; size_t page = offset / PAGE_SIZE; _ASSERTE(page < 32); int bit = (int)(1 << page); if (!(g_COWPageMapMap & bit)) { if (!VirtualAlloc(elem, 1, MEM_COMMIT, PAGE_READWRITE)) return false; InterlockedOr(&g_COWPageMapMap, bit); } return true; }
EXPORT TUINT hal_setsignal(struct THALBase *hal, TUINT newsig, TUINT sigmask) { struct HALSpecific *hws = hal->hmb_Specific; struct HALThread *wth = TlsGetValue(hws->hsp_TLSIndex); #ifndef HAL_USE_ATOMICS TUINT oldsig; EnterCriticalSection(&wth->hth_SigLock); oldsig = wth->hth_SigState; wth->hth_SigState &= ~sigmask; wth->hth_SigState |= newsig; LeaveCriticalSection(&wth->hth_SigLock); return oldsig; #else TUINT cmask = ~sigmask | newsig; TUINT before_consume = InterlockedAnd(&wth->hth_SigState, cmask); if (! newsig) return before_consume; TUINT before_publish = InterlockedOr(&wth->hth_SigState, newsig); return (before_consume & ~cmask) | (before_publish & cmask); #endif }
int aio_socket_accept(aio_socket_t socket, aio_onaccept proc, void* param) { int ret; DWORD dwBytes = 0; WSAPROTOCOL_INFOW pi; struct aio_context *ctx = (struct aio_context*)socket; struct aio_context_action *aio; ret = sizeof(pi); if (0 != getsockopt(ctx->socket, SOL_SOCKET, SO_PROTOCOL_INFO, (char*)&pi, &ret)) return WSAGetLastError(); aio = util_alloc(ctx); aio->action = iocp_accept; aio->accept.proc = proc; aio->accept.param = param; aio->accept.socket = WSASocket(pi.iAddressFamily, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); if(INVALID_SOCKET == aio->accept.socket) { closesocket(aio->accept.socket); util_free(aio); return WSAGetLastError(); } dwBytes = sizeof(aio->accept.buffer) / 2; assert(0 == (AIO_READ & InterlockedOr(&ctx->flags, AIO_READ))); if (!AcceptEx(ctx->socket, aio->accept.socket, aio->accept.buffer, 0, dwBytes, dwBytes, &dwBytes, &aio->overlapped)) { ret = aio_socket_result(aio, AIO_READ); if(0 != ret) { closesocket(aio->accept.socket); return ret; } } return 0; }
static TBOOL hal_replytimereq(struct TTimeRequest *tr) { TBOOL success = TFALSE; struct TMessage *msg = TGETMSGPTR(tr); struct TMsgPort *mp = msg->tmsg_RPort; CRITICAL_SECTION *mplock = THALGetObject((TAPTR) &mp->tmp_Lock, CRITICAL_SECTION); if (TryEnterCriticalSection(mplock)) { struct TTask *sigtask = mp->tmp_SigTask; struct HALThread *t = THALGetObject((TAPTR) &sigtask->tsk_Thread, struct HALThread); #ifndef HAL_USE_ATOMICS if (TryEnterCriticalSection(&t->hth_SigLock)) #endif { tr->ttr_Req.io_Error = 0; msg->tmsg_Flags = TMSG_STATUS_REPLIED | TMSGF_QUEUED; TAddTail(&mp->tmp_MsgList, &msg->tmsg_Node); #ifndef HAL_USE_ATOMICS if (mp->tmp_Signal & ~t->hth_SigState) { t->hth_SigState |= mp->tmp_Signal; SetEvent(t->hth_SigEvent); } LeaveCriticalSection(&t->hth_SigLock); #else if (mp->tmp_Signal & ~(TUINT) InterlockedOr(&t->hth_SigState, mp->tmp_Signal)) SetEvent(t->hth_SigEvent); #endif success = TTRUE; } LeaveCriticalSection(mplock); } return success; }
/** * Drive a safe hook PDO with a safe hook FDO * * @param DriverObject * The driver object provided by the caller * * @param PhysicalDeviceObject * The PDO to probe and attach the safe hook FDO to * * @return * The status of the operation */ static NTSTATUS STDCALL WvSafeHookDriveDevice( IN DRIVER_OBJECT * drv_obj, IN DEVICE_OBJECT * pdo ) { NTSTATUS status; S_X86_SEG16OFF16 * safe_hook; UCHAR * phys_mem; UINT32 hook_phys_addr; WV_S_PROBE_SAFE_MBR_HOOK * hook; LONG flags; DEVICE_OBJECT * fdo; S_WV_SAFE_HOOK_BUS * bus; if (pdo->DriverObject != drv_obj || !(safe_hook = WvlGetSafeHook(pdo))) { status = STATUS_NOT_SUPPORTED; goto err_safe_hook; } /* Ok, we'll try to drive this PDO with an FDO */ phys_mem = WvlMapUnmapLowMemory(NULL); if (!phys_mem) { status = STATUS_INSUFFICIENT_RESOURCES; goto err_phys_mem; } hook_phys_addr = M_X86_SEG16OFF16_ADDR(safe_hook); hook = (VOID *) (phys_mem + hook_phys_addr); /* * Quickly claim the safe hook. Let's hope other drivers offer * the same courtesy */ flags = InterlockedOr(&hook->Flags, 1); if (flags & 1) { DBG("Safe hook already claimed\n"); status = STATUS_DEVICE_BUSY; goto err_claimed; } fdo = NULL; status = WvlCreateDevice( WvSafeHookMiniDriver, sizeof *bus, NULL, FILE_DEVICE_CONTROLLER, FILE_DEVICE_SECURE_OPEN, FALSE, &fdo ); if (!NT_SUCCESS(status)) goto err_fdo; ASSERT(fdo); bus = fdo->DeviceExtension; ASSERT(bus); bus->DeviceExtension->IrpDispatch = WvSafeHookIrpDispatch; bus->Flags = 0; bus->PhysicalDeviceObject = pdo; bus->BusRelations->Count = 0; bus->BusRelations->Objects[0] = NULL; bus->PreviousInt13hHandler[0] = hook->PrevHook; /* Attach the FDO to the PDO */ if (!WvlAttachDeviceToDeviceStack(fdo, pdo)) { DBG("Error driving PDO %p!\n", (VOID *) pdo); status = STATUS_DRIVER_INTERNAL_ERROR; goto err_lower; } fdo->Flags &= ~DO_DEVICE_INITIALIZING; DBG("Driving PDO %p with FDO %p\n", (VOID *) pdo, (VOID *) fdo); status = STATUS_SUCCESS; goto out; err_lower: WvlDeleteDevice(fdo); err_fdo: flags = InterlockedAnd(&hook->Flags, ~1); err_claimed: out: WvlMapUnmapLowMemory(phys_mem); err_phys_mem: err_safe_hook: if (!NT_SUCCESS(status)) DBG("Refusing to drive PDO %p\n", (VOID *) pdo); return status; }
/********************************************************** NDIS-required procedure for MSI DPC handling Parameters: PVOID MiniportInterruptContext (Adapter context) IN ULONG MessageId - specific interrupt index ***********************************************************/ static VOID MiniportMSIInterruptDpc( IN PVOID MiniportInterruptContext, IN ULONG MessageId, IN PVOID MiniportDpcContext, #if NDIS_SUPPORT_NDIS620 IN PVOID ReceiveThrottleParameters, IN PVOID NdisReserved2 #else IN PULONG NdisReserved1, IN PULONG NdisReserved2 #endif ) { PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER *)MiniportInterruptContext; ULONG interruptSource = MessageToInterruptSource(pContext, MessageId); #if NDIS_SUPPORT_NDIS620 BOOLEAN bSpawnNextDpc = FALSE; PNDIS_RECEIVE_THROTTLE_PARAMETERS RxThrottleParameters = (PNDIS_RECEIVE_THROTTLE_PARAMETERS)ReceiveThrottleParameters; DPrintf(5, ("[%s] (Message %d, source %d)\n", __FUNCTION__, MessageId, interruptSource)); RxThrottleParameters->MoreNblsPending = 0; interruptSource = ParaNdis_DPCWorkBody(pContext, RxThrottleParameters->MaxNblsToIndicate); if (interruptSource) { InterlockedOr(&pContext->InterruptStatus, interruptSource); if (interruptSource & isReceive) { if (NDIS_INDICATE_ALL_NBLS != RxThrottleParameters->MaxNblsToIndicate) { RxThrottleParameters->MoreNblsPending = 1; DPrintf(3, ("[%s] Requested additional RX DPC\n", __FUNCTION__)); } else bSpawnNextDpc = TRUE; } if (interruptSource & isTransmit) bSpawnNextDpc = TRUE; if (bSpawnNextDpc) { GROUP_AFFINITY Affinity; GetAffinityForCurrentCpu(&Affinity); NdisMQueueDpcEx(pContext->InterruptHandle, MessageId, &Affinity, MiniportDpcContext); } } #else UNREFERENCED_PARAMETER(NdisReserved1); DPrintf(5, ("[%s] (Message %d, source %d)\n", __FUNCTION__, MessageId, interruptSource)); interruptSource = ParaNdis_DPCWorkBody(pContext, PARANDIS_UNLIMITED_PACKETS_TO_INDICATE); if (interruptSource) { DPrintf(4, ("[%s] Queued additional DPC for %d\n", __FUNCTION__, interruptSource)); InterlockedOr(&pContext->InterruptStatus, interruptSource); NdisMQueueDpc(pContext->InterruptHandle, MessageId, 1 << KeGetCurrentProcessorNumber(), MiniportDpcContext); } #endif UNREFERENCED_PARAMETER(NdisReserved2); }
void FastInterlockOr(uint32_t volatile *p, uint32_t msk) { InterlockedOr((LONG *)p, msk); }
guint (g_atomic_int_or) (volatile guint *atomic, guint val) { return InterlockedOr (atomic, val); }
// // Routine Description: // // PL011pInterruptIsr is called by PL011EvtInterruptIsr // to process interrupts events at ISR level. // The routine saves the received event mask in the device extension // for DPC processing. // If RX/TX FIFO events occur, the routine calls the RX/TX handlers // to copy new/pending data from/to RX/TX FIFOs. // // Arguments: // // DevExtPtr - Our device extension. // // Return Value: // // TRUE If interrupt has been serviced, i.e. the source was the PL011 UART, // otherwise FALSE. // _Use_decl_annotations_ BOOLEAN PL011pInterruptIsr( PL011_DEVICE_EXTENSION* DevExtPtr ) { // // Interrupt status register // ULONG regUARTRIS = PL011HwReadRegisterUlong( PL011HwRegAddress(DevExtPtr, UARTRIS) ); if ((regUARTRIS & UART_INTERUPPTS_ALL) == 0) { // // Not the UART interrupt // return FALSE; } // // Update the events mask to be handled at DPC // level. // InterlockedOr( reinterpret_cast<volatile LONG*>(&DevExtPtr->IntEventsForDpc), regUARTRIS ); // // RX interrupt: // If a character has been received, or the FIFO is // not empty, and RX timeout has occurred. // Basically if RX FIFO is not empty. // // Copy the RX FIFO to our local RX buffer. // if ((regUARTRIS & (UARTRIS_RXIS|UARTRIS_RTIS)) != 0) { // // Copy new data from RX FIFO to PIO RX buffer. // (void)PL011RxPioFifoCopy(DevExtPtr, nullptr); // // Update the state to RX_PIO_STATE__DATA_READY if // we are still reading data to let the read engine // know new data is ready. // (void)PL011RxPioStateSetCompare( DevExtPtr->SerCx2PioReceive, PL011_RX_PIO_STATE::RX_PIO_STATE__DATA_READY, PL011_RX_PIO_STATE::RX_PIO_STATE__READ_DATA ); } // if (RX interrupt) // // TX interrupt: // If TX FIFOs occupancy has gone bellow the configured // trigger level. // // Copy our local TX buffer to TX FIFO. // if ((regUARTRIS & UARTRIS_TXIS) != 0) { // // Copy pending data from PIO TX buffer to TX FIFO. // PL011TxPioFifoCopy(DevExtPtr, nullptr); (void)PL011TxPioStateSetCompare( DevExtPtr->SerCx2PioTransmit, PL011_TX_PIO_STATE::TX_PIO_STATE__DATA_SENT, PL011_TX_PIO_STATE::TX_PIO_STATE__SEND_DATA ); } // if (TX interrupt) // // Acknowledge the events we just processed. // PL011HwWriteRegisterUlong( PL011HwRegAddress(DevExtPtr, UARTICR), regUARTRIS ); return TRUE; }
NTSTATUS NTAPI VdmpStartExecution(VOID) { PETHREAD Thread = PsGetCurrentThread(); PKTRAP_FRAME VdmFrame; NTSTATUS Status; PVDM_TIB VdmTib; BOOLEAN Interrupts; KIRQL OldIrql; CONTEXT VdmContext; PAGED_CODE(); /* Get the thread's VDM frame and TIB */ VdmFrame = (PVOID)((ULONG_PTR)Thread->Tcb.InitialStack - sizeof(FX_SAVE_AREA) - sizeof(KTRAP_FRAME)); Status = VdmpGetVdmTib(&VdmTib); if (!NT_SUCCESS(Status)) return STATUS_INVALID_SYSTEM_SERVICE; /* Go to APC level */ KeRaiseIrql(APC_LEVEL, &OldIrql); /* Check if interrupts are enabled */ Interrupts = (BOOLEAN)(VdmTib->VdmContext.EFlags & EFLAGS_INTERRUPT_MASK); /* We don't support full VDM yet, this shouldn't happen */ ASSERT(*VdmState == 0); ASSERT(VdmTib->VdmContext.EFlags & EFLAGS_V86_MASK); /* Check if VME is supported and V86 mode was enabled */ if ((KeI386VirtualIntExtensions) && (VdmTib->VdmContext.EFlags & EFLAGS_V86_MASK)) { /* Check if interrupts are enabled */ if (Interrupts) { /* Set fake IF flag */ VdmTib->VdmContext.EFlags |= EFLAGS_VIF; } else { /* Remove fake IF flag, turn on real IF flag */ VdmTib->VdmContext.EFlags &= ~EFLAGS_VIF; VdmTib->VdmContext.EFlags |= EFLAGS_INTERRUPT_MASK; } } else { /* Set interrupt state in the VDM State */ if (VdmTib->VdmContext.EFlags & EFLAGS_INTERRUPT_MASK) { /* Enable them as well */ InterlockedOr((PLONG)VdmState, EFLAGS_INTERRUPT_MASK); } else { /* Disable them */ InterlockedAnd((PLONG)VdmState, ~EFLAGS_INTERRUPT_MASK); } /* Enable the interrupt flag */ VdmTib->VdmContext.EFlags |= EFLAGS_INTERRUPT_MASK; } /* Get the VDM context and make sure it's not an edited frame */ VdmContext = VdmTib->VdmContext; if (!(VdmContext.SegCs & FRAME_EDITED)) { /* Fail */ KeLowerIrql(OldIrql); return STATUS_INVALID_SYSTEM_SERVICE; } /* Now do the VDM Swap */ VdmSwapContext(VdmFrame, &VdmTib->MonitorContext, &VdmContext); /* Lower the IRQL and return EAX */ KeLowerIrql(OldIrql); return VdmFrame->Eax; }
/* * FUNCTION: Terminates the current thread * See "Windows Internals" - Chapter 13, Page 50-53 */ VOID NTAPI PspExitThread(IN NTSTATUS ExitStatus) { CLIENT_DIED_MSG TerminationMsg; NTSTATUS Status; PTEB Teb; PEPROCESS CurrentProcess; PETHREAD Thread, OtherThread, PreviousThread = NULL; PVOID DeallocationStack; SIZE_T Dummy; BOOLEAN Last = FALSE; PTERMINATION_PORT TerminationPort, NextPort; PLIST_ENTRY FirstEntry, CurrentEntry; PKAPC Apc; PTOKEN PrimaryToken; PAGED_CODE(); PSTRACE(PS_KILL_DEBUG, "ExitStatus: %d\n", ExitStatus); /* Get the Current Thread and Process */ Thread = PsGetCurrentThread(); CurrentProcess = Thread->ThreadsProcess; ASSERT((Thread) == PsGetCurrentThread()); /* Can't terminate a thread if it attached another process */ if (KeIsAttachedProcess()) { /* Bugcheck */ KeBugCheckEx(INVALID_PROCESS_ATTACH_ATTEMPT, (ULONG_PTR)CurrentProcess, (ULONG_PTR)Thread->Tcb.ApcState.Process, (ULONG_PTR)Thread->Tcb.ApcStateIndex, (ULONG_PTR)Thread); } /* Lower to Passive Level */ KeLowerIrql(PASSIVE_LEVEL); /* Can't be a worker thread */ if (Thread->ActiveExWorker) { /* Bugcheck */ KeBugCheckEx(ACTIVE_EX_WORKER_THREAD_TERMINATION, (ULONG_PTR)Thread, 0, 0, 0); } /* Can't have pending APCs */ if (Thread->Tcb.CombinedApcDisable != 0) { /* Bugcheck */ KeBugCheckEx(KERNEL_APC_PENDING_DURING_EXIT, 0, Thread->Tcb.CombinedApcDisable, 0, 1); } /* Lock the thread */ ExWaitForRundownProtectionRelease(&Thread->RundownProtect); /* Cleanup the power state */ PopCleanupPowerState((PPOWER_STATE)&Thread->Tcb.PowerState); /* Call the WMI Callback for Threads */ //WmiTraceThread(Thread, NULL, FALSE); /* Run Thread Notify Routines before we desintegrate the thread */ PspRunCreateThreadNotifyRoutines(Thread, FALSE); /* Lock the Process before we modify its thread entries */ KeEnterCriticalRegion(); ExAcquirePushLockExclusive(&CurrentProcess->ProcessLock); /* Decrease the active thread count, and check if it's 0 */ if (!(--CurrentProcess->ActiveThreads)) { /* Set the delete flag */ InterlockedOr((PLONG)&CurrentProcess->Flags, PSF_PROCESS_DELETE_BIT); /* Remember we are last */ Last = TRUE; /* Check if this termination is due to the thread dying */ if (ExitStatus == STATUS_THREAD_IS_TERMINATING) { /* Check if the last thread was pending */ if (CurrentProcess->ExitStatus == STATUS_PENDING) { /* Use the last exit status */ CurrentProcess->ExitStatus = CurrentProcess-> LastThreadExitStatus; } } else { /* Just a normal exit, write the code */ CurrentProcess->ExitStatus = ExitStatus; } /* Loop all the current threads */ FirstEntry = &CurrentProcess->ThreadListHead; CurrentEntry = FirstEntry->Flink; while (FirstEntry != CurrentEntry) { /* Get the thread on the list */ OtherThread = CONTAINING_RECORD(CurrentEntry, ETHREAD, ThreadListEntry); /* Check if it's a thread that's still alive */ if ((OtherThread != Thread) && !(KeReadStateThread(&OtherThread->Tcb)) && (ObReferenceObjectSafe(OtherThread))) { /* It's a live thread and we referenced it, unlock process */ ExReleasePushLockExclusive(&CurrentProcess->ProcessLock); KeLeaveCriticalRegion(); /* Wait on the thread */ KeWaitForSingleObject(OtherThread, Executive, KernelMode, FALSE, NULL); /* Check if we had a previous thread to dereference */ if (PreviousThread) ObDereferenceObject(PreviousThread); /* Remember the thread and re-lock the process */ PreviousThread = OtherThread; KeEnterCriticalRegion(); ExAcquirePushLockExclusive(&CurrentProcess->ProcessLock); } /* Go to the next thread */ CurrentEntry = CurrentEntry->Flink; } } else if (ExitStatus != STATUS_THREAD_IS_TERMINATING) { /* Write down the exit status of the last thread to get killed */ CurrentProcess->LastThreadExitStatus = ExitStatus; } /* Unlock the Process */ ExReleasePushLockExclusive(&CurrentProcess->ProcessLock); KeLeaveCriticalRegion(); /* Check if we had a previous thread to dereference */ if (PreviousThread) ObDereferenceObject(PreviousThread); /* Check if the process has a debug port and if this is a user thread */ if ((CurrentProcess->DebugPort) && !(Thread->SystemThread)) { /* Notify the Debug API. */ Last ? DbgkExitProcess(CurrentProcess->ExitStatus) : DbgkExitThread(ExitStatus); } /* Check if this is a Critical Thread */ if ((KdDebuggerEnabled) && (Thread->BreakOnTermination)) { /* Break to debugger */ PspCatchCriticalBreak("Critical thread 0x%p (in %s) exited\n", Thread, CurrentProcess->ImageFileName); } /* Check if it's the last thread and this is a Critical Process */ if ((Last) && (CurrentProcess->BreakOnTermination)) { /* Check if a debugger is here to handle this */ if (KdDebuggerEnabled) { /* Break to debugger */ PspCatchCriticalBreak("Critical process 0x%p (in %s) exited\n", CurrentProcess, CurrentProcess->ImageFileName); } else { /* Bugcheck, we can't allow this */ KeBugCheckEx(CRITICAL_PROCESS_DIED, (ULONG_PTR)CurrentProcess, 0, 0, 0); } } /* Sanity check */ ASSERT(Thread->Tcb.CombinedApcDisable == 0); /* Process the Termination Ports */ TerminationPort = Thread->TerminationPort; if (TerminationPort) { /* Setup the message header */ TerminationMsg.h.u2.ZeroInit = 0; TerminationMsg.h.u2.s2.Type = LPC_CLIENT_DIED; TerminationMsg.h.u1.s1.TotalLength = sizeof(TerminationMsg); TerminationMsg.h.u1.s1.DataLength = sizeof(TerminationMsg) - sizeof(PORT_MESSAGE); /* Loop each port */ do { /* Save the Create Time */ TerminationMsg.CreateTime = Thread->CreateTime; /* Loop trying to send message */ while (TRUE) { /* Send the LPC Message */ Status = LpcRequestPort(TerminationPort->Port, &TerminationMsg.h); if ((Status == STATUS_NO_MEMORY) || (Status == STATUS_INSUFFICIENT_RESOURCES)) { /* Wait a bit and try again */ KeDelayExecutionThread(KernelMode, FALSE, &ShortTime); continue; } break; } /* Dereference this LPC Port */ ObDereferenceObject(TerminationPort->Port); /* Move to the next one */ NextPort = TerminationPort->Next; /* Free the Termination Port Object */ ExFreePoolWithTag(TerminationPort, '=TsP'); /* Keep looping as long as there is a port */ TerminationPort = NextPort; } while (TerminationPort); } else if (((ExitStatus == STATUS_THREAD_IS_TERMINATING) && (Thread->DeadThread)) || !(Thread->DeadThread)) { /* * This case is special and deserves some extra comments. What * basically happens here is that this thread doesn't have a termination * port, which means that it died before being fully created. Since we * still have to notify an LPC Server, we'll use the exception port, * which we know exists. However, we need to know how far the thread * actually got created. We have three possibilities: * * - NtCreateThread returned an error really early: DeadThread is set. * - NtCreateThread managed to create the thread: DeadThread is off. * - NtCreateThread was creating the thread (with DeadThread set, * but the thread got killed prematurely: STATUS_THREAD_IS_TERMINATING * is our exit code.) * * For the 2 & 3rd scenarios, the thread has been created far enough to * warrant notification to the LPC Server. */ /* Setup the message header */ TerminationMsg.h.u2.ZeroInit = 0; TerminationMsg.h.u2.s2.Type = LPC_CLIENT_DIED; TerminationMsg.h.u1.s1.TotalLength = sizeof(TerminationMsg); TerminationMsg.h.u1.s1.DataLength = sizeof(TerminationMsg) - sizeof(PORT_MESSAGE); /* Make sure the process has an exception port */ if (CurrentProcess->ExceptionPort) { /* Save the Create Time */ TerminationMsg.CreateTime = Thread->CreateTime; /* Loop trying to send message */ while (TRUE) { /* Send the LPC Message */ Status = LpcRequestPort(CurrentProcess->ExceptionPort, &TerminationMsg.h); if ((Status == STATUS_NO_MEMORY) || (Status == STATUS_INSUFFICIENT_RESOURCES)) { /* Wait a bit and try again */ KeDelayExecutionThread(KernelMode, FALSE, &ShortTime); continue; } break; } } } /* Rundown Win32 Thread if there is one */ if (Thread->Tcb.Win32Thread) PspW32ThreadCallout(Thread, PsW32ThreadCalloutExit); /* If we are the last thread and have a W32 Process */ if ((Last) && (CurrentProcess->Win32Process)) { /* Run it down too */ PspW32ProcessCallout(CurrentProcess, FALSE); } /* Make sure Stack Swap is enabled */ if (!Thread->Tcb.EnableStackSwap) { /* Stack swap really shouldn't be disabled during exit! */ KeBugCheckEx(KERNEL_STACK_LOCKED_AT_EXIT, 0, 0, 0, 0); } /* Cancel I/O for the thread. */ IoCancelThreadIo(Thread); /* Rundown Timers */ ExTimerRundown(); /* FIXME: Rundown Registry Notifications (NtChangeNotify) CmNotifyRunDown(Thread); */ /* Rundown Mutexes */ KeRundownThread(); /* Check if we have a TEB */ Teb = Thread->Tcb.Teb; if (Teb) { /* Check if the thread is still alive */ if (!Thread->DeadThread) { /* Check if we need to free its stack */ if (Teb->FreeStackOnTermination) { /* Set the TEB's Deallocation Stack as the Base Address */ Dummy = 0; DeallocationStack = Teb->DeallocationStack; /* Free the Thread's Stack */ ZwFreeVirtualMemory(NtCurrentProcess(), &DeallocationStack, &Dummy, MEM_RELEASE); } /* Free the debug handle */ if (Teb->DbgSsReserved[1]) ObCloseHandle(Teb->DbgSsReserved[1], UserMode); } /* Decommit the TEB */ MmDeleteTeb(CurrentProcess, Teb); Thread->Tcb.Teb = NULL; } /* Free LPC Data */ LpcExitThread(Thread); /* Save the exit status and exit time */ Thread->ExitStatus = ExitStatus; KeQuerySystemTime(&Thread->ExitTime); /* Sanity check */ ASSERT(Thread->Tcb.CombinedApcDisable == 0); /* Check if this is the final thread or not */ if (Last) { /* Set the process exit time */ CurrentProcess->ExitTime = Thread->ExitTime; /* Exit the process */ PspExitProcess(TRUE, CurrentProcess); /* Get the process token and check if we need to audit */ PrimaryToken = PsReferencePrimaryToken(CurrentProcess); if (SeDetailedAuditingWithToken(PrimaryToken)) { /* Audit the exit */ SeAuditProcessExit(CurrentProcess); } /* Dereference the process token */ ObFastDereferenceObject(&CurrentProcess->Token, PrimaryToken); /* Check if this is a VDM Process and rundown the VDM DPCs if so */ if (CurrentProcess->VdmObjects) { /* VdmRundownDpcs(CurrentProcess); */ } /* Kill the process in the Object Manager */ ObKillProcess(CurrentProcess); /* Check if we have a section object */ if (CurrentProcess->SectionObject) { /* Dereference and clear the Section Object */ ObDereferenceObject(CurrentProcess->SectionObject); CurrentProcess->SectionObject = NULL; } /* Check if the process is part of a job */ if (CurrentProcess->Job) { /* Remove the process from the job */ PspExitProcessFromJob(CurrentProcess->Job, CurrentProcess); } } /* Disable APCs */ KeEnterCriticalRegion(); /* Disable APC queueing, force a resumption */ Thread->Tcb.ApcQueueable = FALSE; KeForceResumeThread(&Thread->Tcb); /* Re-enable APCs */ KeLeaveCriticalRegion(); /* Flush the User APCs */ FirstEntry = KeFlushQueueApc(&Thread->Tcb, UserMode); if (FirstEntry) { /* Start with the first entry */ CurrentEntry = FirstEntry; do { /* Get the APC */ Apc = CONTAINING_RECORD(CurrentEntry, KAPC, ApcListEntry); /* Move to the next one */ CurrentEntry = CurrentEntry->Flink; /* Rundown the APC or de-allocate it */ if (Apc->RundownRoutine) { /* Call its own routine */ Apc->RundownRoutine(Apc); } else { /* Do it ourselves */ ExFreePool(Apc); } } while (CurrentEntry != FirstEntry); } /* Clean address space if this was the last thread */ if (Last) MmCleanProcessAddressSpace(CurrentProcess); /* Call the Lego routine */ if (Thread->Tcb.LegoData) PspRunLegoRoutine(&Thread->Tcb); /* Flush the APC queue, which should be empty */ FirstEntry = KeFlushQueueApc(&Thread->Tcb, KernelMode); if ((FirstEntry) || (Thread->Tcb.CombinedApcDisable != 0)) { /* Bugcheck time */ KeBugCheckEx(KERNEL_APC_PENDING_DURING_EXIT, (ULONG_PTR)FirstEntry, Thread->Tcb.CombinedApcDisable, KeGetCurrentIrql(), 0); } /* Signal the process if this was the last thread */ if (Last) KeSetProcess(&CurrentProcess->Pcb, 0, FALSE); /* Terminate the Thread from the Scheduler */ KeTerminateThread(0); }
VOID NTAPI PspExitProcess(IN BOOLEAN LastThread, IN PEPROCESS Process) { ULONG Actual; PAGED_CODE(); PSTRACE(PS_KILL_DEBUG, "LastThread: %u Process: %p\n", LastThread, Process); PSREFTRACE(Process); /* Set Process Exit flag */ InterlockedOr((PLONG)&Process->Flags, PSF_PROCESS_EXITING_BIT); /* Check if we are the last thread */ if (LastThread) { /* Notify the WMI Process Callback */ //WmiTraceProcess(Process, FALSE); /* Run the Notification Routines */ PspRunCreateProcessNotifyRoutines(Process, FALSE); } /* Cleanup the power state */ PopCleanupPowerState((PPOWER_STATE)&Process->Pcb.PowerState); /* Clear the security port */ if (!Process->SecurityPort) { /* So we don't double-dereference */ Process->SecurityPort = (PVOID)1; } else if (Process->SecurityPort != (PVOID)1) { /* Dereference it */ ObDereferenceObject(Process->SecurityPort); Process->SecurityPort = (PVOID)1; } /* Check if we are the last thread */ if (LastThread) { /* Check if we have to set the Timer Resolution */ if (Process->SetTimerResolution) { /* Set it to default */ ZwSetTimerResolution(KeMaximumIncrement, 0, &Actual); } /* Check if we are part of a Job that has a completion port */ if ((Process->Job) && (Process->Job->CompletionPort)) { /* FIXME: Check job status code and do I/O completion if needed */ } /* FIXME: Notify the Prefetcher */ } else { /* Clear process' address space here */ MmCleanProcessAddressSpace(Process); } }
/** PnP IRP dispatcher */ static NTSTATUS STDCALL WvDummyDispatchPnpIrp( IN DEVICE_OBJECT * dev_obj, IN IRP * irp ) { IO_STACK_LOCATION * io_stack_loc; NTSTATUS status; S_WVL_DUMMY_PDO * dummy; LONG flags; ASSERT(dev_obj); dummy = dev_obj->DeviceExtension; ASSERT(dummy); ASSERT(irp); io_stack_loc = IoGetCurrentIrpStackLocation(irp); ASSERT(io_stack_loc); switch (io_stack_loc->MinorFunction) { case IRP_MN_QUERY_ID: return WvDummyPnpQueryId(dev_obj, irp); case IRP_MN_QUERY_DEVICE_TEXT: return WvDummyPnpQueryDeviceText(dev_obj, irp); case IRP_MN_QUERY_BUS_INFORMATION: return WvDummyPnpQueryBusInfo(dev_obj, irp); case IRP_MN_QUERY_CAPABILITIES: return WvDummyPnpQueryCapabilities(dev_obj, irp); case IRP_MN_QUERY_REMOVE_DEVICE: status = STATUS_SUCCESS; irp->IoStatus.Information = 0; break; case IRP_MN_SURPRISE_REMOVAL: WvlIncrementResourceUsage(dummy->DeviceExtension->Usage); flags = InterlockedOr(&dummy->Flags, CvWvDummyFlagSurpriseRemoved); status = STATUS_SUCCESS; irp->IoStatus.Information = 0; break; case IRP_MN_REMOVE_DEVICE: flags = InterlockedOr(&dummy->Flags, 0); if (flags & CvWvDummyFlagSurpriseRemoved) WvlDecrementResourceUsage(dummy->DeviceExtension->Usage); status = STATUS_SUCCESS; irp->IoStatus.Information = 0; break; case IRP_MN_START_DEVICE: status = STATUS_SUCCESS; break; default: /* Return whatever upper drivers in the stack yielded */ status = irp->IoStatus.Status; } irp->IoStatus.Status = status; WvlPassIrpUp(dev_obj, irp, IO_NO_INCREMENT); return status; }