:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / ntoskrnl / ke / spinlock.c
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS kernel
5  * FILE:            ntoskrnl/ke/spinlock.c
6  * PURPOSE:         Implements spinlocks
7  * PROGRAMMER:      David Welch (welch@cwcom.net)
8  * UPDATE HISTORY:
9  *                  3/6/98: Created
10  */
11
12 /*
13  * NOTE: On a uniprocessor machine spinlocks are implemented by raising
14  * the irq level
15  */
16
17 /* INCLUDES ****************************************************************/
18
19 #include <ddk/ntddk.h>
20 #include <roscfg.h>
21
22 #include <internal/debug.h>
23
24 /* FUNCTIONS ***************************************************************/
25
26 BOOLEAN STDCALL
27 KeSynchronizeExecution (PKINTERRUPT             Interrupt,
28                         PKSYNCHRONIZE_ROUTINE   SynchronizeRoutine,
29                         PVOID                   SynchronizeContext)
30 /*
31  * FUNCTION: Synchronizes the execution of a given routine with the ISR
32  * of a given interrupt object
33  * ARGUMENTS:
34  *       Interrupt = Interrupt object to synchronize with
35  *       SynchronizeRoutine = Routine to call whose execution is 
36  *                            synchronized with the ISR
37  *       SynchronizeContext = Parameter to pass to the synchronized routine
38  * RETURNS: TRUE if the operation succeeded
39  */
40 {
41    KIRQL oldlvl;
42    BOOLEAN ret;
43    
44    KeRaiseIrql(Interrupt->SynchLevel,&oldlvl);
45    KeAcquireSpinLockAtDpcLevel(Interrupt->IrqLock);
46    
47    ret = SynchronizeRoutine(SynchronizeContext);
48    
49    KeReleaseSpinLockFromDpcLevel(Interrupt->IrqLock);
50    KeLowerIrql(oldlvl);
51    
52    return(ret);
53 }
54
55 VOID STDCALL
56 KeInitializeSpinLock (PKSPIN_LOCK       SpinLock)
57 /*
58  * FUNCTION: Initalizes a spinlock
59  * ARGUMENTS:
60  *           SpinLock = Caller supplied storage for the spinlock
61  */
62 {
63    SpinLock->Lock = 0;
64 }
65
66 VOID STDCALL
67 KeAcquireSpinLockAtDpcLevel (PKSPIN_LOCK        SpinLock)
68 /*
69  * FUNCTION: Acquires a spinlock when the caller is already running at 
70  * dispatch level
71  * ARGUMENTS:
72  *        SpinLock = Spinlock to acquire
73  */
74 {
75    ULONG i;
76
77    /*
78     * FIXME: This depends on gcc assembling this test to a single load from
79     * the spinlock's value.
80     */
81    if ((ULONG)SpinLock->Lock >= 2)
82      {
83         DbgPrint("Lock %x has bad value %x\n", SpinLock, SpinLock->Lock);
84         KeBugCheck(0);
85      }
86    
87    while ((i = InterlockedExchange(&SpinLock->Lock, 1)) == 1)
88      {
89 #ifndef MP
90        DbgPrint("Spinning on spinlock %x current value %x\n", SpinLock, i);
91        KeBugCheck(0);
92 #else /* not MP */
93        /* Avoid reading the value again too fast */
94 #endif /* MP */
95      }
96 }
97
98 VOID STDCALL
99 KeReleaseSpinLockFromDpcLevel (PKSPIN_LOCK      SpinLock)
100 /*
101  * FUNCTION: Releases a spinlock when the caller was running at dispatch
102  * level before acquiring it
103  * ARGUMENTS: 
104  *         SpinLock = Spinlock to release
105  */
106 {
107    if (SpinLock->Lock != 1)
108      {
109         DbgPrint("Releasing unacquired spinlock %x\n", SpinLock);
110         KeBugCheck(0);
111      }
112    (void)InterlockedExchange(&SpinLock->Lock, 0);
113 }
114
115 /* EOF */