2 * Copyright (c) 2012-2013 Apple Inc. All rights reserved.
4 * @APPLE_APACHE_LICENSE_HEADER_START@
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @APPLE_APACHE_LICENSE_HEADER_END@
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.
27 #ifndef __DISPATCH_ALLOCATOR_INTERNAL__
28 #define __DISPATCH_ALLOCATOR_INTERNAL__
30 #ifndef DISPATCH_ALLOCATOR
31 #if TARGET_OS_MAC && (defined(__LP64__) || TARGET_OS_EMBEDDED)
32 #define DISPATCH_ALLOCATOR 1
36 #ifndef DISPATCH_USE_NANOZONE
37 #if TARGET_OS_MAC && defined(__LP64__)
38 #define DISPATCH_USE_NANOZONE 1
42 #ifndef DISPATCH_USE_MALLOCZONE
43 #if (TARGET_OS_MAC && !DISPATCH_USE_NANOZONE) || \
44 (!TARGET_OS_MAC && HAVE_MALLOC_CREATE_ZONE)
45 #define DISPATCH_USE_MALLOCZONE 1
49 #ifndef DISPATCH_CONTINUATION_MALLOC
50 #if DISPATCH_USE_NANOZONE || !DISPATCH_ALLOCATOR
51 #define DISPATCH_CONTINUATION_MALLOC 1
55 #if !DISPATCH_ALLOCATOR && !DISPATCH_CONTINUATION_MALLOC
56 #error Invalid allocator configuration
59 #if DISPATCH_ALLOCATOR && DISPATCH_CONTINUATION_MALLOC
60 #define DISPATCH_ALLOC_NOINLINE DISPATCH_NOINLINE
62 #define DISPATCH_ALLOC_NOINLINE
66 #pragma mark DISPATCH_ALLOCATOR
68 #if DISPATCH_ALLOCATOR
70 // Configuration here!
71 #define NUM_CPU dispatch_hw_config(logical_cpus)
72 #define MAGAZINES_PER_HEAP (NUM_CPU)
74 // Do you care about compaction or performance?
75 #if TARGET_OS_EMBEDDED
76 #define PACK_FIRST_PAGE_WITH_CONTINUATIONS 1
78 #define PACK_FIRST_PAGE_WITH_CONTINUATIONS 0
82 #define PAGE_MAX_SIZE PAGE_SIZE
85 #define PAGE_MAX_MASK PAGE_MASK
87 #define DISPATCH_ALLOCATOR_PAGE_SIZE PAGE_MAX_SIZE
88 #define DISPATCH_ALLOCATOR_PAGE_MASK PAGE_MAX_MASK
91 #if TARGET_OS_EMBEDDED
92 #define PAGES_PER_MAGAZINE 64
94 #define PAGES_PER_MAGAZINE 512
97 // Use the largest type your platform is comfortable doing atomic ops with.
98 // TODO: rdar://11477843
99 typedef unsigned long bitmap_t
;
100 #if defined(__LP64__)
101 #define BYTES_PER_BITMAP 8
103 #define BYTES_PER_BITMAP 4
106 #define BITMAP_C(v) ((bitmap_t)(v))
107 #define BITMAP_ALL_ONES (~BITMAP_C(0))
111 #define CONTINUATIONS_PER_BITMAP (BYTES_PER_BITMAP * 8)
112 #define BITMAPS_PER_SUPERMAP (BYTES_PER_SUPERMAP * 8)
114 #define BYTES_PER_MAGAZINE (PAGES_PER_MAGAZINE * DISPATCH_ALLOCATOR_PAGE_SIZE)
115 #define CONSUMED_BYTES_PER_BITMAP (BYTES_PER_BITMAP + \
116 (DISPATCH_CONTINUATION_SIZE * CONTINUATIONS_PER_BITMAP))
118 #define BYTES_PER_SUPERMAP BYTES_PER_BITMAP
119 #define CONSUMED_BYTES_PER_SUPERMAP (BYTES_PER_SUPERMAP + \
120 (BITMAPS_PER_SUPERMAP * CONSUMED_BYTES_PER_BITMAP))
122 #define BYTES_PER_HEAP (BYTES_PER_MAGAZINE * MAGAZINES_PER_HEAP)
124 #define BYTES_PER_PAGE DISPATCH_ALLOCATOR_PAGE_SIZE
125 #define CONTINUATIONS_PER_PAGE (BYTES_PER_PAGE / DISPATCH_CONTINUATION_SIZE)
126 #define BITMAPS_PER_PAGE (CONTINUATIONS_PER_PAGE / CONTINUATIONS_PER_BITMAP)
128 // Assumption: metadata will be only in the first page.
129 #define SUPERMAPS_PER_MAGAZINE ((BYTES_PER_MAGAZINE - BYTES_PER_PAGE) / \
130 CONSUMED_BYTES_PER_SUPERMAP)
131 #define BITMAPS_PER_MAGAZINE (SUPERMAPS_PER_MAGAZINE * BITMAPS_PER_SUPERMAP)
132 #define CONTINUATIONS_PER_MAGAZINE \
133 (BITMAPS_PER_MAGAZINE * CONTINUATIONS_PER_BITMAP)
135 #define HEAP_MASK (~(uintptr_t)(BYTES_PER_HEAP - 1))
136 #define MAGAZINE_MASK (~(uintptr_t)(BYTES_PER_MAGAZINE - 1))
138 // this will round up such that first_bitmap_in_same_page() can mask the address
139 // of a bitmap_t in the maps to obtain the first bitmap for that same page
140 #define ROUND_UP_TO_BITMAP_ALIGNMENT(x) \
141 (((x) + ((BITMAPS_PER_PAGE * BYTES_PER_BITMAP) - 1u)) & \
142 ~((BITMAPS_PER_PAGE * BYTES_PER_BITMAP) - 1u))
143 // Since these are both powers of two, we end up with not only the max alignment,
144 // but happily the least common multiple, which will be the greater of the two.
145 #define ROUND_UP_TO_BITMAP_ALIGNMENT_AND_CONTINUATION_SIZE(x) (ROUND_UP_TO_CONTINUATION_SIZE(ROUND_UP_TO_BITMAP_ALIGNMENT(x)))
146 #define PADDING_TO_BITMAP_ALIGNMENT_AND_CONTINUATION_SIZE(x) (ROUND_UP_TO_BITMAP_ALIGNMENT_AND_CONTINUATION_SIZE(x) - (x))
148 #define PADDING_TO_CONTINUATION_SIZE(x) (ROUND_UP_TO_CONTINUATION_SIZE(x) - (x))
150 #if defined(__LP64__)
151 #define SIZEOF_HEADER 16
153 #define SIZEOF_HEADER 8
156 #define SIZEOF_SUPERMAPS (BYTES_PER_SUPERMAP * SUPERMAPS_PER_MAGAZINE)
157 #define SIZEOF_MAPS (BYTES_PER_BITMAP * BITMAPS_PER_SUPERMAP * \
158 SUPERMAPS_PER_MAGAZINE)
160 // header is expected to end on supermap's required alignment
161 #define HEADER_TO_SUPERMAPS_PADDING 0
162 // we want to align the maps to a continuation size, but we must also have proper padding
163 // so that we can perform first_bitmap_in_same_page()
164 #define SUPERMAPS_TO_MAPS_PADDING (PADDING_TO_BITMAP_ALIGNMENT_AND_CONTINUATION_SIZE( \
165 SIZEOF_SUPERMAPS + HEADER_TO_SUPERMAPS_PADDING + SIZEOF_HEADER))
167 #define MAPS_TO_FPMAPS_PADDING (PADDING_TO_CONTINUATION_SIZE(SIZEOF_MAPS))
169 #define BYTES_LEFT_IN_FIRST_PAGE (BYTES_PER_PAGE - \
170 (SIZEOF_HEADER + HEADER_TO_SUPERMAPS_PADDING + SIZEOF_SUPERMAPS + \
171 SUPERMAPS_TO_MAPS_PADDING + SIZEOF_MAPS + MAPS_TO_FPMAPS_PADDING))
173 #if PACK_FIRST_PAGE_WITH_CONTINUATIONS
175 #define FULL_BITMAPS_IN_FIRST_PAGE \
176 (BYTES_LEFT_IN_FIRST_PAGE / CONSUMED_BYTES_PER_BITMAP)
177 #define REMAINDER_IN_FIRST_PAGE (BYTES_LEFT_IN_FIRST_PAGE - \
178 (FULL_BITMAPS_IN_FIRST_PAGE * CONSUMED_BYTES_PER_BITMAP) - \
179 (FULL_BITMAPS_IN_FIRST_PAGE ? 0 : \
180 ROUND_UP_TO_CONTINUATION_SIZE(BYTES_PER_BITMAP)))
182 #define REMAINDERED_CONTINUATIONS_IN_FIRST_PAGE \
183 (REMAINDER_IN_FIRST_PAGE / DISPATCH_CONTINUATION_SIZE)
184 #define CONTINUATIONS_IN_FIRST_PAGE (FULL_BITMAPS_IN_FIRST_PAGE * \
185 CONTINUATIONS_PER_BITMAP) + REMAINDERED_CONTINUATIONS_IN_FIRST_PAGE
186 #define BITMAPS_IN_FIRST_PAGE (FULL_BITMAPS_IN_FIRST_PAGE + \
187 (REMAINDERED_CONTINUATIONS_IN_FIRST_PAGE == 0 ? 0 : 1))
189 #define FPMAPS_TO_FPCONTS_PADDING (PADDING_TO_CONTINUATION_SIZE(\
190 BYTES_PER_BITMAP * BITMAPS_IN_FIRST_PAGE))
192 #else // PACK_FIRST_PAGE_WITH_CONTINUATIONS
194 #define MAPS_TO_CONTS_PADDING BYTES_LEFT_IN_FIRST_PAGE
196 #endif // PACK_FIRST_PAGE_WITH_CONTINUATIONS
198 #define AFTER_CONTS_PADDING (BYTES_PER_MAGAZINE - (BYTES_PER_PAGE + \
199 (DISPATCH_CONTINUATION_SIZE * CONTINUATIONS_PER_MAGAZINE)))
201 // This is the object our allocator allocates: a chunk of memory rounded up
202 // from sizeof(struct dispatch_continuation_s) to the cacheline size, so
203 // unrelated continuations don't share cachelines. It'd be nice if
204 // dispatch_continuation_s included this rounding/padding, but it doesn't.
205 typedef char padded_continuation
[DISPATCH_CONTINUATION_SIZE
];
207 // A dispatch_heap_t is the base address of an array of dispatch_magazine_s,
208 // one magazine per CPU.
209 typedef struct dispatch_magazine_s
* dispatch_heap_t
;
211 struct dispatch_magazine_header_s
{
212 // Link to the next heap in the chain. Only used in magazine 0's header
213 dispatch_heap_t dh_next
;
215 // Points to the first bitmap in the page where this CPU successfully
216 // allocated a continuation last time. Only used in the first heap.
217 bitmap_t
*last_found_page
;
220 // A magazine is a complex data structure. It must be exactly
221 // PAGES_PER_MAGAZINE * PAGE_SIZE bytes long, and that value must be a
222 // power of 2. (See magazine_for_continuation()).
223 struct dispatch_magazine_s
{
225 struct dispatch_magazine_header_s header
;
227 // Align supermaps as needed.
228 #if HEADER_TO_SUPERMAPS_PADDING > 0
229 char _pad0
[HEADER_TO_SUPERMAPS_PADDING
];
232 // Second-level bitmap; each set bit means a bitmap_t in maps[][]
233 // is completely full (and can be skipped while searching).
234 bitmap_t supermaps
[SUPERMAPS_PER_MAGAZINE
];
236 // Align maps to a cacheline.
237 #if SUPERMAPS_TO_MAPS_PADDING > 0
238 char _pad1
[SUPERMAPS_TO_MAPS_PADDING
];
241 // Each bit in maps[][] is the free/used state of a member of conts[][][].
242 bitmap_t maps
[SUPERMAPS_PER_MAGAZINE
][BITMAPS_PER_SUPERMAP
];
244 // Align fp_maps to a cacheline.
245 #if MAPS_TO_FPMAPS_PADDING > 0
246 char _pad2
[MAPS_TO_FPMAPS_PADDING
];
249 #if PACK_FIRST_PAGE_WITH_CONTINUATIONS
250 // Bitmaps for the continuations that live in the first page, which
251 // are treated specially (they have faster search code).
252 bitmap_t fp_maps
[BITMAPS_IN_FIRST_PAGE
];
254 // Align fp_conts to cacheline.
255 #if FPMAPS_TO_FPCONTS_PADDING > 0
256 char _pad3
[FPMAPS_TO_FPCONTS_PADDING
];
259 // Continuations that live in the first page.
260 padded_continuation fp_conts
[CONTINUATIONS_IN_FIRST_PAGE
];
262 #else // PACK_FIRST_PAGE_WITH_CONTINUATIONS
264 #if MAPS_TO_CONTS_PADDING > 0
265 char _pad4
[MAPS_TO_CONTS_PADDING
];
267 #endif // PACK_FIRST_PAGE_WITH_CONTINUATIONS
269 // This is the big array of continuations.
270 // This must start on a page boundary.
271 padded_continuation conts
[SUPERMAPS_PER_MAGAZINE
][BITMAPS_PER_SUPERMAP
]
272 [CONTINUATIONS_PER_BITMAP
];
274 // Fill the unused space to exactly BYTES_PER_MAGAZINE
275 #if AFTER_CONTS_PADDING > 0
276 char _pad5
[AFTER_CONTS_PADDING
];
281 #define DISPATCH_ALLOCATOR_SCRIBBLE ((uintptr_t)0xAFAFAFAFAFAFAFAF)
284 #endif // DISPATCH_ALLOCATOR
286 #endif // __DISPATCH_ALLOCATOR_INTERNAL__