示例#1
0
static VOID
V4vVirqNotifyDpc(KDPC *dpc, VOID *dctx, PVOID sarg1, PVOID sarg2)
{
    XENV4V_EXTENSION  *pde = V4vGetDeviceExtension((DEVICE_OBJECT*)dctx);
    XENV4V_CONTEXT   **ctxList;
    ULONG              count = 0, i;
    KLOCK_QUEUE_HANDLE lqh;

    UNREFERENCED_PARAMETER(dpc);
    UNREFERENCED_PARAMETER(sarg1);
    UNREFERENCED_PARAMETER(sarg2);

    // In MP guests when not using VIRQs, have to lock the DPC processing
    KeAcquireInStackQueuedSpinLockAtDpcLevel(&pde->dpcLock, &lqh);

    // Get a list of active contexts and their rings
    ctxList = V4vGetAllContexts(pde, &count);

    // Loop over the contexts and process read IO for each.
    for (i = 0; ((ctxList != NULL)&&(i < count)); i++) {
        V4vProcessContextReads(pde, ctxList[i]);        
    }

    // Return the context list and drop the ref count
    V4vPutAllContexts(pde, ctxList, count);

    // Now process the notify and satisfy writes that are queued
    V4vProcessNotify(pde);

    KeReleaseInStackQueuedSpinLockFromDpcLevel(&lqh);
}
示例#2
0
// Buffer the log entry to the log buffer.
_Use_decl_annotations_ static NTSTATUS LogpBufferMessage(const char *message,
                                                         LogBufferInfo *info) {
  NT_ASSERT(info);

  // Acquire a spin lock to add the log safely.
  KLOCK_QUEUE_HANDLE lock_handle = {};
  const auto old_irql = KeGetCurrentIrql();
  if (old_irql < DISPATCH_LEVEL) {
    KeAcquireInStackQueuedSpinLock(&info->spin_lock, &lock_handle);
  } else {
    KeAcquireInStackQueuedSpinLockAtDpcLevel(&info->spin_lock, &lock_handle);
  }
  NT_ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);

  // Copy the current log to the buffer.
  SIZE_T used_buffer_size = info->log_buffer_tail - info->log_buffer_head;
  auto status =
      RtlStringCchCopyA(const_cast<char *>(info->log_buffer_tail),
                        kLogpBufferUsableSize - used_buffer_size, message);

  // Update info.log_max_usage if necessary.
  if (NT_SUCCESS(status)) {
    const auto message_length = strlen(message) + 1;
    info->log_buffer_tail += message_length;
    used_buffer_size += message_length;
    if (used_buffer_size > info->log_max_usage) {
      info->log_max_usage = used_buffer_size;  // Update
    }
  } else {
    info->log_max_usage = kLogpBufferSize;  // Indicates overflow
  }
  *info->log_buffer_tail = '\0';

  if (old_irql < DISPATCH_LEVEL) {
    KeReleaseInStackQueuedSpinLock(&lock_handle);
  } else {
    KeReleaseInStackQueuedSpinLockFromDpcLevel(&lock_handle);
  }
  return status;
}
示例#3
0
// Releases a spin lock
ScopedSpinLockAtDpc::~ScopedSpinLockAtDpc() {
  KeReleaseInStackQueuedSpinLockFromDpcLevel(&lock_handle_);
}
示例#4
0
NTSTATUS
InsertNBs(
	_Inout_ KKDRV_QUEUE_DATA *queueData,
	_In_ NET_BUFFER_LIST *head
	)
{
	NTSTATUS status = STATUS_SUCCESS;
	KLOCK_QUEUE_HANDLE lockHandle;

	NET_BUFFER_LIST *nbl = head;
	NET_BUFFER *nb;

	while (nbl)
	{
		nb = NET_BUFFER_LIST_FIRST_NB(nbl);

		while (nb)
		{
			PVOID data;
			ULONG dataLength = NET_BUFFER_DATA_LENGTH(nb);
			PKKDRV_PACKET packet = (PKKDRV_PACKET)ExAllocatePoolWithTag(
				NonPagedPool,
				KKDRV_PACKET_SIZE + dataLength,
				KKDRV_TAG
				);
			if (packet == NULL)
			{
				return STATUS_INSUFFICIENT_RESOURCES;
			};

			packet->dataLength = dataLength;
			data = NdisGetDataBuffer(nb, dataLength, NULL, 1, 0);
			if (data == NULL)
			{
				NdisGetDataBuffer(nb, dataLength, &packet->data, 1, 0);
			}
			else
			{
				RtlCopyMemory(&(packet->data), data, dataLength);
			}

			KeAcquireInStackQueuedSpinLockAtDpcLevel(
				&queueData->queueLock,
				&lockHandle
				);

			InsertTailList(&queueData->queue, &packet->entry);
			queueData->queueLength++;

			if (queueData->queueLength > queueData->queueLengthMax)
			{
				PLIST_ENTRY entry = RemoveHeadList(&queueData->queue);
				ExFreePoolWithTag(entry, KKDRV_TAG);
				queueData->queueLength--;
			}

			KeReleaseInStackQueuedSpinLockFromDpcLevel(
				&lockHandle
				);

			nb = nb->Next;
		}

		nbl = nbl->Next;
	}

	return status;
}
示例#5
0
VOID
FASTCALL
KeWaitForGate (
    __inout PKGATE Gate,
    __in KWAIT_REASON WaitReason,
    __in KPROCESSOR_MODE WaitMode
    )

