+#pragma mark -
+#pragma mark os_unfair_recursive_lock
+
+OS_ATOMIC_EXPORT
+void os_unfair_recursive_lock_lock_with_options(os_unfair_recursive_lock_t lock,
+ os_unfair_lock_options_t options);
+
+OS_ATOMIC_EXPORT
+bool os_unfair_recursive_lock_trylock(os_unfair_recursive_lock_t lock);
+
+OS_ATOMIC_EXPORT
+void os_unfair_recursive_lock_unlock(os_unfair_recursive_lock_t lock);
+
+OS_ATOMIC_EXPORT
+bool os_unfair_recursive_lock_tryunlock4objc(os_unfair_recursive_lock_t lock);
+
+
+static inline os_lock_owner_t
+_os_unfair_lock_owner(os_unfair_lock_t lock)
+{
+ _os_unfair_lock_t l = (_os_unfair_lock_t)lock;
+ return OS_ULOCK_OWNER(os_atomic_load(&l->oul_value, relaxed));
+}
+
+void
+os_unfair_recursive_lock_lock_with_options(os_unfair_recursive_lock_t lock,
+ os_unfair_lock_options_t options)
+{
+ os_lock_owner_t cur, self = _os_lock_owner_get_self();
+ _os_unfair_lock_t l = (_os_unfair_lock_t)&lock->ourl_lock;
+
+ if (likely(os_atomic_cmpxchgv2o(l, oul_value,
+ OS_LOCK_NO_OWNER, self, &cur, acquire))) {
+ return;
+ }
+
+ if (OS_ULOCK_OWNER(cur) == self) {
+ lock->ourl_count++;
+ return;
+ }
+
+ return _os_unfair_lock_lock_slow(l, self, options);
+}
+
+bool
+os_unfair_recursive_lock_trylock(os_unfair_recursive_lock_t lock)
+{
+ os_lock_owner_t cur, self = _os_lock_owner_get_self();
+ _os_unfair_lock_t l = (_os_unfair_lock_t)&lock->ourl_lock;
+
+ if (likely(os_atomic_cmpxchgv2o(l, oul_value,
+ OS_LOCK_NO_OWNER, self, &cur, acquire))) {
+ return true;
+ }
+
+ if (likely(OS_ULOCK_OWNER(cur) == self)) {
+ lock->ourl_count++;
+ return true;
+ }
+
+ return false;
+}
+
+
+OS_ALWAYS_INLINE
+static inline void
+_os_unfair_recursive_lock_unlock(os_unfair_recursive_lock_t lock,
+ os_lock_owner_t self)
+{
+ if (unlikely(lock->ourl_count)) {
+ os_lock_owner_t cur = _os_unfair_lock_owner(&lock->ourl_lock);
+ if (unlikely(cur != self)) {
+ _os_unfair_lock_unowned_abort(cur);
+ }
+ lock->ourl_count--;
+ return;
+ }
+
+ _os_unfair_lock_t l = (_os_unfair_lock_t)lock;
+ os_ulock_value_t current;
+ current = os_atomic_xchg2o(l, oul_value, OS_LOCK_NO_OWNER, release);
+ if (likely(current == self)) return;
+ return _os_unfair_lock_unlock_slow(l, current, self, 0);
+}
+
+void
+os_unfair_recursive_lock_unlock(os_unfair_recursive_lock_t lock)
+{
+ os_lock_owner_t self = _os_lock_owner_get_self();
+ _os_unfair_recursive_lock_unlock(lock, self);
+}
+
+bool
+os_unfair_recursive_lock_tryunlock4objc(os_unfair_recursive_lock_t lock)
+{
+ os_lock_owner_t cur = _os_unfair_lock_owner(&lock->ourl_lock);
+ os_lock_owner_t self = _os_lock_owner_get_self();
+ if (likely(cur == self)) {
+ _os_unfair_recursive_lock_unlock(lock, self);
+ return true;
+ }
+ return false;
+}
+
+