~webapps/unity-js-scopes/node.js

« back to all changes in this revision

Viewing changes to deps/uv/src/unix/thread.c

  • Committer: Marcus Tomlinson
  • Date: 2015-11-13 07:59:04 UTC
  • Revision ID: marcus.tomlinson@canonical.com-20151113075904-h0swczmoq1rvstfc
Node v4 (stable)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "uv.h"
 
23
#include "internal.h"
 
24
 
 
25
#include <pthread.h>
 
26
#include <assert.h>
 
27
#include <errno.h>
 
28
 
 
29
#include <sys/time.h>
 
30
 
 
31
#undef NANOSEC
 
32
#define NANOSEC ((uint64_t) 1e9)
 
33
 
 
34
 
 
35
struct thread_ctx {
 
36
  void (*entry)(void* arg);
 
37
  void* arg;
 
38
};
 
39
 
 
40
 
 
41
static void* uv__thread_start(void *arg)
 
42
{
 
43
  struct thread_ctx *ctx_p;
 
44
  struct thread_ctx ctx;
 
45
 
 
46
  ctx_p = arg;
 
47
  ctx = *ctx_p;
 
48
  uv__free(ctx_p);
 
49
  ctx.entry(ctx.arg);
 
50
 
 
51
  return 0;
 
52
}
 
53
 
 
54
 
 
55
int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
 
56
  struct thread_ctx* ctx;
 
57
  int err;
 
58
 
 
59
  ctx = uv__malloc(sizeof(*ctx));
 
60
  if (ctx == NULL)
 
61
    return UV_ENOMEM;
 
62
 
 
63
  ctx->entry = entry;
 
64
  ctx->arg = arg;
 
65
 
 
66
  err = pthread_create(tid, NULL, uv__thread_start, ctx);
 
67
 
 
68
  if (err)
 
69
    uv__free(ctx);
 
70
 
 
71
  return -err;
 
72
}
 
73
 
 
74
 
 
75
uv_thread_t uv_thread_self(void) {
 
76
  return pthread_self();
 
77
}
 
78
 
 
79
int uv_thread_join(uv_thread_t *tid) {
 
80
  return -pthread_join(*tid, NULL);
 
81
}
 
82
 
 
83
 
 
84
int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) {
 
85
  return pthread_equal(*t1, *t2);
 
86
}
 
87
 
 
88
 
 
89
int uv_mutex_init(uv_mutex_t* mutex) {
 
90
#if defined(NDEBUG) || !defined(PTHREAD_MUTEX_ERRORCHECK)
 
91
  return -pthread_mutex_init(mutex, NULL);
 
92
#else
 
93
  pthread_mutexattr_t attr;
 
94
  int err;
 
95
 
 
96
  if (pthread_mutexattr_init(&attr))
 
97
    abort();
 
98
 
 
99
  if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK))
 
100
    abort();
 
101
 
 
102
  err = pthread_mutex_init(mutex, &attr);
 
103
 
 
104
  if (pthread_mutexattr_destroy(&attr))
 
105
    abort();
 
106
 
 
107
  return -err;
 
108
#endif
 
109
}
 
110
 
 
111
 
 
112
void uv_mutex_destroy(uv_mutex_t* mutex) {
 
113
  if (pthread_mutex_destroy(mutex))
 
114
    abort();
 
115
}
 
116
 
 
117
 
 
118
void uv_mutex_lock(uv_mutex_t* mutex) {
 
119
  if (pthread_mutex_lock(mutex))
 
120
    abort();
 
121
}
 
122
 
 
123
 
 
124
int uv_mutex_trylock(uv_mutex_t* mutex) {
 
125
  int err;
 
126
 
 
127
  /* FIXME(bnoordhuis) EAGAIN means recursive lock limit reached. Arguably
 
128
   * a bug, should probably abort rather than return -EAGAIN.
 
129
   */
 
130
  err = pthread_mutex_trylock(mutex);
 
131
  if (err && err != EBUSY && err != EAGAIN)
 
132
    abort();
 
133
 
 
134
  return -err;
 
135
}
 
136
 
 
137
 
 
138
void uv_mutex_unlock(uv_mutex_t* mutex) {
 
139
  if (pthread_mutex_unlock(mutex))
 
140
    abort();
 
141
}
 
142
 
 
143
 
 
144
int uv_rwlock_init(uv_rwlock_t* rwlock) {
 
145
  return -pthread_rwlock_init(rwlock, NULL);
 
146
}
 
