FreeRDP
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 
38 static BOOL MutexCloseHandle(HANDLE handle);
39 
40 static BOOL MutexIsHandled(HANDLE handle)
41 {
42  return WINPR_HANDLE_IS_HANDLED(handle, HANDLE_TYPE_MUTEX, FALSE);
43 }
44 
45 static 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 
57 BOOL 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 
100 static 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 
122 HANDLE 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 
139 HANDLE 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 
168 HANDLE 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 
184 HANDLE 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 
200 HANDLE 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 
210 HANDLE 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 
220 BOOL 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