ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

gate.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Kernel
00003  * LICENSE:         GPL - See COPYING in the top level directory
00004  * FILE:            ntoskrnl/ke/gate.c
00005  * PURPOSE:         Implements the Gate Dispatcher Object
00006  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
00007  */
00008 
00009 /* INCLUDES *****************************************************************/
00010 
00011 #include <ntoskrnl.h>
00012 #define NDEBUG
00013 #include <debug.h>
00014 
00015 /* FUNCTIONS ****************************************************************/
00016 
00017 VOID
00018 FASTCALL
00019 KeInitializeGate(IN PKGATE Gate)
00020 {
00021     /* Initialize the Dispatcher Header */
00022     Gate->Header.Type = GateObject;
00023     Gate->Header.Signalling = FALSE;
00024     Gate->Header.Size = sizeof(KGATE) / sizeof(ULONG);
00025     Gate->Header.SignalState = 0;
00026     InitializeListHead(&(Gate->Header.WaitListHead));
00027 }
00028 
00029 VOID
00030 FASTCALL
00031 KeWaitForGate(IN PKGATE Gate,
00032               IN KWAIT_REASON WaitReason,
00033               IN KPROCESSOR_MODE WaitMode)
00034 {
00035     KLOCK_QUEUE_HANDLE ApcLock;
00036     PKTHREAD Thread = KeGetCurrentThread();
00037     PKWAIT_BLOCK GateWaitBlock;
00038     LONG_PTR Status;
00039     PKQUEUE Queue;
00040     ASSERT_GATE(Gate);
00041     ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
00042 
00043     /* Start wait loop */
00044     do
00045     {
00046         /* Acquire the APC lock */
00047         KiAcquireApcLock(Thread, &ApcLock);
00048 
00049         /* Check if a kernel APC is pending and we're below APC_LEVEL */
00050         if ((Thread->ApcState.KernelApcPending) &&
00051             !(Thread->SpecialApcDisable) &&
00052             (ApcLock.OldIrql < APC_LEVEL))
00053         {
00054             /* Release the lock, this will fire the APC */
00055             KiReleaseApcLock(&ApcLock);
00056         }
00057         else
00058         {
00059             /* Check if we have a queue and lock the dispatcher if so */
00060             Queue = Thread->Queue;
00061             if (Queue) KiAcquireDispatcherLockAtDpcLevel();
00062 
00063             /* Lock the thread */
00064             KiAcquireThreadLock(Thread);
00065 
00066             /* Lock the gate */
00067             KiAcquireDispatcherObject(&Gate->Header);
00068 
00069             /* Check if it's already signaled */
00070             if (Gate->Header.SignalState)
00071             {
00072                 /* Unsignal it */
00073                 Gate->Header.SignalState = 0;
00074 
00075                 /* Release the gate and thread locks */
00076                 KiReleaseDispatcherObject(&Gate->Header);
00077                 KiReleaseThreadLock(Thread);
00078 
00079                 /* Release the gate lock */
00080                 if (Queue) KiReleaseDispatcherLockFromDpcLevel();
00081 
00082                 /* Release the APC lock and return */
00083                 KiReleaseApcLock(&ApcLock);
00084                 break;
00085             }
00086 
00087             /* Setup a Wait Block */
00088             GateWaitBlock = &Thread->WaitBlock[0];
00089             GateWaitBlock->Object = (PVOID)Gate;
00090             GateWaitBlock->Thread = Thread;
00091 
00092             /* Set the Thread Wait Data */
00093             Thread->WaitMode = WaitMode;
00094             Thread->WaitReason = WaitReason;
00095             Thread->WaitIrql = ApcLock.OldIrql;
00096             Thread->State = GateWait;
00097             Thread->GateObject = Gate;
00098 
00099             /* Insert into the Wait List */
00100             InsertTailList(&Gate->Header.WaitListHead,
00101                            &GateWaitBlock->WaitListEntry);
00102 
00103             /* Release the gate lock */
00104             KiReleaseDispatcherObject(&Gate->Header);
00105 
00106             /* Set swap busy */
00107             KiSetThreadSwapBusy(Thread);
00108 
00109             /* Release the thread lock */
00110             KiReleaseThreadLock(Thread);
00111 
00112             /* Check if we had a queue */
00113             if (Queue)
00114             {
00115                 /* Wake it up */
00116                 KiActivateWaiterQueue(Queue);
00117 
00118                 /* Release the dispatcher lock */
00119                 KiReleaseDispatcherLockFromDpcLevel();
00120             }
00121 
00122             /* Release the APC lock but stay at DPC level */
00123             KiReleaseApcLockFromDpcLevel(&ApcLock);
00124 
00125             /* Find a new thread to run */
00126             Status = KiSwapThread(Thread, KeGetCurrentPrcb());
00127 
00128             /* Make sure we weren't executing an APC */
00129             if (Status == STATUS_SUCCESS) return;
00130         }
00131     } while (TRUE);
00132 }
00133 
00134 VOID
00135 FASTCALL
00136 KeSignalGateBoostPriority(IN PKGATE Gate)
00137 {
00138     PKTHREAD WaitThread;
00139     PKWAIT_BLOCK WaitBlock;
00140     KIRQL OldIrql;
00141     ASSERT_GATE(Gate);
00142     ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
00143 
00144     /* Start entry loop */
00145     for (;;)
00146     {
00147         /* Raise to synch level */
00148         OldIrql = KeRaiseIrqlToSynchLevel();
00149 
00150         /* Lock the gate */
00151         KiAcquireDispatcherObject(&Gate->Header);
00152 
00153         /* Make sure we're not already signaled or that the list is empty */
00154         if (Gate->Header.SignalState) break;
00155 
00156         /* Check if our wait list is empty */
00157         if (IsListEmpty(&Gate->Header.WaitListHead))
00158         {
00159             /* It is, so signal the event */
00160             Gate->Header.SignalState = 1;
00161             break;
00162         }
00163         else
00164         {
00165             /* Get WaitBlock */
00166             WaitBlock = CONTAINING_RECORD(Gate->Header.WaitListHead.Flink,
00167                                           KWAIT_BLOCK,
00168                                           WaitListEntry);
00169 
00170             /* Get the Associated thread */
00171             WaitThread = WaitBlock->Thread;
00172 
00173             /* Check to see if the waiting thread is locked */
00174             if (KiTryThreadLock(WaitThread))
00175             {
00176                 /* Unlock the gate */
00177                 KiReleaseDispatcherObject(&Gate->Header);
00178 
00179                 /* Lower IRQL and loop again */
00180                 KeLowerIrql(OldIrql);
00181                 continue;
00182             }
00183 
00184             /* Remove it */
00185             RemoveEntryList(&WaitBlock->WaitListEntry);
00186 
00187             /* Clear wait status */
00188             WaitThread->WaitStatus = STATUS_SUCCESS;
00189 
00190             /* Set state and CPU */
00191             WaitThread->State = DeferredReady;
00192             WaitThread->DeferredProcessor = KeGetCurrentPrcb()->Number;
00193 
00194             /* Release the gate lock */
00195             KiReleaseDispatcherObject(&Gate->Header);
00196 
00197             /* Release the thread lock */
00198             KiReleaseThreadLock(WaitThread);
00199 
00200             /* FIXME: Boosting */
00201 
00202             /* Check if we have a queue */
00203             if (WaitThread->Queue)
00204             {
00205                 /* Acquire the dispatcher lock */
00206                 KiAcquireDispatcherLockAtDpcLevel();
00207 
00208                 /* Check if we still have one */
00209                 if (WaitThread->Queue)
00210                 {
00211                     /* Increment active threads */
00212                     WaitThread->Queue->CurrentCount++;
00213                 }
00214 
00215                 /* Release lock */
00216                 KiReleaseDispatcherLockFromDpcLevel();
00217             }
00218 
00219             /* Make the thread ready */
00220             KiReadyThread(WaitThread);
00221 
00222             /* Exit the dispatcher */
00223             KiExitDispatcher(OldIrql);
00224             return;
00225         }
00226     }
00227 
00228     /* If we got here, then there's no rescheduling. */
00229     KiReleaseDispatcherObject(&Gate->Header);
00230     KeLowerIrql(OldIrql);
00231 }
00232 
00233 /* EOF */

Generated on Sat May 26 2012 04:36:19 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.