147
 
 
148
 
 
149
void uv_rwlock_destroy(uv_rwlock_t* rwlock) {
 
150
  if (pthread_rwlock_destroy(rwlock))
 
151
    abort();
 
152
}
 
153
 
 
154
 
 
155
void uv_rwlock_rdlock(uv_rwlock_t* rwlock) {
 
156
  if (pthread_rwlock_rdlock(rwlock))
 
157
    abort();
 
158
}
 
159
 
 
160
 
 
161
int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) {
 
162
  int err;
 
163
 
 
164
  err = pthread_rwlock_tryrdlock(rwlock);
 
165
  if (err && err != EBUSY && err != EAGAIN)
 
166
    abort();
 
167
 
 
168
  return -err;
 
169
}
 
170
 
 
171
 
 
172
void uv_rwlock_rdunlock(uv_rwlock_t* rwlock) {
 
173
  if (pthread_rwlock_unlock(rwlock))
 
174
    abort();
 
175
}
 
176
 
 
177
 
 
178
void uv_rwlock_wrlock(uv_rwlock_t* rwlock) {
 
179
  if (pthread_rwlock_wrlock(rwlock))
 
180
    abort();
 
181
}
 
182
 
 
183
 
 
184
int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) {
 
185
  int err;
 
186
 
 
187
  err = pthread_rwlock_trywrlock(rwlock);
 
188
  if (err && err != EBUSY && err != EAGAIN)
 
189
    abort();
 
190
 
 
191
  return -err;
 
192
}
 
193
 
 
194
 
 
195
void uv_rwlock_wrunlock(uv_rwlock_t* rwlock) {
 
196
  if (pthread_rwlock_unlock(rwlock))
 
197
    abort();
 
198
}
 
199
 
 
200
 
 
201
void uv_once(uv_once_t* guard, void (*callback)(void)) {
 
202
  if (pthread_once(guard, callback))
 
203
    abort();
 
204
}
 
205
 
 
206
#if defined(__APPLE__) && defined(__MACH__)
 
207
 
 
208
int uv_sem_init(uv_sem_t* sem, unsigned int value) {
 
209
  kern_return_t err;
 
210
 
 
211
  err = semaphore_create(mach_task_self(), sem, SYNC_POLICY_FIFO, value);
 
212
  if (err == KERN_SUCCESS)
 
213
    return 0;
 
214
  if (err == KERN_INVALID_ARGUMENT)
 
215
    return -EINVAL;
 
216
  if (err == KERN_RESOURCE_SHORTAGE)
 
217
    return -ENOMEM;
 
218
 
 
219
  abort();
 
220
  return -EINVAL;  /* Satisfy the compiler. */
 
221
}
 
222
 
 
223
 
 
224
void uv_sem_destroy(uv_sem_t* sem) {
 
225
  if (semaphore_destroy(mach_task_self(), *sem))
 
226
    abort();
 
227
}
 
228
 
 
229
 
 
230
void uv_sem_post(uv_sem_t* sem) {
 
231
  if (semaphore_signal(*sem))
 
232
    abort();
 
233
}
 
234
 
 
235
 
 
236
void uv_sem_wait(uv_sem_t* sem) {
 
237
  int r;
 
238
 
 
239
  do
 
240
    r = semaphore_wait(*sem);
 
241
  while (r == KERN_ABORTED);
 
242
 
 
243
  if (r != KERN_SUCCESS)
 
244
    abort();
 
245
}
 
246
 
 
247
 
 
248
int uv_sem_trywait(uv_sem_t* sem) {
 
249
  mach_timespec_t interval;
 
250
  kern_return_t err;
 
251
 
 
252
  interval.tv_sec = 0;
 
253
  interval.tv_nsec = 0;
 
254
 
 
255
  err = semaphore_timedwait(*sem, interval);
 
256
  if (err == KERN_SUCCESS)
 
257
    return 0;
 
258
  if (err == KERN_OPERATION_TIMED_OUT)
 
259
    return -EAGAIN;
 
260
 
 
261
  abort();
 
262
  return -EINVAL;  /* Satisfy the compiler. */
 
263
}
 
264
 
 
265
#else /* !(defined(__APPLE__) && defined(__MACH__)) */
 
266
 
 
267
int uv_sem_init(uv_sem_t* sem, unsigned int value) {
 
268
  if (sem_init(sem, 0, value))
 
269
    return -errno;
 
270
  return 0;
 
271
}
 
