Re-implemented using a real semaphore.
[wine] / scheduler / mutex.c
1 /*
2  * Win32 mutexes
3  *
4  * Copyright 1998 Alexandre Julliard
5  */
6
7 #include <assert.h>
8 #include "windows.h"
9 #include "winerror.h"
10 #include "k32obj.h"
11 #include "process.h"
12 #include "thread.h"
13 #include "heap.h"
14 #include "server/request.h"
15 #include "server.h"
16
17 typedef struct _MUTEX
18 {
19     K32OBJ         header;
20 } MUTEX;
21
22 static void MUTEX_Destroy( K32OBJ *obj );
23
24 const K32OBJ_OPS MUTEX_Ops =
25 {
26     MUTEX_Destroy      /* destroy */
27 };
28
29
30 /***********************************************************************
31  *           CreateMutex32A   (KERNEL32.166)
32  */
33 HANDLE32 WINAPI CreateMutex32A( SECURITY_ATTRIBUTES *sa, BOOL32 owner,
34                                 LPCSTR name )
35 {
36     struct create_mutex_request req;
37     struct create_mutex_reply reply;
38     int len = name ? strlen(name) + 1 : 0;
39     HANDLE32 handle;
40     MUTEX *mutex;
41
42     req.owned   = owner;
43     req.inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
44
45     CLIENT_SendRequest( REQ_CREATE_MUTEX, -1, 2, &req, sizeof(req), name, len );
46     CLIENT_WaitReply( &len, NULL, 1, &reply, sizeof(reply) );
47     CHECK_LEN( len, sizeof(reply) );
48     if (reply.handle == -1) return 0;
49
50     SYSTEM_LOCK();
51     mutex = (MUTEX *)K32OBJ_Create( K32OBJ_MUTEX, sizeof(*mutex),
52                                     name, reply.handle, MUTEX_ALL_ACCESS,
53                                     sa, &handle );
54     if (mutex) K32OBJ_DecCount( &mutex->header );
55     if (handle == INVALID_HANDLE_VALUE32) handle = 0;
56     SYSTEM_UNLOCK();
57     return handle;
58 }
59
60
61 /***********************************************************************
62  *           CreateMutex32W   (KERNEL32.167)
63  */
64 HANDLE32 WINAPI CreateMutex32W( SECURITY_ATTRIBUTES *sa, BOOL32 owner,
65                                 LPCWSTR name )
66 {
67     LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
68     HANDLE32 ret = CreateMutex32A( sa, owner, nameA );
69     if (nameA) HeapFree( GetProcessHeap(), 0, nameA );
70     return ret;
71 }
72
73
74 /***********************************************************************
75  *           OpenMutex32A   (KERNEL32.541)
76  */
77 HANDLE32 WINAPI OpenMutex32A( DWORD access, BOOL32 inherit, LPCSTR name )
78 {
79     HANDLE32 handle = 0;
80     K32OBJ *obj;
81     struct open_named_obj_request req;
82     struct open_named_obj_reply reply;
83     int len = name ? strlen(name) + 1 : 0;
84
85     req.type    = OPEN_MUTEX;
86     req.access  = access;
87     req.inherit = inherit;
88     CLIENT_SendRequest( REQ_OPEN_NAMED_OBJ, -1, 2, &req, sizeof(req), name, len );
89     CLIENT_WaitReply( &len, NULL, 1, &reply, sizeof(reply) );
90     CHECK_LEN( len, sizeof(reply) );
91     if (reply.handle != -1)
92     {
93         SYSTEM_LOCK();
94         if ((obj = K32OBJ_FindNameType( name, K32OBJ_MUTEX )) != NULL)
95         {
96             handle = HANDLE_Alloc( PROCESS_Current(), obj, access, inherit, reply.handle );
97             K32OBJ_DecCount( obj );
98             if (handle == INVALID_HANDLE_VALUE32)
99                 handle = 0; /* must return 0 on failure, not -1 */
100         }
101         else CLIENT_CloseHandle( reply.handle );
102         SYSTEM_UNLOCK();
103     }
104     return handle;
105 }
106
107
108 /***********************************************************************
109  *           OpenMutex32W   (KERNEL32.542)
110  */
111 HANDLE32 WINAPI OpenMutex32W( DWORD access, BOOL32 inherit, LPCWSTR name )
112 {
113     LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
114     HANDLE32 ret = OpenMutex32A( access, inherit, nameA );
115     if (nameA) HeapFree( GetProcessHeap(), 0, nameA );
116     return ret;
117 }
118
119
120 /***********************************************************************
121  *           ReleaseMutex   (KERNEL32.582)
122  */
123 BOOL32 WINAPI ReleaseMutex( HANDLE32 handle )
124 {
125     struct release_mutex_request req;
126
127     req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
128                                          K32OBJ_MUTEX, MUTEX_MODIFY_STATE );
129     if (req.handle == -1) return FALSE;
130     CLIENT_SendRequest( REQ_RELEASE_MUTEX, -1, 1, &req, sizeof(req) );
131     return !CLIENT_WaitReply( NULL, NULL, 0 );
132 }
133
134
135 /***********************************************************************
136  *           MUTEX_Destroy
137  */
138 static void MUTEX_Destroy( K32OBJ *obj )
139 {
140     MUTEX *mutex = (MUTEX *)obj;
141     assert( obj->type == K32OBJ_MUTEX );
142     obj->type = K32OBJ_UNKNOWN;
143     HeapFree( SystemHeap, 0, mutex );
144 }