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