mirror of https://github.com/lukechilds/node.git
Browse Source
Fixes: https://github.com/nodejs/node/issues/4002 Fixes: https://github.com/nodejs/node/issues/5384 Fixes: https://github.com/nodejs/node/issues/6563 Refs: https://github.com/nodejs/node/issues/2680#issuecomment-213521708 PR-URL: https://github.com/nodejs/node/pull/6796 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Johan Bergström <bugs@bergstroem.nu> Reviewed-By: Myles Borins <myles.borins@gmail.com>v7.x
Saúl Ibarra Corretgé
9 years ago
55 changed files with 962 additions and 550 deletions
@ -0,0 +1,64 @@ |
|||
/*
|
|||
Copyright (c) 2016, Kari Tristan Helgason <kthelgason@gmail.com> |
|||
|
|||
Permission to use, copy, modify, and/or distribute this software for any |
|||
purpose with or without fee is hereby granted, provided that the above |
|||
copyright notice and this permission notice appear in all copies. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
|||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
|||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
|||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|||
*/ |
|||
|
|||
#ifndef _UV_PTHREAD_BARRIER_ |
|||
#define _UV_PTHREAD_BARRIER_ |
|||
#include <errno.h> |
|||
#include <pthread.h> |
|||
#include <semaphore.h> /* sem_t */ |
|||
|
|||
#define PTHREAD_BARRIER_SERIAL_THREAD 0x12345 |
|||
|
|||
/*
|
|||
* To maintain ABI compatibility with |
|||
* libuv v1.x struct is padded according |
|||
* to target platform |
|||
*/ |
|||
#if defined(__ANDROID__) |
|||
# define UV_BARRIER_STRUCT_PADDING \ |
|||
sizeof(pthread_mutex_t) + \ |
|||
sizeof(pthread_cond_t) + \ |
|||
sizeof(unsigned int) - \ |
|||
sizeof(void *) |
|||
#elif defined(__APPLE__) |
|||
# define UV_BARRIER_STRUCT_PADDING \ |
|||
sizeof(pthread_mutex_t) + \ |
|||
2 * sizeof(sem_t) + \ |
|||
2 * sizeof(unsigned int) - \ |
|||
sizeof(void *) |
|||
#endif |
|||
|
|||
typedef struct { |
|||
pthread_mutex_t mutex; |
|||
pthread_cond_t cond; |
|||
unsigned threshold; |
|||
unsigned in; |
|||
unsigned out; |
|||
} _uv_barrier; |
|||
|
|||
typedef struct { |
|||
_uv_barrier* b; |
|||
char _pad[UV_BARRIER_STRUCT_PADDING]; |
|||
} pthread_barrier_t; |
|||
|
|||
int pthread_barrier_init(pthread_barrier_t* barrier, |
|||
const void* barrier_attr, |
|||
unsigned count); |
|||
|
|||
int pthread_barrier_wait(pthread_barrier_t* barrier); |
|||
int pthread_barrier_destroy(pthread_barrier_t *barrier); |
|||
|
|||
#endif /* _UV_PTHREAD_BARRIER_ */ |
@ -0,0 +1,120 @@ |
|||
/*
|
|||
Copyright (c) 2016, Kari Tristan Helgason <kthelgason@gmail.com> |
|||
|
|||
Permission to use, copy, modify, and/or distribute this software for any |
|||
purpose with or without fee is hereby granted, provided that the above |
|||
copyright notice and this permission notice appear in all copies. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
|||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
|||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
|||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|||
*/ |
|||
#include "uv-common.h" |
|||
#include "pthread-barrier.h" |
|||
|
|||
#include <stdlib.h> |
|||
#include <assert.h> |
|||
|
|||
/* TODO: support barrier_attr */ |
|||
int pthread_barrier_init(pthread_barrier_t* barrier, |
|||
const void* barrier_attr, |
|||
unsigned count) { |
|||
int rc; |
|||
_uv_barrier* b; |
|||
|
|||
if (barrier == NULL || count == 0) |
|||
return EINVAL; |
|||
|
|||
if (barrier_attr != NULL) |
|||
return ENOTSUP; |
|||
|
|||
b = uv__malloc(sizeof(*b)); |
|||
if (b == NULL) |
|||
return ENOMEM; |
|||
|
|||
b->in = 0; |
|||
b->out = 0; |
|||
b->threshold = count; |
|||
|
|||
if ((rc = pthread_mutex_init(&b->mutex, NULL)) != 0) |
|||
goto error2; |
|||
if ((rc = pthread_cond_init(&b->cond, NULL)) != 0) |
|||
goto error; |
|||
|
|||
barrier->b = b; |
|||
return 0; |
|||
|
|||
error: |
|||
pthread_mutex_destroy(&b->mutex); |
|||
error2: |
|||
uv__free(b); |
|||
return rc; |
|||
} |
|||
|
|||
int pthread_barrier_wait(pthread_barrier_t* barrier) { |
|||
int rc; |
|||
_uv_barrier* b; |
|||
|
|||
if (barrier == NULL || barrier->b == NULL) |
|||
return EINVAL; |
|||
|
|||
b = barrier->b; |
|||
/* Lock the mutex*/ |
|||
if ((rc = pthread_mutex_lock(&b->mutex)) != 0) |
|||
return rc; |
|||
|
|||
/* Increment the count. If this is the first thread to reach the threshold,
|
|||
wake up waiters, unlock the mutex, then return |
|||
PTHREAD_BARRIER_SERIAL_THREAD. */ |
|||
if (++b->in == b->threshold) { |
|||
b->in = 0; |
|||
b->out = b->threshold - 1; |
|||
assert(pthread_cond_signal(&b->cond) == 0); |
|||
|
|||
pthread_mutex_unlock(&b->mutex); |
|||
return PTHREAD_BARRIER_SERIAL_THREAD; |
|||
} |
|||
/* Otherwise, wait for other threads until in is set to 0,
|
|||
then return 0 to indicate this is not the first thread. */ |
|||
do { |
|||
if ((rc = pthread_cond_wait(&b->cond, &b->mutex)) != 0) |
|||
break; |
|||
} while (b->in != 0); |
|||
|
|||
/* mark thread exit */ |
|||
b->out--; |
|||
pthread_cond_signal(&b->cond); |
|||
pthread_mutex_unlock(&b->mutex); |
|||
return rc; |
|||
} |
|||
|
|||
int pthread_barrier_destroy(pthread_barrier_t* barrier) { |
|||
int rc; |
|||
_uv_barrier* b; |
|||
|
|||
if (barrier == NULL || barrier->b == NULL) |
|||
return EINVAL; |
|||
|
|||
b = barrier->b; |
|||
|
|||
if ((rc = pthread_mutex_lock(&b->mutex)) != 0) |
|||
return rc; |
|||
|
|||
if (b->in > 0 || b->out > 0) |
|||
rc = EBUSY; |
|||
|
|||
pthread_mutex_unlock(&b->mutex); |
|||
|
|||
if (rc) |
|||
return rc; |
|||
|
|||
pthread_cond_destroy(&b->cond); |
|||
pthread_mutex_destroy(&b->mutex); |
|||
uv__free(barrier->b); |
|||
barrier->b = NULL; |
|||
return 0; |
|||
} |
Loading…
Reference in new issue