272
 
 
273
 
 
274
void uv_sem_destroy(uv_sem_t* sem) {
 
275
  if (sem_destroy(sem))
 
276
    abort();
 
277
}
 
278
 
 
279
 
 
280
void uv_sem_post(uv_sem_t* sem) {
 
281
  if (sem_post(sem))
 
282
    abort();
 
283
}
 
284
 
 
285
 
 
286
void uv_sem_wait(uv_sem_t* sem) {
 
287
  int r;
 
288
 
 
289
  do
 
290
    r = sem_wait(sem);
 
291
  while (r == -1 && errno == EINTR);
 
292
 
 
293
  if (r)
 
294
    abort();
 
295
}
 
296
 
 
297
 
 
298
int uv_sem_trywait(uv_sem_t* sem) {
 
299
  int r;
 
300
 
 
301
  do
 
302
    r = sem_trywait(sem);
 
303
  while (r == -1 && errno == EINTR);
 
304
 
 
305
  if (r) {
 
306
    if (errno == EAGAIN)
 
307
      return -EAGAIN;
 
308
    abort();
 
309
  }
 
310
 
 
311
  return 0;
 
312
}
 
313
 
 
314
#endif /* defined(__APPLE__) && defined(__MACH__) */
 
315
 
 
316
 
 
317
#if defined(__APPLE__) && defined(__MACH__)
 
318
 
 
319
int uv_cond_init(uv_cond_t* cond) {
 
320
  return -pthread_cond_init(cond, NULL);
 
321
}
 
322
 
 
323
#else /* !(defined(__APPLE__) && defined(__MACH__)) */
 
324
 
 
325
int uv_cond_init(uv_cond_t* cond) {
 
326
  pthread_condattr_t attr;
 
327
  int err;
 
328
 
 
329
  err = pthread_condattr_init(&attr);
 
330
  if (err)
 
331
    return -err;
 
332
 
 
333
#if !(defined(__ANDROID__) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC))
 
334
  err = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
 
335
  if (err)
 
336
    goto error2;
 
337
#endif
 
338
 
 
339
  err = pthread_cond_init(cond, &attr);
 
340
  if (err)
 
341
    goto error2;
 
342
 
 
343
  err = pthread_condattr_destroy(&attr);
 
344
  if (err)
 
345
    goto error;
 
346
 
 
347
  return 0;
 
348
 
 
349
error:
 
350
  pthread_cond_destroy(cond);
 
351
error2:
 
352
  pthread_condattr_destroy(&attr);
 
353
  return -err;
 
354
}
 
355
 
 
356
#endif /* defined(__APPLE__) && defined(__MACH__) */
 
357
 
 
358
void uv_cond_destroy(uv_cond_t* cond) {
 
359
  if (pthread_cond_destroy(cond))
 
360
    abort();
 
361
}
 
362
 
 
363
void uv_cond_signal(uv_cond_t* cond) {
 
364
  if (pthread_cond_signal(cond))
 
365
    abort();
 
366
}
 
367
 
 
368
void uv_cond_broadcast(uv_cond_t* cond) {
 
369
  if (pthread_cond_broadcast(cond))
 
370
    abort();
 
371
}
 
372
 
 
373
void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
 
374
  if (pthread_cond_wait(cond, mutex))
 
375
    abort();
 
376
}
 
377
 
 
378
 
 
379
int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
 
380
  int r;
 
381
  struct timespec ts;
 
382
 
 
383
#if defined(__APPLE__) && defined(__MACH__)
 
384
  ts.tv_sec = timeout / NANOSEC;
 
385
  ts.tv_nsec = timeout % NANOSEC;
 
386
  r = pthread_cond_timedwait_relative_np(cond, mutex, &ts);
 
387
#else
 
388
  timeout += uv__hrtime(UV_CLOCK_PRECISE);
 
389
  ts.tv_sec = timeout / NANOSEC;
 
390
  ts.tv_nsec = timeout % NANOSEC;
 
391
#if defined(__ANDROID__) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)
 
392
  /*
 
393
   * The bionic pthread implementation doesn't support CLOCK_MONOTONIC,
 
394
   * but has this alternative function instead.
 
395
   */
 
396
  r = pthread_cond_timedwait_monotonic_np(cond, mutex, &ts);
 
397
#else
 
398
  r = pthread_cond_timedwait(cond, mutex, &ts);
 
