[WIN32K]
[reactos.git] / reactos / subsystems / win32 / win32k / eng / semaphor.c
1 #include <win32k.h>
2
3 #define NDEBUG
4 #include <debug.h>
5
6 /*
7 * @implemented
8 */
9 HSEMAPHORE
10 APIENTRY
11 EngCreateSemaphore ( VOID )
12 {
13 // www.osr.com/ddk/graphics/gdifncs_95lz.htm
14 PERESOURCE psem = ExAllocatePoolWithTag( NonPagedPool, sizeof(ERESOURCE), GDITAG_SEMAPHORE );
15 if ( !psem )
16 return NULL;
17 if ( !NT_SUCCESS(ExInitializeResourceLite ( psem )) )
18 {
19 ExFreePoolWithTag ( psem, GDITAG_SEMAPHORE );
20 return NULL;
21 }
22 return (HSEMAPHORE)psem;
23 }
24
25 VOID
26 FASTCALL
27 IntGdiAcquireSemaphore ( HSEMAPHORE hsem )
28 {
29 KeEnterCriticalRegion();
30 ExAcquireResourceExclusiveLite ( (PERESOURCE)hsem, TRUE );
31 }
32
33 /*
34 * @implemented
35 */
36 VOID
37 APIENTRY
38 EngAcquireSemaphore ( IN HSEMAPHORE hsem )
39 {
40 // www.osr.com/ddk/graphics/gdifncs_14br.htm
41 PTHREADINFO W32Thread;
42 ASSERT(hsem);
43 IntGdiAcquireSemaphore ( hsem );
44 W32Thread = PsGetThreadWin32Thread(PsGetCurrentThread());
45 if (W32Thread) W32Thread->dwEngAcquireCount++;
46 }
47
48
49 VOID
50 FASTCALL
51 IntGdiReleaseSemaphore ( HSEMAPHORE hsem )
52 {
53 ExReleaseResourceLite ( (PERESOURCE)hsem );
54 KeLeaveCriticalRegion();
55 }
56
57 /*
58 * @implemented
59 */
60 VOID
61 APIENTRY
62 EngReleaseSemaphore ( IN HSEMAPHORE hsem )
63 {
64 // www.osr.com/ddk/graphics/gdifncs_5u3r.htm
65 PTHREADINFO W32Thread;
66 ASSERT(hsem);
67 W32Thread = PsGetThreadWin32Thread(PsGetCurrentThread());
68 if (W32Thread) --W32Thread->dwEngAcquireCount;
69 IntGdiReleaseSemaphore ( hsem );
70 }
71
72 VOID
73 NTAPI
74 EngAcquireSemaphoreShared(
75 IN HSEMAPHORE hsem)
76 {
77 PTHREADINFO pti;
78
79 ASSERT(hsem);
80 ExEnterCriticalRegionAndAcquireResourceShared((PERESOURCE)hsem);
81 pti = PsGetThreadWin32Thread(PsGetCurrentThread());
82 if (pti) ++pti->dwEngAcquireCount;
83 }
84
85 /*
86 * @implemented
87 */
88 VOID
89 APIENTRY
90 EngDeleteSemaphore ( IN HSEMAPHORE hsem )
91 {
92 // www.osr.com/ddk/graphics/gdifncs_13c7.htm
93 ASSERT ( hsem );
94
95 ExDeleteResourceLite((PERESOURCE)hsem);
96
97 ExFreePoolWithTag( (PVOID)hsem, GDITAG_SEMAPHORE);
98 }
99
100 /*
101 * @implemented
102 */
103 BOOL
104 APIENTRY
105 EngIsSemaphoreOwned ( IN HSEMAPHORE hsem )
106 {
107 // www.osr.com/ddk/graphics/gdifncs_6wmf.htm
108 ASSERT(hsem);
109 return (((PERESOURCE)hsem)->ActiveCount > 0);
110 }
111
112 /*
113 * @implemented
114 */
115 BOOL
116 APIENTRY
117 EngIsSemaphoreOwnedByCurrentThread ( IN HSEMAPHORE hsem )
118 {
119 // www.osr.com/ddk/graphics/gdifncs_9yxz.htm
120 ASSERT(hsem);
121 return ExIsResourceAcquiredExclusiveLite ( (PERESOURCE)hsem );
122 }
123
124 /*
125 * @implemented
126 */
127 BOOL APIENTRY
128 EngInitializeSafeSemaphore(
129 OUT ENGSAFESEMAPHORE *Semaphore)
130 {
131 HSEMAPHORE hSem;
132
133 if (InterlockedIncrement(&Semaphore->lCount) == 1)
134 {
135 /* Create the semaphore */
136 hSem = EngCreateSemaphore();
137 if (hSem == 0)
138 {
139 InterlockedDecrement(&Semaphore->lCount);
140 return FALSE;
141 }
142 /* FIXME - not thread-safe! Check result of InterlockedCompareExchangePointer
143 and delete semaphore if already initialized! */
144 (void)InterlockedExchangePointer((volatile PVOID *)&Semaphore->hsem, hSem);
145 }
146 else
147 {
148 /* Wait for the other thread to create the semaphore */
149 ASSERT(Semaphore->lCount > 1);
150 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL);
151 while (Semaphore->hsem == NULL);
152 }
153
154 return TRUE;
155 }
156
157 /*
158 * @implemented
159 */
160 VOID APIENTRY
161 EngDeleteSafeSemaphore(
162 IN OUT ENGSAFESEMAPHORE *Semaphore)
163 {
164 if (InterlockedDecrement(&Semaphore->lCount) == 0)
165 {
166 /* FIXME - not thread-safe! Use result of InterlockedCompareExchangePointer! */
167 EngDeleteSemaphore(Semaphore->hsem);
168 (void)InterlockedExchangePointer((volatile PVOID *)&Semaphore->hsem, NULL);
169 }
170 }
171
172