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
32typedef 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
46DISPATCH_ALWAYS_INLINE
47static inline uint32_t
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
70extern 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
79DISPATCH_ALWAYS_INLINE
80static inline uint32_t
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(__APPLE__)
87	switch (c) {
88	case _dispatch_hw_config_logical_cpus:
89		name = "hw.logicalcpu_max"; break;
90	case _dispatch_hw_config_physical_cpus:
91		name = "hw.physicalcpu_max"; break;
92	case _dispatch_hw_config_active_cpus:
93		name = "hw.activecpu"; break;
94	}
95#elif defined(__FreeBSD__)
96	 (void)c; name = "kern.smp.cpus";
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
115static inline 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
129static inline long
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
140static inline uint32_t
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