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