48ee574f24ac04bf04df5618f4a824119edf3da5
[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 ASSERT(hsem);
72 W32Thread = PsGetThreadWin32Thread(PsGetCurrentThread());
73 if (W32Thread) --W32Thread->dwEngAcquireCount;
74 ExReleaseResourceAndLeaveCriticalRegion((PERESOURCE)hsem);
75 }
76
77 _Acquires_lock_(_Global_critical_region_)
78 _Requires_lock_not_held_(*hsem)
79 _Acquires_shared_lock_(*hsem)
80 VOID
81 NTAPI
82 EngAcquireSemaphoreShared(
83 _Inout_ HSEMAPHORE hsem)
84 {
85 PTHREADINFO pti;
86
87 ASSERT(hsem);
88 ExEnterCriticalRegionAndAcquireResourceShared((PERESOURCE)hsem);
89 pti = PsGetThreadWin32Thread(PsGetCurrentThread());
90 if (pti) ++pti->dwEngAcquireCount;
91 }
92
93 /*
94 * @implemented
95 */
96 _Requires_lock_not_held_(*hsem)
97 VOID
98 APIENTRY
99 EngDeleteSemaphore(
100 _Inout_ __drv_freesMem(Mem) HSEMAPHORE hsem)
101 {
102 // www.osr.com/ddk/graphics/gdifncs_13c7.htm
103 ASSERT(hsem);
104
105 ExDeleteResourceLite((PERESOURCE)hsem);
106 ExFreePoolWithTag((PVOID)hsem, GDITAG_SEMAPHORE);
107 }
108
109 /*
110 * @implemented
111 */
112 BOOL
113 APIENTRY
114 EngIsSemaphoreOwned(
115 _In_ HSEMAPHORE hsem)
116 {
117 // www.osr.com/ddk/graphics/gdifncs_6wmf.htm
118 ASSERT(hsem);
119 return (((PERESOURCE)hsem)->ActiveCount > 0);
120 }
121
122 /*
123 * @implemented
124 */
125 BOOL
126 APIENTRY
127 EngIsSemaphoreOwnedByCurrentThread(
128 _In_ HSEMAPHORE hsem)
129 {
130 // www.osr.com/ddk/graphics/gdifncs_9yxz.htm
131 ASSERT(hsem);
132 return ExIsResourceAcquiredExclusiveLite((PERESOURCE)hsem);
133 }
134
135 /*
136 * @implemented
137 */
138 BOOL
139 APIENTRY
140 EngInitializeSafeSemaphore(
141 _Out_ ENGSAFESEMAPHORE *Semaphore)
142 {
143 HSEMAPHORE hSem;
144
145 if (InterlockedIncrement(&Semaphore->lCount) == 1)
146 {
147 /* Create the semaphore */
148 hSem = EngCreateSemaphore();
149 if (hSem == 0)
150 {
151 InterlockedDecrement(&Semaphore->lCount);
152 return FALSE;
153 }
154 /* FIXME: Not thread-safe! Check result of InterlockedCompareExchangePointer
155 and delete semaphore if already initialized! */
156 (void)InterlockedExchangePointer((volatile PVOID *)&Semaphore->hsem, hSem);
157 }
158 else
159 {
160 /* Wait for the other thread to create the semaphore */
161 ASSERT(Semaphore->lCount > 1);
162 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL);
163 while (Semaphore->hsem == NULL);
164 }
165
166 return TRUE;
167 }
168
169 /*
170 * @implemented
171 */
172 VOID
173 APIENTRY
174 EngDeleteSafeSemaphore(
175 _Inout_ _Post_invalid_ ENGSAFESEMAPHORE *pssem)
176 {
177 if (InterlockedDecrement(&pssem->lCount) == 0)
178 {
179 /* FIXME: Not thread-safe! Use result of InterlockedCompareExchangePointer! */
180 EngDeleteSemaphore(pssem->hsem);
181 (void)InterlockedExchangePointer((volatile PVOID *)&pssem->hsem, NULL);
182 }
183 }
184
185 /* EOF */