[WIN32K]
[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 __drv_allocatesMem(Mem)
10 _Post_writable_byte_size_(sizeof(ERESOURCE))
11 HSEMAPHORE
12 APIENTRY
13 EngCreateSemaphore(
14 VOID)
15 {
16 // www.osr.com/ddk/graphics/gdifncs_95lz.htm
17 PERESOURCE psem = ExAllocatePoolWithTag(NonPagedPool,
18 sizeof(ERESOURCE),
19 GDITAG_SEMAPHORE);
20 if (!psem)
21 return NULL;
22
23 if (!NT_SUCCESS(ExInitializeResourceLite(psem)))
24 {
25 ExFreePoolWithTag(psem, GDITAG_SEMAPHORE );
26 return NULL;
27 }
28
29 return (HSEMAPHORE)psem;
30 }
31
32 /*
33 * @implemented
34 */
35 _Requires_lock_not_held_(*hsem)
36 _Acquires_exclusive_lock_(*hsem)
37 _Acquires_lock_(_Global_critical_region_)
38 VOID
39 APIENTRY
40 EngAcquireSemaphore(
41 _Inout_ HSEMAPHORE hsem)
42 {
43 // www.osr.com/ddk/graphics/gdifncs_14br.htm
44 PTHREADINFO W32Thread;
45
46 /* On Windows a NULL hsem is ignored */
47 if (hsem == NULL)
48 {
49 DPRINT1("EngAcquireSemaphore called with hsem == NULL!\n");
50 return;
51 }
52
53 ExEnterCriticalRegionAndAcquireResourceExclusive((PERESOURCE)hsem);
54 W32Thread = PsGetThreadWin32Thread(PsGetCurrentThread());
55 if (W32Thread) W32Thread->dwEngAcquireCount++;
56 }
57
58 /*
59 * @implemented
60 */
61 _Requires_lock_held_(*hsem)
62 _Releases_lock_(*hsem)
63 _Releases_lock_(_Global_critical_region_)
64 VOID
65 APIENTRY
66 EngReleaseSemaphore(
67 _Inout_ HSEMAPHORE hsem)
68 {
69 // www.osr.com/ddk/graphics/gdifncs_5u3r.htm
70 PTHREADINFO W32Thread;
71
72 /* On Windows a NULL hsem is ignored */
73 if (hsem == NULL)
74 {
75 DPRINT1("EngReleaseSemaphore called with hsem == NULL!\n");
76 return;
77 }
78
79 W32Thread = PsGetThreadWin32Thread(PsGetCurrentThread());
80 if (W32Thread) --W32Thread->dwEngAcquireCount;
81 ExReleaseResourceAndLeaveCriticalRegion((PERESOURCE)hsem);
82 }
83
84 _Acquires_lock_(_Global_critical_region_)
85 _Requires_lock_not_held_(*hsem)
86 _Acquires_shared_lock_(*hsem)
87 VOID
88 NTAPI
89 EngAcquireSemaphoreShared(
90 _Inout_ HSEMAPHORE hsem)
91 {
92 PTHREADINFO pti;
93
94 ASSERT(hsem);
95 ExEnterCriticalRegionAndAcquireResourceShared((PERESOURCE)hsem);
96 pti = PsGetThreadWin32Thread(PsGetCurrentThread());
97 if (pti) ++pti->dwEngAcquireCount;
98 }
99
100 /*
101 * @implemented
102 */
103 _Requires_lock_not_held_(*hsem)
104 VOID
105 APIENTRY
106 EngDeleteSemaphore(
107 _Inout_ __drv_freesMem(Mem) HSEMAPHORE hsem)
108 {
109 // www.osr.com/ddk/graphics/gdifncs_13c7.htm
110 ASSERT(hsem);
111
112 ExDeleteResourceLite((PERESOURCE)hsem);
113 ExFreePoolWithTag((PVOID)hsem, GDITAG_SEMAPHORE);
114 }
115
116 /*
117 * @implemented
118 */
119 BOOL
120 APIENTRY
121 EngIsSemaphoreOwned(
122 _In_ HSEMAPHORE hsem)
123 {
124 // www.osr.com/ddk/graphics/gdifncs_6wmf.htm
125 ASSERT(hsem);
126 return (((PERESOURCE)hsem)->ActiveCount > 0);
127 }
128
129 /*
130 * @implemented
131 */
132 BOOL
133 APIENTRY
134 EngIsSemaphoreOwnedByCurrentThread(
135 _In_ HSEMAPHORE hsem)
136 {
137 // www.osr.com/ddk/graphics/gdifncs_9yxz.htm
138 ASSERT(hsem);
139 return ExIsResourceAcquiredExclusiveLite((PERESOURCE)hsem);
140 }
141
142 /*
143 * @implemented
144 */
145 BOOL
146 APIENTRY
147 EngInitializeSafeSemaphore(
148 _Out_ ENGSAFESEMAPHORE *Semaphore)
149 {
150 HSEMAPHORE hSem;
151
152 if (InterlockedIncrement(&Semaphore->lCount) == 1)
153 {
154 /* Create the semaphore */
155 hSem = EngCreateSemaphore();
156 if (hSem == 0)
157 {
158 InterlockedDecrement(&Semaphore->lCount);
159 return FALSE;
160 }
161 /* FIXME: Not thread-safe! Check result of InterlockedCompareExchangePointer
162 and delete semaphore if already initialized! */
163 (void)InterlockedExchangePointer((volatile PVOID *)&Semaphore->hsem, hSem);
164 }
165 else
166 {
167 /* Wait for the other thread to create the semaphore */
168 ASSERT(Semaphore->lCount > 1);
169 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL);
170 while (Semaphore->hsem == NULL);
171 }
172
173 return TRUE;
174 }
175
176 /*
177 * @implemented
178 */
179 VOID
180 APIENTRY
181 EngDeleteSafeSemaphore(
182 _Inout_ _Post_invalid_ ENGSAFESEMAPHORE *pssem)
183 {
184 if (InterlockedDecrement(&pssem->lCount) == 0)
185 {
186 /* FIXME: Not thread-safe! Use result of InterlockedCompareExchangePointer! */
187 EngDeleteSemaphore(pssem->hsem);
188 (void)InterlockedExchangePointer((volatile PVOID *)&pssem->hsem, NULL);
189 }
190 }
191
192 /* EOF */