399
#endif /* __ANDROID__ */
 
400
#endif
 
401
 
 
402
 
 
403
  if (r == 0)
 
404
    return 0;
 
405
 
 
406
  if (r == ETIMEDOUT)
 
407
    return -ETIMEDOUT;
 
408
 
 
409
  abort();
 
410
  return -EINVAL;  /* Satisfy the compiler. */
 
411
}
 
412
 
 
413
 
 
414
#if defined(__APPLE__) && defined(__MACH__)
 
415
 
 
416
int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
 
417
  int err;
 
418
 
 
419
  barrier->n = count;
 
420
  barrier->count = 0;
 
421
 
 
422
  err = uv_mutex_init(&barrier->mutex);
 
423
  if (err)
 
424
    return -err;
 
425
 
 
426
  err = uv_sem_init(&barrier->turnstile1, 0);
 
427
  if (err)
 
428
    goto error2;
 
429
 
 
430
  err = uv_sem_init(&barrier->turnstile2, 1);
 
431
  if (err)
 
432
    goto error;
 
433
 
 
434
  return 0;
 
435
 
 
436
error:
 
437
  uv_sem_destroy(&barrier->turnstile1);
 
438
error2:
 
439
  uv_mutex_destroy(&barrier->mutex);
 
440
  return -err;
 
441
 
 
442
}
 
443
 
 
444
 
 
445
void uv_barrier_destroy(uv_barrier_t* barrier) {
 
446
  uv_sem_destroy(&barrier->turnstile2);
 
447
  uv_sem_destroy(&barrier->turnstile1);
 
448
  uv_mutex_destroy(&barrier->mutex);
 
449
}
 
450
 
 
451
 
 
452
int uv_barrier_wait(uv_barrier_t* barrier) {
 
453
  int serial_thread;
 
454
 
 
455
  uv_mutex_lock(&barrier->mutex);
 
456
  if (++barrier->count == barrier->n) {
 
457
    uv_sem_wait(&barrier->turnstile2);
 
458
    uv_sem_post(&barrier->turnstile1);
 
459
  }
 
460
  uv_mutex_unlock(&barrier->mutex);
 
461
 
 
462
  uv_sem_wait(&barrier->turnstile1);
 
463
  uv_sem_post(&barrier->turnstile1);
 
464
 
 
465
  uv_mutex_lock(&barrier->mutex);
 
466
  serial_thread = (--barrier->count == 0);
 
467
  if (serial_thread) {
 
468
    uv_sem_wait(&barrier->turnstile1);
 
469
    uv_sem_post(&barrier->turnstile2);
 
470
  }
 
471
  uv_mutex_unlock(&barrier->mutex);
 
472
 
 
473
  uv_sem_wait(&barrier->turnstile2);
 
474
  uv_sem_post(&barrier->turnstile2);
 
475
  return serial_thread;
 
476
}
 
477
 
 
478
#else /* !(defined(__APPLE__) && defined(__MACH__)) */
 
479
 
 
480
int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
 
481
  return -pthread_barrier_init(barrier, NULL, count);
 
482
}
 
483
 
 
484
 
 
485
void uv_barrier_destroy(uv_barrier_t* barrier) {
 
486
  if (pthread_barrier_destroy(barrier))
 
487
    abort();
 
488
}
 
489
 
 
490
 
 
491
int uv_barrier_wait(uv_barrier_t* barrier) {
 
492
  int r = pthread_barrier_wait(barrier);
 
493
  if (r && r != PTHREAD_BARRIER_SERIAL_THREAD)
 
494
    abort();
 
495
  return r == PTHREAD_BARRIER_SERIAL_THREAD;
 
496
}
 
497
 
 
498
#endif /* defined(__APPLE__) && defined(__MACH__) */
 
499
 
 
500
int uv_key_create(uv_key_t* key) {
 
501
  return -pthread_key_create(key, NULL);
 
502
}
 
503
 
 
504
 
 
505
void uv_key_delete(uv_key_t* key) {
 
506
  if (pthread_key_delete(*key))
 
507
    abort();
 
508
}
 
509
 
 
510
 
 
511
void* uv_key_get(uv_key_t* key) {
 
512
  return pthread_getspecific(*key);
 
513
}
 
514
 
 
515
 
 
516
void uv_key_set(uv_key_t* key, void* value) {
 
517
  if (pthread_setspecific(*key, value))
 
518
    abort();
 
519
}