2 * Copyright (c) 2018 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
27 #define PREREQUISITE_FULFILLED (~0u)
31 pthread_dependency_init_np(pthread_dependency_t
*pr
, pthread_t pth
,
32 pthread_dependency_attr_t
*attrs
)
34 if (attrs
) *(volatile char *)attrs
;
35 *pr
= (pthread_dependency_t
)PTHREAD_DEPENDENCY_INITIALIZER_NP(pth
);
40 _pthread_dependency_fulfill_slow(pthread_dependency_t
*pr
, uint32_t old
)
42 if (old
== PREREQUISITE_FULFILLED
) {
43 PTHREAD_CLIENT_CRASH(0, "Fufilling pthread_dependency_t twice");
45 if (os_unlikely(old
!= _pthread_mach_thread_self_direct())) {
46 PTHREAD_CLIENT_CRASH(old
, "Fulfilled a dependency "
47 "not owned by current thread");
50 int ret
= __ulock_wake(UL_UNFAIR_LOCK
| ULF_NO_ERRNO
, &pr
->__pdep_opaque1
, 0);
56 PTHREAD_INTERNAL_CRASH(-ret
, "__ulock_wake() failed");
61 PTHREAD_NOEXPORT_VARIANT
63 pthread_dependency_fulfill_np(pthread_dependency_t
*pr
, void *value
)
67 pr
->__pdep_opaque2
= (uint64_t)(uintptr_t)value
;
68 old
= os_atomic_xchg(&pr
->__pdep_opaque1
, PREREQUISITE_FULFILLED
, release
);
70 if (old
!= 0) _pthread_dependency_fulfill_slow(pr
, old
);
73 PTHREAD_NOEXPORT_VARIANT
75 pthread_dependency_wait_np(pthread_dependency_t
*pr
)
77 if (os_atomic_cmpxchg(&pr
->__pdep_opaque1
, 0, pr
->__pdep_owner
, relaxed
)) {
80 ret
= __ulock_wait(UL_UNFAIR_LOCK
| ULF_NO_ERRNO
, &pr
->__pdep_opaque1
,
86 if (pr
->__pdep_opaque1
== pr
->__pdep_owner
) goto again
;
89 PTHREAD_CLIENT_CRASH(pr
->__pdep_owner
, "Waiting on orphaned dependency");
91 PTHREAD_CLIENT_CRASH(-ret
, "__ulock_wait() failed");
95 uint32_t cur
= os_atomic_load(&pr
->__pdep_opaque1
, acquire
);
96 if (cur
== PREREQUISITE_FULFILLED
) {
97 return (void *)(uintptr_t)pr
->__pdep_opaque2
;
99 PTHREAD_CLIENT_CRASH(cur
, "Corrupted pthread_dependency_t");
102 PTHREAD_NOEXPORT_VARIANT
void*
103 _pthread_atomic_xchg_ptr(void **p
, void *v
)
105 return os_atomic_xchg(p
, v
, seq_cst
);
108 PTHREAD_NOEXPORT_VARIANT
uint32_t
109 _pthread_atomic_xchg_uint32_relaxed(uint32_t *p
, uint32_t v
)
111 return os_atomic_xchg(p
, v
, relaxed
);
114 #endif // !VARIANT_DYLD