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