|
|
/*-------------------------------------------------------------------
| waitmask.c -
3-30-99 - fix cancel event operation(race-condition) to avoid potential bug-check on queued eventwait cancel. 11-24-98 - update event kdprint debug messages - kpb Copyright 1993-99 Comtrol Corporation. All rights reserved. |--------------------------------------------------------------------*/ #include "precomp.h"
/*------------------------------------------------------------------
SerialCancelWait - (setup in ioctl.c currently, 3-28-98, kpb) This routine is used to cancel a irp that is waiting on a comm event. |-------------------------------------------------------------------*/ VOID SerialCancelWait(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{ PSERIAL_DEVICE_EXTENSION Extension = DeviceObject->DeviceExtension;
MyKdPrint(D_Ioctl,("CancelWait\n")) // take out, 3-30-99, kpb... Extension->IrpMaskLocation = NULL;
if (Extension->CurrentWaitIrp) { PIRP Irp_tmp;
MyKdPrint(D_Ioctl,("Cancel a Wait\n"))
//***** add, 3-30-99, kpb, cause crash on read thread in dos box without
// grab from ISR timer or interrupt routine.
SyncUp(Driver.InterruptObject, &Driver.TimerLock, SerialGrabWaitFromIsr, Extension); //***** end add, 3-30-99
// ExtTrace(Extension,D_Ioctl, "Cancel Event");
Extension->CurrentWaitIrp->IoStatus.Information = 0; Extension->CurrentWaitIrp->IoStatus.Status = STATUS_CANCELLED;
Irp_tmp = Extension->CurrentWaitIrp; IoSetCancelRoutine(Irp_tmp, NULL); // add 9-15-97, kpb
Extension->CurrentWaitIrp = 0; IoReleaseCancelSpinLock(Irp->CancelIrql); SerialCompleteRequest(Extension, Irp_tmp, IO_SERIAL_INCREMENT); } else { IoReleaseCancelSpinLock(Irp->CancelIrql); ExtTrace(Extension,D_Ioctl, "Err Cancel Event!"); MyKdPrint(D_Ioctl,("No Wait to Cancel\n")) } }
/*------------------------------------------------------------------
SerialCompleteWait - called by isr.c via CommWaitDpc. It nulls out IrpMaskLocation to signal control passed back to us. |-------------------------------------------------------------------*/ VOID SerialCompleteWait(IN PKDPC Dpc,IN PVOID DeferredContext, IN PVOID SystemContext1, IN PVOID SystemContext2) { PSERIAL_DEVICE_EXTENSION Extension = DeferredContext; KIRQL OldIrql; PIRP Irp_tmp;
UNREFERENCED_PARAMETER(Dpc); UNREFERENCED_PARAMETER(SystemContext1); UNREFERENCED_PARAMETER(SystemContext2);
MyKdPrint(D_Ioctl,("Complete Wait\n")) IoAcquireCancelSpinLock(&OldIrql);
if (Extension->CurrentWaitIrp != 0) { MyKdPrint(D_Ioctl,("Complete a Wait\n")) ExtTrace2(Extension,D_Ioctl, "Event Done Got:%xH Mask:%xH", *(ULONG *) Extension->CurrentWaitIrp->AssociatedIrp.SystemBuffer, Extension->IsrWaitMask);
Extension->WaitIsISRs = 0; Extension->IrpMaskLocation = &Extension->DummyIrpMaskLoc;
// caller sets the ULONG bit flags indicating event at .SystemBuffer
//*(ULONG *)Extension->CurrentWaitIrp->AssociatedIrp.SystemBuffer = 0;
Extension->CurrentWaitIrp->IoStatus.Status = STATUS_SUCCESS; Extension->CurrentWaitIrp->IoStatus.Information = sizeof(ULONG); Irp_tmp = Extension->CurrentWaitIrp; IoSetCancelRoutine(Irp_tmp, NULL); // add 9-15-97, kpb
Extension->CurrentWaitIrp = 0; IoReleaseCancelSpinLock(OldIrql); SerialCompleteRequest(Extension, Irp_tmp, IO_SERIAL_INCREMENT); } else { MyKdPrint(D_Ioctl,("No wait to complete\n")) IoReleaseCancelSpinLock(OldIrql); } }
/*------------------------------------------------------------------
SerialGrabWaitFromIsr - Take back the wait packet from the ISR by reseting IrpMaskLocation in extension. Need to use a sync with isr/timer routine to avoid contention in multiprocessor environments.
Called from sync routine or with timer spinlock held.
App - Can set IrpMaskLocation to give read-irp handling to the ISR without syncing to ISR. ISR - Can reset ReadPending to give wait-irp handling back to app-time.
If App wants to grab control of read-irp handling back from ISR, then it must sync-up with the isr/timer routine which has control. |-------------------------------------------------------------------*/ BOOLEAN SerialGrabWaitFromIsr(PSERIAL_DEVICE_EXTENSION Extension) { Extension->WaitIsISRs = 0; Extension->IrpMaskLocation = &Extension->DummyIrpMaskLoc; return FALSE; }
|