libuv-svace-build

Форк
0
470 строк · 10.8 Кб
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
typedef void (*uv__once_cb)(void);
36

37
typedef struct {
38
  uv__once_cb callback;
39
} uv__once_data_t;
40

41
static BOOL WINAPI uv__once_inner(INIT_ONCE *once, void* param, void** context) {
42
  uv__once_data_t* data = param;
43

44
  data->callback();
45

46
  return TRUE;
47
}
48

49
void uv_once(uv_once_t* guard, uv__once_cb callback) {
50
  uv__once_data_t data = { .callback = callback };
51
  InitOnceExecuteOnce(&guard->init_once, uv__once_inner, (void*) &data, NULL);
52
}
53

54

55
/* Verify that uv_thread_t can be stored in a TLS slot. */
56
STATIC_ASSERT(sizeof(uv_thread_t) <= sizeof(void*));
57

58
static uv_key_t uv__current_thread_key;
59
static uv_once_t uv__current_thread_init_guard = UV_ONCE_INIT;
60

61

62
static void uv__init_current_thread_key(void) {
63
  if (uv_key_create(&uv__current_thread_key))
64
    abort();
65
}
66

67

68
struct thread_ctx {
69
  void (*entry)(void* arg);
70
  void* arg;
71
  uv_thread_t self;
72
};
73

74

75
static UINT __stdcall uv__thread_start(void* arg) {
76
  struct thread_ctx *ctx_p;
77
  struct thread_ctx ctx;
78

79
  ctx_p = arg;
80
  ctx = *ctx_p;
81
  uv__free(ctx_p);
82

83
  uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key);
84
  uv_key_set(&uv__current_thread_key, ctx.self);
85

86
  ctx.entry(ctx.arg);
87

88
  return 0;
89
}
90

91

92
int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
93
  uv_thread_options_t params;
94
  params.flags = UV_THREAD_NO_FLAGS;
95
  return uv_thread_create_ex(tid, &params, entry, arg);
96
}
97

98
int uv_thread_create_ex(uv_thread_t* tid,
99
                        const uv_thread_options_t* params,
100
                        void (*entry)(void *arg),
101
                        void *arg) {
102
  struct thread_ctx* ctx;
103
  int err;
104
  HANDLE thread;
105
  SYSTEM_INFO sysinfo;
106
  size_t stack_size;
107
  size_t pagesize;
108

109
  stack_size =
110
      params->flags & UV_THREAD_HAS_STACK_SIZE ? params->stack_size : 0;
111

112
  if (stack_size != 0) {
113
    GetNativeSystemInfo(&sysinfo);
114
    pagesize = (size_t)sysinfo.dwPageSize;
115
    /* Round up to the nearest page boundary. */
116
    stack_size = (stack_size + pagesize - 1) &~ (pagesize - 1);
117

118
    if ((unsigned)stack_size != stack_size)
119
      return UV_EINVAL;
120
  }
121

122
  ctx = uv__malloc(sizeof(*ctx));
123
  if (ctx == NULL)
124
    return UV_ENOMEM;
125

126
  ctx->entry = entry;
127
  ctx->arg = arg;
128

129
  /* Create the thread in suspended state so we have a chance to pass
130
   * its own creation handle to it */
131
  thread = (HANDLE) _beginthreadex(NULL,
132
                                   (unsigned)stack_size,
133
                                   uv__thread_start,
134
                                   ctx,
135
                                   CREATE_SUSPENDED,
136
                                   NULL);
137
  if (thread == NULL) {
138
    err = errno;
139
    uv__free(ctx);
140
  } else {
141
    err = 0;
142
    *tid = thread;
143
    ctx->self = thread;
144
    ResumeThread(thread);
145
  }
146

147
  switch (err) {
148
    case 0:
149
      return 0;
150
    case EACCES:
151
      return UV_EACCES;
152
    case EAGAIN:
153
      return UV_EAGAIN;
154
    case EINVAL:
155
      return UV_EINVAL;
156
  }
157

158
  return UV_EIO;
159
}
160

