test-thread.c
Go to the documentation of this file.
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 "task.h"
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h> /* memset */
28 
29 #ifdef __POSIX__
30 #include <pthread.h>
31 #endif
32 
35  unsigned int counter;
38 };
39 
40 
41 struct fs_req {
43  unsigned int counter;
46 };
47 
48 
49 struct test_thread {
52 };
53 
54 static void getaddrinfo_do(struct getaddrinfo_req* req);
56  int status,
57  struct addrinfo* res);
58 static void fs_do(struct fs_req* req);
59 static void fs_cb(uv_fs_t* handle);
60 
61 static int thread_called;
63 
64 
65 static void getaddrinfo_do(struct getaddrinfo_req* req) {
66  int r;
67 
68  r = uv_getaddrinfo(req->loop,
69  &req->handle,
71  "localhost",
72  NULL,
73  NULL);
74  ASSERT(r == 0);
75 }
76 
77 
79  int status,
80  struct addrinfo* res) {
81  struct getaddrinfo_req* req;
82 
83  ASSERT(status == 0);
84 
86  uv_freeaddrinfo(res);
87 
88  if (--req->counter)
90 }
91 
92 
93 static void fs_do(struct fs_req* req) {
94  int r;
95 
96  r = uv_fs_stat(req->loop, &req->handle, ".", fs_cb);
97  ASSERT(r == 0);
98 }
99 
100 
101 static void fs_cb(uv_fs_t* handle) {
102  struct fs_req* req = container_of(handle, struct fs_req, handle);
103 
105 
106  if (--req->counter)
107  fs_do(req);
108 }
109 
110 
111 static void do_work(void* arg) {
112  struct getaddrinfo_req getaddrinfo_reqs[4];
113  struct fs_req fs_reqs[4];
114  uv_loop_t loop;
115  size_t i;
116  struct test_thread* thread = arg;
117 
118  ASSERT(0 == uv_loop_init(&loop));
119 
120  for (i = 0; i < ARRAY_SIZE(getaddrinfo_reqs); i++) {
121  struct getaddrinfo_req* req = getaddrinfo_reqs + i;
122  req->counter = 4;
123  req->loop = &loop;
125  }
126 
127  for (i = 0; i < ARRAY_SIZE(fs_reqs); i++) {
128  struct fs_req* req = fs_reqs + i;
129  req->counter = 4;
130  req->loop = &loop;
131  fs_do(req);
132  }
133 
134  ASSERT(0 == uv_run(&loop, UV_RUN_DEFAULT));
135  ASSERT(0 == uv_loop_close(&loop));
136  thread->thread_called = 1;
137 }
138 
139 
140 static void thread_entry(void* arg) {
141  ASSERT(arg == (void *) 42);
142  thread_called++;
143 }
144 
145 
146 TEST_IMPL(thread_create) {
148  int r;
149 
150  r = uv_thread_create(&tid, thread_entry, (void *) 42);
151  ASSERT(r == 0);
152 
153  r = uv_thread_join(&tid);
154  ASSERT(r == 0);
155 
156  ASSERT(thread_called == 1);
157 
158  return 0;
159 }
160 
161 
162 /* Hilariously bad test name. Run a lot of tasks in the thread pool and verify
163  * that each "finished" callback is run in its originating thread.
164  */
165 TEST_IMPL(threadpool_multiple_event_loops) {
166  struct test_thread threads[8];
167  size_t i;
168  int r;
169 
170  memset(threads, 0, sizeof(threads));
171 
172  for (i = 0; i < ARRAY_SIZE(threads); i++) {
174  ASSERT(r == 0);
175  }
176 
177  for (i = 0; i < ARRAY_SIZE(threads); i++) {
179  ASSERT(r == 0);
180  ASSERT(threads[i].thread_called == 1);
181  }
182 
183  return 0;
184 }
185 
186 
187 static void tls_thread(void* arg) {
188  ASSERT(NULL == uv_key_get(&tls_key));
191  uv_key_set(&tls_key, NULL);
192  ASSERT(NULL == uv_key_get(&tls_key));
193 }
194 
195 
196 TEST_IMPL(thread_local_storage) {
197  char name[] = "main";
198  uv_thread_t threads[2];
199  ASSERT(0 == uv_key_create(&tls_key));
200  ASSERT(NULL == uv_key_get(&tls_key));
205  ASSERT(0 == uv_thread_join(threads + 0));
206  ASSERT(0 == uv_thread_join(threads + 1));
208  return 0;
209 }
210 
211 
212 static void thread_check_stack(void* arg) {
213 #if defined(__APPLE__)
214  size_t expected;
215  expected = arg == NULL ? 0 : ((uv_thread_options_t*)arg)->stack_size;
216  /* 512 kB is the default stack size of threads other than the main thread
217  * on MacOS. */
218  if (expected == 0)
219  expected = 512 * 1024;
220  ASSERT(pthread_get_stacksize_np(pthread_self()) >= expected);
221 #elif defined(__linux__) && defined(__GLIBC__)
222  size_t expected;
223  struct rlimit lim;
224  size_t stack_size;
225  pthread_attr_t attr;
226  ASSERT(0 == getrlimit(RLIMIT_STACK, &lim));
227  if (lim.rlim_cur == RLIM_INFINITY)
228  lim.rlim_cur = 2 << 20; /* glibc default. */
229  ASSERT(0 == pthread_getattr_np(pthread_self(), &attr));
230  ASSERT(0 == pthread_attr_getstacksize(&attr, &stack_size));
231  expected = arg == NULL ? 0 : ((uv_thread_options_t*)arg)->stack_size;
232  if (expected == 0)
233  expected = (size_t)lim.rlim_cur;
234  ASSERT(stack_size >= expected);
235  ASSERT(0 == pthread_attr_destroy(&attr));
236 #endif
237 }
238 
239 
243  ASSERT(0 == uv_thread_join(&thread));
244  return 0;
245 }
246 
247 TEST_IMPL(thread_stack_size_explicit) {
250 
252  options.stack_size = 1024 * 1024;
255  ASSERT(0 == uv_thread_join(&thread));
256 
257  options.stack_size = 8 * 1024 * 1024; /* larger than most default os sizes */
260  ASSERT(0 == uv_thread_join(&thread));
261 
262  options.stack_size = 0;
265  ASSERT(0 == uv_thread_join(&thread));
266 
267 #ifdef PTHREAD_STACK_MIN
268  options.stack_size = PTHREAD_STACK_MIN - 42; /* unaligned size */
271  ASSERT(0 == uv_thread_join(&thread));
272 
273  options.stack_size = PTHREAD_STACK_MIN / 2 - 42; /* unaligned size */
276  ASSERT(0 == uv_thread_join(&thread));
277 #endif
278 
279  /* unaligned size, should be larger than PTHREAD_STACK_MIN */
280  options.stack_size = 1234567;
283  ASSERT(0 == uv_thread_join(&thread));
284 
285  return 0;
286 }
thread_entry
static void thread_entry(void *arg)
Definition: test-thread.c:140
async_greeter_server_with_graceful_shutdown.loop
loop
Definition: async_greeter_server_with_graceful_shutdown.py:59
fs_req::loop
uv_loop_t * loop
Definition: test-thread.c:44
test_thread
Definition: test-thread.c:49
getaddrinfo_req::handle
uv_getaddrinfo_t handle
Definition: test-thread.c:37
ARRAY_SIZE
#define ARRAY_SIZE(array)
Definition: bloaty.cc:101
thread_stack_size
static size_t thread_stack_size(void)
Definition: libuv/src/unix/thread.c:171
thread_check_stack
static void thread_check_stack(void *arg)
Definition: test-thread.c:212
task.h
memset
return memset(p, 0, total)
getaddrinfo_req::thread_id
uv_thread_t thread_id
Definition: test-thread.c:34
getaddrinfo_req
Definition: test-thread.c:33
uv_fs_stat
UV_EXTERN int uv_fs_stat(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb)
Definition: unix/fs.c:1954
uv_getaddrinfo_s
Definition: uv.h:871
string.h
options
double_dict options[]
Definition: capstone_test.c:55
UV_THREAD_HAS_STACK_SIZE
@ UV_THREAD_HAS_STACK_SIZE
Definition: uv.h:1736
fs_req::counter
unsigned int counter
Definition: test-thread.c:43
uv_connect_s::handle
uv_stream_t * handle
Definition: uv.h:583
thread_called
static int thread_called
Definition: test-thread.c:61
ASSERT
#define ASSERT(expr)
Definition: task.h:102
getaddrinfo_req::loop
uv_loop_t * loop
Definition: test-thread.c:36
status
absl::Status status
Definition: rls.cc:251
setup.name
name
Definition: setup.py:542
uv_thread_join
UV_EXTERN int uv_thread_join(uv_thread_t *tid)
Definition: libuv/src/unix/thread.c:271
fs_req::thread_id
uv_thread_t thread_id
Definition: test-thread.c:42
uv_run
UV_EXTERN int uv_run(uv_loop_t *, uv_run_mode mode)
Definition: unix/core.c:361
container_of
#define container_of(ptr, type, member)
Definition: uv-common.h:57
uv_key_delete
UV_EXTERN void uv_key_delete(uv_key_t *key)
Definition: libuv/src/unix/thread.c:838
uv_fs_s
Definition: uv.h:1294
test_thread::thread_id
uv_thread_t thread_id
Definition: test-thread.c:50
threads
static uv_thread_t * threads
Definition: threadpool.c:38
uv_thread_options_s
Definition: uv.h:1739
TEST_IMPL
TEST_IMPL(thread_create)
Definition: test-thread.c:146
tid
int tid
Definition: fake_binder_test.cc:236
getaddrinfo_cb
static void getaddrinfo_cb(uv_getaddrinfo_t *handle, int status, struct addrinfo *res)
Definition: test-thread.c:78
fs_do
static void fs_do(struct fs_req *req)
Definition: test-thread.c:93
uv_loop_close
UV_EXTERN int uv_loop_close(uv_loop_t *loop)
Definition: uv-common.c:761
uv_key_get
UV_EXTERN void * uv_key_get(uv_key_t *key)
Definition: libuv/src/unix/thread.c:844
uv_key_t
Definition: win.h:284
fs_req
Definition: test-thread.c:41
req
static uv_connect_t req
Definition: test-connection-fail.c:30
UV_RUN_DEFAULT
@ UV_RUN_DEFAULT
Definition: uv.h:254
uv_thread_create_ex
UV_EXTERN int uv_thread_create_ex(uv_thread_t *tid, const uv_thread_options_t *params, uv_thread_cb entry, void *arg)
Definition: libuv/src/unix/thread.c:215
tls_key
static uv_key_t tls_key
Definition: test-thread.c:62
do_work
static void do_work(void *arg)
Definition: test-thread.c:111
arg
Definition: cmdline.cc:40
uv_loop_init
UV_EXTERN int uv_loop_init(uv_loop_t *loop)
Definition: loop.c:30
uv_thread_create
UV_EXTERN int uv_thread_create(uv_thread_t *tid, uv_thread_cb entry, void *arg)
Definition: libuv/src/unix/thread.c:209
fs_cb
static void fs_cb(uv_fs_t *handle)
Definition: test-thread.c:101
getaddrinfo_req::counter
unsigned int counter
Definition: test-thread.c:35
fs_req::handle
uv_fs_t handle
Definition: test-thread.c:45
uv_freeaddrinfo
UV_EXTERN void uv_freeaddrinfo(struct addrinfo *ai)
Definition: unix/getaddrinfo.c:223
uv.h
attr
OPENSSL_EXPORT X509_ATTRIBUTE * attr
Definition: x509.h:1666
thread_id
static uv_thread_t thread_id
Definition: benchmark-million-async.c:32
fix_build_deps.r
r
Definition: fix_build_deps.py:491
uv_key_set
UV_EXTERN void uv_key_set(uv_key_t *key, void *value)
Definition: libuv/src/unix/thread.c:849
arg
struct arg arg
test_thread::thread_called
int thread_called
Definition: test-thread.c:51
uv_getaddrinfo
UV_EXTERN int uv_getaddrinfo(uv_loop_t *loop, uv_getaddrinfo_t *req, uv_getaddrinfo_cb getaddrinfo_cb, const char *node, const char *service, const struct addrinfo *hints)
Definition: unix/getaddrinfo.c:141
uv_fs_req_cleanup
UV_EXTERN void uv_fs_req_cleanup(uv_fs_t *req)
Definition: unix/fs.c:2024
tls_thread
static void tls_thread(void *arg)
Definition: test-thread.c:187
handle
static csh handle
Definition: test_arm_regression.c:16
uv_thread_t
pthread_t uv_thread_t
Definition: unix.h:134
uv_loop_s
Definition: uv.h:1767
getaddrinfo_do
static void getaddrinfo_do(struct getaddrinfo_req *req)
Definition: test-thread.c:65
uv_key_create
UV_EXTERN int uv_key_create(uv_key_t *key)
Definition: libuv/src/unix/thread.c:833
addrinfo
Definition: ares_ipv6.h:43
thread
static uv_thread_t thread
Definition: test-async-null-cb.c:29
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230


grpc
Author(s):
autogenerated on Fri May 16 2025 03:00:27