]> git.saurik.com Git - apple/libdispatch.git/blame - src/shims/hw_config.h
libdispatch-913.30.4.tar.gz
[apple/libdispatch.git] / src / shims / hw_config.h
CommitLineData
e85f4437 1/*
98cf8cd2 2 * Copyright (c) 2011-2013 Apple Inc. All rights reserved.
e85f4437
A
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
6b746eb4
A
30#ifdef __SIZEOF_POINTER__
31#define DISPATCH_SIZEOF_PTR __SIZEOF_POINTER__
32#elif defined(_WIN64)
33#define DISPATCH_SIZEOF_PTR 8
34#elif defined(_WIN32)
35#define DISPATCH_SIZEOF_PTR 4
36#elif defined(_MSC_VER)
37#error "could not determine pointer size as a constant int for MSVC"
38#elif defined(__LP64__) || defined(__LLP64__)
39#define DISPATCH_SIZEOF_PTR 8
40#elif defined(__ILP32__)
41#define DISPATCH_SIZEOF_PTR 4
42#else
43#error "could not determine pointer size as a constant int"
44#endif // __SIZEOF_POINTER__
45
98cf8cd2
A
46#if !TARGET_OS_WIN32
47
48typedef enum {
49 _dispatch_hw_config_logical_cpus,
50 _dispatch_hw_config_physical_cpus,
51 _dispatch_hw_config_active_cpus,
52} _dispatch_hw_config_t;
53
54#if !defined(DISPATCH_HAVE_HW_CONFIG_COMMPAGE) && \
55 defined(_COMM_PAGE_LOGICAL_CPUS) && \
56 defined(_COMM_PAGE_PHYSICAL_CPUS) && defined(_COMM_PAGE_ACTIVE_CPUS)
57#define DISPATCH_HAVE_HW_CONFIG_COMMPAGE 1
e85f4437
A
58#endif
59
98cf8cd2 60#if DISPATCH_HAVE_HW_CONFIG_COMMPAGE
517da941 61
98cf8cd2 62DISPATCH_ALWAYS_INLINE
e85f4437 63static inline uint32_t
98cf8cd2 64_dispatch_hw_get_config(_dispatch_hw_config_t c)
e85f4437 65{
98cf8cd2
A
66 uintptr_t p;
67 switch (c) {
68 case _dispatch_hw_config_logical_cpus:
69 p = _COMM_PAGE_LOGICAL_CPUS; break;
70 case _dispatch_hw_config_physical_cpus:
71 p = _COMM_PAGE_PHYSICAL_CPUS; break;
72 case _dispatch_hw_config_active_cpus:
73 p = _COMM_PAGE_ACTIVE_CPUS; break;
74 }
75 return *(uint8_t*)p;
e85f4437
A
76}
77
98cf8cd2
A
78#define dispatch_hw_config(c) \
79 _dispatch_hw_get_config(_dispatch_hw_config_##c)
80
81#define DISPATCH_HW_CONFIG()
82#define _dispatch_hw_config_init()
83
84#else // DISPATCH_HAVE_HW_CONFIG_COMMPAGE
85
86extern struct _dispatch_hw_configs_s {
87 uint32_t logical_cpus;
88 uint32_t physical_cpus;
89 uint32_t active_cpus;
90} _dispatch_hw_config;
91
92#define DISPATCH_HW_CONFIG() struct _dispatch_hw_configs_s _dispatch_hw_config
93#define dispatch_hw_config(c) (_dispatch_hw_config.c)
94
95DISPATCH_ALWAYS_INLINE
e85f4437 96static inline uint32_t
98cf8cd2 97_dispatch_hw_get_config(_dispatch_hw_config_t c)
e85f4437
A
98{
99 uint32_t val = 1;
beb15981
A
100#if defined(__linux__) && HAVE_SYSCONF
101 switch (c) {
102 case _dispatch_hw_config_logical_cpus:
103 case _dispatch_hw_config_physical_cpus:
6b746eb4 104 return (uint32_t)sysconf(_SC_NPROCESSORS_CONF);
beb15981 105 case _dispatch_hw_config_active_cpus:
6b746eb4
A
106 {
107#ifdef __USE_GNU
108 // Prefer pthread_getaffinity_np because it considers
109 // scheduler cpu affinity. This matters if the program
110 // is restricted to a subset of the online cpus (eg via numactl).
111 cpu_set_t cpuset;
112 if (pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset) == 0)
113 return (uint32_t)CPU_COUNT(&cpuset);
114#endif
115 return (uint32_t)sysconf(_SC_NPROCESSORS_ONLN);
116 }
beb15981
A
117 }
118#else
98cf8cd2
A
119 const char *name = NULL;
120 int r;
121#if defined(__APPLE__)
122 switch (c) {
123 case _dispatch_hw_config_logical_cpus:
124 name = "hw.logicalcpu_max"; break;
125 case _dispatch_hw_config_physical_cpus:
126 name = "hw.physicalcpu_max"; break;
127 case _dispatch_hw_config_active_cpus:
128 name = "hw.activecpu"; break;
129 }
130#elif defined(__FreeBSD__)
131 (void)c; name = "kern.smp.cpus";
e85f4437 132#endif
98cf8cd2
A
133 if (name) {
134 size_t valsz = sizeof(val);
135 r = sysctlbyname(name, &val, &valsz, NULL, 0);
136 (void)dispatch_assume_zero(r);
137 dispatch_assert(valsz == sizeof(uint32_t));
138 } else {
139#if HAVE_SYSCONF && defined(_SC_NPROCESSORS_ONLN)
140 r = (int)sysconf(_SC_NPROCESSORS_ONLN);
141 if (r > 0) val = (uint32_t)r;
142#endif
143 }
beb15981 144#endif
e85f4437
A
145 return val;
146}
147
98cf8cd2
A
148#define dispatch_hw_config_init(c) \
149 _dispatch_hw_get_config(_dispatch_hw_config_##c)
150
151static inline void
152_dispatch_hw_config_init(void)
e85f4437 153{
98cf8cd2
A
154 dispatch_hw_config(logical_cpus) = dispatch_hw_config_init(logical_cpus);
155 dispatch_hw_config(physical_cpus) = dispatch_hw_config_init(physical_cpus);
156 dispatch_hw_config(active_cpus) = dispatch_hw_config_init(active_cpus);
e85f4437
A
157}
158
98cf8cd2
A
159#undef dispatch_hw_config_init
160
161#endif // DISPATCH_HAVE_HW_CONFIG_COMMPAGE
162
517da941
A
163#else // TARGET_OS_WIN32
164
165static inline long
166_dispatch_count_bits(unsigned long value)
167{
168 long bits = 0;
169 while (value) {
170 bits += (value & 1);
171 value = value >> 1;
172 }
173 return bits;
174}
175
517da941
A
176static inline uint32_t
177_dispatch_get_ncpus(void)
178{
179 uint32_t val;
180 DWORD_PTR procmask, sysmask;
181 if (GetProcessAffinityMask(GetCurrentProcess(), &procmask, &sysmask)) {
182 val = _dispatch_count_bits(procmask);
183 } else {
184 val = 1;
185 }
186 return val;
187}
188#endif // TARGET_OS_WIN32
189
e85f4437 190#endif /* __DISPATCH_SHIMS_HW_CONFIG__ */