4 * Copyright 1998 Alexandre Julliard
14 #include "server/request.h"
20 THREAD_QUEUE wait_queue
;
25 static BOOL32
SEMAPHORE_Signaled( K32OBJ
*obj
, DWORD thread_id
);
26 static BOOL32
SEMAPHORE_Satisfied( K32OBJ
*obj
, DWORD thread_id
);
27 static void SEMAPHORE_AddWait( K32OBJ
*obj
, DWORD thread_id
);
28 static void SEMAPHORE_RemoveWait( K32OBJ
*obj
, DWORD thread_id
);
29 static void SEMAPHORE_Destroy( K32OBJ
*obj
);
31 const K32OBJ_OPS SEMAPHORE_Ops
=
33 SEMAPHORE_Signaled
, /* signaled */
34 SEMAPHORE_Satisfied
, /* satisfied */
35 SEMAPHORE_AddWait
, /* add_wait */
36 SEMAPHORE_RemoveWait
, /* remove_wait */
39 SEMAPHORE_Destroy
/* destroy */
43 /***********************************************************************
44 * CreateSemaphore32A (KERNEL32.174)
46 HANDLE32 WINAPI
CreateSemaphore32A( SECURITY_ATTRIBUTES
*sa
, LONG initial
,
47 LONG max
, LPCSTR name
)
49 struct create_semaphore_request req
;
50 struct create_semaphore_reply reply
;
51 int len
= name
? strlen(name
) + 1 : 0;
55 /* Check parameters */
57 if ((max
<= 0) || (initial
< 0) || (initial
> max
))
59 SetLastError( ERROR_INVALID_PARAMETER
);
60 return INVALID_HANDLE_VALUE32
;
63 req
.initial
= (unsigned int)initial
;
64 req
.max
= (unsigned int)max
;
65 req
.inherit
= (sa
&& (sa
->nLength
>=sizeof(*sa
)) && sa
->bInheritHandle
);
67 CLIENT_SendRequest( REQ_CREATE_SEMAPHORE
, -1, 2, &req
, sizeof(req
), name
, len
);
68 CLIENT_WaitReply( &len
, NULL
, 1, &reply
, sizeof(reply
) );
69 CHECK_LEN( len
, sizeof(reply
) );
70 if (reply
.handle
== -1) return NULL
;
73 sem
= (SEMAPHORE
*)K32OBJ_Create( K32OBJ_SEMAPHORE
, sizeof(*sem
),
74 name
, reply
.handle
, SEMAPHORE_ALL_ACCESS
,
78 /* Finish initializing it */
79 sem
->wait_queue
= NULL
;
82 K32OBJ_DecCount( &sem
->header
);
89 /***********************************************************************
90 * CreateSemaphore32W (KERNEL32.175)
92 HANDLE32 WINAPI
CreateSemaphore32W( SECURITY_ATTRIBUTES
*sa
, LONG initial
,
93 LONG max
, LPCWSTR name
)
95 LPSTR nameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, name
);
96 HANDLE32 ret
= CreateSemaphore32A( sa
, initial
, max
, nameA
);
97 if (nameA
) HeapFree( GetProcessHeap(), 0, nameA
);
102 /***********************************************************************
103 * OpenSemaphore32A (KERNEL32.545)
105 HANDLE32 WINAPI
OpenSemaphore32A( DWORD access
, BOOL32 inherit
, LPCSTR name
)
110 if ((obj
= K32OBJ_FindNameType( name
, K32OBJ_SEMAPHORE
)) != NULL
)
112 handle
= HANDLE_Alloc( PROCESS_Current(), obj
, access
, inherit
, -1 );
113 K32OBJ_DecCount( obj
);
120 /***********************************************************************
121 * OpenSemaphore32W (KERNEL32.546)
123 HANDLE32 WINAPI
OpenSemaphore32W( DWORD access
, BOOL32 inherit
, LPCWSTR name
)
125 LPSTR nameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, name
);
126 HANDLE32 ret
= OpenSemaphore32A( access
, inherit
, nameA
);
127 if (nameA
) HeapFree( GetProcessHeap(), 0, nameA
);
132 /***********************************************************************
133 * ReleaseSemaphore (KERNEL32.583)
135 BOOL32 WINAPI
ReleaseSemaphore( HANDLE32 handle
, LONG count
, LONG
*previous
)
137 struct release_semaphore_request req
;
142 SetLastError( ERROR_INVALID_PARAMETER
);
146 if (!(sem
= (SEMAPHORE
*)HANDLE_GetObjPtr( PROCESS_Current(), handle
,
148 SEMAPHORE_MODIFY_STATE
, &req
.handle
)))
153 if (req
.handle
!= -1)
155 struct release_semaphore_reply reply
;
159 req
.count
= (unsigned int)count
;
160 CLIENT_SendRequest( REQ_RELEASE_SEMAPHORE
, -1, 1, &req
, sizeof(req
) );
161 if (CLIENT_WaitReply( &len
, NULL
, 1, &reply
, sizeof(reply
) )) return FALSE
;
162 CHECK_LEN( len
, sizeof(reply
) );
163 if (previous
) *previous
= reply
.prev_count
;
166 if (previous
) *previous
= sem
->count
;
167 if (sem
->count
+ count
> sem
->max
)
170 SetLastError( ERROR_TOO_MANY_POSTS
);
175 /* There cannot be any thread waiting if the count is > 0 */
176 assert( sem
->wait_queue
== NULL
);
182 SYNC_WakeUp( &sem
->wait_queue
, count
);
184 K32OBJ_DecCount( &sem
->header
);
190 /***********************************************************************
193 static BOOL32
SEMAPHORE_Signaled( K32OBJ
*obj
, DWORD thread_id
)
195 SEMAPHORE
*sem
= (SEMAPHORE
*)obj
;
196 assert( obj
->type
== K32OBJ_SEMAPHORE
);
197 return (sem
->count
> 0);
201 /***********************************************************************
202 * SEMAPHORE_Satisfied
204 * Wait on this object has been satisfied.
206 static BOOL32
SEMAPHORE_Satisfied( K32OBJ
*obj
, DWORD thread_id
)
208 SEMAPHORE
*sem
= (SEMAPHORE
*)obj
;
209 assert( obj
->type
== K32OBJ_SEMAPHORE
);
210 assert( sem
->count
> 0 );
212 return FALSE
; /* Not abandoned */
216 /***********************************************************************
219 * Add current thread to object wait queue.
221 static void SEMAPHORE_AddWait( K32OBJ
*obj
, DWORD thread_id
)
223 SEMAPHORE
*sem
= (SEMAPHORE
*)obj
;
224 assert( obj
->type
== K32OBJ_SEMAPHORE
);
225 THREAD_AddQueue( &sem
->wait_queue
, THREAD_ID_TO_THDB(thread_id
) );
229 /***********************************************************************
230 * SEMAPHORE_RemoveWait
232 * Remove thread from object wait queue.
234 static void SEMAPHORE_RemoveWait( K32OBJ
*obj
, DWORD thread_id
)
236 SEMAPHORE
*sem
= (SEMAPHORE
*)obj
;
237 assert( obj
->type
== K32OBJ_SEMAPHORE
);
238 THREAD_RemoveQueue( &sem
->wait_queue
, THREAD_ID_TO_THDB(thread_id
) );
242 /***********************************************************************
245 static void SEMAPHORE_Destroy( K32OBJ
*obj
)
247 SEMAPHORE
*sem
= (SEMAPHORE
*)obj
;
248 assert( obj
->type
== K32OBJ_SEMAPHORE
);
249 /* There cannot be any thread on the list since the ref count is 0 */
250 assert( sem
->wait_queue
== NULL
);
251 obj
->type
= K32OBJ_UNKNOWN
;
252 HeapFree( SystemHeap
, 0, sem
);