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