11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * All rights reserved.
41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Redistribution and use in source and binary forms, with or without
61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * modification, are permitted provided that the following conditions
71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * are met:
81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *  * Redistributions of source code must retain the above copyright
91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *  * Redistributions in binary form must reproduce the above copyright
111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    notice, this list of conditions and the following disclaimer in
121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    the documentation and/or other materials provided with the
131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    distribution.
141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * SUCH DAMAGE.
271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
28d0c884d3595ecca03c3e70de9909c090cd5f9caePierre Peiffer
293e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes#include <pthread.h>
303e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes
31d0c884d3595ecca03c3e70de9909c090cd5f9caePierre Peiffer#include <errno.h>
32d0c884d3595ecca03c3e70de9909c090cd5f9caePierre Peiffer#include <limits.h>
3384114c8dd5b17efecf7988f263ce431208d7be5aElliott Hughes#include <sys/mman.h>
34d0c884d3595ecca03c3e70de9909c090cd5f9caePierre Peiffer#include <unistd.h>
35d0c884d3595ecca03c3e70de9909c090cd5f9caePierre Peiffer
361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "pthread_internal.h"
37eb847bc8666842a3cfc9c06e8458ad1abebebaf0Elliott Hughes
38eb847bc8666842a3cfc9c06e8458ad1abebebaf0Elliott Hughes#include "private/bionic_atomic_inline.h"
39eb847bc8666842a3cfc9c06e8458ad1abebebaf0Elliott Hughes#include "private/bionic_futex.h"
40eb847bc8666842a3cfc9c06e8458ad1abebebaf0Elliott Hughes#include "private/bionic_tls.h"
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
427c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopianextern void pthread_debug_mutex_lock_check(pthread_mutex_t *mutex);
437c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopianextern void pthread_debug_mutex_unlock_check(pthread_mutex_t *mutex);
447c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian
451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* a mutex is implemented as a 32-bit integer holding the following fields
461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * bits:     name     description
4840eabe24e4e3ae8ebe437f1f4e43cf39cbba2e9eElliott Hughes * 31-16     tid      owner thread's tid (recursive and errorcheck only)
491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 15-14     type     mutex type
5088f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner * 13        shared   process-shared flag
5188f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner * 12-2      counter  counter of recursive mutexes
521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 1-0       state    lock state (0, 1 or 2)
531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
55e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* Convenience macro, creates a mask of 'bits' bits that starts from
56e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * the 'shift'-th least significant bit in a 32-bit word.
57e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *
58e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * Examples: FIELD_MASK(0,4)  -> 0xf
59e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *           FIELD_MASK(16,9) -> 0x1ff0000
60e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner */
61e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  FIELD_MASK(shift,bits)           (((1 << (bits))-1) << (shift))
62e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
63e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* This one is used to create a bit pattern from a given field value */
64e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  FIELD_TO_BITS(val,shift,bits)    (((val) & ((1 << (bits))-1)) << (shift))
65e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
66e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* And this one does the opposite, i.e. extract a field's value from a bit pattern */
67e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  FIELD_FROM_BITS(val,shift,bits)  (((val) >> (shift)) & ((1 << (bits))-1))
68e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
69e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* Mutex state:
70e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *
71e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * 0 for unlocked
72e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * 1 for locked, no waiters
73e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * 2 for locked, maybe waiters
74e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner */
75e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_SHIFT      0
76e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_LEN        2
77e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
78e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_MASK           FIELD_MASK(MUTEX_STATE_SHIFT, MUTEX_STATE_LEN)
79e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_FROM_BITS(v)   FIELD_FROM_BITS(v, MUTEX_STATE_SHIFT, MUTEX_STATE_LEN)
80e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_TO_BITS(v)     FIELD_TO_BITS(v, MUTEX_STATE_SHIFT, MUTEX_STATE_LEN)
81e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
82e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_UNLOCKED            0   /* must be 0 to match __PTHREAD_MUTEX_INIT_VALUE */
83e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_LOCKED_UNCONTENDED  1   /* must be 1 due to atomic dec in unlock operation */
84e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_LOCKED_CONTENDED    2   /* must be 1 + LOCKED_UNCONTENDED due to atomic dec */
85e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
86e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_FROM_BITS(v)    FIELD_FROM_BITS(v, MUTEX_STATE_SHIFT, MUTEX_STATE_LEN)
87e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_TO_BITS(v)      FIELD_TO_BITS(v, MUTEX_STATE_SHIFT, MUTEX_STATE_LEN)
88e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
89e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_BITS_UNLOCKED            MUTEX_STATE_TO_BITS(MUTEX_STATE_UNLOCKED)
90e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_BITS_LOCKED_UNCONTENDED  MUTEX_STATE_TO_BITS(MUTEX_STATE_LOCKED_UNCONTENDED)
91e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_BITS_LOCKED_CONTENDED    MUTEX_STATE_TO_BITS(MUTEX_STATE_LOCKED_CONTENDED)
92e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
93e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* return true iff the mutex if locked with no waiters */
94e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_BITS_IS_LOCKED_UNCONTENDED(v)  (((v) & MUTEX_STATE_MASK) == MUTEX_STATE_BITS_LOCKED_UNCONTENDED)
95e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
96e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* return true iff the mutex if locked with maybe waiters */
97e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_BITS_IS_LOCKED_CONTENDED(v)   (((v) & MUTEX_STATE_MASK) == MUTEX_STATE_BITS_LOCKED_CONTENDED)
98e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
99e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* used to flip from LOCKED_UNCONTENDED to LOCKED_CONTENDED */
100e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_BITS_FLIP_CONTENTION(v)      ((v) ^ (MUTEX_STATE_BITS_LOCKED_CONTENDED ^ MUTEX_STATE_BITS_LOCKED_UNCONTENDED))
101e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
102e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* Mutex counter:
103e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *
104e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * We need to check for overflow before incrementing, and we also need to
105e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * detect when the counter is 0
106e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner */
107e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_COUNTER_SHIFT         2
108e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_COUNTER_LEN           11
109e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_COUNTER_MASK          FIELD_MASK(MUTEX_COUNTER_SHIFT, MUTEX_COUNTER_LEN)
110e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
111e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_COUNTER_BITS_WILL_OVERFLOW(v)    (((v) & MUTEX_COUNTER_MASK) == MUTEX_COUNTER_MASK)
112e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_COUNTER_BITS_IS_ZERO(v)          (((v) & MUTEX_COUNTER_MASK) == 0)
113e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
114e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* Used to increment the counter directly after overflow has been checked */
115e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_COUNTER_BITS_ONE      FIELD_TO_BITS(1,MUTEX_COUNTER_SHIFT,MUTEX_COUNTER_LEN)
116e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
117e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* Returns true iff the counter is 0 */
118e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_COUNTER_BITS_ARE_ZERO(v)  (((v) & MUTEX_COUNTER_MASK) == 0)
1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
120e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* Mutex shared bit flag
121e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *
122e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * This flag is set to indicate that the mutex is shared among processes.
123e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * This changes the futex opcode we use for futex wait/wake operations
124e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * (non-shared operations are much faster).
125e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner */
126e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_SHARED_SHIFT    13
127e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_SHARED_MASK     FIELD_MASK(MUTEX_SHARED_SHIFT,1)
128e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
129e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* Mutex type:
130e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *
131e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * We support normal, recursive and errorcheck mutexes.
132e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *
133e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * The constants defined here *cannot* be changed because they must match
134e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * the C library ABI which defines the following initialization values in
135e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * <pthread.h>:
136e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *
137e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *   __PTHREAD_MUTEX_INIT_VALUE
138e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *   __PTHREAD_RECURSIVE_MUTEX_VALUE
139e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *   __PTHREAD_ERRORCHECK_MUTEX_INIT_VALUE
140e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner */
141e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_TYPE_SHIFT      14
142e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_TYPE_LEN        2
143e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_TYPE_MASK       FIELD_MASK(MUTEX_TYPE_SHIFT,MUTEX_TYPE_LEN)
144022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner
145e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_TYPE_NORMAL          0  /* Must be 0 to match __PTHREAD_MUTEX_INIT_VALUE */
146e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_TYPE_RECURSIVE       1
147e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_TYPE_ERRORCHECK      2
148e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
149e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_TYPE_TO_BITS(t)       FIELD_TO_BITS(t, MUTEX_TYPE_SHIFT, MUTEX_TYPE_LEN)
150e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
151e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_TYPE_BITS_NORMAL      MUTEX_TYPE_TO_BITS(MUTEX_TYPE_NORMAL)
152e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_TYPE_BITS_RECURSIVE   MUTEX_TYPE_TO_BITS(MUTEX_TYPE_RECURSIVE)
153e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_TYPE_BITS_ERRORCHECK  MUTEX_TYPE_TO_BITS(MUTEX_TYPE_ERRORCHECK)
154e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
155e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* Mutex owner field:
156e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *
157e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * This is only used for recursive and errorcheck mutexes. It holds the
15840eabe24e4e3ae8ebe437f1f4e43cf39cbba2e9eElliott Hughes * tid of the owning thread. Note that this works because the Linux
15940eabe24e4e3ae8ebe437f1f4e43cf39cbba2e9eElliott Hughes * kernel _only_ uses 16-bit values for tids.
160e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *
161e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * More specifically, it will wrap to 10000 when it reaches over 32768 for
162e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * application processes. You can check this by running the following inside
163e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * an adb shell session:
164e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *
165e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    OLDPID=$$;
166e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    while true; do
167e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    NEWPID=$(sh -c 'echo $$')
168e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if [ "$NEWPID" -gt 32768 ]; then
169e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        echo "AARGH: new PID $NEWPID is too high!"
170e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        exit 1
171e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    fi
172e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if [ "$NEWPID" -lt "$OLDPID" ]; then
173e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        echo "****** Wrapping from PID $OLDPID to $NEWPID. *******"
174e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    else
175e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        echo -n "$NEWPID!"
176e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    fi
177e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    OLDPID=$NEWPID
178e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    done
179e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
180e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * Note that you can run the same example on a desktop Linux system,
181e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * the wrapping will also happen at 32768, but will go back to 300 instead.
182e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner */
183e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_OWNER_SHIFT     16
184e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_OWNER_LEN       16
185e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
186e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_OWNER_FROM_BITS(v)    FIELD_FROM_BITS(v,MUTEX_OWNER_SHIFT,MUTEX_OWNER_LEN)
187e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_OWNER_TO_BITS(v)      FIELD_TO_BITS(v,MUTEX_OWNER_SHIFT,MUTEX_OWNER_LEN)
188e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
189e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* Convenience macros.
190e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *
191e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * These are used to form or modify the bit pattern of a given mutex value
192e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner */
1931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
19688f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner/* a mutex attribute holds the following fields
19788f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner *
19888f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner * bits:     name       description
19988f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner * 0-3       type       type of mutex
20088f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner * 4         shared     process-shared flag
20188f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner */
20288f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner#define  MUTEXATTR_TYPE_MASK   0x000f
20388f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner#define  MUTEXATTR_SHARED_MASK 0x0010
2041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint pthread_mutexattr_init(pthread_mutexattr_t *attr)
2071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
20839b644a0e270df453c53d6060cd364391bb1c512Elliott Hughes    *attr = PTHREAD_MUTEX_DEFAULT;
20939b644a0e270df453c53d6060cd364391bb1c512Elliott Hughes    return 0;
2101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
2111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
21439b644a0e270df453c53d6060cd364391bb1c512Elliott Hughes    *attr = -1;
21539b644a0e270df453c53d6060cd364391bb1c512Elliott Hughes    return 0;
2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
21839b644a0e270df453c53d6060cd364391bb1c512Elliott Hughesint pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type_p)
2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
22039b644a0e270df453c53d6060cd364391bb1c512Elliott Hughes    int type = (*attr & MUTEXATTR_TYPE_MASK);
22139b644a0e270df453c53d6060cd364391bb1c512Elliott Hughes
22239b644a0e270df453c53d6060cd364391bb1c512Elliott Hughes    if (type < PTHREAD_MUTEX_NORMAL || type > PTHREAD_MUTEX_ERRORCHECK) {
22339b644a0e270df453c53d6060cd364391bb1c512Elliott Hughes        return EINVAL;
2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
22539b644a0e270df453c53d6060cd364391bb1c512Elliott Hughes
22639b644a0e270df453c53d6060cd364391bb1c512Elliott Hughes    *type_p = type;
22739b644a0e270df453c53d6060cd364391bb1c512Elliott Hughes    return 0;
2281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
2291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
2311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
23239b644a0e270df453c53d6060cd364391bb1c512Elliott Hughes    if (type < PTHREAD_MUTEX_NORMAL || type > PTHREAD_MUTEX_ERRORCHECK ) {
23339b644a0e270df453c53d6060cd364391bb1c512Elliott Hughes        return EINVAL;
2341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
23539b644a0e270df453c53d6060cd364391bb1c512Elliott Hughes
23639b644a0e270df453c53d6060cd364391bb1c512Elliott Hughes    *attr = (*attr & ~MUTEXATTR_TYPE_MASK) | type;
23739b644a0e270df453c53d6060cd364391bb1c512Elliott Hughes    return 0;
2381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
2391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* process-shared mutexes are not supported at the moment */
2411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int  pshared)
2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
244b7681167cbe91c2bb95cccdc08f75184ed1fb839Mathias Agopian    switch (pshared) {
245b7681167cbe91c2bb95cccdc08f75184ed1fb839Mathias Agopian    case PTHREAD_PROCESS_PRIVATE:
24688f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner        *attr &= ~MUTEXATTR_SHARED_MASK;
24788f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner        return 0;
24888f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner
249b7681167cbe91c2bb95cccdc08f75184ed1fb839Mathias Agopian    case PTHREAD_PROCESS_SHARED:
250b7681167cbe91c2bb95cccdc08f75184ed1fb839Mathias Agopian        /* our current implementation of pthread actually supports shared
251b7681167cbe91c2bb95cccdc08f75184ed1fb839Mathias Agopian         * mutexes but won't cleanup if a process dies with the mutex held.
252b7681167cbe91c2bb95cccdc08f75184ed1fb839Mathias Agopian         * Nevertheless, it's better than nothing. Shared mutexes are used
253b7681167cbe91c2bb95cccdc08f75184ed1fb839Mathias Agopian         * by surfaceflinger and audioflinger.
254b7681167cbe91c2bb95cccdc08f75184ed1fb839Mathias Agopian         */
25588f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner        *attr |= MUTEXATTR_SHARED_MASK;
256b7681167cbe91c2bb95cccdc08f75184ed1fb839Mathias Agopian        return 0;
257b7681167cbe91c2bb95cccdc08f75184ed1fb839Mathias Agopian    }
25888f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner    return EINVAL;
2591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
2601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
261c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesint pthread_mutexattr_getpshared(const pthread_mutexattr_t* attr, int* pshared) {
26239b644a0e270df453c53d6060cd364391bb1c512Elliott Hughes    *pshared = (*attr & MUTEXATTR_SHARED_MASK) ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE;
2631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    return 0;
2641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
2651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
266dff7203ee99ccac446b9a1c4371753a5216c6db4Elliott Hughesint pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* attr) {
267d4e753fea9345c24dcce89531dff9019bef14eb3Elliott Hughes    if (__predict_true(attr == NULL)) {
268e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        mutex->value = MUTEX_TYPE_BITS_NORMAL;
26988f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner        return 0;
270ba9c6f0989ae94778ba2b9f597adc827c9dc81e8David 'Digit' Turner    }
27188f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner
272dff7203ee99ccac446b9a1c4371753a5216c6db4Elliott Hughes    int value = 0;
273dff7203ee99ccac446b9a1c4371753a5216c6db4Elliott Hughes    if ((*attr & MUTEXATTR_SHARED_MASK) != 0) {
27488f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner        value |= MUTEX_SHARED_MASK;
275dff7203ee99ccac446b9a1c4371753a5216c6db4Elliott Hughes    }
27688f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner
27788f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner    switch (*attr & MUTEXATTR_TYPE_MASK) {
27888f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner    case PTHREAD_MUTEX_NORMAL:
279e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        value |= MUTEX_TYPE_BITS_NORMAL;
28088f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner        break;
28188f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner    case PTHREAD_MUTEX_RECURSIVE:
282e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        value |= MUTEX_TYPE_BITS_RECURSIVE;
28388f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner        break;
28488f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner    case PTHREAD_MUTEX_ERRORCHECK:
285e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        value |= MUTEX_TYPE_BITS_ERRORCHECK;
28688f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner        break;
28788f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner    default:
28888f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner        return EINVAL;
28988f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner    }
29088f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner
29188f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner    mutex->value = value;
29288f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner    return 0;
2931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
2941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
2971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Lock a non-recursive mutex.
2981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
2991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * As noted above, there are three states:
3001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *   0 (unlocked, no contention)
3011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *   1 (locked, no contention)
3021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *   2 (locked, contention)
3031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
3041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Non-recursive mutexes don't use the thread-id or counter fields, and the
3051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * "type" value is zero, so the only bits that will be set are the ones in
3061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * the lock state field.
3071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
308624996026b844ff2eba2283f4dc83ec363d85a11Elliott Hughesstatic inline void _normal_lock(pthread_mutex_t* mutex, int shared) {
309e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    /* convenience shortcuts */
310e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    const int unlocked           = shared | MUTEX_STATE_BITS_UNLOCKED;
311e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    const int locked_uncontended = shared | MUTEX_STATE_BITS_LOCKED_UNCONTENDED;
3128641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio    /*
3138641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio     * The common case is an unlocked mutex, so we begin by trying to
314e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * change the lock's state from 0 (UNLOCKED) to 1 (LOCKED).
315e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * __bionic_cmpxchg() returns 0 if it made the swap successfully.
316e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * If the result is nonzero, this lock is already held by another thread.
3178641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio     */
318e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if (__bionic_cmpxchg(unlocked, locked_uncontended, &mutex->value) != 0) {
319e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        const int locked_contended = shared | MUTEX_STATE_BITS_LOCKED_CONTENDED;
3201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /*
3218641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * We want to go to sleep until the mutex is available, which
322e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         * requires promoting it to state 2 (CONTENDED). We need to
323e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         * swap in the new state value and then wait until somebody wakes us up.
3248641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         *
325e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner         * __bionic_swap() returns the previous value.  We swap 2 in and
3268641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * see if we got zero back; if so, we have acquired the lock.  If
3278641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * not, another thread still holds the lock and we wait again.
3288641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         *
3298641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * The second argument to the __futex_wait() call is compared
3308641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * against the current value.  If it doesn't match, __futex_wait()
3318641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * returns immediately (otherwise, it sleeps for a time specified
3328641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * by the third argument; 0 means sleep forever).  This ensures
3338641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * that the mutex is in state 2 when we go to sleep on it, which
3348641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * guarantees a wake-up call.
3358641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         */
336624996026b844ff2eba2283f4dc83ec363d85a11Elliott Hughes        while (__bionic_swap(locked_contended, &mutex->value) != unlocked) {
337624996026b844ff2eba2283f4dc83ec363d85a11Elliott Hughes            __futex_wait_ex(&mutex->value, shared, locked_contended, NULL);
338624996026b844ff2eba2283f4dc83ec363d85a11Elliott Hughes        }
3391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
340fcd00ebbdf3e7f4e1e7782a65ae10fb0fc03a1aaAndy McFadden    ANDROID_MEMBAR_FULL();
3411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
3421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
3441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Release a non-recursive mutex.  The caller is responsible for determining
3451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * that we are in fact the owner of this lock.
3461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
347624996026b844ff2eba2283f4dc83ec363d85a11Elliott Hughesstatic inline void _normal_unlock(pthread_mutex_t* mutex, int shared) {
348fcd00ebbdf3e7f4e1e7782a65ae10fb0fc03a1aaAndy McFadden    ANDROID_MEMBAR_FULL();
349fcd00ebbdf3e7f4e1e7782a65ae10fb0fc03a1aaAndy McFadden
3508641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio    /*
35188f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner     * The mutex state will be 1 or (rarely) 2.  We use an atomic decrement
352e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner     * to release the lock.  __bionic_atomic_dec() returns the previous value;
3538641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio     * if it wasn't 1 we have to do some additional work.
3548641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio     */
355e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if (__bionic_atomic_dec(&mutex->value) != (shared|MUTEX_STATE_BITS_LOCKED_UNCONTENDED)) {
3561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /*
3578641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * Start by releasing the lock.  The decrement changed it from
3588641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * "contended lock" to "uncontended lock", which means we still
3598641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * hold it, and anybody who tries to sneak in will push it back
3608641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * to state 2.
3618641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         *
3628641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * Once we set it to zero the lock is up for grabs.  We follow
3638641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * this with a __futex_wake() to ensure that one of the waiting
3648641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * threads has a chance to grab it.
3658641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         *
3668641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * This doesn't cause a race with the swap/wait pair in
3678641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * _normal_lock(), because the __futex_wait() call there will
3688641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * return immediately if the mutex value isn't 2.
3698641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         */
37088f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner        mutex->value = shared;
3718641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio
3728641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio        /*
3738641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * Wake up one waiting thread.  We don't know which thread will be
3748641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * woken or when it'll start executing -- futexes make no guarantees
3758641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * here.  There may not even be a thread waiting.
3768641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         *
3778641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * The newly-woken thread will replace the 0 we just set above
3788641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * with 2, which means that when it eventually releases the mutex
3798641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * it will also call FUTEX_WAKE.  This results in one extra wake
3808641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * call whenever a lock is contended, but lets us avoid forgetting
3818641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * anyone without requiring us to track the number of sleepers.
3828641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         *
3838641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * It's possible for another thread to sneak in and grab the lock
3848641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * between the zero assignment above and the wake call below.  If
3858641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * the new thread is "slow" and holds the lock for a while, we'll
3868641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * wake up a sleeper, which will swap in a 2 and then go back to
3878641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * sleep since the lock is still held.  If the new thread is "fast",
3888641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * running to completion before we call wake, the thread we
3898641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * eventually wake will find an unlocked mutex and will execute.
3908641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * Either way we have correct behavior and nobody is orphaned on
3918641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * the wait queue.
3928641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         */
3936304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner        __futex_wake_ex(&mutex->value, shared, 1);
3941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
3951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
3961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
397022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner/* This common inlined function is used to increment the counter of an
398022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner * errorcheck or recursive mutex.
399022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner *
400022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner * For errorcheck mutexes, it will return EDEADLK
401022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner * If the counter overflows, it will return EAGAIN
402022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner * Otherwise, it atomically increments the counter and returns 0
403022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner * after providing an acquire barrier.
404022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner *
405022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner * mtype is the current mutex type
406022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner * mvalue is the current mutex value (already loaded)
407022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner * mutex pointers to the mutex.
408022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner */
409624996026b844ff2eba2283f4dc83ec363d85a11Elliott Hughesstatic inline __always_inline int _recursive_increment(pthread_mutex_t* mutex, int mvalue, int mtype) {
410e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if (mtype == MUTEX_TYPE_BITS_ERRORCHECK) {
411022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner        /* trying to re-lock a mutex we already acquired */
412022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner        return EDEADLK;
413022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    }
414022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner
415022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    /* Detect recursive lock overflow and return EAGAIN.
416022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner     * This is safe because only the owner thread can modify the
417b57db7581cabb98651c4d8940d65c5c404b914adDavid 'Digit' Turner     * counter bits in the mutex value.
418022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner     */
419e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if (MUTEX_COUNTER_BITS_WILL_OVERFLOW(mvalue)) {
420022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner        return EAGAIN;
421022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    }
422022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner
423022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    /* We own the mutex, but other threads are able to change
424b57db7581cabb98651c4d8940d65c5c404b914adDavid 'Digit' Turner     * the lower bits (e.g. promoting it to "contended"), so we
425e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * need to use an atomic cmpxchg loop to update the counter.
426b57db7581cabb98651c4d8940d65c5c404b914adDavid 'Digit' Turner     */
427e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    for (;;) {
428e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        /* increment counter, overflow was already checked */
429e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        int newval = mvalue + MUTEX_COUNTER_BITS_ONE;
430d4e753fea9345c24dcce89531dff9019bef14eb3Elliott Hughes        if (__predict_true(__bionic_cmpxchg(mvalue, newval, &mutex->value) == 0)) {
431e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            /* mutex is still locked, not need for a memory barrier */
432e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            return 0;
433e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        }
434e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        /* the value was changed, this happens when another thread changes
435e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         * the lower state bits from 1 to 2 to indicate contention. This
436e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         * cannot change the counter, so simply reload and try again.
437e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         */
438e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        mvalue = mutex->value;
439e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    }
4401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
4411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
44207f1ded1399805fa9367f4db2936832b0c22b7a5Elliott Hughesint pthread_mutex_lock(pthread_mutex_t* mutex) {
4431543fdf616ddebee7819214437527f380e5c743bElliott Hughes#if !defined(__LP64__)
4441543fdf616ddebee7819214437527f380e5c743bElliott Hughes    if (mutex == NULL) {
4451543fdf616ddebee7819214437527f380e5c743bElliott Hughes        return EINVAL;
4461543fdf616ddebee7819214437527f380e5c743bElliott Hughes    }
4471543fdf616ddebee7819214437527f380e5c743bElliott Hughes#endif
4481543fdf616ddebee7819214437527f380e5c743bElliott Hughes
449a12c54454f3a6132988b68873903f6e9eed7f384Wink Saville    int mvalue, mtype, tid, shared;
45040e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
451022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    mvalue = mutex->value;
452022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    mtype = (mvalue & MUTEX_TYPE_MASK);
453022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    shared = (mvalue & MUTEX_SHARED_MASK);
45440e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
455ff03a7aaade5826e3708f6e320d0612d4cdbdb72Brigid Smith    /* Handle non-recursive case first */
456d4e753fea9345c24dcce89531dff9019bef14eb3Elliott Hughes    if ( __predict_true(mtype == MUTEX_TYPE_BITS_NORMAL) ) {
457022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner        _normal_lock(mutex, shared);
45840e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner        return 0;
45940e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    }
46040e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
46140e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    /* Do we already own this recursive or error-check mutex ? */
46240eabe24e4e3ae8ebe437f1f4e43cf39cbba2e9eElliott Hughes    tid = __get_thread()->tid;
463e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if ( tid == MUTEX_OWNER_FROM_BITS(mvalue) )
464022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner        return _recursive_increment(mutex, mvalue, mtype);
46540e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
466e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    /* Add in shared state to avoid extra 'or' operations below */
4676304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner    mtype |= shared;
46888f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner
469e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    /* First, if the mutex is unlocked, try to quickly acquire it.
470e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * In the optimistic case where this works, set the state to 1 to
471e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * indicate locked with no contention */
472e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if (mvalue == mtype) {
473e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        int newval = MUTEX_OWNER_TO_BITS(tid) | mtype | MUTEX_STATE_BITS_LOCKED_UNCONTENDED;
474e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        if (__bionic_cmpxchg(mvalue, newval, &mutex->value) == 0) {
475e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            ANDROID_MEMBAR_FULL();
476e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            return 0;
47740e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner        }
478e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        /* argh, the value changed, reload before entering the loop */
479e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        mvalue = mutex->value;
480e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    }
48140e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
482e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    for (;;) {
483e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        int newval;
48440e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
485e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        /* if the mutex is unlocked, its value should be 'mtype' and
486e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         * we try to acquire it by setting its owner and state atomically.
487e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         * NOTE: We put the state to 2 since we _know_ there is contention
488e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         * when we are in this loop. This ensures all waiters will be
489e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         * unlocked.
49040e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner         */
491e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        if (mvalue == mtype) {
492e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            newval = MUTEX_OWNER_TO_BITS(tid) | mtype | MUTEX_STATE_BITS_LOCKED_CONTENDED;
493e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            /* TODO: Change this to __bionic_cmpxchg_acquire when we
494e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner             *        implement it to get rid of the explicit memory
495e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner             *        barrier below.
496e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner             */
497d4e753fea9345c24dcce89531dff9019bef14eb3Elliott Hughes            if (__predict_false(__bionic_cmpxchg(mvalue, newval, &mutex->value) != 0)) {
498e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner                mvalue = mutex->value;
499e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner                continue;
500e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            }
501e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            ANDROID_MEMBAR_FULL();
502e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            return 0;
503e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        }
504e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
505e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        /* the mutex is already locked by another thread, if its state is 1
506e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         * we will change it to 2 to indicate contention. */
507e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        if (MUTEX_STATE_BITS_IS_LOCKED_UNCONTENDED(mvalue)) {
508e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            newval = MUTEX_STATE_BITS_FLIP_CONTENTION(mvalue); /* locked state 1 => state 2 */
509d4e753fea9345c24dcce89531dff9019bef14eb3Elliott Hughes            if (__predict_false(__bionic_cmpxchg(mvalue, newval, &mutex->value) != 0)) {
510e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner                mvalue = mutex->value;
511e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner                continue;
512e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            }
513e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            mvalue = newval;
514e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        }
515e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
516e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        /* wait until the mutex is unlocked */
517e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        __futex_wait_ex(&mutex->value, shared, mvalue, NULL);
51840e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
519e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        mvalue = mutex->value;
52040e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    }
521e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    /* NOTREACHED */
5221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
5231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
52407f1ded1399805fa9367f4db2936832b0c22b7a5Elliott Hughesint pthread_mutex_unlock(pthread_mutex_t* mutex) {
5251543fdf616ddebee7819214437527f380e5c743bElliott Hughes#if !defined(__LP64__)
5261543fdf616ddebee7819214437527f380e5c743bElliott Hughes    if (mutex == NULL) {
5271543fdf616ddebee7819214437527f380e5c743bElliott Hughes        return EINVAL;
5281543fdf616ddebee7819214437527f380e5c743bElliott Hughes    }
5291543fdf616ddebee7819214437527f380e5c743bElliott Hughes#endif
5301543fdf616ddebee7819214437527f380e5c743bElliott Hughes
531a12c54454f3a6132988b68873903f6e9eed7f384Wink Saville    int mvalue, mtype, tid, shared;
532ba9c6f0989ae94778ba2b9f597adc827c9dc81e8David 'Digit' Turner
533022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    mvalue = mutex->value;
534022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    mtype  = (mvalue & MUTEX_TYPE_MASK);
535022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    shared = (mvalue & MUTEX_SHARED_MASK);
53640e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
53740e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    /* Handle common case first */
538d4e753fea9345c24dcce89531dff9019bef14eb3Elliott Hughes    if (__predict_true(mtype == MUTEX_TYPE_BITS_NORMAL)) {
539022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner        _normal_unlock(mutex, shared);
5408641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio        return 0;
541ba9c6f0989ae94778ba2b9f597adc827c9dc81e8David 'Digit' Turner    }
54240e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
54340e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    /* Do we already own this recursive or error-check mutex ? */
54440eabe24e4e3ae8ebe437f1f4e43cf39cbba2e9eElliott Hughes    tid = __get_thread()->tid;
545e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if ( tid != MUTEX_OWNER_FROM_BITS(mvalue) )
54640e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner        return EPERM;
54740e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
548e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    /* If the counter is > 0, we can simply decrement it atomically.
549e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * Since other threads can mutate the lower state bits (and only the
550e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * lower state bits), use a cmpxchg to do it.
551e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     */
552e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if (!MUTEX_COUNTER_BITS_IS_ZERO(mvalue)) {
553e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        for (;;) {
554e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            int newval = mvalue - MUTEX_COUNTER_BITS_ONE;
555d4e753fea9345c24dcce89531dff9019bef14eb3Elliott Hughes            if (__predict_true(__bionic_cmpxchg(mvalue, newval, &mutex->value) == 0)) {
556e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner                /* success: we still own the mutex, so no memory barrier */
557e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner                return 0;
558e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            }
559e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            /* the value changed, so reload and loop */
560e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            mvalue = mutex->value;
561e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        }
56240e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    }
563e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
564e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    /* the counter is 0, so we're going to unlock the mutex by resetting
565e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * its value to 'unlocked'. We need to perform a swap in order
566e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * to read the current state, which will be 2 if there are waiters
567e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * to awake.
568e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     *
569e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * TODO: Change this to __bionic_swap_release when we implement it
570e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     *        to get rid of the explicit memory barrier below.
571e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     */
572e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    ANDROID_MEMBAR_FULL();  /* RELEASE BARRIER */
573e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    mvalue = __bionic_swap(mtype | shared | MUTEX_STATE_BITS_UNLOCKED, &mutex->value);
57440e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
57540e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    /* Wake one waiting thread, if any */
576e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if (MUTEX_STATE_BITS_IS_LOCKED_CONTENDED(mvalue)) {
5776304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner        __futex_wake_ex(&mutex->value, shared, 1);
57888f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner    }
57940e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    return 0;
5801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
5811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
58207f1ded1399805fa9367f4db2936832b0c22b7a5Elliott Hughesint pthread_mutex_trylock(pthread_mutex_t* mutex) {
583a12c54454f3a6132988b68873903f6e9eed7f384Wink Saville    int mvalue, mtype, tid, shared;
5841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
585022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    mvalue = mutex->value;
586022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    mtype  = (mvalue & MUTEX_TYPE_MASK);
587022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    shared = (mvalue & MUTEX_SHARED_MASK);
5881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
58940e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    /* Handle common case first */
590d4e753fea9345c24dcce89531dff9019bef14eb3Elliott Hughes    if ( __predict_true(mtype == MUTEX_TYPE_BITS_NORMAL) )
59140e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    {
592e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        if (__bionic_cmpxchg(shared|MUTEX_STATE_BITS_UNLOCKED,
593e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner                             shared|MUTEX_STATE_BITS_LOCKED_UNCONTENDED,
594e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner                             &mutex->value) == 0) {
595fcd00ebbdf3e7f4e1e7782a65ae10fb0fc03a1aaAndy McFadden            ANDROID_MEMBAR_FULL();
5968641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio            return 0;
597fcd00ebbdf3e7f4e1e7782a65ae10fb0fc03a1aaAndy McFadden        }
59840e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
59940e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner        return EBUSY;
60040e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    }
60140e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
60240e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    /* Do we already own this recursive or error-check mutex ? */
60340eabe24e4e3ae8ebe437f1f4e43cf39cbba2e9eElliott Hughes    tid = __get_thread()->tid;
604e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if ( tid == MUTEX_OWNER_FROM_BITS(mvalue) )
605022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner        return _recursive_increment(mutex, mvalue, mtype);
60640e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
607e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    /* Same as pthread_mutex_lock, except that we don't want to wait, and
608e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * the only operation that can succeed is a single cmpxchg to acquire the
609e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * lock if it is released / not owned by anyone. No need for a complex loop.
610e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     */
611e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    mtype |= shared | MUTEX_STATE_BITS_UNLOCKED;
612e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    mvalue = MUTEX_OWNER_TO_BITS(tid) | mtype | MUTEX_STATE_BITS_LOCKED_UNCONTENDED;
61340e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
614d4e753fea9345c24dcce89531dff9019bef14eb3Elliott Hughes    if (__predict_true(__bionic_cmpxchg(mtype, mvalue, &mutex->value) == 0)) {
615e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        ANDROID_MEMBAR_FULL();
616e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        return 0;
617e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    }
61840e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
619e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    return EBUSY;
6201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
6211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6220e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughesstatic int __pthread_mutex_timedlock(pthread_mutex_t* mutex, const timespec* abs_timeout, clockid_t clock) {
6230e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  timespec ts;
6243f56b7f65adb9ee35cd0f878ca00b92011eec427David 'Digit' Turner
6250e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  int mvalue = mutex->value;
6260e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  int mtype  = (mvalue & MUTEX_TYPE_MASK);
6270e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  int shared = (mvalue & MUTEX_SHARED_MASK);
6283f56b7f65adb9ee35cd0f878ca00b92011eec427David 'Digit' Turner
6290e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  // Handle common case first.
6300e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  if (__predict_true(mtype == MUTEX_TYPE_BITS_NORMAL)) {
6310e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    const int unlocked           = shared | MUTEX_STATE_BITS_UNLOCKED;
6320e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    const int locked_uncontended = shared | MUTEX_STATE_BITS_LOCKED_UNCONTENDED;
6330e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    const int locked_contended   = shared | MUTEX_STATE_BITS_LOCKED_CONTENDED;
6343f56b7f65adb9ee35cd0f878ca00b92011eec427David 'Digit' Turner
6350e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    // Fast path for uncontended lock. Note: MUTEX_TYPE_BITS_NORMAL is 0.
6360e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    if (__bionic_cmpxchg(unlocked, locked_uncontended, &mutex->value) == 0) {
6370e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes      ANDROID_MEMBAR_FULL();
6380e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes      return 0;
6390e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    }
64040e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
6410e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    // Loop while needed.
6420e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    while (__bionic_swap(locked_contended, &mutex->value) != unlocked) {
6430e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes      if (__timespec_from_absolute(&ts, abs_timeout, clock) < 0) {
6440e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes        return ETIMEDOUT;
6450e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes      }
6460e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes      __futex_wait_ex(&mutex->value, shared, locked_contended, &ts);
6470e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    }
6480e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    ANDROID_MEMBAR_FULL();
6490e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    return 0;
6500e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  }
651e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
6520e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  // Do we already own this recursive or error-check mutex?
6530e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  pid_t tid = __get_thread()->tid;
6540e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  if (tid == MUTEX_OWNER_FROM_BITS(mvalue)) {
6550e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    return _recursive_increment(mutex, mvalue, mtype);
6560e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  }
6578641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio
6580e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  // The following implements the same loop as pthread_mutex_lock_impl
6590e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  // but adds checks to ensure that the operation never exceeds the
6600e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  // absolute expiration time.
6610e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  mtype |= shared;
66240e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
6630e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  // First try a quick lock.
6640e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  if (mvalue == mtype) {
6650e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    mvalue = MUTEX_OWNER_TO_BITS(tid) | mtype | MUTEX_STATE_BITS_LOCKED_UNCONTENDED;
6660e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    if (__predict_true(__bionic_cmpxchg(mtype, mvalue, &mutex->value) == 0)) {
6670e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes      ANDROID_MEMBAR_FULL();
6680e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes      return 0;
6690e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    }
6700e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    mvalue = mutex->value;
6710e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  }
6720e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes
6730e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  while (true) {
6740e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    // If the value is 'unlocked', try to acquire it directly.
6750e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    // NOTE: put state to 2 since we know there is contention.
6760e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    if (mvalue == mtype) { // Unlocked.
6770e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes      mvalue = MUTEX_OWNER_TO_BITS(tid) | mtype | MUTEX_STATE_BITS_LOCKED_CONTENDED;
6780e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes      if (__bionic_cmpxchg(mtype, mvalue, &mutex->value) == 0) {
679fcd00ebbdf3e7f4e1e7782a65ae10fb0fc03a1aaAndy McFadden        ANDROID_MEMBAR_FULL();
68040e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner        return 0;
6810e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes      }
6820e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes      // The value changed before we could lock it. We need to check
6830e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes      // the time to avoid livelocks, reload the value, then loop again.
6840e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes      if (__timespec_from_absolute(&ts, abs_timeout, clock) < 0) {
6850e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes        return ETIMEDOUT;
6860e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes      }
6870e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes
6880e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes      mvalue = mutex->value;
6890e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes      continue;
69040e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    }
6913f56b7f65adb9ee35cd0f878ca00b92011eec427David 'Digit' Turner
6920e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    // The value is locked. If 'uncontended', try to switch its state
6930e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    // to 'contented' to ensure we get woken up later.
6940e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    if (MUTEX_STATE_BITS_IS_LOCKED_UNCONTENDED(mvalue)) {
6950e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes      int newval = MUTEX_STATE_BITS_FLIP_CONTENTION(mvalue);
6960e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes      if (__bionic_cmpxchg(mvalue, newval, &mutex->value) != 0) {
6970e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes        // This failed because the value changed, reload it.
698e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        mvalue = mutex->value;
6990e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes      } else {
7000e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes        // This succeeded, update mvalue.
7010e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes        mvalue = newval;
7020e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes      }
703e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    }
70488f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner
7050e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    // Check time and update 'ts'.
7060e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    if (__timespec_from_absolute(&ts, abs_timeout, clock) < 0) {
7070e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes      return ETIMEDOUT;
7080e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    }
70940e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
7100e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    // Only wait to be woken up if the state is '2', otherwise we'll
7110e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    // simply loop right now. This can happen when the second cmpxchg
7120e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    // in our loop failed because the mutex was unlocked by another thread.
7130e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    if (MUTEX_STATE_BITS_IS_LOCKED_CONTENDED(mvalue)) {
7140e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes      if (__futex_wait_ex(&mutex->value, shared, mvalue, &ts) == -ETIMEDOUT) {
7150e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes        return ETIMEDOUT;
7160e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes      }
7170e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes      mvalue = mutex->value;
718ba9c6f0989ae94778ba2b9f597adc827c9dc81e8David 'Digit' Turner    }
7190e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  }
7200e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  /* NOTREACHED */
721ba9c6f0989ae94778ba2b9f597adc827c9dc81e8David 'Digit' Turner}
722ba9c6f0989ae94778ba2b9f597adc827c9dc81e8David 'Digit' Turner
7230e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes#if !defined(__LP64__)
7240e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughesextern "C" int pthread_mutex_lock_timeout_np(pthread_mutex_t* mutex, unsigned ms) {
7250e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  timespec abs_timeout;
7260e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  clock_gettime(CLOCK_MONOTONIC, &abs_timeout);
7270e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  abs_timeout.tv_sec  += ms / 1000;
7280e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  abs_timeout.tv_nsec += (ms % 1000) * 1000000;
7290e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  if (abs_timeout.tv_nsec >= 1000000000) {
7300e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    abs_timeout.tv_sec++;
7310e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes    abs_timeout.tv_nsec -= 1000000000;
7320e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  }
7330e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes
73407f1ded1399805fa9367f4db2936832b0c22b7a5Elliott Hughes  int error = __pthread_mutex_timedlock(mutex, &abs_timeout, CLOCK_MONOTONIC);
73507f1ded1399805fa9367f4db2936832b0c22b7a5Elliott Hughes  if (error == ETIMEDOUT) {
73607f1ded1399805fa9367f4db2936832b0c22b7a5Elliott Hughes    error = EBUSY;
7370e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  }
73807f1ded1399805fa9367f4db2936832b0c22b7a5Elliott Hughes  return error;
7390e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes}
7400e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes#endif
7410e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes
7420e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughesint pthread_mutex_timedlock(pthread_mutex_t* mutex, const timespec* abs_timeout) {
7430e714a5b41451e84c5ded93a42c9a4b0a9440691Elliott Hughes  return __pthread_mutex_timedlock(mutex, abs_timeout, CLOCK_REALTIME);
7447c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian}
7457c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian
74607f1ded1399805fa9367f4db2936832b0c22b7a5Elliott Hughesint pthread_mutex_destroy(pthread_mutex_t* mutex) {
74707f1ded1399805fa9367f4db2936832b0c22b7a5Elliott Hughes  // Use trylock to ensure that the mutex is valid and not already locked.
74807f1ded1399805fa9367f4db2936832b0c22b7a5Elliott Hughes  int error = pthread_mutex_trylock(mutex);
74907f1ded1399805fa9367f4db2936832b0c22b7a5Elliott Hughes  if (error != 0) {
75007f1ded1399805fa9367f4db2936832b0c22b7a5Elliott Hughes    return error;
75107f1ded1399805fa9367f4db2936832b0c22b7a5Elliott Hughes  }
75207f1ded1399805fa9367f4db2936832b0c22b7a5Elliott Hughes  mutex->value = 0xdead10cc;
75307f1ded1399805fa9367f4db2936832b0c22b7a5Elliott Hughes  return 0;
7547c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian}
755