int
___pthread_mutex_unlock (pthread_mutex_t *mutex)
{
return __pthread_mutex_unlock_usercnt (mutex, 1);
}
libc_hidden_ver (___pthread_mutex_unlock, __pthread_mutex_unlock)
int
__pthread_mutex_unlock_usercnt (pthread_mutex_t *mutex, int decr)
{
/* See concurrency notes regarding mutex type which is loaded from __kind
in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */
int type = PTHREAD_MUTEX_TYPE_ELISION (mutex);
if (__builtin_expect (type
& ~(PTHREAD_MUTEX_KIND_MASK_NP
|PTHREAD_MUTEX_ELISION_FLAGS_NP), 0))
return __pthread_mutex_unlock_full (mutex, decr);
if (__builtin_expect (type, PTHREAD_MUTEX_TIMED_NP)
== PTHREAD_MUTEX_TIMED_NP)
{
/* Always reset the owner field. */
normal:
mutex->__data.__owner = 0;
if (decr)
/* One less user. */
--mutex->__data.__nusers;
/* Unlock. */
lll_mutex_unlock_optimized (mutex);
LIBC_PROBE (mutex_release, 1, mutex);
return 0;
}
else if (__glibc_likely (type == PTHREAD_MUTEX_TIMED_ELISION_NP))
{
/* Don't reset the owner/users fields for elision. */
return lll_unlock_elision (mutex->__data.__lock, mutex->__data.__elision,
PTHREAD_MUTEX_PSHARED (mutex));
}
else if (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex)
== PTHREAD_MUTEX_RECURSIVE_NP, 1))
{
/* Recursive mutex. */
if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
return EPERM;
if (--mutex->__data.__count != 0)
/* We still hold the mutex. */
return 0;
goto normal;
}
else if (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex)
== PTHREAD_MUTEX_ADAPTIVE_NP, 1))
goto normal;
else
{
/* Error checking mutex. */
assert (type == PTHREAD_MUTEX_ERRORCHECK_NP);
if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid)
|| ! lll_islocked (mutex->__data.__lock))
return EPERM;
goto normal;
}
}
libc_hidden_def (__pthread_mutex_unlock_usercnt)
static int
__pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr)
{
int newowner = 0;
int private;
switch (PTHREAD_MUTEX_TYPE (mutex))
{
case PTHREAD_MUTEX_ROBUST_RECURSIVE_NP:
/* Recursive mutex. */
if ((mutex->__data.__lock & FUTEX_TID_MASK)
== THREAD_GETMEM (THREAD_SELF, tid)
&& __builtin_expect (mutex->__data.__owner
== PTHREAD_MUTEX_INCONSISTENT, 0))
{
if (--mutex->__data.__count != 0)
/* We still hold the mutex. */
return ENOTRECOVERABLE;
goto notrecoverable;
}
if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
return EPERM;
if (--mutex->__data.__count != 0)
/* We still hold the mutex. */
return 0;
goto robust;
case PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP:
case PTHREAD_MUTEX_ROBUST_NORMAL_NP:
case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP:
if ((mutex->__data.__lock & FUTEX_TID_MASK)
!= THREAD_GETMEM (THREAD_SELF, tid)
|| ! lll_islocked (mutex->__data.__lock))
return EPERM;
/* If the previous owner died and the caller did not succeed in
making the state consistent, mark the mutex as unrecoverable
and make all waiters. */
if (__builtin_expect (mutex->__data.__owner
== PTHREAD_MUTEX_INCONSISTENT, 0))
notrecoverable:
newowner = PTHREAD_MUTEX_NOTRECOVERABLE;
robust:
/* Remove mutex from the list. */
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
&mutex->__data.__list.__next);
/* We must set op_pending before we dequeue the mutex. Also see
comments at ENQUEUE_MUTEX. */
__asm ("" ::: "memory");
DEQUEUE_MUTEX (mutex);
mutex->__data.__owner = newowner;
if (decr)
/* One less user. */
--mutex->__data.__nusers;
/* Unlock by setting the lock to 0 (not acquired); if the lock had
FUTEX_WAITERS set previously, then wake any waiters.
The unlock operation must be the last access to the mutex to not
violate the mutex destruction requirements (see __lll_unlock). */
private = PTHREAD_ROBUST_MUTEX_PSHARED (mutex);
if (__glibc_unlikely ((atomic_exchange_rel (&mutex->__data.__lock, 0)
& FUTEX_WAITERS) != 0))
futex_wake ((unsigned int *) &mutex->__data.__lock, 1, private);
/* We must clear op_pending after we release the mutex.
FIXME However, this violates the mutex destruction requirements
because another thread could acquire the mutex, destroy it, and
reuse the memory for something else; then, if this thread crashes,
and the memory happens to have a value equal to the TID, the kernel
will believe it is still related to the mutex (which has been
destroyed already) and will modify some other random object. */
__asm ("" ::: "memory");
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
break;
/* The PI support requires the Linux futex system call. If that's not
available, pthread_mutex_init should never have allowed the type to
be set. So it will get the default case for an invalid type. */
#ifdef __NR_futex
case PTHREAD_MUTEX_PI_RECURSIVE_NP:
/* Recursive mutex. */
if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
return EPERM;
if (--mutex->__data.__count != 0)
/* We still hold the mutex. */
return 0;
goto continue_pi_non_robust;
case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP:
/* Recursive mutex. */
if ((mutex->__data.__lock & FUTEX_TID_MASK)
== THREAD_GETMEM (THREAD_SELF, tid)
&& __builtin_expect (mutex->__data.__owner
== PTHREAD_MUTEX_INCONSISTENT, 0))
{
if (--mutex->__data.__count != 0)
/* We still hold the mutex. */
return ENOTRECOVERABLE;
goto pi_notrecoverable;
}
if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
return EPERM;
if (--mutex->__data.__count != 0)
/* We still hold the mutex. */
return 0;
goto continue_pi_robust;
case PTHREAD_MUTEX_PI_ERRORCHECK_NP:
case PTHREAD_MUTEX_PI_NORMAL_NP:
case PTHREAD_MUTEX_PI_ADAPTIVE_NP:
case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP:
case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
if ((mutex->__data.__lock & FUTEX_TID_MASK)
!= THREAD_GETMEM (THREAD_SELF, tid)
|| ! lll_islocked (mutex->__data.__lock))
return EPERM;
/* If the previous owner died and the caller did not succeed in
making the state consistent, mark the mutex as unrecoverable
and make all waiters. */
/* See concurrency notes regarding __kind in struct __pthread_mutex_s
in sysdeps/nptl/bits/thread-shared-types.h. */
if ((atomic_load_relaxed (&(mutex->__data.__kind))
& PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0
&& __builtin_expect (mutex->__data.__owner
== PTHREAD_MUTEX_INCONSISTENT, 0))
pi_notrecoverable:
newowner = PTHREAD_MUTEX_NOTRECOVERABLE;
/* See concurrency notes regarding __kind in struct __pthread_mutex_s
in sysdeps/nptl/bits/thread-shared-types.h. */
if ((atomic_load_relaxed (&(mutex->__data.__kind))
& PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0)
{
continue_pi_robust:
/* Remove mutex from the list.
Note: robust PI futexes are signaled by setting bit 0. */
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
(void *) (((uintptr_t) &mutex->__data.__list.__next)
| 1));
/* We must set op_pending before we dequeue the mutex. Also see
comments at ENQUEUE_MUTEX. */
__asm ("" ::: "memory");
DEQUEUE_MUTEX (mutex);
}
continue_pi_non_robust:
mutex->__data.__owner = newowner;
if (decr)
/* One less user. */
--mutex->__data.__nusers;
/* Unlock. Load all necessary mutex data before releasing the mutex
to not violate the mutex destruction requirements (see
lll_unlock). */
/* See concurrency notes regarding __kind in struct __pthread_mutex_s
in sysdeps/nptl/bits/thread-shared-types.h. */
int robust = atomic_load_relaxed (&(mutex->__data.__kind))
& PTHREAD_MUTEX_ROBUST_NORMAL_NP;
private = (robust
? PTHREAD_ROBUST_MUTEX_PSHARED (mutex)
: PTHREAD_MUTEX_PSHARED (mutex));
/* Unlock the mutex using a CAS unless there are futex waiters or our
TID is not the value of __lock anymore, in which case we let the
kernel take care of the situation. Use release MO in the CAS to
synchronize with acquire MO in lock acquisitions. */
int l = atomic_load_relaxed (&mutex->__data.__lock);
do
{
if (((l & FUTEX_WAITERS) != 0)
|| (l != THREAD_GETMEM (THREAD_SELF, tid)))
{
futex_unlock_pi ((unsigned int *) &mutex->__data.__lock,
private);
break;
}
}
while (!atomic_compare_exchange_weak_release (&mutex->__data.__lock,
&l, 0));
/* This happens after the kernel releases the mutex but violates the
mutex destruction requirements; see comments in the code handling
PTHREAD_MUTEX_ROBUST_NORMAL_NP. */
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
break;
#endif /* __NR_futex. */
case PTHREAD_MUTEX_PP_RECURSIVE_NP:
/* Recursive mutex. */
if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
return EPERM;
if (--mutex->__data.__count != 0)
/* We still hold the mutex. */
return 0;
goto pp;
case PTHREAD_MUTEX_PP_ERRORCHECK_NP:
/* Error checking mutex. */
if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid)
|| (mutex->__data.__lock & ~ PTHREAD_MUTEX_PRIO_CEILING_MASK) == 0)
return EPERM;
/* FALLTHROUGH */
case PTHREAD_MUTEX_PP_NORMAL_NP:
case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
/* Always reset the owner field. */
pp:
mutex->__data.__owner = 0;
if (decr)
/* One less user. */
--mutex->__data.__nusers;
/* Unlock. Use release MO in the CAS to synchronize with acquire MO in
lock acquisitions. */
int newval;
int oldval = atomic_load_relaxed (&mutex->__data.__lock);
do
{
newval = oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK;
}
while (!atomic_compare_exchange_weak_release (&mutex->__data.__lock,
&oldval, newval));
if ((oldval & ~PTHREAD_MUTEX_PRIO_CEILING_MASK) > 1)
futex_wake ((unsigned int *)&mutex->__data.__lock, 1,
PTHREAD_MUTEX_PSHARED (mutex));
int oldprio = newval >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
LIBC_PROBE (mutex_release, 1, mutex);
return __pthread_tpp_change_priority (oldprio, -1);
default:
/* Correct code cannot set any other type. */
return EINVAL;
}
LIBC_PROBE (mutex_release, 1, mutex);
return 0;
}
00010bf0 <__pthread_mutex_unlock_full>:
10bf0: 68c2 ldr r2, [r0, #12]
10bf2: b5f0 push {r4, r5, r6, r7, lr}
10bf4: f002 037f and.w r3, r2, #127 ; 0x7f
10bf8: 3b10 subs r3, #16
10bfa: 2b33 cmp r3, #51 ; 0x33
10bfc: f200 816b bhi.w 10ed6 <__pthread_mutex_unlock_full+0x2e6>
10c00: e8df f013 tbh [pc, r3, lsl #1]
10c04: 009f0082 .word 0x009f0082
10c08: 00820082 .word 0x00820082
10c0c: 01690169 .word 0x01690169
10c10: 01690169 .word 0x01690169
10c14: 01690169 .word 0x01690169
10c18: 01690169 .word 0x01690169
10c1c: 01690169 .word 0x01690169
10c20: 01690169 .word 0x01690169
10c24: 010100e0 .word 0x010100e0
10c28: 00e000e0 .word 0x00e000e0
10c2c: 01690169 .word 0x01690169
10c30: 01690169 .word 0x01690169
10c34: 01690169 .word 0x01690169
10c38: 01690169 .word 0x01690169
10c3c: 01690169 .word 0x01690169
10c40: 01690169 .word 0x01690169
10c44: 013800e0 .word 0x013800e0
10c48: 00e000e0 .word 0x00e000e0
10c4c: 01690169 .word 0x01690169
10c50: 01690169 .word 0x01690169
10c54: 01690169 .word 0x01690169
10c58: 01690169 .word 0x01690169
10c5c: 01690169 .word 0x01690169
10c60: 01690169 .word 0x01690169
10c64: 006a003a .word 0x006a003a
10c68: 003a0074 .word 0x003a0074
10c6c: 6843 ldr r3, [r0, #4]
10c6e: 3b01 subs r3, #1
10c70: 6043 str r3, [r0, #4]
10c72: 2b00 cmp r3, #0
10c74: f040 8131 bne.w 10eda <__pthread_mutex_unlock_full+0x2ea>
10c78: 6803 ldr r3, [r0, #0]
10c7a: 2200 movs r2, #0
10c7c: 6082 str r2, [r0, #8]
10c7e: b111 cbz r1, 10c86 <__pthread_mutex_unlock_full+0x96>
10c80: 6902 ldr r2, [r0, #16]
10c82: 3a01 subs r2, #1
10c84: 6102 str r2, [r0, #16]
10c86: 2100 movs r1, #0
10c88: f6cf 71f8 movt r1, #65528 ; 0xfff8
10c8c: e000 b.n 10c90 <__pthread_mutex_unlock_full+0xa0>
10c8e: 4613 mov r3, r2
10c90: ea03 0401 and.w r4, r3, r1
10c94: f3bf 8f5b dmb ish
10c98: e850 2f00 ldrex r2, [r0]
10c9c: 429a cmp r2, r3
10c9e: d103 bne.n 10ca8 <__pthread_mutex_unlock_full+0xb8>
10ca0: e840 4500 strex r5, r4, [r0]
10ca4: 2d00 cmp r5, #0
10ca6: d1f7 bne.n 10c98 <__pthread_mutex_unlock_full+0xa8>
10ca8: 429a cmp r2, r3
10caa: d1f0 bne.n 10c8e <__pthread_mutex_unlock_full+0x9e>
10cac: f3c3 0312 ubfx r3, r3, #0, #19
10cb0: 2b01 cmp r3, #1
10cb2: d90a bls.n 10cca <__pthread_mutex_unlock_full+0xda>
10cb4: 68c1 ldr r1, [r0, #12]
10cb6: 2201 movs r2, #1
10cb8: 2300 movs r3, #0
10cba: f04f 0cf0 mov.w ip, #240 ; 0xf0
10cbe: f001 0180 and.w r1, r1, #128 ; 0x80
10cc2: f081 0181 eor.w r1, r1, #129 ; 0x81
10cc6: f004 fc63 bl 15590 <__libc_do_syscall>
10cca: 14e0 asrs r0, r4, #19
10ccc: f04f 31ff mov.w r1, #4294967295 ; 0xffffffff
10cd0: e8bd 40f0 ldmia.w sp!, {r4, r5, r6, r7, lr}
10cd4: f000 ba16 b.w 11104 <__pthread_tpp_change_priority>
10cd8: ee1d 3f70 mrc 15, 0, r3, cr13, cr0, {3}
10cdc: 6882 ldr r2, [r0, #8]
10cde: f5a3 6398 sub.w r3, r3, #1216 ; 0x4c0
10ce2: 6e9b ldr r3, [r3, #104] ; 0x68
10ce4: 429a cmp r2, r3
10ce6: d0c1 beq.n 10c6c <__pthread_mutex_unlock_full+0x7c>
10ce8: 2001 movs r0, #1
10cea: bdf0 pop {r4, r5, r6, r7, pc}
10cec: ee1d 3f70 mrc 15, 0, r3, cr13, cr0, {3}
10cf0: 6882 ldr r2, [r0, #8]
10cf2: f5a3 6398 sub.w r3, r3, #1216 ; 0x4c0
10cf6: 6e9b ldr r3, [r3, #104] ; 0x68
10cf8: 429a cmp r2, r3
10cfa: d1f5 bne.n 10ce8 <__pthread_mutex_unlock_full+0xf8>
10cfc: 6803 ldr r3, [r0, #0]
10cfe: f3c3 0212 ubfx r2, r3, #0, #19
10d02: 2a00 cmp r2, #0
10d04: d1b9 bne.n 10c7a <__pthread_mutex_unlock_full+0x8a>
10d06: e7ef b.n 10ce8 <__pthread_mutex_unlock_full+0xf8>
10d08: 6802 ldr r2, [r0, #0]
10d0a: ee1d 4f70 mrc 15, 0, r4, cr13, cr0, {3}
10d0e: f5a4 6498 sub.w r4, r4, #1216 ; 0x4c0
10d12: 6ea5 ldr r5, [r4, #104] ; 0x68
10d14: fab2 f382 clz r3, r2
10d18: f022 4240 bic.w r2, r2, #3221225472 ; 0xc0000000
10d1c: 095b lsrs r3, r3, #5
10d1e: 42aa cmp r2, r5
10d20: bf18 it ne
10d22: f043 0301 orrne.w r3, r3, #1
10d26: 2b00 cmp r3, #0
10d28: d1de bne.n 10ce8 <__pthread_mutex_unlock_full+0xf8>
10d2a: 6882 ldr r2, [r0, #8]
10d2c: f64f 73fe movw r3, #65534 ; 0xfffe
10d30: f6c7 73ff movt r3, #32767 ; 0x7fff
10d34: f06f 4600 mvn.w r6, #2147483648 ; 0x80000000
10d38: 42b2 cmp r2, r6
10d3a: bf0c ite eq
10d3c: 461e moveq r6, r3
10d3e: 2600 movne r6, #0
10d40: e013 b.n 10d6a <__pthread_mutex_unlock_full+0x17a>
10d42: ee1d 4f70 mrc 15, 0, r4, cr13, cr0, {3}
10d46: 6803 ldr r3, [r0, #0]
10d48: f5a4 6498 sub.w r4, r4, #1216 ; 0x4c0
10d4c: 6885 ldr r5, [r0, #8]
10d4e: 6ea2 ldr r2, [r4, #104] ; 0x68
10d50: f023 4340 bic.w r3, r3, #3221225472 ; 0xc0000000
10d54: 4293 cmp r3, r2
10d56: f000 80c2 beq.w 10ede <__pthread_mutex_unlock_full+0x2ee>
10d5a: 42aa cmp r2, r5
10d5c: d1c4 bne.n 10ce8 <__pthread_mutex_unlock_full+0xf8>
10d5e: 6843 ldr r3, [r0, #4]
10d60: 1e5e subs r6, r3, #1
10d62: 6046 str r6, [r0, #4]
10d64: 2e00 cmp r6, #0
10d66: f040 80b8 bne.w 10eda <__pthread_mutex_unlock_full+0x2ea>
10d6a: f100 0514 add.w r5, r0, #20
10d6e: 67a5 str r5, [r4, #120] ; 0x78
10d70: 6f23 ldr r3, [r4, #112] ; 0x70
10d72: f023 0301 bic.w r3, r3, #1
10d76: 429d cmp r5, r3
10d78: f000 80de beq.w 10f38 <__pthread_mutex_unlock_full+0x348>
10d7c: 681a ldr r2, [r3, #0]
10d7e: f022 0201 bic.w r2, r2, #1
10d82: 4295 cmp r5, r2
10d84: d101 bne.n 10d8a <__pthread_mutex_unlock_full+0x19a>
10d86: e0e1 b.n 10f4c <__pthread_mutex_unlock_full+0x35c>
10d88: 461a mov r2, r3
10d8a: 6813 ldr r3, [r2, #0]
10d8c: f023 0301 bic.w r3, r3, #1
10d90: 429d cmp r5, r3
10d92: d1f9 bne.n 10d88 <__pthread_mutex_unlock_full+0x198>
10d94: 682b ldr r3, [r5, #0]
10d96: 6013 str r3, [r2, #0]
10d98: 2300 movs r3, #0
10d9a: 6143 str r3, [r0, #20]
10d9c: 6086 str r6, [r0, #8]
10d9e: b111 cbz r1, 10da6 <__pthread_mutex_unlock_full+0x1b6>
10da0: 6903 ldr r3, [r0, #16]
10da2: 3b01 subs r3, #1
10da4: 6103 str r3, [r0, #16]
10da6: 2300 movs r3, #0
10da8: f3bf 8f5b dmb ish
10dac: e850 2f00 ldrex r2, [r0]
10db0: e840 3100 strex r1, r3, [r0]
10db4: 2900 cmp r1, #0
10db6: d1f9 bne.n 10dac <__pthread_mutex_unlock_full+0x1bc>
10db8: 429a cmp r2, r3
10dba: f2c0 80c9 blt.w 10f50 <__pthread_mutex_unlock_full+0x360>
10dbe: 2000 movs r0, #0
10dc0: 67a0 str r0, [r4, #120] ; 0x78
10dc2: bdf0 pop {r4, r5, r6, r7, pc}
10dc4: 6803 ldr r3, [r0, #0]
10dc6: ee1d 4f70 mrc 15, 0, r4, cr13, cr0, {3}
10dca: f5a4 6498 sub.w r4, r4, #1216 ; 0x4c0
10dce: 6ea6 ldr r6, [r4, #104] ; 0x68
10dd0: fab3 f583 clz r5, r3
10dd4: f023 4740 bic.w r7, r3, #3221225472 ; 0xc0000000
10dd8: 096d lsrs r5, r5, #5
10dda: 42b7 cmp r7, r6
10ddc: bf18 it ne
10dde: f045 0501 orrne.w r5, r5, #1
10de2: 2d00 cmp r5, #0
10de4: d180 bne.n 10ce8 <__pthread_mutex_unlock_full+0xf8>
10de6: f012 0510 ands.w r5, r2, #16
10dea: f000 809d beq.w 10f28 <__pthread_mutex_unlock_full+0x338>
10dee: 6882 ldr r2, [r0, #8]
10df0: f64f 73fe movw r3, #65534 ; 0xfffe
10df4: f6c7 73ff movt r3, #32767 ; 0x7fff
10df8: f06f 4600 mvn.w r6, #2147483648 ; 0x80000000
10dfc: 42b2 cmp r2, r6
10dfe: bf0c ite eq
10e00: 461e moveq r6, r3
10e02: 2600 movne r6, #0
10e04: e048 b.n 10e98 <__pthread_mutex_unlock_full+0x2a8>
10e06: ee1d 4f70 mrc 15, 0, r4, cr13, cr0, {3}
10e0a: 6885 ldr r5, [r0, #8]
10e0c: f5a4 6498 sub.w r4, r4, #1216 ; 0x4c0
10e10: 6ea3 ldr r3, [r4, #104] ; 0x68
10e12: 429d cmp r5, r3
10e14: f47f af68 bne.w 10ce8 <__pthread_mutex_unlock_full+0xf8>
10e18: 6843 ldr r3, [r0, #4]
10e1a: 1e5e subs r6, r3, #1
10e1c: 6046 str r6, [r0, #4]
10e1e: 2e00 cmp r6, #0
10e20: d15b bne.n 10eda <__pthread_mutex_unlock_full+0x2ea>
10e22: 6803 ldr r3, [r0, #0]
10e24: f002 0510 and.w r5, r2, #16
10e28: 6086 str r6, [r0, #8]
10e2a: b111 cbz r1, 10e32 <__pthread_mutex_unlock_full+0x242>
10e2c: 6901 ldr r1, [r0, #16]
10e2e: 3901 subs r1, #1
10e30: 6101 str r1, [r0, #16]
10e32: 2180 movs r1, #128 ; 0x80
10e34: 2d00 cmp r5, #0
10e36: d07c beq.n 10f32 <__pthread_mutex_unlock_full+0x342>
10e38: 2b00 cmp r3, #0
10e3a: db12 blt.n 10e62 <__pthread_mutex_unlock_full+0x272>
10e3c: 2600 movs r6, #0
10e3e: e00d b.n 10e5c <__pthread_mutex_unlock_full+0x26c>
10e40: f3bf 8f5b dmb ish
10e44: e850 5f00 ldrex r5, [r0]
10e48: 429d cmp r5, r3
10e4a: d103 bne.n 10e54 <__pthread_mutex_unlock_full+0x264>
10e4c: e840 6200 strex r2, r6, [r0]
10e50: 2a00 cmp r2, #0
10e52: d1f7 bne.n 10e44 <__pthread_mutex_unlock_full+0x254>
10e54: 429d cmp r5, r3
10e56: d00a beq.n 10e6e <__pthread_mutex_unlock_full+0x27e>
10e58: 1e2b subs r3, r5, #0
10e5a: db02 blt.n 10e62 <__pthread_mutex_unlock_full+0x272>
10e5c: 6ea5 ldr r5, [r4, #104] ; 0x68
10e5e: 429d cmp r5, r3
10e60: d0ee beq.n 10e40 <__pthread_mutex_unlock_full+0x250>
10e62: f081 0187 eor.w r1, r1, #135 ; 0x87
10e66: f04f 0cf0 mov.w ip, #240 ; 0xf0
10e6a: f004 fb91 bl 15590 <__libc_do_syscall>
10e6e: 2000 movs r0, #0
10e70: 67a0 str r0, [r4, #120] ; 0x78
10e72: bdf0 pop {r4, r5, r6, r7, pc}
10e74: ee1d 4f70 mrc 15, 0, r4, cr13, cr0, {3}
10e78: 6803 ldr r3, [r0, #0]
10e7a: f5a4 6498 sub.w r4, r4, #1216 ; 0x4c0
10e7e: 6886 ldr r6, [r0, #8]
10e80: 6ea5 ldr r5, [r4, #104] ; 0x68
10e82: f023 4740 bic.w r7, r3, #3221225472 ; 0xc0000000
10e86: 42af cmp r7, r5
10e88: d03a beq.n 10f00 <__pthread_mutex_unlock_full+0x310>
10e8a: 42b5 cmp r5, r6
10e8c: f47f af2c bne.w 10ce8 <__pthread_mutex_unlock_full+0xf8>
10e90: 6843 ldr r3, [r0, #4]
10e92: 1e5e subs r6, r3, #1
10e94: 6046 str r6, [r0, #4]
10e96: bb06 cbnz r6, 10eda <__pthread_mutex_unlock_full+0x2ea>
10e98: f100 0514 add.w r5, r0, #20
10e9c: f045 0301 orr.w r3, r5, #1
10ea0: 67a3 str r3, [r4, #120] ; 0x78
10ea2: 6f23 ldr r3, [r4, #112] ; 0x70
10ea4: f023 0301 bic.w r3, r3, #1
10ea8: 429d cmp r5, r3
10eaa: d048 beq.n 10f3e <__pthread_mutex_unlock_full+0x34e>
10eac: 681a ldr r2, [r3, #0]
10eae: f022 0201 bic.w r2, r2, #1
10eb2: 4295 cmp r5, r2
10eb4: d101 bne.n 10eba <__pthread_mutex_unlock_full+0x2ca>
10eb6: e052 b.n 10f5e <__pthread_mutex_unlock_full+0x36e>
10eb8: 461a mov r2, r3
10eba: 6813 ldr r3, [r2, #0]
10ebc: f023 0301 bic.w r3, r3, #1
10ec0: 429d cmp r5, r3
10ec2: d1f9 bne.n 10eb8 <__pthread_mutex_unlock_full+0x2c8>
10ec4: 682b ldr r3, [r5, #0]
10ec6: 6013 str r3, [r2, #0]
10ec8: 68c2 ldr r2, [r0, #12]
10eca: 2500 movs r5, #0
10ecc: 6145 str r5, [r0, #20]
10ece: 6803 ldr r3, [r0, #0]
10ed0: f002 0510 and.w r5, r2, #16
10ed4: e7a8 b.n 10e28 <__pthread_mutex_unlock_full+0x238>
10ed6: 2016 movs r0, #22
10ed8: bdf0 pop {r4, r5, r6, r7, pc}
10eda: 2000 movs r0, #0
10edc: bdf0 pop {r4, r5, r6, r7, pc}
10ede: f06f 4300 mvn.w r3, #2147483648 ; 0x80000000
10ee2: 429d cmp r5, r3
10ee4: f47f af39 bne.w 10d5a <__pthread_mutex_unlock_full+0x16a>
10ee8: 6843 ldr r3, [r0, #4]
10eea: f64f 76fe movw r6, #65534 ; 0xfffe
10eee: f6c7 76ff movt r6, #32767 ; 0x7fff
10ef2: 3b01 subs r3, #1
10ef4: 6043 str r3, [r0, #4]
10ef6: 2b00 cmp r3, #0
10ef8: f43f af37 beq.w 10d6a <__pthread_mutex_unlock_full+0x17a>
10efc: 2083 movs r0, #131 ; 0x83
10efe: bdf0 pop {r4, r5, r6, r7, pc}
10f00: f06f 4700 mvn.w r7, #2147483648 ; 0x80000000
10f04: 42be cmp r6, r7
10f06: d1c0 bne.n 10e8a <__pthread_mutex_unlock_full+0x29a>
10f08: 6845 ldr r5, [r0, #4]
10f0a: 3d01 subs r5, #1
10f0c: 6045 str r5, [r0, #4]
10f0e: 2d00 cmp r5, #0
10f10: d1f4 bne.n 10efc <__pthread_mutex_unlock_full+0x30c>
10f12: 06d5 lsls r5, r2, #27
10f14: d504 bpl.n 10f20 <__pthread_mutex_unlock_full+0x330>
10f16: f64f 76fe movw r6, #65534 ; 0xfffe
10f1a: f6c7 76ff movt r6, #32767 ; 0x7fff
10f1e: e7bb b.n 10e98 <__pthread_mutex_unlock_full+0x2a8>
10f20: f64f 75fe movw r5, #65534 ; 0xfffe
10f24: f6c7 75ff movt r5, #32767 ; 0x7fff
10f28: 6085 str r5, [r0, #8]
10f2a: 2500 movs r5, #0
10f2c: 2900 cmp r1, #0
10f2e: f47f af7d bne.w 10e2c <__pthread_mutex_unlock_full+0x23c>
10f32: f002 0180 and.w r1, r2, #128 ; 0x80
10f36: e77f b.n 10e38 <__pthread_mutex_unlock_full+0x248>
10f38: 6943 ldr r3, [r0, #20]
10f3a: 6723 str r3, [r4, #112] ; 0x70
10f3c: e72e b.n 10d9c <__pthread_mutex_unlock_full+0x1ac>
10f3e: 6945 ldr r5, [r0, #20]
10f40: 68c2 ldr r2, [r0, #12]
10f42: 6803 ldr r3, [r0, #0]
10f44: 6725 str r5, [r4, #112] ; 0x70
10f46: f002 0510 and.w r5, r2, #16
10f4a: e76d b.n 10e28 <__pthread_mutex_unlock_full+0x238>
10f4c: 461a mov r2, r3
10f4e: e721 b.n 10d94 <__pthread_mutex_unlock_full+0x1a4>
10f50: 2101 movs r1, #1
10f52: f04f 0cf0 mov.w ip, #240 ; 0xf0
10f56: 460a mov r2, r1
10f58: f004 fb1a bl 15590 <__libc_do_syscall>
10f5c: e72f b.n 10dbe <__pthread_mutex_unlock_full+0x1ce>
10f5e: 461a mov r2, r3
10f60: e7b0 b.n 10ec4 <__pthread_mutex_unlock_full+0x2d4>
10f62: bf00 nop