Rizin
unix-like reverse engineering framework and cli tools
thread.c
Go to the documentation of this file.
1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to
5  * deal in the Software without restriction, including without limitation the
6  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7  * sell copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19  * IN THE SOFTWARE.
20  */
21 
22 #include <assert.h>
23 #include <limits.h>
24 #include <stdlib.h>
25 
26 #if defined(__MINGW64_VERSION_MAJOR)
27 /* MemoryBarrier expands to __mm_mfence in some cases (x86+sse2), which may
28  * require this header in some versions of mingw64. */
29 #include <intrin.h>
30 #endif
31 
32 #include "uv.h"
33 #include "internal.h"
34 
35 static void uv__once_inner(uv_once_t* guard, void (*callback)(void)) {
36  DWORD result;
37  HANDLE existing_event, created_event;
38 
39  created_event = CreateEvent(NULL, 1, 0, NULL);
40  if (created_event == 0) {
41  /* Could fail in a low-memory situation? */
42  uv_fatal_error(GetLastError(), "CreateEvent");
43  }
44 
45  existing_event = InterlockedCompareExchangePointer(&guard->event,
46  created_event,
47  NULL);
48 
49  if (existing_event == NULL) {
50  /* We won the race */
51  callback();
52 
53  result = SetEvent(created_event);
54  assert(result);
55  guard->ran = 1;
56 
57  } else {
58  /* We lost the race. Destroy the event we created and wait for the existing
59  * one to become signaled. */
60  CloseHandle(created_event);
61  result = WaitForSingleObject(existing_event, INFINITE);
62  assert(result == WAIT_OBJECT_0);
63  }
64 }
65 
66 
67 void uv_once(uv_once_t* guard, void (*callback)(void)) {
68  /* Fast case - avoid WaitForSingleObject. */
69  if (guard->ran) {
70  return;
71  }
72 
73  uv__once_inner(guard, callback);
74 }
75 
76 
77 /* Verify that uv_thread_t can be stored in a TLS slot. */
78 STATIC_ASSERT(sizeof(uv_thread_t) <= sizeof(void*));
79 
82 
83 
84 static void uv__init_current_thread_key(void) {
86  abort();
87 }
88 
89 
90 struct thread_ctx {
91  void (*entry)(void* arg);
92  void* arg;
94 };
95 
96 
97 static UINT __stdcall uv__thread_start(void* arg) {
98  struct thread_ctx *ctx_p;
99  struct thread_ctx ctx;
100 
101  ctx_p = arg;
102  ctx = *ctx_p;
103  uv__free(ctx_p);
104 
106  uv_key_set(&uv__current_thread_key, (void*) ctx.self);
107 
108  ctx.entry(ctx.arg);
109 
110  return 0;
111 }
112 
113 
114 int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
115  uv_thread_options_t params;
116  params.flags = UV_THREAD_NO_FLAGS;
117  return uv_thread_create_ex(tid, &params, entry, arg);
118 }
119 
121  const uv_thread_options_t* params,
122  void (*entry)(void *arg),
123  void *arg) {
124  struct thread_ctx* ctx;
125  int err;
126  HANDLE thread;
127  SYSTEM_INFO sysinfo;
128  size_t stack_size;
129  size_t pagesize;
130 
131  stack_size =
132  params->flags & UV_THREAD_HAS_STACK_SIZE ? params->stack_size : 0;
133 
134  if (stack_size != 0) {
135  GetNativeSystemInfo(&sysinfo);
136  pagesize = (size_t)sysinfo.dwPageSize;
137  /* Round up to the nearest page boundary. */
138  stack_size = (stack_size + pagesize - 1) &~ (pagesize - 1);
139 
140  if ((unsigned)stack_size != stack_size)
141  return UV_EINVAL;
142  }
143 
144  ctx = uv__malloc(sizeof(*ctx));
145  if (ctx == NULL)
146  return UV_ENOMEM;
147 
148  ctx->entry = entry;
149  ctx->arg = arg;
150 
151  /* Create the thread in suspended state so we have a chance to pass
152  * its own creation handle to it */
153  thread = (HANDLE) _beginthreadex(NULL,
154  (unsigned)stack_size,
156  ctx,
157  CREATE_SUSPENDED,
158  NULL);
159  if (thread == NULL) {
160  err = errno;
161  uv__free(ctx);
162  } else {
163  err = 0;
164  *tid = thread;
165  ctx->self = thread;
166  ResumeThread(thread);
167  }
168 
169  switch (err) {
170  case 0:
171  return 0;
172  case EACCES:
173  return UV_EACCES;
174  case EAGAIN:
175  return UV_EAGAIN;
176  case EINVAL:
177  return UV_EINVAL;
178  }
179 
180  return UV_EIO;
181 }
182 
183 
187 }
188 
189 
191  if (WaitForSingleObject(*tid, INFINITE))
192  return uv_translate_sys_error(GetLastError());
193  else {
194  CloseHandle(*tid);
195  *tid = 0;
196  MemoryBarrier(); /* For feature parity with pthread_join(). */
197  return 0;
198  }
199 }
200 
201 
202 int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) {
203  return *t1 == *t2;
204 }
205 
206 
208  InitializeCriticalSection(mutex);
209  return 0;
210 }
211 
212 
214  return uv_mutex_init(mutex);
215 }
216 
217 
219  DeleteCriticalSection(mutex);
220 }
221 
222 
224  EnterCriticalSection(mutex);
225 }
226 
227 
229  if (TryEnterCriticalSection(mutex))
230  return 0;
231  else
232  return UV_EBUSY;
233 }
234 
235 
237  LeaveCriticalSection(mutex);
238 }
239 
240 
242  /* Initialize the semaphore that acts as the write lock. */
243  HANDLE handle = CreateSemaphoreW(NULL, 1, 1, NULL);
244  if (handle == NULL)
245  return uv_translate_sys_error(GetLastError());
246  rwlock->state_.write_semaphore_ = handle;
247 
248  /* Initialize the critical section protecting the reader count. */
249  InitializeCriticalSection(&rwlock->state_.num_readers_lock_);
250 
251  /* Initialize the reader count. */
252  rwlock->state_.num_readers_ = 0;
253 
254  return 0;
255 }
256 
257 
259  DeleteCriticalSection(&rwlock->state_.num_readers_lock_);
260  CloseHandle(rwlock->state_.write_semaphore_);
261 }
262 
263 
265  /* Acquire the lock that protects the reader count. */
266  EnterCriticalSection(&rwlock->state_.num_readers_lock_);
267 
268  /* Increase the reader count, and lock for write if this is the first
269  * reader.
270  */
271  if (++rwlock->state_.num_readers_ == 1) {
272  DWORD r = WaitForSingleObject(rwlock->state_.write_semaphore_, INFINITE);
273  if (r != WAIT_OBJECT_0)
274  uv_fatal_error(GetLastError(), "WaitForSingleObject");
275  }
276 
277  /* Release the lock that protects the reader count. */
278  LeaveCriticalSection(&rwlock->state_.num_readers_lock_);
279 }
280 
281 
283  int err;
284 
285  if (!TryEnterCriticalSection(&rwlock->state_.num_readers_lock_))
286  return UV_EBUSY;
287 
288  err = 0;
289 
290  if (rwlock->state_.num_readers_ == 0) {
291  /* Currently there are no other readers, which means that the write lock
292  * needs to be acquired.
293  */
294  DWORD r = WaitForSingleObject(rwlock->state_.write_semaphore_, 0);
295  if (r == WAIT_OBJECT_0)
296  rwlock->state_.num_readers_++;
297  else if (r == WAIT_TIMEOUT)
298  err = UV_EBUSY;
299  else if (r == WAIT_FAILED)
300  uv_fatal_error(GetLastError(), "WaitForSingleObject");
301 
302  } else {
303  /* The write lock has already been acquired because there are other
304  * active readers.
305  */
306  rwlock->state_.num_readers_++;
307  }
308 
309  LeaveCriticalSection(&rwlock->state_.num_readers_lock_);
310  return err;
311 }
312 
313 
315  EnterCriticalSection(&rwlock->state_.num_readers_lock_);
316 
317  if (--rwlock->state_.num_readers_ == 0) {
318  if (!ReleaseSemaphore(rwlock->state_.write_semaphore_, 1, NULL))
319  uv_fatal_error(GetLastError(), "ReleaseSemaphore");
320  }
321 
322  LeaveCriticalSection(&rwlock->state_.num_readers_lock_);
323 }
324 
325 
327  DWORD r = WaitForSingleObject(rwlock->state_.write_semaphore_, INFINITE);
328  if (r != WAIT_OBJECT_0)
329  uv_fatal_error(GetLastError(), "WaitForSingleObject");
330 }
331 
332 
334  DWORD r = WaitForSingleObject(rwlock->state_.write_semaphore_, 0);
335  if (r == WAIT_OBJECT_0)
336  return 0;
337  else if (r == WAIT_TIMEOUT)
338  return UV_EBUSY;
339  else
340  uv_fatal_error(GetLastError(), "WaitForSingleObject");
341 }
342 
343 
345  if (!ReleaseSemaphore(rwlock->state_.write_semaphore_, 1, NULL))
346  uv_fatal_error(GetLastError(), "ReleaseSemaphore");
347 }
348 
349 
350 int uv_sem_init(uv_sem_t* sem, unsigned int value) {
351  *sem = CreateSemaphore(NULL, value, INT_MAX, NULL);
352  if (*sem == NULL)
353  return uv_translate_sys_error(GetLastError());
354  else
355  return 0;
356 }
357 
358 
360  if (!CloseHandle(*sem))
361  abort();
362 }
363 
364 
365 void uv_sem_post(uv_sem_t* sem) {
366  if (!ReleaseSemaphore(*sem, 1, NULL))
367  abort();
368 }
369 
370 
371 void uv_sem_wait(uv_sem_t* sem) {
372  if (WaitForSingleObject(*sem, INFINITE) != WAIT_OBJECT_0)
373  abort();
374 }
375 
376 
378  DWORD r = WaitForSingleObject(*sem, 0);
379 
380  if (r == WAIT_OBJECT_0)
381  return 0;
382 
383  if (r == WAIT_TIMEOUT)
384  return UV_EAGAIN;
385 
386  abort();
387  return -1; /* Satisfy the compiler. */
388 }
389 
390 
392  InitializeConditionVariable(&cond->cond_var);
393  return 0;
394 }
395 
396 
398  /* nothing to do */
399  (void) &cond;
400 }
401 
402 
404  WakeConditionVariable(&cond->cond_var);
405 }
406 
407 
409  WakeAllConditionVariable(&cond->cond_var);
410 }
411 
412 
414  if (!SleepConditionVariableCS(&cond->cond_var, mutex, INFINITE))
415  abort();
416 }
417 
419  if (SleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6)))
420  return 0;
421  if (GetLastError() != ERROR_TIMEOUT)
422  abort();
423  return UV_ETIMEDOUT;
424 }
425 
426 
427 int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
428  int err;
429 
430  barrier->n = count;
431  barrier->count = 0;
432 
433  err = uv_mutex_init(&barrier->mutex);
434  if (err)
435  return err;
436 
437  err = uv_sem_init(&barrier->turnstile1, 0);
438  if (err)
439  goto error2;
440 
441  err = uv_sem_init(&barrier->turnstile2, 1);
442  if (err)
443  goto error;
444 
445  return 0;
446 
447 error:
448  uv_sem_destroy(&barrier->turnstile1);
449 error2:
450  uv_mutex_destroy(&barrier->mutex);
451  return err;
452 
453 }
454 
455 
457  uv_sem_destroy(&barrier->turnstile2);
458  uv_sem_destroy(&barrier->turnstile1);
459  uv_mutex_destroy(&barrier->mutex);
460 }
461 
462 
464  int serial_thread;
465 
466  uv_mutex_lock(&barrier->mutex);
467  if (++barrier->count == barrier->n) {
468  uv_sem_wait(&barrier->turnstile2);
469  uv_sem_post(&barrier->turnstile1);
470  }
471  uv_mutex_unlock(&barrier->mutex);
472 
473  uv_sem_wait(&barrier->turnstile1);
474  uv_sem_post(&barrier->turnstile1);
475 
476  uv_mutex_lock(&barrier->mutex);
477  serial_thread = (--barrier->count == 0);
478  if (serial_thread) {
479  uv_sem_wait(&barrier->turnstile1);
480  uv_sem_post(&barrier->turnstile2);
481  }
482  uv_mutex_unlock(&barrier->mutex);
483 
484  uv_sem_wait(&barrier->turnstile2);
485  uv_sem_post(&barrier->turnstile2);
486  return serial_thread;
487 }
488 
489 
491  key->tls_index = TlsAlloc();
492  if (key->tls_index == TLS_OUT_OF_INDEXES)
493  return UV_ENOMEM;
494  return 0;
495 }
496 
497 
499  if (TlsFree(key->tls_index) == FALSE)
500  abort();
501  key->tls_index = TLS_OUT_OF_INDEXES;
502 }
503 
504 
506  void* value;
507 
508  value = TlsGetValue(key->tls_index);
509  if (value == NULL)
510  if (GetLastError() != ERROR_SUCCESS)
511  abort();
512 
513  return value;
514 }
515 
516 
517 void uv_key_set(uv_key_t* key, void* value) {
518  if (TlsSetValue(key->tls_index, value) == FALSE)
519  abort();
520 }
static const char * arg(RzAnalysis *a, csh *handle, cs_insn *insn, char *buf, int n)
Definition: arm_esil32.c:136
static bool err
Definition: armass.c:435
static mcore_handle handle
Definition: asm_mcore.c:8
static int value
Definition: cmd_api.c:93
#define INT_MAX
Definition: cp-demangle.c:131
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len key
Definition: sflib.h:118
void uv_fatal_error(const int errorno, const char *syscall)
Definition: error.c:35
static const char struct stat static buf struct stat static buf static vhangup int struct rusage static rusage sysinfo
Definition: sflib.h:147
assert(limit<=UINT32_MAX/2)
#define FALSE
Definition: mybfd.h:102
#define EINVAL
Definition: sftypes.h:132
int size_t
Definition: sftypes.h:40
unsigned long uint64_t
Definition: sftypes.h:28
#define EACCES
Definition: sftypes.h:123
#define EAGAIN
Definition: sftypes.h:121
#define cond(bop, top, mask, flags)
Definition: zipcmp.c:77
void * arg
Definition: thread.c:92
void(* entry)(void *arg)
Definition: thread.c:91
unsigned int n
Definition: win.h:277
uv_mutex_t mutex
Definition: win.h:279
uv_sem_t turnstile2
Definition: win.h:281
unsigned int count
Definition: win.h:278
uv_sem_t turnstile1
Definition: win.h:280
Definition: win.h:284
unsigned int flags
Definition: uv.h:1753
size_t stack_size
Definition: uv.h:1754
uv_timer_t timeout
Definition: main.c:9
int uv_barrier_wait(uv_barrier_t *barrier)
Definition: thread.c:89
int uv_rwlock_trywrlock(uv_rwlock_t *rwlock)
Definition: thread.c:399
int uv_thread_create_ex(uv_thread_t *tid, const uv_thread_options_t *params, void(*entry)(void *arg), void *arg)
Definition: thread.c:216
int uv_cond_init(uv_cond_t *cond)
Definition: thread.c:704
void uv_key_set(uv_key_t *key, void *value)
Definition: thread.c:839
void uv_cond_signal(uv_cond_t *cond)
Definition: thread.c:769
int uv_rwlock_init(uv_rwlock_t *rwlock)
Definition: thread.c:356
void uv_sem_wait(uv_sem_t *sem)
Definition: thread.c:678
void uv_rwlock_rdlock(uv_rwlock_t *rwlock)
Definition: thread.c:367
int uv_mutex_trylock(uv_mutex_t *mutex)
Definition: thread.c:336
void uv_mutex_unlock(uv_mutex_t *mutex)
Definition: thread.c:350
void uv_rwlock_wrlock(uv_rwlock_t *rwlock)
Definition: thread.c:393
void * uv_key_get(uv_key_t *key)
Definition: thread.c:834
int uv_sem_trywait(uv_sem_t *sem)
Definition: thread.c:686
int uv_mutex_init_recursive(uv_mutex_t *mutex)
Definition: thread.c:305
int uv_thread_join(uv_thread_t *tid)
Definition: thread.c:272
int uv_thread_create(uv_thread_t *tid, void(*entry)(void *arg), void *arg)
Definition: thread.c:210
void uv_sem_post(uv_sem_t *sem)
Definition: thread.c:670
void uv_mutex_destroy(uv_mutex_t *mutex)
Definition: thread.c:324
int uv_thread_equal(const uv_thread_t *t1, const uv_thread_t *t2)
Definition: thread.c:277
uv_thread_t uv_thread_self(void)
Definition: thread.c:268
void uv_once(uv_once_t *guard, void(*callback)(void))
Definition: thread.c:419
void uv_rwlock_rdunlock(uv_rwlock_t *rwlock)
Definition: thread.c:387
int uv_key_create(uv_key_t *key)
Definition: thread.c:823
void uv_cond_destroy(uv_cond_t *cond)
Definition: thread.c:735
int uv_rwlock_tryrdlock(uv_rwlock_t *rwlock)
Definition: thread.c:373
void uv_barrier_destroy(uv_barrier_t *barrier)
Definition: thread.c:118
int uv_cond_timedwait(uv_cond_t *cond, uv_mutex_t *mutex, uint64_t timeout)
Definition: thread.c:785
int uv_sem_init(uv_sem_t *sem, unsigned int value)
Definition: thread.c:650
void uv_cond_broadcast(uv_cond_t *cond)
Definition: thread.c:774
void uv_rwlock_destroy(uv_rwlock_t *rwlock)
Definition: thread.c:361
int uv_mutex_init(uv_mutex_t *mutex)
Definition: thread.c:282
void uv_mutex_lock(uv_mutex_t *mutex)
Definition: thread.c:330
void uv_cond_wait(uv_cond_t *cond, uv_mutex_t *mutex)
Definition: thread.c:779
int uv_barrier_init(uv_barrier_t *barrier, unsigned int count)
Definition: thread.c:55
void uv_sem_destroy(uv_sem_t *sem)
Definition: thread.c:662
void uv_key_delete(uv_key_t *key)
Definition: thread.c:828
void uv_rwlock_wrunlock(uv_rwlock_t *rwlock)
Definition: thread.c:413
static UINT __stdcall uv__thread_start(void *arg)
Definition: thread.c:97
static uv_key_t uv__current_thread_key
Definition: thread.c:80
static uv_once_t uv__current_thread_init_guard
Definition: thread.c:81
static void uv__init_current_thread_key(void)
Definition: thread.c:84
STATIC_ASSERT(sizeof(uv_thread_t)<=sizeof(void *))
static void uv__once_inner(uv_once_t *guard, void(*callback)(void))
Definition: thread.c:35
static uv_mutex_t mutex
Definition: threadpool.c:34
Definition: win.h:249
unsigned int num_readers_
Definition: win.h:261
CRITICAL_SECTION num_readers_lock_
Definition: win.h:262
HANDLE write_semaphore_
Definition: win.h:263
struct uv_rwlock_t::@394 state_
UV_PLATFORM_SEM_T uv_sem_t
Definition: unix.h:139
pthread_mutex_t uv_mutex_t
Definition: unix.h:137
pthread_t uv_thread_t
Definition: unix.h:136
pthread_once_t uv_once_t
Definition: unix.h:135
#define UV_ONCE_INIT
Definition: unix.h:133
void error(const char *msg)
Definition: untgz.c:593
void * uv__malloc(size_t size)
Definition: uv-common.c:75
void uv__free(void *ptr)
Definition: uv-common.c:81
@ UV_THREAD_HAS_STACK_SIZE
Definition: uv.h:1749
@ UV_THREAD_NO_FLAGS
Definition: uv.h:1748
UV_EXTERN int uv_translate_sys_error(int sys_errno)
Definition: core.c:1249
DWORD * HANDLE
DWORD