]>
git.saurik.com Git - apple/libdispatch.git/blob - src/shims/atomic_sfb.h
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_SHIMS_ATOMIC_SFB__
28 #define __DISPATCH_SHIMS_ATOMIC_SFB__
30 #if defined(__x86_64__) || defined(__i386__)
32 // Returns UINT_MAX if all the bits in p were already set.
33 DISPATCH_ALWAYS_INLINE
34 static inline unsigned int
35 os_atomic_set_first_bit(volatile unsigned long *p
, unsigned int max
)
37 unsigned long val
, bit
;
38 if (max
> (sizeof(val
) * 8)) {
41 "mov %[_p], %[_val] \n\t"
43 "bsf %[_val], %[_bit] \n\t" /* val is 0 => set zf */
46 "bts %[_bit], %[_p] \n\t" /* cf = prev bit val */
47 "jc 1b \n\t" /* lost race, retry */
50 "mov %[_all_ones], %[_bit]" "\n\t"
52 : [_p
] "=m" (*p
), [_val
] "=&r" (val
), [_bit
] "=&r" (bit
)
53 : [_all_ones
] "i" ((typeof(bit
))UINT_MAX
) : "memory", "cc");
57 "mov %[_p], %[_val] \n\t"
59 "bsf %[_val], %[_bit] \n\t" /* val is 0 => set zf */
61 "cmp %[_max], %[_bit] \n\t"
64 "bts %[_bit], %[_p] \n\t" /* cf = prev bit val */
65 "jc 1b \n\t" /* lost race, retry */
68 "mov %[_all_ones], %[_bit]" "\n\t"
70 : [_p
] "=m" (*p
), [_val
] "=&r" (val
), [_bit
] "=&r" (bit
)
71 : [_all_ones
] "i" ((typeof(bit
))UINT_MAX
),
72 [_max
] "g" ((typeof(bit
))max
) : "memory", "cc");
74 return (unsigned int)bit
;
79 #if __clang__ && __clang_major__ < 5 // <rdar://problem/13833871>
80 #define __builtin_ffs(x) __builtin_ffs((unsigned int)(x))
83 DISPATCH_ALWAYS_INLINE
84 static inline unsigned int
85 os_atomic_set_first_bit(volatile unsigned long *p
, unsigned int max_index
)
88 unsigned long b
, b_masked
;
90 os_atomic_rmw_loop(p
, b
, b_masked
, relaxed
, {
91 // ffs returns 1 + index, or 0 if none set
92 index
= (unsigned int)__builtin_ffsl((long)~b
);
93 if (slowpath(index
== 0)) {
94 os_atomic_rmw_loop_give_up(return UINT_MAX
);
97 if (slowpath(index
> max_index
)) {
98 os_atomic_rmw_loop_give_up(return UINT_MAX
);
100 b_masked
= b
| (1UL << index
);
108 #endif // __DISPATCH_SHIMS_ATOMIC_SFB__