161
int uv_thread_setaffinity(uv_thread_t* tid,
162
                          char* cpumask,
163
                          char* oldmask,
164
                          size_t mask_size) {
165
  int i;
166
  HANDLE hproc;
167
  DWORD_PTR procmask;
168
  DWORD_PTR sysmask;
169
  DWORD_PTR threadmask;
170
  DWORD_PTR oldthreadmask;
171
  int cpumasksize;
172

173
  cpumasksize = uv_cpumask_size();
174
  assert(cpumasksize > 0);
175
  if (mask_size < (size_t)cpumasksize)
176
    return UV_EINVAL;
177

178
  hproc = GetCurrentProcess();
179
  if (!GetProcessAffinityMask(hproc, &procmask, &sysmask))
180
    return uv_translate_sys_error(GetLastError());
181

182
  threadmask = 0;
183
  for (i = 0; i < cpumasksize; i++) {
184
    if (cpumask[i]) {
185
      if (procmask & (1 << i))
186
        threadmask |= 1 << i;
187
      else
188
        return UV_EINVAL;
189
    }
190
  }
191

192
  oldthreadmask = SetThreadAffinityMask(*tid, threadmask);
193
  if (oldthreadmask == 0)
194
    return uv_translate_sys_error(GetLastError());
195

196
  if (oldmask != NULL) {
197
    for (i = 0; i < cpumasksize; i++)
198
      oldmask[i] = (oldthreadmask >> i) & 1;
199
  }
200

201
  return 0;
202
}
203

204
int uv_thread_getaffinity(uv_thread_t* tid,
205
                          char* cpumask,
206
                          size_t mask_size) {
207
  int i;
208
  HANDLE hproc;
209
  DWORD_PTR procmask;
210
  DWORD_PTR sysmask;
211
  DWORD_PTR threadmask;
212
  int cpumasksize;
213

214
  cpumasksize = uv_cpumask_size();
215
  assert(cpumasksize > 0);
216
  if (mask_size < (size_t)cpumasksize)
217
    return UV_EINVAL;
218

219
  hproc = GetCurrentProcess();
220
  if (!GetProcessAffinityMask(hproc, &procmask, &sysmask))
221
    return uv_translate_sys_error(GetLastError());
222

223
  threadmask = SetThreadAffinityMask(*tid, procmask);
224
  if (threadmask == 0 || SetThreadAffinityMask(*tid, threadmask) == 0)
225
    return uv_translate_sys_error(GetLastError());
226

227
  for (i = 0; i < cpumasksize; i++)
228
    cpumask[i] = (threadmask >> i) & 1;
229

230
  return 0;
231
}
232

233
int uv_thread_getcpu(void) {
234
  return GetCurrentProcessorNumber();
235
}
236

237
uv_thread_t uv_thread_self(void) {
238
  uv_thread_t key;
239
  uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key);
240
  key = uv_key_get(&uv__current_thread_key);
241
  if (key == NULL) {
242
      /* If the thread wasn't started by uv_thread_create (such as the main
243
       * thread), we assign an id to it now. */
244
      if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
245
                           GetCurrentProcess(), &key, 0,
246
                           FALSE, DUPLICATE_SAME_ACCESS)) {
247
          uv_fatal_error(GetLastError(), "DuplicateHandle");
248
      }
249
      uv_key_set(&uv__current_thread_key, key);
250
  }
251
  return key;
252
}
253

254

255
int uv_thread_join(uv_thread_t *tid) {
256
  if (WaitForSingleObject(*tid, INFINITE))
257
    return uv_translate_sys_error(GetLastError());
258
  else {
259
    CloseHandle(*tid);
260
    *tid = 0;
261
    MemoryBarrier();  /* For feature parity with pthread_join(). */
262
    return 0;
263
  }
264
}
265

266

267
int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) {
268
  return *t1 == *t2;
269
}
270

271

272
int uv_mutex_init(uv_mutex_t* mutex) {
273
  InitializeCriticalSection(mutex);
274
  return 0;
275
}
276

277

278
int uv_mutex_init_recursive(uv_mutex_t* mutex) {
279
  return uv_mutex_init(mutex);
280
}
281

282

283
void uv_mutex_destroy(uv_mutex_t* mutex) {
284
  DeleteCriticalSection(mutex);
285
}
286

287

288
void uv_mutex_lock(uv_mutex_t* mutex) {
289
  EnterCriticalSection(mutex);
290
}
291

292

293
int uv_mutex_trylock(uv_mutex_t* mutex) {
294
  if (TryEnterCriticalSection(mutex))
295
    return 0;
296
  else
297
    return UV_EBUSY;
298
}
299

300

301
void uv_mutex_unlock(uv_mutex_t* mutex) {
302
  LeaveCriticalSection(mutex);
303
}
304

305
/* Ensure that the ABI for this type remains stable in v1.x */
306
#ifdef _WIN64
307
STATIC_ASSERT(sizeof(uv_rwlock_t) == 80);
308
#else
309
STATIC_ASSERT(sizeof(uv_rwlock_t) == 48);
310
#endif
311

312
int uv_rwlock_init(uv_rwlock_t* rwlock) {
313
  memset(rwlock, 0, sizeof(*rwlock));
314
  InitializeSRWLock(&rwlock->read_write_lock_);
315

316
  return 0;
317
}
318

