]>
Commit | Line | Data |
---|---|---|
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 | ||
48 | typedef 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 | 62 | DISPATCH_ALWAYS_INLINE |
e85f4437 | 63 | static 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 | ||
86 | extern 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 | ||
95 | DISPATCH_ALWAYS_INLINE | |
e85f4437 | 96 | static 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 | ||
151 | static 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 | ||
165 | static 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 |
176 | static 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__ */ |