FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
mutex.c
1
20#include <winpr/config.h>
21
22#include <winpr/synch.h>
23#include <winpr/debug.h>
24#include <winpr/wlog.h>
25#include <winpr/string.h>
26
27#include "synch.h"
28
29#ifndef _WIN32
30
31#include <errno.h>
32
33#include "../handle/handle.h"
34
35#include "../log.h"
36#define TAG WINPR_TAG("sync.mutex")
37
38static BOOL MutexCloseHandle(HANDLE handle);
39
40static BOOL MutexIsHandled(HANDLE handle)
41{
42 return WINPR_HANDLE_IS_HANDLED(handle, HANDLE_TYPE_MUTEX, FALSE);
43}
44
45static int MutexGetFd(HANDLE handle)
46{
47 WINPR_MUTEX* mux = (WINPR_MUTEX*)handle;
48
49 if (!MutexIsHandled(handle))
50 return -1;
51
52 /* TODO: Mutex does not support file handles... */
53 (void)mux;
54 return -1;
55}
56
57BOOL MutexCloseHandle(HANDLE handle)
58{
59 WINPR_MUTEX* mutex = (WINPR_MUTEX*)handle;
60 int rc = 0;
61
62 if (!MutexIsHandled(handle))
63 return FALSE;
64
65 if ((rc = pthread_mutex_destroy(&mutex->mutex)))
66 {
67 char ebuffer[256] = { 0 };
68 WLog_ERR(TAG, "pthread_mutex_destroy failed with %s [%d]",
69 winpr_strerror(rc, ebuffer, sizeof(ebuffer)), rc);
70#if defined(WITH_DEBUG_MUTEX)
71 {
72 size_t used = 0;
73 void* stack = winpr_backtrace(20);
74 char** msg = NULL;
75
76 if (stack)
77 msg = winpr_backtrace_symbols(stack, &used);
78
79 if (msg)
80 {
81 for (size_t i = 0; i < used; i++)
82 WLog_ERR(TAG, "%2" PRIdz ": %s", i, msg[i]);
83 }
84
85 free(msg);
86 winpr_backtrace_free(stack);
87 }
88#endif
93 }
94
95 free(mutex->name);
96 free(handle);
97 return TRUE;
98}
99
100static HANDLE_OPS ops = { MutexIsHandled,
101 MutexCloseHandle,
102 MutexGetFd,
103 NULL, /* CleanupHandle */
104 NULL,
105 NULL,
106 NULL,
107 NULL,
108 NULL,
109 NULL,
110 NULL,
111 NULL,
112 NULL,
113 NULL,
114 NULL,
115 NULL,
116 NULL,
117 NULL,
118 NULL,
119 NULL,
120 NULL };
121
122HANDLE CreateMutexW(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCWSTR lpName)
123{
124 HANDLE handle = NULL;
125 char* name = NULL;
126
127 if (lpName)
128 {
129 name = ConvertWCharToUtf8Alloc(lpName, NULL);
130 if (!name)
131 return NULL;
132 }
133
134 handle = CreateMutexA(lpMutexAttributes, bInitialOwner, name);
135 free(name);
136 return handle;
137}
138
139HANDLE CreateMutexA(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCSTR lpName)
140{
141 HANDLE handle = NULL;
142 WINPR_MUTEX* mutex = NULL;
143 mutex = (WINPR_MUTEX*)calloc(1, sizeof(WINPR_MUTEX));
144
145 if (lpMutexAttributes)
146 WLog_WARN(TAG, "[%s] does not support lpMutexAttributes", lpName);
147
148 if (mutex)
149 {
150 pthread_mutexattr_t attr;
151 pthread_mutexattr_init(&attr);
152 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
153 pthread_mutex_init(&mutex->mutex, &attr);
154 WINPR_HANDLE_SET_TYPE_AND_MODE(mutex, HANDLE_TYPE_MUTEX, WINPR_FD_READ);
155 mutex->common.ops = &ops;
156 handle = (HANDLE)mutex;
157
158 if (bInitialOwner)
159 pthread_mutex_lock(&mutex->mutex);
160
161 if (lpName)
162 mutex->name = strdup(lpName); /* Non runtime relevant information, skip NULL check */
163 }
164
165 return handle;
166}
167
168HANDLE CreateMutexExA(LPSECURITY_ATTRIBUTES lpMutexAttributes, LPCSTR lpName, DWORD dwFlags,
169 DWORD dwDesiredAccess)
170{
171 BOOL initial = FALSE;
172 /* TODO: support access modes */
173
174 if (dwDesiredAccess != 0)
175 WLog_WARN(TAG, "[%s] does not support dwDesiredAccess 0x%08" PRIx32, lpName,
176 dwDesiredAccess);
177
178 if (dwFlags & CREATE_MUTEX_INITIAL_OWNER)
179 initial = TRUE;
180
181 return CreateMutexA(lpMutexAttributes, initial, lpName);
182}
183
184HANDLE CreateMutexExW(LPSECURITY_ATTRIBUTES lpMutexAttributes, LPCWSTR lpName, DWORD dwFlags,
185 DWORD dwDesiredAccess)
186{
187 BOOL initial = FALSE;
188
189 /* TODO: support access modes */
190 if (dwDesiredAccess != 0)
191 WLog_WARN(TAG, "[%s] does not support dwDesiredAccess 0x%08" PRIx32, lpName,
192 dwDesiredAccess);
193
194 if (dwFlags & CREATE_MUTEX_INITIAL_OWNER)
195 initial = TRUE;
196
197 return CreateMutexW(lpMutexAttributes, initial, lpName);
198}
199
200HANDLE OpenMutexA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName)
201{
202 /* TODO: Implement */
203 WINPR_UNUSED(dwDesiredAccess);
204 WINPR_UNUSED(bInheritHandle);
205 WINPR_UNUSED(lpName);
206 WLog_ERR(TAG, "TODO: Implement");
207 return NULL;
208}
209
210HANDLE OpenMutexW(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName)
211{
212 /* TODO: Implement */
213 WINPR_UNUSED(dwDesiredAccess);
214 WINPR_UNUSED(bInheritHandle);
215 WINPR_UNUSED(lpName);
216 WLog_ERR(TAG, "TODO: Implement");
217 return NULL;
218}
219
220BOOL ReleaseMutex(HANDLE hMutex)
221{
222 ULONG Type = 0;
223 WINPR_HANDLE* Object = NULL;
224
225 if (!winpr_Handle_GetInfo(hMutex, &Type, &Object))
226 return FALSE;
227
228 if (Type == HANDLE_TYPE_MUTEX)
229 {
230 WINPR_MUTEX* mutex = (WINPR_MUTEX*)Object;
231 int rc = pthread_mutex_unlock(&mutex->mutex);
232
233 if (rc)
234 {
235 char ebuffer[256] = { 0 };
236 WLog_ERR(TAG, "pthread_mutex_unlock failed with %s [%d]",
237 winpr_strerror(rc, ebuffer, sizeof(ebuffer)), rc);
238 return FALSE;
239 }
240
241 return TRUE;
242 }
243
244 return FALSE;
245}
246
247#endif