1 /* 2 * Copyright (c) 2022 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@backplane.com> 6 * 7 * This code uses concepts and configuration based on 'synth', by 8 * John R. Marino <draco@marino.st>, which was written in ada. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 3. Neither the name of The DragonFly Project nor the names of its 21 * contributors may be used to endorse or promote products derived 22 * from this software without specific, prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 28 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 29 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 32 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 33 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 34 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 */ 37 /* 38 * Put builders into (numa) cpu domains to improve cache interactions 39 * (This is totally optional) 40 */ 41 #include "dsynth.h" 42 43 /* 44 * Number of NUMA domains or integral multiple of same. Recommend a 45 * value of 0 (disabled), 2 or 4. Set with Numa_setsize parameter. 46 */ 47 int NumaSetSize = 0; 48 49 /* 50 * Set the domain for the given slot number. -1 == reset to default. 51 */ 52 void 53 setNumaDomain(int slot) 54 { 55 static int numa_initialized; 56 static cpu_set_t defset; 57 58 /* 59 * Auto-initialization (0) -> Enabled (1) or Disabled (-1) 60 */ 61 if (numa_initialized == 0) { 62 if (NumaSetSize <= 1) { 63 /* 64 * Disabled 65 */ 66 numa_initialized = -1; 67 } else if (pthread_getaffinity_np(pthread_self(), 68 sizeof(defset), &defset) != 0) 69 { 70 /* 71 * Missing pthreads support 72 */ 73 dlog(DLOG_ALL, 74 "Warning: pthread_*affinity*() " 75 "not supported\n"); 76 numa_initialized = -1; 77 } else { 78 /* 79 * Operational, default set saved 80 */ 81 numa_initialized = 1; 82 } 83 } 84 85 /* 86 * Do nothing if disabled 87 */ 88 if (numa_initialized < 0) 89 return; 90 91 /* 92 * Set domain for requested slot number or -1 to return to default 93 */ 94 if (slot < 0) { 95 /* 96 * Return to default 97 */ 98 pthread_setaffinity_np(pthread_self(), sizeof(defset), &defset); 99 } else if (NumCores <= NumaSetSize * 2) { 100 /* 101 * Not enough cores to partition 102 */ 103 /* do nothing */ 104 } else { 105 /* 106 * Set cpumask to N-way partitioned mask of cpu threads, 107 * hopefully in the same NUMA domain. 108 * 109 * XXX hacked for the moment to assume a simple partitioning 110 * in linear blocks of cores, with the second half of the 111 * cpu space being the related sibling hyperthreads. 112 */ 113 cpu_set_t cpuset; 114 int hcores = NumCores / 2; 115 int count = (hcores + NumaSetSize - 1) / NumaSetSize; 116 int i; 117 118 slot = slot % NumaSetSize; 119 slot *= count; 120 slot %= hcores; 121 CPU_ZERO(&cpuset); 122 for (i = 0; i < count; ++i) { 123 CPU_SET(slot + i, &cpuset); 124 CPU_SET(slot + hcores + i, &cpuset); 125 } 126 pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset); 127 } 128 } 129