/*++

Routine Description:

    This function waits until the signal state of a gate object is set. If
    the state of the gate object is signaled when the wait is executed, then
    no wait will occur.

Arguments:

    Gate - Supplies a pointer to a dispatcher object of type Gate.

    WaitReason - Supplies the reason for the wait.

    WaitMode  - Supplies the processor mode in which the wait is to occur.

Return Value:

    None.

--*/

{

    PKTHREAD CurrentThread;
    KLOCK_QUEUE_HANDLE LockHandle;
    PKQUEUE Queue;
    PKWAIT_BLOCK WaitBlock;
    NTSTATUS WaitStatus;

    ASSERT_GATE(Gate);

    ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

    //
    // Raise IRQL to SYNCH_LEVEL and acquire the APC queue lock.
    //

    CurrentThread = KeGetCurrentThread();
    do {
        KeAcquireInStackQueuedSpinLockRaiseToSynch(&CurrentThread->ApcQueueLock,
                                                   &LockHandle);

        //
        // Test to determine if a kernel APC is pending.
        //
        // If a kernel APC is pending, the special APC disable count is zero,
        // and the previous IRQL was less than APC_LEVEL, then a kernel APC
        // was queued by another processor just after IRQL was raised to
        // SYNCH_LEVEL, but before the APC queue lock was acquired.
        //
        // N.B. This can only happen in a multiprocessor system.
        //

        if (CurrentThread->ApcState.KernelApcPending &&
            (CurrentThread->SpecialApcDisable == 0) &&
            (LockHandle.OldIrql < APC_LEVEL)) {

            //
            // Unlock the APC queue lock and lower IRQL to its previous value.
            // An APC interrupt will immediately occur which will result in
            // the delivery of the kernel APC if possible.
            //

            KeReleaseInStackQueuedSpinLock(&LockHandle);
            continue;
        }

        //
        // If the current thread is associated with a queue object, then
        // acquire the dispatcher lock.
        //

        if ((Queue = CurrentThread->Queue) != NULL) {
            KiLockDispatcherDatabaseAtSynchLevel();
        }

        //
        // Acquire the thread lock and the object lock.
        //
        // If the object is already signaled, then clear the signaled state,
        // release the object lock, release the thread lock, and lower IRQL
        // to its previous value. Otherwise, set the thread state to gate
        // wait, set the address of the gate object, insert the thread in the
        // object wait list, set context swap busy, release the object lock,
        // release the thread lock, and switch to a new thread.
        //

        KiAcquireThreadLock(CurrentThread);
        KiAcquireKobjectLock(Gate);
        if (Gate->Header.SignalState != 0) {
            Gate->Header.SignalState = 0;
            KiReleaseKobjectLock(Gate);
            KiReleaseThreadLock(CurrentThread);
            if (Queue != NULL) {
                KiUnlockDispatcherDatabaseFromSynchLevel();
            }

            KeReleaseInStackQueuedSpinLock(&LockHandle);
            break;
    
        } else {
            WaitBlock = &CurrentThread->WaitBlock[0];
            WaitBlock->Object = Gate;
            WaitBlock->Thread = CurrentThread;
            CurrentThread->WaitMode = WaitMode;
            CurrentThread->WaitReason = WaitReason;
            CurrentThread->WaitIrql = LockHandle.OldIrql;
            CurrentThread->State = GateWait;
            CurrentThread->GateObject = Gate;
            InsertTailList(&Gate->Header.WaitListHead, &WaitBlock->WaitListEntry);
            KiReleaseKobjectLock(Gate);
            KiSetContextSwapBusy(CurrentThread);
            KiReleaseThreadLock(CurrentThread);

            //
            // If the current thread is associated with a queue object, then
            // activate another thread if possible.
            //

            if (Queue != NULL) {
                if ((Queue = CurrentThread->Queue) != NULL) {
                    KiActivateWaiterQueue(Queue);
                }

                KiUnlockDispatcherDatabaseFromSynchLevel();
            }

            KeReleaseInStackQueuedSpinLockFromDpcLevel(&LockHandle);
            WaitStatus = (NTSTATUS)KiSwapThread(CurrentThread, KeGetCurrentPrcb());
            if (WaitStatus == STATUS_SUCCESS) {
                return;
            }
        }

    } while (TRUE);

    return;
}