test-barrier.c revision 1.1 1 1.1 christos /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2 1.1 christos *
3 1.1 christos * Permission is hereby granted, free of charge, to any person obtaining a copy
4 1.1 christos * of this software and associated documentation files (the "Software"), to
5 1.1 christos * deal in the Software without restriction, including without limitation the
6 1.1 christos * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 1.1 christos * sell copies of the Software, and to permit persons to whom the Software is
8 1.1 christos * furnished to do so, subject to the following conditions:
9 1.1 christos *
10 1.1 christos * The above copyright notice and this permission notice shall be included in
11 1.1 christos * all copies or substantial portions of the Software.
12 1.1 christos *
13 1.1 christos * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 1.1 christos * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 1.1 christos * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 1.1 christos * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 1.1 christos * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 1.1 christos * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 1.1 christos * IN THE SOFTWARE.
20 1.1 christos */
21 1.1 christos
22 1.1 christos #include "uv.h"
23 1.1 christos #include "task.h"
24 1.1 christos
25 1.1 christos #include <string.h>
26 1.1 christos #include <errno.h>
27 1.1 christos
28 1.1 christos typedef struct {
29 1.1 christos uv_barrier_t barrier;
30 1.1 christos int delay;
31 1.1 christos volatile int posted;
32 1.1 christos int main_barrier_wait_rval;
33 1.1 christos int worker_barrier_wait_rval;
34 1.1 christos } worker_config;
35 1.1 christos
36 1.1 christos
37 1.1 christos static void worker(void* arg) {
38 1.1 christos worker_config* c = arg;
39 1.1 christos
40 1.1 christos if (c->delay)
41 1.1 christos uv_sleep(c->delay);
42 1.1 christos
43 1.1 christos c->worker_barrier_wait_rval = uv_barrier_wait(&c->barrier);
44 1.1 christos }
45 1.1 christos
46 1.1 christos
47 1.1 christos TEST_IMPL(barrier_1) {
48 1.1 christos uv_thread_t thread;
49 1.1 christos worker_config wc;
50 1.1 christos
51 1.1 christos memset(&wc, 0, sizeof(wc));
52 1.1 christos
53 1.1 christos ASSERT(0 == uv_barrier_init(&wc.barrier, 2));
54 1.1 christos ASSERT(0 == uv_thread_create(&thread, worker, &wc));
55 1.1 christos
56 1.1 christos uv_sleep(100);
57 1.1 christos wc.main_barrier_wait_rval = uv_barrier_wait(&wc.barrier);
58 1.1 christos
59 1.1 christos ASSERT(0 == uv_thread_join(&thread));
60 1.1 christos uv_barrier_destroy(&wc.barrier);
61 1.1 christos
62 1.1 christos ASSERT(1 == (wc.main_barrier_wait_rval ^ wc.worker_barrier_wait_rval));
63 1.1 christos
64 1.1 christos return 0;
65 1.1 christos }
66 1.1 christos
67 1.1 christos
68 1.1 christos TEST_IMPL(barrier_2) {
69 1.1 christos uv_thread_t thread;
70 1.1 christos worker_config wc;
71 1.1 christos
72 1.1 christos memset(&wc, 0, sizeof(wc));
73 1.1 christos wc.delay = 100;
74 1.1 christos
75 1.1 christos ASSERT(0 == uv_barrier_init(&wc.barrier, 2));
76 1.1 christos ASSERT(0 == uv_thread_create(&thread, worker, &wc));
77 1.1 christos
78 1.1 christos wc.main_barrier_wait_rval = uv_barrier_wait(&wc.barrier);
79 1.1 christos
80 1.1 christos ASSERT(0 == uv_thread_join(&thread));
81 1.1 christos uv_barrier_destroy(&wc.barrier);
82 1.1 christos
83 1.1 christos ASSERT(1 == (wc.main_barrier_wait_rval ^ wc.worker_barrier_wait_rval));
84 1.1 christos
85 1.1 christos return 0;
86 1.1 christos }
87 1.1 christos
88 1.1 christos
89 1.1 christos TEST_IMPL(barrier_3) {
90 1.1 christos uv_thread_t thread;
91 1.1 christos worker_config wc;
92 1.1 christos
93 1.1 christos memset(&wc, 0, sizeof(wc));
94 1.1 christos
95 1.1 christos ASSERT(0 == uv_barrier_init(&wc.barrier, 2));
96 1.1 christos ASSERT(0 == uv_thread_create(&thread, worker, &wc));
97 1.1 christos
98 1.1 christos wc.main_barrier_wait_rval = uv_barrier_wait(&wc.barrier);
99 1.1 christos
100 1.1 christos ASSERT(0 == uv_thread_join(&thread));
101 1.1 christos uv_barrier_destroy(&wc.barrier);
102 1.1 christos
103 1.1 christos ASSERT(1 == (wc.main_barrier_wait_rval ^ wc.worker_barrier_wait_rval));
104 1.1 christos
105 1.1 christos return 0;
106 1.1 christos }
107 1.1 christos
108 1.1 christos static void serial_worker(void* data) {
109 1.1 christos uv_barrier_t* barrier;
110 1.1 christos
111 1.1 christos barrier = data;
112 1.1 christos if (uv_barrier_wait(barrier) > 0)
113 1.1 christos uv_barrier_destroy(barrier);
114 1.1 christos
115 1.1 christos uv_sleep(100); /* Wait a bit before terminating. */
116 1.1 christos }
117 1.1 christos
118 1.1 christos /* Ensure that uv_barrier_wait returns positive only after all threads have
119 1.1 christos * exited the barrier. If this value is returned too early and the barrier is
120 1.1 christos * destroyed prematurely, then this test may see a crash. */
121 1.1 christos TEST_IMPL(barrier_serial_thread) {
122 1.1 christos uv_thread_t threads[4];
123 1.1 christos uv_barrier_t barrier;
124 1.1 christos unsigned i;
125 1.1 christos
126 1.1 christos ASSERT(0 == uv_barrier_init(&barrier, ARRAY_SIZE(threads) + 1));
127 1.1 christos
128 1.1 christos for (i = 0; i < ARRAY_SIZE(threads); ++i)
129 1.1 christos ASSERT(0 == uv_thread_create(&threads[i], serial_worker, &barrier));
130 1.1 christos
131 1.1 christos if (uv_barrier_wait(&barrier) > 0)
132 1.1 christos uv_barrier_destroy(&barrier);
133 1.1 christos
134 1.1 christos for (i = 0; i < ARRAY_SIZE(threads); ++i)
135 1.1 christos ASSERT(0 == uv_thread_join(&threads[i]));
136 1.1 christos
137 1.1 christos return 0;
138 1.1 christos }
139 1.1 christos
140 1.1 christos /* Single thread uv_barrier_wait should return correct return value. */
141 1.1 christos TEST_IMPL(barrier_serial_thread_single) {
142 1.1 christos uv_barrier_t barrier;
143 1.1 christos
144 1.1 christos ASSERT(0 == uv_barrier_init(&barrier, 1));
145 1.1 christos ASSERT(0 < uv_barrier_wait(&barrier));
146 1.1 christos uv_barrier_destroy(&barrier);
147 1.1 christos return 0;
148 1.1 christos }
149