xref: /NextBSD/lib/libdispatch/src/shims/hw_config.h (revision 33da5adc555b3bc29986eeadca03829e4ad06b1e)
1 /*
2  * Copyright (c) 2011-2013 Apple Inc. All rights reserved.
3  *
4  * @APPLE_APACHE_LICENSE_HEADER_START@
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * @APPLE_APACHE_LICENSE_HEADER_END@
19  */
20 
21 /*
22  * IMPORTANT: This header file describes INTERNAL interfaces to libdispatch
23  * which are subject to change in future releases of Mac OS X. Any applications
24  * relying on these interfaces WILL break.
25  */
26 
27 #ifndef __DISPATCH_SHIMS_HW_CONFIG__
28 #define __DISPATCH_SHIMS_HW_CONFIG__
29 
30 #if !TARGET_OS_WIN32
31 
32 typedef enum {
33 	_dispatch_hw_config_logical_cpus,
34 	_dispatch_hw_config_physical_cpus,
35 	_dispatch_hw_config_active_cpus,
36 } _dispatch_hw_config_t;
37 
38 #if !defined(DISPATCH_HAVE_HW_CONFIG_COMMPAGE) && \
39 		defined(_COMM_PAGE_LOGICAL_CPUS) && \
40 		defined(_COMM_PAGE_PHYSICAL_CPUS) && defined(_COMM_PAGE_ACTIVE_CPUS)
41 #define DISPATCH_HAVE_HW_CONFIG_COMMPAGE 1
42 #endif
43 
44 #if DISPATCH_HAVE_HW_CONFIG_COMMPAGE
45 
46 DISPATCH_ALWAYS_INLINE
47 static inline uint32_t
_dispatch_hw_get_config(_dispatch_hw_config_t c)48 _dispatch_hw_get_config(_dispatch_hw_config_t c)
49 {
50 	uintptr_t p;
51 	switch (c) {
52 	case _dispatch_hw_config_logical_cpus:
53 		p =  _COMM_PAGE_LOGICAL_CPUS; break;
54 	case _dispatch_hw_config_physical_cpus:
55 		p = _COMM_PAGE_PHYSICAL_CPUS; break;
56 	case _dispatch_hw_config_active_cpus:
57 		p = _COMM_PAGE_ACTIVE_CPUS; break;
58 	}
59 	return *(uint8_t*)p;
60 }
61 
62 #define dispatch_hw_config(c) \
63 		_dispatch_hw_get_config(_dispatch_hw_config_##c)
64 
65 #define DISPATCH_HW_CONFIG()
66 #define _dispatch_hw_config_init()
67 
68 #else // DISPATCH_HAVE_HW_CONFIG_COMMPAGE
69 
70 extern struct _dispatch_hw_configs_s {
71 	uint32_t logical_cpus;
72 	uint32_t physical_cpus;
73 	uint32_t active_cpus;
74 } _dispatch_hw_config;
75 
76 #define DISPATCH_HW_CONFIG() struct _dispatch_hw_configs_s _dispatch_hw_config
77 #define dispatch_hw_config(c) (_dispatch_hw_config.c)
78 
79 DISPATCH_ALWAYS_INLINE
80 static inline uint32_t
_dispatch_hw_get_config(_dispatch_hw_config_t c)81 _dispatch_hw_get_config(_dispatch_hw_config_t c)
82 {
83 	uint32_t val = 1;
84 	const char *name = NULL;
85 	int r;
86 #if defined(__FreeBSD__)
87 	(void)c; name = "kern.smp.cpus";
88 #elif defined(__APPLE__)
89 	switch (c) {
90 	case _dispatch_hw_config_logical_cpus:
91 		name = "hw.logicalcpu_max"; break;
92 	case _dispatch_hw_config_physical_cpus:
93 		name = "hw.physicalcpu_max"; break;
94 	case _dispatch_hw_config_active_cpus:
95 		name = "hw.activecpu"; break;
96 	}
97 #endif
98 	if (name) {
99 		size_t valsz = sizeof(val);
100 		r = sysctlbyname(name, &val, &valsz, NULL, 0);
101 		(void)dispatch_assume_zero(r);
102 		dispatch_assert(valsz == sizeof(uint32_t));
103 	} else {
104 #if HAVE_SYSCONF && defined(_SC_NPROCESSORS_ONLN)
105 		r = (int)sysconf(_SC_NPROCESSORS_ONLN);
106 		if (r > 0) val = (uint32_t)r;
107 #endif
108 	}
109 	return val;
110 }
111 
112 #define dispatch_hw_config_init(c) \
113 		_dispatch_hw_get_config(_dispatch_hw_config_##c)
114 
115 static inline void
_dispatch_hw_config_init(void)116 _dispatch_hw_config_init(void)
117 {
118 	dispatch_hw_config(logical_cpus) = dispatch_hw_config_init(logical_cpus);
119 	dispatch_hw_config(physical_cpus) = dispatch_hw_config_init(physical_cpus);
120 	dispatch_hw_config(active_cpus) = dispatch_hw_config_init(active_cpus);
121 }
122 
123 #undef dispatch_hw_config_init
124 
125 #endif // DISPATCH_HAVE_HW_CONFIG_COMMPAGE
126 
127 #else // TARGET_OS_WIN32
128 
129 static inline long
_dispatch_count_bits(unsigned long value)130 _dispatch_count_bits(unsigned long value)
131 {
132 	long bits = 0;
133 	while (value) {
134 		bits += (value & 1);
135 		value = value >> 1;
136 	}
137 	return bits;
138 }
139 
140 static inline uint32_t
_dispatch_get_ncpus(void)141 _dispatch_get_ncpus(void)
142 {
143 	uint32_t val;
144 	DWORD_PTR procmask, sysmask;
145 	if (GetProcessAffinityMask(GetCurrentProcess(), &procmask, &sysmask)) {
146 		val = _dispatch_count_bits(procmask);
147 	} else {
148 		val = 1;
149 	}
150 	return val;
151 }
152 #endif // TARGET_OS_WIN32
153 
154 #endif /* __DISPATCH_SHIMS_HW_CONFIG__ */
155