xref: /dragonfly/usr.bin/dsynth/numa.c (revision 2b3f93ea)
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