2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ex/sem.c
5 * PURPOSE: Semaphore Implementation
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
8 * David Welch (welch@mcmail.com)
11 /* INCLUDES *****************************************************************/
15 #include <internal/debug.h>
17 /* GLOBALS ******************************************************************/
19 POBJECT_TYPE ExSemaphoreObjectType
;
21 static GENERIC_MAPPING ExSemaphoreMapping
=
23 STANDARD_RIGHTS_READ
| SEMAPHORE_QUERY_STATE
,
24 STANDARD_RIGHTS_WRITE
| SEMAPHORE_MODIFY_STATE
,
25 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
| SEMAPHORE_QUERY_STATE
,
29 static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass
[] =
31 /* SemaphoreBasicInformation */
32 ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION
), sizeof(ULONG
), ICIF_QUERY
),
38 ExpInitializeSemaphoreImplementation(VOID
)
40 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
43 DPRINT("Creating Semaphore Object Type\n");
45 /* Create the Event Pair Object Type */
46 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
47 RtlInitUnicodeString(&Name
, L
"Semaphore");
48 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
49 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(KSEMAPHORE
);
50 ObjectTypeInitializer
.GenericMapping
= ExSemaphoreMapping
;
51 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
52 ObjectTypeInitializer
.InvalidAttributes
= OBJ_OPENLINK
;
53 ObjectTypeInitializer
.ValidAccessMask
= SEMAPHORE_ALL_ACCESS
;
54 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &ExSemaphoreObjectType
);
62 NtCreateSemaphore(OUT PHANDLE SemaphoreHandle
,
63 IN ACCESS_MASK DesiredAccess
,
64 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
68 PKSEMAPHORE Semaphore
;
70 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
71 NTSTATUS Status
= STATUS_SUCCESS
;
74 /* Check Output Safety */
75 if(PreviousMode
!= KernelMode
)
79 ProbeForWriteHandle(SemaphoreHandle
);
81 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
83 Status
= _SEH_GetExceptionCode();
87 if(!NT_SUCCESS(Status
)) return Status
;
90 /* Make sure the counts make sense */
91 if (MaximumCount
<= 0 || InitialCount
< 0 || InitialCount
> MaximumCount
)
93 DPRINT("Invalid Count Data!\n");
94 return STATUS_INVALID_PARAMETER
;
97 /* Create the Semaphore Object */
98 Status
= ObCreateObject(PreviousMode
,
99 ExSemaphoreObjectType
,
108 /* Check for Success */
109 if (NT_SUCCESS(Status
))
112 KeInitializeSemaphore(Semaphore
,
116 /* Insert it into the Object Tree */
117 Status
= ObInsertObject((PVOID
)Semaphore
,
123 ObDereferenceObject(Semaphore
);
125 /* Check for success and return handle */
126 if(NT_SUCCESS(Status
))
130 *SemaphoreHandle
= hSemaphore
;
132 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
134 Status
= _SEH_GetExceptionCode();
149 NtOpenSemaphore(OUT PHANDLE SemaphoreHandle
,
150 IN ACCESS_MASK DesiredAccess
,
151 IN POBJECT_ATTRIBUTES ObjectAttributes
)
154 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
155 NTSTATUS Status
= STATUS_SUCCESS
;
158 /* Check Output Safety */
159 if(PreviousMode
!= KernelMode
)
163 ProbeForWriteHandle(SemaphoreHandle
);
165 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
167 Status
= _SEH_GetExceptionCode();
171 if(!NT_SUCCESS(Status
)) return Status
;
174 /* Open the Object */
175 Status
= ObOpenObjectByName(ObjectAttributes
,
176 ExSemaphoreObjectType
,
183 /* Check for success and return handle */
184 if(NT_SUCCESS(Status
))
188 *SemaphoreHandle
= hSemaphore
;
190 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
192 Status
= _SEH_GetExceptionCode();
205 NtQuerySemaphore(IN HANDLE SemaphoreHandle
,
206 IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass
,
207 OUT PVOID SemaphoreInformation
,
208 IN ULONG SemaphoreInformationLength
,
209 OUT PULONG ReturnLength OPTIONAL
)
211 PKSEMAPHORE Semaphore
;
212 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
213 NTSTATUS Status
= STATUS_SUCCESS
;
217 /* Check buffers and class validity */
218 Status
= DefaultQueryInfoBufferCheck(SemaphoreInformationClass
,
219 ExSemaphoreInfoClass
,
220 sizeof(ExSemaphoreInfoClass
) / sizeof(ExSemaphoreInfoClass
[0]),
221 SemaphoreInformation
,
222 SemaphoreInformationLength
,
225 if(!NT_SUCCESS(Status
))
227 /* Invalid buffers */
228 DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status
);
233 Status
= ObReferenceObjectByHandle(SemaphoreHandle
,
234 SEMAPHORE_QUERY_STATE
,
235 ExSemaphoreObjectType
,
240 /* Check for success */
241 if(NT_SUCCESS(Status
))
245 PSEMAPHORE_BASIC_INFORMATION BasicInfo
= (PSEMAPHORE_BASIC_INFORMATION
)SemaphoreInformation
;
247 /* Return the basic information */
248 BasicInfo
->CurrentCount
= KeReadStateSemaphore(Semaphore
);
249 BasicInfo
->MaximumCount
= Semaphore
->Limit
;
252 if(ReturnLength
) *ReturnLength
= sizeof(SEMAPHORE_BASIC_INFORMATION
);
255 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
257 Status
= _SEH_GetExceptionCode();
260 /* Dereference the Object */
261 ObDereferenceObject(Semaphore
);
273 NtReleaseSemaphore(IN HANDLE SemaphoreHandle
,
274 IN LONG ReleaseCount
,
275 OUT PLONG PreviousCount OPTIONAL
)
277 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
278 PKSEMAPHORE Semaphore
;
279 NTSTATUS Status
= STATUS_SUCCESS
;
283 /* Check buffer validity */
284 if(PreviousCount
&& PreviousMode
!= KernelMode
)
288 ProbeForWriteLong(PreviousCount
);
290 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
292 Status
= _SEH_GetExceptionCode();
296 if(!NT_SUCCESS(Status
)) return Status
;
299 /* Make sure count makes sense */
300 if (ReleaseCount
<= 0)
302 DPRINT("Invalid Release Count\n");
303 return STATUS_INVALID_PARAMETER
;
307 Status
= ObReferenceObjectByHandle(SemaphoreHandle
,
308 SEMAPHORE_MODIFY_STATE
,
309 ExSemaphoreObjectType
,
314 /* Check for success */
315 if (NT_SUCCESS(Status
))
317 /* Release the semaphore */
320 LONG PrevCount
= KeReleaseSemaphore(Semaphore
,
324 ObDereferenceObject(Semaphore
);
326 /* Return the old count if requested */
329 *PreviousCount
= PrevCount
;
332 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
334 Status
= _SEH_GetExceptionCode();