Commit the stuff. Lots of changes. I'll write a proper list of changes when it's...
[reactos.git] / subsystems / win32 / win32k / eng / semaphor.c
1 #include <w32k.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), TAG_GSEM );
15 if ( !psem )
16 return NULL;
17 if ( !NT_SUCCESS(ExInitializeResourceLite ( psem )) )
18 {
19 ExFreePoolWithTag ( psem, TAG_GSEM );
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 ASSERT(hsem);
78 ExEnterCriticalRegionAndAcquireResourceShared((PERESOURCE)hsem);
79 }
80
81 /*
82 * @implemented
83 */
84 VOID
85 APIENTRY
86 EngDeleteSemaphore ( IN HSEMAPHORE hsem )
87 {
88 // www.osr.com/ddk/graphics/gdifncs_13c7.htm
89 ASSERT ( hsem );
90
91 ExDeleteResourceLite((PERESOURCE)hsem);
92
93 ExFreePoolWithTag( (PVOID)hsem, TAG_GSEM);
94 }
95
96 /*
97 * @implemented
98 */
99 BOOL
100 APIENTRY
101 EngIsSemaphoreOwned ( IN HSEMAPHORE hsem )
102 {
103 // www.osr.com/ddk/graphics/gdifncs_6wmf.htm
104 ASSERT(hsem);
105 return (((PERESOURCE)hsem)->ActiveCount > 0);
106 }
107
108 /*
109 * @implemented
110 */
111 BOOL
112 APIENTRY
113 EngIsSemaphoreOwnedByCurrentThread ( IN HSEMAPHORE hsem )
114 {
115 // www.osr.com/ddk/graphics/gdifncs_9yxz.htm
116 ASSERT(hsem);
117 return ExIsResourceAcquiredExclusiveLite ( (PERESOURCE)hsem );
118 }
119
120 /*
121 * @implemented
122 */
123 BOOL APIENTRY
124 EngInitializeSafeSemaphore(
125 OUT ENGSAFESEMAPHORE *Semaphore)
126 {
127 HSEMAPHORE hSem;
128
129 if (InterlockedIncrement(&Semaphore->lCount) == 1)
130 {
131 /* Create the semaphore */
132 hSem = EngCreateSemaphore();
133 if (hSem == 0)
134 {
135 InterlockedDecrement(&Semaphore->lCount);
136 return FALSE;
137 }
138 /* FIXME - not thread-safe! Check result of InterlockedCompareExchangePointer
139 and delete semaphore if already initialized! */
140 (void)InterlockedExchangePointer((volatile PVOID *)&Semaphore->hsem, hSem);
141 }
142 else
143 {
144 /* Wait for the other thread to create the semaphore */
145 ASSERT(Semaphore->lCount > 1);
146 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL);
147 while (Semaphore->hsem == NULL);
148 }
149
150 return TRUE;
151 }
152
153 /*
154 * @implemented
155 */
156 VOID APIENTRY
157 EngDeleteSafeSemaphore(
158 IN OUT ENGSAFESEMAPHORE *Semaphore)
159 {
160 if (InterlockedDecrement(&Semaphore->lCount) == 0)
161 {
162 /* FIXME - not thread-safe! Use result of InterlockedCompareExchangePointer! */
163 EngDeleteSemaphore(Semaphore->hsem);
164 (void)InterlockedExchangePointer((volatile PVOID *)&Semaphore->hsem, NULL);
165 }
166 }
167
168