libuv/src/win/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());
247 
248  /* Initialize the critical section protecting the reader count. */
249  InitializeCriticalSection(&rwlock->state_.num_readers_lock_);
250 
251  /* Initialize the reader count. */
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)
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  */
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 
366  if (!ReleaseSemaphore(*sem, 1, NULL))
367  abort();
368 }
369 
370 
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 
428  int err;
429 
430  barrier->n = count;
431  barrier->count = 0;
432 
434  if (err)
435  return err;
436 
438  if (err)
439  goto error2;
440 
442  if (err)
443  goto error;
444 
445  return 0;
446 
447 error:
449 error2:
451  return err;
452 
453 }
454 
455 
460 }
461 
462 
464  int serial_thread;
465 
467  if (++barrier->count == barrier->n) {
470  }
472 
475 
477  serial_thread = (--barrier->count == 0);
478  if (serial_thread) {
481  }
483 
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 }
sem
static uv_sem_t sem
Definition: test-signal-multiple-loops.c:52
_gevent_test_main.result
result
Definition: _gevent_test_main.py:96
uv_sem_wait
void uv_sem_wait(uv_sem_t *sem)
Definition: libuv/src/win/thread.c:371
uv__current_thread_key
static uv_key_t uv__current_thread_key
Definition: libuv/src/win/thread.c:80
uv_rwlock_t::state_
struct uv_rwlock_t::@396 state_
uv_mutex_init
int uv_mutex_init(uv_mutex_t *mutex)
Definition: libuv/src/win/thread.c:207
ctx
Definition: benchmark-async.c:30
UV_THREAD_NO_FLAGS
@ UV_THREAD_NO_FLAGS
Definition: uv.h:1735
uv_barrier_t::mutex
uv_mutex_t mutex
Definition: win.h:279
mutex
static uv_mutex_t mutex
Definition: threadpool.c:34
uv__malloc
void * uv__malloc(size_t size)
Definition: uv-common.c:75
uv_rwlock_wrlock
void uv_rwlock_wrlock(uv_rwlock_t *rwlock)
Definition: libuv/src/win/thread.c:326
uv_thread_create
int uv_thread_create(uv_thread_t *tid, void(*entry)(void *arg), void *arg)
Definition: libuv/src/win/thread.c:114
uv_cond_init
int uv_cond_init(uv_cond_t *cond)
Definition: libuv/src/win/thread.c:391
uv_sem_post
void uv_sem_post(uv_sem_t *sem)
Definition: libuv/src/win/thread.c:365
uv_mutex_init_recursive
int uv_mutex_init_recursive(uv_mutex_t *mutex)
Definition: libuv/src/win/thread.c:213
UV_THREAD_HAS_STACK_SIZE
@ UV_THREAD_HAS_STACK_SIZE
Definition: uv.h:1736
error
grpc_error_handle error
Definition: retry_filter.cc:499
uv_cond_broadcast
void uv_cond_broadcast(uv_cond_t *cond)
Definition: libuv/src/win/thread.c:408
error_ref_leak.err
err
Definition: error_ref_leak.py:35
uv_rwlock_t::num_readers_
unsigned int num_readers_
Definition: win.h:261
uv_mutex_destroy
void uv_mutex_destroy(uv_mutex_t *mutex)
Definition: libuv/src/win/thread.c:218
uv_cond_wait
void uv_cond_wait(uv_cond_t *cond, uv_mutex_t *mutex)
Definition: libuv/src/win/thread.c:413
ctx
static struct test_ctx ctx
Definition: test-ipc-send-recv.c:65
uv_once
void uv_once(uv_once_t *guard, void(*callback)(void))
Definition: libuv/src/win/thread.c:67
uv_rwlock_trywrlock
int uv_rwlock_trywrlock(uv_rwlock_t *rwlock)
Definition: libuv/src/win/thread.c:333
STATIC_ASSERT
STATIC_ASSERT(sizeof(uv_thread_t)<=sizeof(void *))
uv_key_delete
void uv_key_delete(uv_key_t *key)
Definition: libuv/src/win/thread.c:498
uv__init_current_thread_key
static void uv__init_current_thread_key(void)
Definition: libuv/src/win/thread.c:84
uv_barrier_t::turnstile1
uv_sem_t turnstile1
Definition: win.h:280
uv_thread_options_s
Definition: uv.h:1739
uv_cond_t
Definition: win.h:249
tid
int tid
Definition: fake_binder_test.cc:236
uv_rwlock_rdlock
void uv_rwlock_rdlock(uv_rwlock_t *rwlock)
Definition: libuv/src/win/thread.c:264
thread_ctx::arg
void * arg
Definition: libuv/src/win/thread.c:92
uv_thread_options_s::stack_size
size_t stack_size
Definition: uv.h:1741
uv_key_t
Definition: win.h:284
uv_translate_sys_error
UV_EXTERN int uv_translate_sys_error(int sys_errno)
Definition: unix/core.c:1244
uv_rwlock_rdunlock
void uv_rwlock_rdunlock(uv_rwlock_t *rwlock)
Definition: libuv/src/win/thread.c:314
uv_thread_equal
int uv_thread_equal(const uv_thread_t *t1, const uv_thread_t *t2)
Definition: libuv/src/win/thread.c:202
cond
static uv_cond_t cond
Definition: threadpool.c:33
uint64_t
unsigned __int64 uint64_t
Definition: stdint-msvc2008.h:90
uv_cond_t::cond_var
CONDITION_VARIABLE cond_var
Definition: win.h:250
uv_barrier_init
int uv_barrier_init(uv_barrier_t *barrier, unsigned int count)
Definition: libuv/src/win/thread.c:427
arg
Definition: cmdline.cc:40
uv_thread_options_s::flags
unsigned int flags
Definition: uv.h:1740
uv_once_t
pthread_once_t uv_once_t
Definition: unix.h:133
uv__free
void uv__free(void *ptr)
Definition: uv-common.c:81
uv_mutex_t
pthread_mutex_t uv_mutex_t
Definition: unix.h:135
uv_mutex_unlock
void uv_mutex_unlock(uv_mutex_t *mutex)
Definition: libuv/src/win/thread.c:236
callback
static void callback(void *arg, int status, int timeouts, struct hostent *host)
Definition: acountry.c:224
uv_barrier_t::n
unsigned int n
Definition: win.h:277
uv__current_thread_init_guard
static uv_once_t uv__current_thread_init_guard
Definition: libuv/src/win/thread.c:81
uv_sem_t
UV_PLATFORM_SEM_T uv_sem_t
Definition: unix.h:137
uv_rwlock_t::write_semaphore_
HANDLE write_semaphore_
Definition: win.h:263
uv_barrier_t::turnstile2
uv_sem_t turnstile2
Definition: win.h:281
uv_rwlock_tryrdlock
int uv_rwlock_tryrdlock(uv_rwlock_t *rwlock)
Definition: libuv/src/win/thread.c:282
uv__thread_start
static UINT __stdcall uv__thread_start(void *arg)
Definition: libuv/src/win/thread.c:97
thread_ctx
Definition: libuv/src/win/thread.c:90
uv_fatal_error
void uv_fatal_error(const int errorno, const char *syscall)
Definition: error.c:35
value
const char * value
Definition: hpack_parser_table.cc:165
uv.h
uv_barrier_t
Definition: unix.h:154
uv_thread_self
uv_thread_t uv_thread_self(void)
Definition: libuv/src/win/thread.c:184
thread_ctx::entry
void(* entry)(void *arg)
Definition: libuv/src/win/thread.c:91
FALSE
const BOOL FALSE
Definition: undname.c:47
uv_sem_destroy
void uv_sem_destroy(uv_sem_t *sem)
Definition: libuv/src/win/thread.c:359
key
const char * key
Definition: hpack_parser_table.cc:164
uv_key_get
void * uv_key_get(uv_key_t *key)
Definition: libuv/src/win/thread.c:505
uv_rwlock_t
Definition: win.h:259
count
int * count
Definition: bloaty/third_party/googletest/googlemock/test/gmock_stress_test.cc:96
uv_sem_trywait
int uv_sem_trywait(uv_sem_t *sem)
Definition: libuv/src/win/thread.c:377
uv_mutex_trylock
int uv_mutex_trylock(uv_mutex_t *mutex)
Definition: libuv/src/win/thread.c:228
uv_cond_signal
void uv_cond_signal(uv_cond_t *cond)
Definition: libuv/src/win/thread.c:403
uv_thread_join
int uv_thread_join(uv_thread_t *tid)
Definition: libuv/src/win/thread.c:190
uv_key_set
void uv_key_set(uv_key_t *key, void *value)
Definition: libuv/src/win/thread.c:517
uv_cond_timedwait
int uv_cond_timedwait(uv_cond_t *cond, uv_mutex_t *mutex, uint64_t timeout)
Definition: libuv/src/win/thread.c:418
fix_build_deps.r
r
Definition: fix_build_deps.py:491
uv_cond_destroy
void uv_cond_destroy(uv_cond_t *cond)
Definition: libuv/src/win/thread.c:397
uv__once_inner
static void uv__once_inner(uv_once_t *guard, void(*callback)(void))
Definition: libuv/src/win/thread.c:35
arg
struct arg arg
uv_rwlock_init
int uv_rwlock_init(uv_rwlock_t *rwlock)
Definition: libuv/src/win/thread.c:241
uv_rwlock_t::num_readers_lock_
CRITICAL_SECTION num_readers_lock_
Definition: win.h:262
thread_ctx::barrier
uv_barrier_t barrier
Definition: test-eintr-handling.c:45
uv_barrier_t::count
unsigned int count
Definition: win.h:278
UV_ONCE_INIT
#define UV_ONCE_INIT
Definition: unix.h:131
uv_rwlock_destroy
void uv_rwlock_destroy(uv_rwlock_t *rwlock)
Definition: libuv/src/win/thread.c:258
handle
static csh handle
Definition: test_arm_regression.c:16
uv_barrier_wait
int uv_barrier_wait(uv_barrier_t *barrier)
Definition: libuv/src/win/thread.c:463
uv_thread_t
pthread_t uv_thread_t
Definition: unix.h:134
internal.h
uv_sem_init
int uv_sem_init(uv_sem_t *sem, unsigned int value)
Definition: libuv/src/win/thread.c:350
intrin.h
uv_mutex_lock
void uv_mutex_lock(uv_mutex_t *mutex)
Definition: libuv/src/win/thread.c:223
uv_barrier_destroy
void uv_barrier_destroy(uv_barrier_t *barrier)
Definition: libuv/src/win/thread.c:456
uv_key_create
int uv_key_create(uv_key_t *key)
Definition: libuv/src/win/thread.c:490
t1
Table t1
Definition: abseil-cpp/absl/container/internal/raw_hash_set_allocator_test.cc:185
rwlock
static uv_rwlock_t rwlock
Definition: test-mutexes.c:30
thread
static uv_thread_t thread
Definition: test-async-null-cb.c:29
uv_rwlock_wrunlock
void uv_rwlock_wrunlock(uv_rwlock_t *rwlock)
Definition: libuv/src/win/thread.c:344
timeout
uv_timer_t timeout
Definition: libuv/docs/code/uvwget/main.c:9
uv_thread_create_ex
int uv_thread_create_ex(uv_thread_t *tid, const uv_thread_options_t *params, void(*entry)(void *arg), void *arg)
Definition: libuv/src/win/thread.c:120


grpc
Author(s):
autogenerated on Fri May 16 2025 03:00:35