mirror of https://github.com/lukechilds/node.git
Timothy J Fontaine
11 years ago
78 changed files with 1389 additions and 580 deletions
@ -0,0 +1,60 @@ |
|||
/* Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
|
|||
* |
|||
* 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_ATOMIC_OPS_H_ |
|||
#define UV_ATOMIC_OPS_H_ |
|||
|
|||
#include "internal.h" /* UV_UNUSED */ |
|||
|
|||
UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)); |
|||
UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)); |
|||
UV_UNUSED(static void cpu_relax(void)); |
|||
|
|||
/* Prefer hand-rolled assembly over the gcc builtins because the latter also
|
|||
* issue full memory barriers. |
|||
*/ |
|||
UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) { |
|||
#if defined(__i386__) || defined(__x86_64__) |
|||
int out; |
|||
__asm__ __volatile__ ("lock; cmpxchg %2, %1;" |
|||
: "=a" (out), "+m" (*(volatile int*) ptr) |
|||
: "r" (newval), "0" (oldval) |
|||
: "memory"); |
|||
return out; |
|||
#else |
|||
return __sync_val_compare_and_swap(ptr, oldval, newval); |
|||
#endif |
|||
} |
|||
|
|||
UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)) { |
|||
#if defined(__i386__) || defined(__x86_64__) |
|||
long out; |
|||
__asm__ __volatile__ ("lock; cmpxchg %2, %1;" |
|||
: "=a" (out), "+m" (*(volatile long*) ptr) |
|||
: "r" (newval), "0" (oldval) |
|||
: "memory"); |
|||
return out; |
|||
#else |
|||
return __sync_val_compare_and_swap(ptr, oldval, newval); |
|||
#endif |
|||
} |
|||
|
|||
UV_UNUSED(static void cpu_relax(void)) { |
|||
#if defined(__i386__) || defined(__x86_64__) |
|||
__asm__ __volatile__ ("rep; nop"); /* a.k.a. PAUSE */ |
|||
#endif |
|||
} |
|||
|
|||
#endif /* UV_ATOMIC_OPS_H_ */ |
@ -0,0 +1,53 @@ |
|||
/* Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
|
|||
* |
|||
* 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_SPINLOCK_H_ |
|||
#define UV_SPINLOCK_H_ |
|||
|
|||
#include "internal.h" /* ACCESS_ONCE, UV_UNUSED */ |
|||
#include "atomic-ops.h" |
|||
|
|||
#define UV_SPINLOCK_INITIALIZER { 0 } |
|||
|
|||
typedef struct { |
|||
int lock; |
|||
} uv_spinlock_t; |
|||
|
|||
UV_UNUSED(static void uv_spinlock_init(uv_spinlock_t* spinlock)); |
|||
UV_UNUSED(static void uv_spinlock_lock(uv_spinlock_t* spinlock)); |
|||
UV_UNUSED(static void uv_spinlock_unlock(uv_spinlock_t* spinlock)); |
|||
UV_UNUSED(static int uv_spinlock_trylock(uv_spinlock_t* spinlock)); |
|||
|
|||
UV_UNUSED(static void uv_spinlock_init(uv_spinlock_t* spinlock)) { |
|||
ACCESS_ONCE(int, spinlock->lock) = 0; |
|||
} |
|||
|
|||
UV_UNUSED(static void uv_spinlock_lock(uv_spinlock_t* spinlock)) { |
|||
while (!uv_spinlock_trylock(spinlock)) cpu_relax(); |
|||
} |
|||
|
|||
UV_UNUSED(static void uv_spinlock_unlock(uv_spinlock_t* spinlock)) { |
|||
ACCESS_ONCE(int, spinlock->lock) = 0; |
|||
} |
|||
|
|||
UV_UNUSED(static int uv_spinlock_trylock(uv_spinlock_t* spinlock)) { |
|||
/* TODO(bnoordhuis) Maybe change to a ticket lock to guarantee fair queueing.
|
|||
* Not really critical until we have locks that are (frequently) contended |
|||
* for by several threads. |
|||
*/ |
|||
return 0 == cmpxchgi(&spinlock->lock, 0, 1); |
|||
} |
|||
|
|||
#endif /* UV_SPINLOCK_H_ */ |
@ -0,0 +1,80 @@ |
|||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
|||
* |
|||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
* of this software and associated documentation files (the "Software"), to |
|||
* deal in the Software without restriction, including without limitation the |
|||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
|||
* sell copies of the Software, and to permit persons to whom the Software is |
|||
* furnished to do so, subject to the following conditions: |
|||
* |
|||
* The above copyright notice and this permission notice shall be included in |
|||
* all copies or substantial portions of the Software. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
|||
* IN THE SOFTWARE. |
|||
*/ |
|||
|
|||
#include "uv.h" |
|||
#include "task.h" |
|||
|
|||
static int check_cb_called; |
|||
static int timer_cb_called; |
|||
static int close_cb_called; |
|||
|
|||
static uv_check_t check_handle; |
|||
static uv_timer_t timer_handle1; |
|||
static uv_timer_t timer_handle2; |
|||
|
|||
|
|||
static void close_cb(uv_handle_t* handle) { |
|||
ASSERT(handle != NULL); |
|||
close_cb_called++; |
|||
} |
|||
|
|||
|
|||
/* check_cb should run before any close_cb */ |
|||
static void check_cb(uv_check_t* handle, int status) { |
|||
ASSERT(check_cb_called == 0); |
|||
ASSERT(timer_cb_called == 1); |
|||
ASSERT(close_cb_called == 0); |
|||
uv_close((uv_handle_t*) handle, close_cb); |
|||
uv_close((uv_handle_t*) &timer_handle2, close_cb); |
|||
check_cb_called++; |
|||
} |
|||
|
|||
|
|||
static void timer_cb(uv_timer_t* handle, int status) { |
|||
uv_close((uv_handle_t*) handle, close_cb); |
|||
timer_cb_called++; |
|||
} |
|||
|
|||
|
|||
TEST_IMPL(close_order) { |
|||
uv_loop_t* loop; |
|||
loop = uv_default_loop(); |
|||
|
|||
uv_check_init(loop, &check_handle); |
|||
uv_check_start(&check_handle, check_cb); |
|||
uv_timer_init(loop, &timer_handle1); |
|||
uv_timer_start(&timer_handle1, timer_cb, 0, 0); |
|||
uv_timer_init(loop, &timer_handle2); |
|||
uv_timer_start(&timer_handle2, timer_cb, 100000, 0); |
|||
|
|||
ASSERT(check_cb_called == 0); |
|||
ASSERT(close_cb_called == 0); |
|||
ASSERT(timer_cb_called == 0); |
|||
|
|||
uv_run(loop, UV_RUN_DEFAULT); |
|||
|
|||
ASSERT(check_cb_called == 1); |
|||
ASSERT(close_cb_called == 3); |
|||
ASSERT(timer_cb_called == 1); |
|||
|
|||
MAKE_VALGRIND_HAPPY(); |
|||
return 0; |
|||
} |
Loading…
Reference in new issue