1 /* Copyright libuv project 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 <string.h>
26
27 #ifndef NO_CPU_AFFINITY
28
check_affinity(void * arg)29 static void check_affinity(void* arg) {
30 int r;
31 char* cpumask;
32 int cpumasksize;
33 uv_thread_t tid;
34
35 cpumask = (char*)arg;
36 cpumasksize = uv_cpumask_size();
37 ASSERT_GT(cpumasksize, 0);
38 tid = uv_thread_self();
39 r = uv_thread_setaffinity(&tid, cpumask, NULL, cpumasksize);
40 ASSERT_OK(r);
41 r = uv_thread_setaffinity(&tid, cpumask + cpumasksize, cpumask, cpumasksize);
42 ASSERT_OK(r);
43 }
44
45
TEST_IMPL(thread_affinity)46 TEST_IMPL(thread_affinity) {
47 int t1first;
48 int t1second;
49 int t2first;
50 int t2second;
51 int cpumasksize;
52 char* cpumask;
53 int ncpus;
54 int r;
55 int c;
56 int i;
57 uv_thread_t threads[3];
58
59 #ifdef _WIN32
60 /* uv_thread_self isn't defined for the main thread on Windows */
61 threads[0] = GetCurrentThread();
62 #else
63 threads[0] = uv_thread_self();
64 #endif
65 cpumasksize = uv_cpumask_size();
66 ASSERT_GT(cpumasksize, 0);
67
68 cpumask = calloc(4 * cpumasksize, 1);
69 ASSERT(cpumask);
70
71 r = uv_thread_getaffinity(&threads[0], cpumask, cpumasksize);
72 ASSERT_OK(r);
73 ASSERT(cpumask[0] && "test must be run with cpu 0 affinity");
74 ncpus = 0;
75 while (cpumask[++ncpus]) { }
76 memset(cpumask, 0, 4 * cpumasksize);
77
78 t1first = cpumasksize * 0;
79 t1second = cpumasksize * 1;
80 t2first = cpumasksize * 2;
81 t2second = cpumasksize * 3;
82
83 cpumask[t1second + 0] = 1;
84 cpumask[t2first + 0] = 1;
85 cpumask[t1first + (ncpus >= 2)] = 1;
86 cpumask[t2second + (ncpus >= 2)] = 1;
87 #ifdef __linux__
88 cpumask[t1second + 2] = 1;
89 cpumask[t2first + 2] = 1;
90 cpumask[t1first + 3] = 1;
91 cpumask[t2second + 3] = 1;
92 #else
93 if (ncpus >= 3) {
94 cpumask[t1second + 2] = 1;
95 cpumask[t2first + 2] = 1;
96 }
97 if (ncpus >= 4) {
98 cpumask[t1first + 3] = 1;
99 cpumask[t2second + 3] = 1;
100 }
101 #endif
102
103 ASSERT_OK(uv_thread_create(threads + 1,
104 check_affinity,
105 &cpumask[t1first]));
106 ASSERT_OK(uv_thread_create(threads + 2,
107 check_affinity,
108 &cpumask[t2first]));
109 ASSERT_OK(uv_thread_join(threads + 1));
110 ASSERT_OK(uv_thread_join(threads + 2));
111
112 ASSERT(cpumask[t1first + 0] == (ncpus == 1));
113 ASSERT(cpumask[t1first + 1] == (ncpus >= 2));
114 ASSERT_OK(cpumask[t1first + 2]);
115 ASSERT(cpumask[t1first + 3] == (ncpus >= 4));
116
117 ASSERT_EQ(1, cpumask[t2first + 0]);
118 ASSERT_OK(cpumask[t2first + 1]);
119 ASSERT(cpumask[t2first + 2] == (ncpus >= 3));
120 ASSERT_OK(cpumask[t2first + 3]);
121
122 c = uv_thread_getcpu();
123 ASSERT_GE(c, 0);
124
125 memset(cpumask, 0, cpumasksize);
126 cpumask[c] = 1;
127 r = uv_thread_setaffinity(&threads[0], cpumask, NULL, cpumasksize);
128 ASSERT_OK(r);
129
130 memset(cpumask, 0, cpumasksize);
131 r = uv_thread_getaffinity(&threads[0], cpumask, cpumasksize);
132 ASSERT_OK(r);
133 for (i = 0; i < cpumasksize; i++) {
134 if (i == c)
135 ASSERT_EQ(1, cpumask[i]);
136 else
137 ASSERT_OK(cpumask[i]);
138 }
139
140 free(cpumask);
141
142 return 0;
143 }
144
145 #else
146
TEST_IMPL(thread_affinity)147 TEST_IMPL(thread_affinity) {
148 int cpumasksize;
149 cpumasksize = uv_cpumask_size();
150 ASSERT_EQ(cpumasksize, UV_ENOTSUP);
151 return 0;
152 }
153
154 #endif
155