319

320
void uv_rwlock_destroy(uv_rwlock_t* rwlock) {
321
  /* SRWLock does not need explicit destruction so long as there are no waiting threads
322
     See: https://docs.microsoft.com/windows/win32/api/synchapi/nf-synchapi-initializesrwlock#remarks */
323
}
324

325

326
void uv_rwlock_rdlock(uv_rwlock_t* rwlock) {
327
  AcquireSRWLockShared(&rwlock->read_write_lock_);
328
}
329

330

331
int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) {
332
  if (!TryAcquireSRWLockShared(&rwlock->read_write_lock_))
333
    return UV_EBUSY;
334

335
  return 0;
336
}
337

338

339
void uv_rwlock_rdunlock(uv_rwlock_t* rwlock) {
340
  ReleaseSRWLockShared(&rwlock->read_write_lock_);
341
}
342

343

344
void uv_rwlock_wrlock(uv_rwlock_t* rwlock) {
345
  AcquireSRWLockExclusive(&rwlock->read_write_lock_);
346
}
347

348

349
int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) {
350
  if (!TryAcquireSRWLockExclusive(&rwlock->read_write_lock_))
351
    return UV_EBUSY;
352

353
  return 0;
354
}
355

356

357
void uv_rwlock_wrunlock(uv_rwlock_t* rwlock) {
358
  ReleaseSRWLockExclusive(&rwlock->read_write_lock_);
359
}
360

361

362
int uv_sem_init(uv_sem_t* sem, unsigned int value) {
363
  *sem = CreateSemaphore(NULL, value, INT_MAX, NULL);
364
  if (*sem == NULL)
365
    return uv_translate_sys_error(GetLastError());
366
  else
367
    return 0;
368
}
369

370

371
void uv_sem_destroy(uv_sem_t* sem) {
372
  if (!CloseHandle(*sem))
373
    abort();
374
}
375

376

377
void uv_sem_post(uv_sem_t* sem) {
378
  if (!ReleaseSemaphore(*sem, 1, NULL))
379
    abort();
380
}
381

382

383
void uv_sem_wait(uv_sem_t* sem) {
384
  if (WaitForSingleObject(*sem, INFINITE) != WAIT_OBJECT_0)
385
    abort();
386
}
387

388

389
int uv_sem_trywait(uv_sem_t* sem) {
390
  DWORD r = WaitForSingleObject(*sem, 0);
391

392
  if (r == WAIT_OBJECT_0)
393
    return 0;
394

395
  if (r == WAIT_TIMEOUT)
396
    return UV_EAGAIN;
397

398
  abort();
399
  return -1; /* Satisfy the compiler. */
400
}
401

402

403
int uv_cond_init(uv_cond_t* cond) {
404
  InitializeConditionVariable(&cond->cond_var);
405
  return 0;
406
}
407

408

409
void uv_cond_destroy(uv_cond_t* cond) {
410
  /* nothing to do */
411
  (void) &cond;
412
}
413

414

415
void uv_cond_signal(uv_cond_t* cond) {
416
  WakeConditionVariable(&cond->cond_var);
417
}
418

419

420
void uv_cond_broadcast(uv_cond_t* cond) {
421
  WakeAllConditionVariable(&cond->cond_var);
422
}
423

424

425
void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
426
  if (!SleepConditionVariableCS(&cond->cond_var, mutex, INFINITE))
427
    abort();
428
}
429

430

431
int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
432
  if (SleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6)))
433
    return 0;
434
  if (GetLastError() != ERROR_TIMEOUT)
435
    abort();
436
  return UV_ETIMEDOUT;
437
}
438

439

440
int uv_key_create(uv_key_t* key) {
441
  key->tls_index = TlsAlloc();
442
  if (key->tls_index == TLS_OUT_OF_INDEXES)
443
    return UV_ENOMEM;
444
  return 0;
445
}
446

447

448
void uv_key_delete(uv_key_t* key) {
449
  if (TlsFree(key->tls_index) == FALSE)
450
    abort();
451
  key->tls_index = TLS_OUT_OF_INDEXES;
452
}
453

454

455
void* uv_key_get(uv_key_t* key) {
456
  void* value;
457

458
  value = TlsGetValue(key->tls_index);
459
  if (value == NULL)
460
    if (GetLastError() != ERROR_SUCCESS)
461
      abort();
462

463
  return value;
464
}
465

466

467
void uv_key_set(uv_key_t* key, void* value) {
468
  if (TlsSetValue(key->tls_index, value) == FALSE)
469
    abort();
470
}
471

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.