5ef403d8670b70a748e8c7dd2ba01bc669fc2c45
[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 /*
73 * @implemented
74 */
75 VOID
76 APIENTRY
77 EngDeleteSemaphore ( IN HSEMAPHORE hsem )
78 {
79 // www.osr.com/ddk/graphics/gdifncs_13c7.htm
80 ASSERT ( hsem );
81
82 ExDeleteResourceLite((PERESOURCE)hsem);
83
84 ExFreePoolWithTag( (PVOID)hsem, TAG_GSEM);
85 }
86
87 /*
88 * @implemented
89 */
90 BOOL
91 APIENTRY
92 EngIsSemaphoreOwned ( IN HSEMAPHORE hsem )
93 {
94 // www.osr.com/ddk/graphics/gdifncs_6wmf.htm
95 ASSERT(hsem);
96 return (((PERESOURCE)hsem)->ActiveCount > 0);
97 }
98
99 /*
100 * @implemented
101 */
102 BOOL
103 APIENTRY
104 EngIsSemaphoreOwnedByCurrentThread ( IN HSEMAPHORE hsem )
105 {
106 // www.osr.com/ddk/graphics/gdifncs_9yxz.htm
107 ASSERT(hsem);
108 return ExIsResourceAcquiredExclusiveLite ( (PERESOURCE)hsem );
109 }
110
111 /*
112 * @implemented
113 */
114 BOOL APIENTRY
115 EngInitializeSafeSemaphore(
116 OUT ENGSAFESEMAPHORE *Semaphore)
117 {
118 HSEMAPHORE hSem;
119
120 if (InterlockedIncrement(&Semaphore->lCount) == 1)
121 {
122 /* Create the semaphore */
123 hSem = EngCreateSemaphore();
124 if (hSem == 0)
125 {
126 InterlockedDecrement(&Semaphore->lCount);
127 return FALSE;
128 }
129 /* FIXME - not thread-safe! Check result of InterlockedCompareExchangePointer
130 and delete semaphore if already initialized! */
131 (void)InterlockedExchangePointer((volatile PVOID *)&Semaphore->hsem, hSem);
132 }
133 else
134 {
135 /* Wait for the other thread to create the semaphore */
136 ASSERT(Semaphore->lCount > 1);
137 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL);
138 while (Semaphore->hsem == NULL);
139 }
140
141 return TRUE;
142 }
143
144 /*
145 * @implemented
146 */
147 VOID APIENTRY
148 EngDeleteSafeSemaphore(
149 IN OUT ENGSAFESEMAPHORE *Semaphore)
150 {
151 if (InterlockedDecrement(&Semaphore->lCount) == 0)
152 {
153 /* FIXME - not thread-safe! Use result of InterlockedCompareExchangePointer! */
154 EngDeleteSemaphore(Semaphore->hsem);
155 (void)InterlockedExchangePointer((volatile PVOID *)&Semaphore->hsem, NULL);
156 }
157 }
158
159