]> git.saurik.com Git - apple/libplatform.git/blob - include/os/lock.h
abc51096755736c9646db9488bc9d920874bc72b
[apple/libplatform.git] / include / os / lock.h
1 /*
2 * Copyright (c) 2016 Apple Inc. All rights reserved.
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 #ifndef __OS_LOCK__
22 #define __OS_LOCK__
23
24 #include <Availability.h>
25 #include <sys/cdefs.h>
26 #include <stddef.h>
27 #include <stdint.h>
28 #include <stdbool.h>
29 #include <os/base.h>
30
31 OS_ASSUME_NONNULL_BEGIN
32
33 /*! @header
34 * Low-level lock API.
35 */
36
37 #define OS_LOCK_API_VERSION 20160309
38
39 __BEGIN_DECLS
40
41 #define OS_UNFAIR_LOCK_AVAILABILITY \
42 __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) \
43 __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0)
44
45 /*!
46 * @typedef os_unfair_lock
47 *
48 * @abstract
49 * Low-level lock that allows waiters to block efficiently on contention.
50 *
51 * In general, higher level synchronization primitives such as those provided by
52 * the pthread or dispatch subsystems should be preferred.
53 *
54 * The values stored in the lock should be considered opaque and implementation
55 * defined, they contain thread ownership information that the system may use
56 * to attempt to resolve priority inversions.
57 *
58 * This lock must be unlocked from the same thread that locked it, attemps to
59 * unlock from a different thread will cause an assertion aborting the process.
60 *
61 * This lock must not be accessed from multiple processes or threads via shared
62 * or multiply-mapped memory, the lock implementation relies on the address of
63 * the lock value and owning process.
64 *
65 * Must be initialized with OS_UNFAIR_LOCK_INIT
66 *
67 * @discussion
68 * Replacement for the deprecated OSSpinLock. Does not spin on contention but
69 * waits in the kernel to be woken up by an unlock.
70 *
71 * As with OSSpinLock there is no attempt at fairness or lock ordering, e.g. an
72 * unlocker can potentially immediately reacquire the lock before a woken up
73 * waiter gets an opportunity to attempt to acquire the lock. This may be
74 * advantageous for performance reasons, but also makes starvation of waiters a
75 * possibility.
76 */
77 OS_UNFAIR_LOCK_AVAILABILITY
78 typedef struct os_unfair_lock_s {
79 uint32_t _os_unfair_lock_opaque;
80 } os_unfair_lock, *os_unfair_lock_t;
81
82 #ifndef OS_UNFAIR_LOCK_INIT
83 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
84 #define OS_UNFAIR_LOCK_INIT ((os_unfair_lock){0})
85 #elif defined(__cplusplus) && __cplusplus >= 201103L
86 #define OS_UNFAIR_LOCK_INIT (os_unfair_lock{})
87 #elif defined(__cplusplus)
88 #define OS_UNFAIR_LOCK_INIT (os_unfair_lock())
89 #else
90 #define OS_UNFAIR_LOCK_INIT {0}
91 #endif
92 #endif // OS_UNFAIR_LOCK_INIT
93
94 /*!
95 * @function os_unfair_lock_lock
96 *
97 * @abstract
98 * Locks an os_unfair_lock.
99 *
100 * @param lock
101 * Pointer to an os_unfair_lock.
102 */
103 OS_UNFAIR_LOCK_AVAILABILITY
104 OS_EXPORT OS_NOTHROW OS_NONNULL_ALL
105 void os_unfair_lock_lock(os_unfair_lock_t lock);
106
107 /*!
108 * @function os_unfair_lock_trylock
109 *
110 * @abstract
111 * Locks an os_unfair_lock if it is not already locked.
112 *
113 * @discussion
114 * It is invalid to surround this function with a retry loop, if this function
115 * returns false, the program must be able to proceed without having acquired
116 * the lock, or it must call os_unfair_lock_lock() directly (a retry loop around
117 * os_unfair_lock_trylock() amounts to an inefficient implementation of
118 * os_unfair_lock_lock() that hides the lock waiter from the system and prevents
119 * resolution of priority inversions).
120 *
121 * @param lock
122 * Pointer to an os_unfair_lock.
123 *
124 * @result
125 * Returns true if the lock was succesfully locked and false if the lock was
126 * already locked.
127 */
128 OS_UNFAIR_LOCK_AVAILABILITY
129 OS_EXPORT OS_NOTHROW OS_WARN_RESULT OS_NONNULL_ALL
130 bool os_unfair_lock_trylock(os_unfair_lock_t lock);
131
132 /*!
133 * @function os_unfair_lock_unlock
134 *
135 * @abstract
136 * Unlocks an os_unfair_lock.
137 *
138 * @param lock
139 * Pointer to an os_unfair_lock.
140 */
141 OS_UNFAIR_LOCK_AVAILABILITY
142 OS_EXPORT OS_NOTHROW OS_NONNULL_ALL
143 void os_unfair_lock_unlock(os_unfair_lock_t lock);
144
145 __END_DECLS
146
147 OS_ASSUME_NONNULL_END
148
149 #endif // __OS_LOCK__