static int socket_recvmsg_unsafe(struct socket_file *f, struct msghdr *msg, int flags) { if (flags & ~LINUX_MSG_DONTWAIT) log_error("socket_sendmsg(): flags (0x%x) contains unsupported bits.", flags); if (f->shared->type != LINUX_SOCK_DGRAM && f->shared->type != LINUX_SOCK_RAW) { /* WSARecvMsg() only supports datagram and raw sockets * For other types we emulate using recvfrom() */ /* TODO: MSG_WAITALL * Per documentation, MSG_WAITALL should only return one type of message, i.e. only from one addr * But in this case (TCP) this should be true */ msg->msg_controllen = 0; msg->msg_flags = 0; /* TODO */ return socket_recvfrom_unsafe(f, msg->msg_iov[0].iov_base, msg->msg_iov[0].iov_len, flags, msg->msg_name, &msg->msg_namelen); } typedef int(*PFNWSARECVMSG)( _In_ SOCKET s, _Inout_ LPWSAMSG lpMsg, _Out_ LPDWORD lpdwNumberOfBytesRecvd, _In_ LPWSAOVERLAPPED lpOverlapped, _In_ LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine ); static PFNWSARECVMSG WSARecvMsg; if (!WSARecvMsg) { GUID guid = WSAID_WSARECVMSG; DWORD bytes; if (WSAIoctl(f->socket, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid), &WSARecvMsg, sizeof(WSARecvMsg), &bytes, NULL, NULL) == SOCKET_ERROR) { log_error("WSAIoctl(WSARecvMsg) failed, error code: %d", WSAGetLastError()); return -L_EIO; } } WSABUF *buffers = (WSABUF *)alloca(sizeof(struct iovec) * msg->msg_iovlen); for (int i = 0; i < msg->msg_iovlen; i++) { buffers[i].len = msg->msg_iov[i].iov_len; buffers[i].buf = msg->msg_iov[i].iov_base; } struct sockaddr_storage addr_storage; int addr_storage_len = sizeof(struct sockaddr_storage); WSAMSG wsamsg; wsamsg.name = (LPSOCKADDR)&addr_storage; wsamsg.namelen = addr_storage_len; wsamsg.lpBuffers = buffers; wsamsg.dwBufferCount = msg->msg_iovlen; wsamsg.Control.buf = msg->msg_control; wsamsg.Control.len = msg->msg_controllen; wsamsg.dwFlags = 0; int r; while ((r = socket_wait_event(f, FD_READ | FD_CLOSE, flags)) == 0) { if (WSARecvMsg(f->socket, &wsamsg, &r, NULL, NULL) != SOCKET_ERROR) break; InterlockedAnd(&f->shared->events, ~FD_READ); int err = WSAGetLastError(); if (err != WSAEWOULDBLOCK) { log_warning("WSARecvMsg() failed, error code: %d", err); return translate_socket_error(err); } } /* Translate WSAMSG back to msghdr */ addr_storage_len = translate_socket_addr_to_linux(&addr_storage, wsamsg.namelen); int copylen = min(msg->msg_namelen, addr_storage_len); memcpy(msg->msg_name, &addr_storage, copylen); msg->msg_namelen = addr_storage_len; msg->msg_controllen = wsamsg.Control.len; msg->msg_flags = 0; if (wsamsg.dwFlags & MSG_TRUNC) msg->msg_flags |= LINUX_MSG_TRUNC; if (wsamsg.dwFlags & MSG_CTRUNC) msg->msg_flags |= LINUX_MSG_CTRUNC; /* TODO: MSG_EOR, MSG_OOB, and MSG_ERRQUEUE */ return r; }
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); }
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; }
/* 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 int socket_sendto_unsafe(struct socket_file *f, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, int addrlen) { if (flags & ~LINUX_MSG_DONTWAIT) log_error("flags (0x%x) contains unsupported bits.", flags); struct sockaddr_storage addr_storage; if (addrlen) { if ((addrlen = translate_socket_addr_to_winsock((const struct sockaddr_storage *)dest_addr, &addr_storage, addrlen)) == SOCKET_ERROR) return -L_EINVAL; dest_addr = (const struct sockaddr *)&addr_storage; } else dest_addr = NULL; int r; while ((r = socket_wait_event(f, FD_WRITE, flags)) == 0) { r = sendto(f->socket, buf, len, 0, dest_addr, addrlen); if (r != SOCKET_ERROR) break; int err = WSAGetLastError(); if (err != WSAEWOULDBLOCK) { log_warning("sendto() failed, error code: %d", err); return translate_socket_error(err); } InterlockedAnd(&f->shared->events, ~FD_WRITE); } return r; }
static int socket_recvfrom_unsafe(struct socket_file *f, void *buf, size_t len, int flags, struct sockaddr *src_addr, int *addrlen) { if (flags & ~(LINUX_MSG_PEEK | LINUX_MSG_DONTWAIT)) log_error("flags (0x%x) contains unsupported bits.", flags); struct sockaddr_storage addr_storage; int addr_storage_len = sizeof(struct sockaddr_storage); int r; while ((r = socket_wait_event(f, FD_READ | FD_CLOSE, flags)) == 0) { if (!(flags & LINUX_MSG_PEEK)) InterlockedAnd(&f->shared->events, ~FD_READ); r = recvfrom(f->socket, buf, len, flags, (struct sockaddr *)&addr_storage, &addr_storage_len); if (r != SOCKET_ERROR) break; int err = WSAGetLastError(); if (err != WSAEWOULDBLOCK) { log_warning("recvfrom() failed, error code: %d", err); return translate_socket_error(err); } } if (addrlen) { addr_storage_len = translate_socket_addr_to_linux(&addr_storage, addr_storage_len); int copylen = min(*addrlen, addr_storage_len); memcpy(src_addr, &addr_storage, copylen); *addrlen = addr_storage_len; } return r; }
////////////////////////////////////////////////////////////////////////// /// iocp action ////////////////////////////////////////////////////////////////////////// static void iocp_accept(struct aio_context* ctx, struct aio_context_action* aio, DWORD error, DWORD bytes) { int locallen, remotelen; struct sockaddr *local; struct sockaddr *remote; assert(0 != (AIO_READ & InterlockedAnd(&ctx->flags, ~AIO_READ))); if(0 == error) { // http://msdn.microsoft.com/en-us/library/windows/desktop/ms737524%28v=vs.85%29.aspx // When the AcceptEx function returns, // the socket sAcceptSocket is in the default state for a connected socket. // The socket sAcceptSocket does not inherit the properties of the socket associated // with sListenSocket parameter until SO_UPDATE_ACCEPT_CONTEXT is set on the socket setsockopt(aio->accept.socket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char*)&ctx->socket, sizeof(ctx->socket)); local = remote = NULL; locallen = remotelen = 0; GetAcceptExSockaddrs(aio->accept.buffer, 0, sizeof(aio->accept.buffer)/2, sizeof(aio->accept.buffer)/2, &local, &locallen, &remote, &remotelen); aio->accept.proc(aio->accept.param, 0, aio->accept.socket, remote, remotelen); //aio->accept.proc(aio->accept.param, 0, aio->accept.socket, ip, (int)ntohs(remote->sin_port)); } else { closesocket(aio->accept.socket); // close handle aio->accept.proc(aio->accept.param, error, 0, NULL, 0); } }
VOID MPCreateThread(VOID (*FunctionPointer)(IN PKDPC, IN PVOID, IN PVOID, IN PVOID)) { /* * * Multi-Processor Consideration :: * * Each processor has it's own IDT. * */ CCHAR i; long currentProcessor =0; PKDPC pkDpc =NULL; KIRQL oldIrql, currentIrql; allProcessorDone =0; currentIrql = KeGetCurrentIrql(); if (currentIrql < DISPATCH_LEVEL) KeRaiseIrql(DISPATCH_LEVEL, &oldIrql); InterlockedAnd(&allProcessorDone, 0); pkDpc = (PKDPC)ExAllocatePoolWithTag(NonPagedPool, KeNumberProcessors * sizeof(KDPC), (ULONG)' pni'); if (!pkDpc) { DbgPrint("Insufficient Resource error\n"); return; } currentProcessor = KeGetCurrentProcessorNumber(); for (i = 0; i < KeNumberProcessors; i++) { cpuNum[i] =i; KeInitializeDpc(&pkDpc[i], FunctionPointer, &cpuNum[i]); KeSetTargetProcessorDpc(&pkDpc[i], i); KeInsertQueueDpc(&pkDpc[i], NULL, NULL); } // wait for all of the processor's hooking initialization. while(InterlockedCompareExchange(&allProcessorDone, KeNumberProcessors - 1, KeNumberProcessors - 1) != KeNumberProcessors - 1) { _asm pause; } if (currentIrql < DISPATCH_LEVEL) KeLowerIrql(oldIrql); if (pkDpc) { ExFreePool(pkDpc); pkDpc = NULL; } }
gsize (g_atomic_pointer_and) (volatile void *atomic, gsize val) { #if GLIB_SIZEOF_VOID_P == 8 return InterlockedAnd64 (atomic, val); #else return InterlockedAnd (atomic, val); #endif }
static inline int aio_socket_result(struct aio_context_action *aio, int flag) { DWORD ret = WSAGetLastError(); if (WSA_IO_PENDING != ret) { assert(0 != (flag & InterlockedAnd(&aio->context->flags, ~flag))); util_free(aio); return ret; } return 0; }
static void iocp_connect(struct aio_context* ctx, struct aio_context_action* aio, DWORD error, DWORD bytes) { (void)bytes; assert(0 != (AIO_WRITE & InterlockedAnd(&ctx->flags, ~AIO_WRITE))); // http://msdn.microsoft.com/en-us/library/windows/desktop/ms737606%28v=vs.85%29.aspx // When the ConnectEx function returns TRUE, the socket s is in the default state for a connected socket. // The socket s does not enable previously set properties or options until SO_UPDATE_CONNECT_CONTEXT is // set on the socket. Use the setsockopt function to set the SO_UPDATE_CONNECT_CONTEXT option. // r = setsockopt( s, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0 ); aio->connect.proc(aio->connect.param, error); }
/** * IRP_MJ_PNP:IRP_MN_REMOVE_DEVICE handler * * IRQL == PASSIVE_LEVEL, system thread * Completed by PDO * Do not send this IRP * Any child PDOs receive one of these IRPs first, except possibly * if they've been surprise-removed * * @return * Success: * Irp->IoStatus.Status == STATUS_SUCCESS */ static NTSTATUS STDCALL WvMemdiskPnpRemoveDevice( IN DEVICE_OBJECT * dev_obj, IN IRP * irp ) { S_WV_MEMDISK_BUS * bus; UCHAR i; DEVICE_OBJECT * child; NTSTATUS status; S_X86_SEG16OFF16 * safe_hook; UCHAR * phys_mem; UINT32 hook_phys_addr; WV_S_PROBE_SAFE_MBR_HOOK * hook; LONG flags; ASSERT(dev_obj); bus = dev_obj->DeviceExtension; ASSERT(bus); ASSERT(irp); /* Unlink the child PDOs, if any */ for (i = 0; i < bus->BusRelations->Count; ++i) { child = bus->BusRelations->Objects[i]; bus->BusRelations->Objects[i] = NULL; /* Best effort */ WvlAssignDeviceToBus(child, NULL); WvlDeleteDevice(child); } bus->BusRelations->Count -= i; /* Send the IRP down */ status = WvlPassIrpDown(dev_obj, irp); /* Detach FDO from PDO */ WvlDetachDevice(dev_obj); /* Schedule deletion of this device when the thread finishes */ WvlDeleteDevice(dev_obj); /* Best effort to "unclaim" the safe hook */ phys_mem = WvlMapUnmapLowMemory(NULL); if (phys_mem) { safe_hook = WvlGetSafeHook(bus->PhysicalDeviceObject); ASSERT(safe_hook); hook_phys_addr = M_X86_SEG16OFF16_ADDR(safe_hook); hook = (VOID *) (phys_mem + hook_phys_addr); flags = InterlockedAnd(&hook->Flags, ~1); WvlMapUnmapLowMemory(phys_mem); } return status; }
__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; }
inline ::LONG and ( volatile ::LONG& x, ::LONG y ) { #if defined(InterlockedAnd) return InterlockedAnd(&x, y); #else LONG i; LONG j; j = x; do { i = j; j = InterlockedCompareExchange(&x, i&y, i); } while (i != j); return j; #endif }
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; }
static int socket_sendmsg_unsafe(struct socket_file *f, const struct msghdr *msg, int flags) { if (flags & ~LINUX_MSG_DONTWAIT) log_error("socket_sendmsg(): flags (0x%x) contains unsupported bits.", flags); WSABUF *buffers = (WSABUF *)alloca(sizeof(struct iovec) * msg->msg_iovlen); for (int i = 0; i < msg->msg_iovlen; i++) { buffers[i].len = msg->msg_iov[i].iov_len; buffers[i].buf = msg->msg_iov[i].iov_base; } struct sockaddr_storage addr_storage; WSAMSG wsamsg; if (msg->msg_namelen) { if ((wsamsg.namelen = translate_socket_addr_to_winsock(msg->msg_name, &addr_storage, msg->msg_namelen)) == SOCKET_ERROR) return -L_EINVAL; wsamsg.name = (LPSOCKADDR)&addr_storage; } else { wsamsg.name = NULL; wsamsg.namelen = 0; } wsamsg.lpBuffers = buffers; wsamsg.dwBufferCount = msg->msg_iovlen; wsamsg.Control.buf = msg->msg_control; wsamsg.Control.len = msg->msg_controllen; wsamsg.dwFlags = 0; int r; while ((r = socket_wait_event(f, FD_WRITE, flags)) == 0) { if (WSASendMsg(f->socket, &wsamsg, 0, &r, NULL, NULL) != SOCKET_ERROR) break; int err = WSAGetLastError(); if (err != WSAEWOULDBLOCK) { log_warning("WSASendMsg() failed, error code: %d", err); return translate_socket_error(err); } InterlockedAnd(&f->shared->events, ~FD_WRITE); } return r; }
__host__ __device__ typename enable_if< sizeof(Integer32) == 4, Integer32 >::type atomic_fetch_and(Integer32 *x, Integer32 y) { #if defined(__CUDA_ARCH__) return atomicAnd(x, y); #elif defined(__GNUC__) return __atomic_fetch_and(x, y, __ATOMIC_SEQ_CST); #elif defined(_MSC_VER) return InterlockedAnd(x, y); #elif defined(__clang__) return __c11_atomic_fetch_and(x, y) #else #error "No atomic_fetch_and implementation." #endif }
static TUINT hal_timedwaitevent(struct THALBase *hal, struct HALThread *t, TTIME *tektime, TUINT sigmask) { struct HALSpecific *hws = hal->hmb_Specific; struct HALThread *wth = TlsGetValue(hws->hsp_TLSIndex); TTIME waitt, curt; TUINT millis; TUINT sig; for (;;) { #ifndef HAL_USE_ATOMICS EnterCriticalSection(&wth->hth_SigLock); sig = wth->hth_SigState & sigmask; wth->hth_SigState &= ~sigmask; LeaveCriticalSection(&wth->hth_SigLock); #else sig = InterlockedAnd(&wth->hth_SigState, ~sigmask) & sigmask; #endif if (sig) break; waitt = *tektime; hal_getsystime(hal, &curt); TSubTime(&waitt, &curt); if (waitt.tdt_Int64 < 0) break; if (waitt.tdt_Int64 > 1000000000000LL) millis = 1000000000; else millis = waitt.tdt_Int64 / 1000; if (millis > 0) WaitForSingleObject(wth->hth_SigEvent, millis); } return sig; }
EXPORT TUINT hal_wait(struct THALBase *hal, TUINT sigmask) { struct HALSpecific *hws = hal->hmb_Specific; struct HALThread *wth = TlsGetValue(hws->hsp_TLSIndex); TUINT sig; for (;;) { #ifndef HAL_USE_ATOMICS EnterCriticalSection(&wth->hth_SigLock); sig = wth->hth_SigState & sigmask; wth->hth_SigState &= ~sigmask; LeaveCriticalSection(&wth->hth_SigLock); #else sig = InterlockedAnd(&wth->hth_SigState, ~sigmask) & sigmask; #endif if (sig) break; WaitForSingleObject(wth->hth_SigEvent, INFINITE); } return sig; }
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 }
static NTSTATUS NTAPI V4vDispatchPnP(PDEVICE_OBJECT fdo, PIRP irp) { NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION isl = IoGetCurrentIrpStackLocation(irp); PXENV4V_EXTENSION pde = V4vGetDeviceExtension(fdo); KEVENT kev; TraceVerbose(("====> '%s'.\n", __FUNCTION__)); TraceVerbose((" =PnP= 0x%x\n", isl->MinorFunction)); status = IoAcquireRemoveLock(&pde->removeLock, irp); if (!NT_SUCCESS(status)) { TraceError(("failed to acquire IO lock - error: 0x%x\n", status)); return V4vSimpleCompleteIrp(irp, status); } switch (isl->MinorFunction) { case IRP_MN_START_DEVICE: KeInitializeEvent(&kev, NotificationEvent, FALSE); // Send the start down and wait for it to complete IoCopyCurrentIrpStackLocationToNext(irp); IoSetCompletionRoutine(irp, V4vStartDeviceIoCompletion, &kev, TRUE, TRUE, TRUE); status = IoCallDriver(pde->ldo, irp); if (status == STATUS_PENDING) { // Wait for everything underneath us to complete TraceVerbose(("Device start waiting for lower device.\n")); KeWaitForSingleObject(&kev, Executive, KernelMode, FALSE, NULL); TraceVerbose(("Device start wait finished.\n")); } status = irp->IoStatus.Status; if (!NT_SUCCESS(status)) { TraceError(("Failed to start lower drivers: %x.\n", status)); IoCompleteRequest(irp, IO_NO_INCREMENT); break; } status = STATUS_SUCCESS; // Connect our interrupt (ec). status = V4vInitializeEventChannel(fdo); if (NT_SUCCESS(status)) { InterlockedExchange(&pde->state, XENV4V_DEV_STARTED); } else { TraceError(("failed to initialize event channel - error: 0x%x\n", status)); } irp->IoStatus.Status = status; IoCompleteRequest(irp, IO_NO_INCREMENT); break; case IRP_MN_STOP_DEVICE: // Stop our device's IO processing V4vStopDevice(fdo, pde); // Pass it down irp->IoStatus.Status = STATUS_SUCCESS; IoSkipCurrentIrpStackLocation(irp); status = IoCallDriver(pde->ldo, irp); break; case IRP_MN_REMOVE_DEVICE: // Stop our device's IO processing V4vStopDevice(fdo, pde); // Cleanup anything here that locks for IO IoReleaseRemoveLockAndWait(&pde->removeLock, irp); // Pass it down first IoSkipCurrentIrpStackLocation(irp); status = IoCallDriver(pde->ldo, irp); // Then detach and cleanup our device xenbus_change_state(XBT_NIL, pde->frontendPath, "state", XENBUS_STATE_CLOSED); IoDetachDevice(pde->ldo); ExDeleteNPagedLookasideList(&pde->destLookasideList); XmFreeMemory(pde->frontendPath); IoDeleteSymbolicLink(&pde->symbolicLink); IoDeleteDevice(fdo); InterlockedAnd(&g_deviceCreated, 0); return status; default: // Pass it down TraceVerbose(("IRP_MJ_PNP MinorFunction %d passed down\n", isl->MinorFunction)); IoSkipCurrentIrpStackLocation(irp); status = IoCallDriver(pde->ldo, irp); }; // Everybody but REMOVE IoReleaseRemoveLock(&pde->removeLock, irp); TraceVerbose(("<==== '%s'.\n", __FUNCTION__)); return status; }
inline void CMyDevice::ExitProcessing(DWORD64 dwControlFlag) { //Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Entry"); InterlockedAnd (&m_dwShutdownControlFlags, ~dwControlFlag); }
NTKERNELAPI VOID FASTCALL ExfWakePushLock ( IN PEX_PUSH_LOCK PushLock, IN EX_PUSH_LOCK TopValue ) /*++ Routine Description: Walks the pushlock waiting list and wakes waiters if the lock is still unacquired. Arguments: PushLock - Push lock to be walked TopValue - Start of the chain (*PushLock) Return Value: None --*/ { EX_PUSH_LOCK OldValue, NewValue; PEX_PUSH_LOCK_WAIT_BLOCK WaitBlock, NextWaitBlock, FirstWaitBlock, PreviousWaitBlock; KIRQL OldIrql; OldValue = TopValue; while (1) { // // Nobody should be walking the list while we manipulate it. // ASSERT (!OldValue.MultipleShared); // // No point waking somebody to find a locked lock. Just clear the waking bit // while (OldValue.Locked) { NewValue.Value = OldValue.Value - EX_PUSH_LOCK_WAKING; ASSERT (!NewValue.Waking); ASSERT (NewValue.Locked); ASSERT (NewValue.Waiting); if ((NewValue.Ptr = InterlockedCompareExchangePointer (&PushLock->Ptr, NewValue.Ptr, OldValue.Ptr)) == OldValue.Ptr) { return; } OldValue = NewValue; } WaitBlock = (PEX_PUSH_LOCK_WAIT_BLOCK) (OldValue.Value & ~(ULONG_PTR)EX_PUSH_LOCK_PTR_BITS); FirstWaitBlock = WaitBlock; while (1) { NextWaitBlock = WaitBlock->Last; if (NextWaitBlock != NULL) { WaitBlock = NextWaitBlock; break; } PreviousWaitBlock = WaitBlock; WaitBlock = WaitBlock->Next; WaitBlock->Previous = PreviousWaitBlock; } if (WaitBlock->Flags&EX_PUSH_LOCK_FLAGS_EXCLUSIVE && (PreviousWaitBlock = WaitBlock->Previous) != NULL) { FirstWaitBlock->Last = PreviousWaitBlock; WaitBlock->Previous = NULL; ASSERT (FirstWaitBlock != WaitBlock); ASSERT (PushLock->Waiting); #if defined (_WIN64) InterlockedAnd64 ((LONG64 *)&PushLock->Value, ~EX_PUSH_LOCK_WAKING); #else InterlockedAnd ((LONG *)&PushLock->Value, ~EX_PUSH_LOCK_WAKING); #endif break; } else { NewValue.Value = 0; ASSERT (!NewValue.Waking); if ((NewValue.Ptr = InterlockedCompareExchangePointer (&PushLock->Ptr, NewValue.Ptr, OldValue.Ptr)) == OldValue.Ptr) { break; } OldValue = NewValue; } } // // If we are waking more than one thread then raise to DPC level to prevent us // getting rescheduled part way through the operation // OldIrql = DISPATCH_LEVEL; if (WaitBlock->Previous != NULL) { KeRaiseIrql (DISPATCH_LEVEL, &OldIrql); } while (1) { NextWaitBlock = WaitBlock->Previous; #if DBG ASSERT (!WaitBlock->Signaled); WaitBlock->Signaled = TRUE; #endif if (!InterlockedBitTestAndReset (&WaitBlock->Flags, EX_PUSH_LOCK_FLAGS_SPINNING_V)) { KeSignalGateBoostPriority (&WaitBlock->WakeGate); } WaitBlock = NextWaitBlock; if (WaitBlock == NULL) { break; } } if (OldIrql != DISPATCH_LEVEL) { KeLowerIrql (OldIrql); } }
static int socket_accept4(struct file *f, struct sockaddr *addr, int *addrlen, int flags) { struct socket_file *socket = (struct socket_file *)f; WaitForSingleObject(socket->mutex, INFINITE); struct sockaddr_storage addr_storage; int addr_storage_len; int r; while ((r = socket_wait_event(socket, FD_ACCEPT, 0)) == 0) { SOCKET socket_handle; addr_storage_len = sizeof(struct sockaddr_storage); if ((socket_handle = accept(socket->socket, (struct sockaddr *)&addr_storage, &addr_storage_len)) != SOCKET_ERROR) { /* Create a new socket */ HANDLE event_handle = init_socket_event(socket_handle); if (!event_handle) { closesocket(socket_handle); log_error("init_socket_event() failed."); r = -L_ENFILE; break; } HANDLE mutex; SECURITY_ATTRIBUTES attr; attr.nLength = sizeof(SECURITY_ATTRIBUTES); attr.lpSecurityDescriptor = NULL; attr.bInheritHandle = TRUE; mutex = CreateMutexW(&attr, FALSE, NULL); struct socket_file *conn_socket = (struct socket_file *)kmalloc(sizeof(struct socket_file)); file_init(&conn_socket->base_file, &socket_ops, 0); conn_socket->socket = socket_handle; conn_socket->event_handle = event_handle; conn_socket->mutex = mutex; conn_socket->shared = (struct socket_file_shared *)kmalloc_shared(sizeof(struct socket_file_shared)); conn_socket->shared->af = socket->shared->af; conn_socket->shared->type = socket->shared->type; conn_socket->shared->events = 0; conn_socket->shared->connect_error = 0; if (flags & O_NONBLOCK) conn_socket->base_file.flags |= O_NONBLOCK; r = vfs_store_file((struct file *)conn_socket, 0); if (r < 0) vfs_release((struct file *)conn_socket); /* Translate address back to Linux format */ if (addr && addrlen) { if (socket->shared->af == LINUX_AF_UNIX) { /* Set addr to unnamed */ struct sockaddr_un *addr_un = (struct sockaddr_un *)addr; *addrlen = sizeof(addr_un->sun_family); } else { *addrlen = translate_socket_addr_to_linux(&addr_storage, addr_storage_len); memcpy(addr, &addr_storage, *addrlen); } } break; } int err = WSAGetLastError(); if (err != WSAEWOULDBLOCK) { log_warning("accept() failed, error code: %d", err); r = translate_socket_error(err); break; } InterlockedAnd(&socket->shared->events, ~FD_ACCEPT); } ReleaseMutex(socket->mutex); return r; }
static void iocp_recv(struct aio_context* ctx, struct aio_context_action* aio, DWORD error, DWORD bytes) { assert(0 != (AIO_READ & InterlockedAnd(&ctx->flags, ~AIO_READ))); aio->recv.proc(aio->recv.param, error, bytes); }
static void iocp_send(struct aio_context* ctx, struct aio_context_action* aio, DWORD error, DWORD bytes) { assert(0 != (AIO_WRITE & InterlockedAnd(&ctx->flags, ~AIO_WRITE))); aio->send.proc(aio->send.param, error, bytes); }
static void iocp_recvfrom(struct aio_context* ctx, struct aio_context_action* aio, DWORD error, DWORD bytes) { assert(0 != (AIO_READ & InterlockedAnd(&ctx->flags, ~AIO_READ))); aio->recvfrom.proc(aio->recvfrom.param, error, bytes, (struct sockaddr*)&aio->recvfrom.addr, aio->recvfrom.addrlen); }
/** * 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; }
void FastInterlockAnd(uint32_t volatile *p, uint32_t msk) { InterlockedAnd((LONG *)p, msk); }
guint (g_atomic_int_and) (volatile guint *atomic, guint val) { return InterlockedAnd (atomic, val); }