pthread_mutex.cpp revision dff7203ee99ccac446b9a1c4371753a5216c6db4
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>
331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/atomics.h>
3484114c8dd5b17efecf7988f263ce431208d7be5aElliott Hughes#include <sys/mman.h>
35d0c884d3595ecca03c3e70de9909c090cd5f9caePierre Peiffer#include <unistd.h>
36d0c884d3595ecca03c3e70de9909c090cd5f9caePierre Peiffer
371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "pthread_internal.h"
38eb847bc8666842a3cfc9c06e8458ad1abebebaf0Elliott Hughes
39eb847bc8666842a3cfc9c06e8458ad1abebebaf0Elliott Hughes#include "private/bionic_atomic_inline.h"
40eb847bc8666842a3cfc9c06e8458ad1abebebaf0Elliott Hughes#include "private/bionic_futex.h"
41eb847bc8666842a3cfc9c06e8458ad1abebebaf0Elliott Hughes#include "private/bionic_tls.h"
42eb847bc8666842a3cfc9c06e8458ad1abebebaf0Elliott Hughes#include "private/thread_private.h"
431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
447c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopianextern void pthread_debug_mutex_lock_check(pthread_mutex_t *mutex);
457c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopianextern void pthread_debug_mutex_unlock_check(pthread_mutex_t *mutex);
467c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian
471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* a mutex is implemented as a 32-bit integer holding the following fields
481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * bits:     name     description
5040eabe24e4e3ae8ebe437f1f4e43cf39cbba2e9eElliott Hughes * 31-16     tid      owner thread's tid (recursive and errorcheck only)
511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 15-14     type     mutex type
5288f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner * 13        shared   process-shared flag
5388f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner * 12-2      counter  counter of recursive mutexes
541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 1-0       state    lock state (0, 1 or 2)
551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
57e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* Convenience macro, creates a mask of 'bits' bits that starts from
58e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * the 'shift'-th least significant bit in a 32-bit word.
59e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *
60e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * Examples: FIELD_MASK(0,4)  -> 0xf
61e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *           FIELD_MASK(16,9) -> 0x1ff0000
62e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner */
63e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  FIELD_MASK(shift,bits)           (((1 << (bits))-1) << (shift))
64e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
65e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* This one is used to create a bit pattern from a given field value */
66e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  FIELD_TO_BITS(val,shift,bits)    (((val) & ((1 << (bits))-1)) << (shift))
67e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
68e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* And this one does the opposite, i.e. extract a field's value from a bit pattern */
69e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  FIELD_FROM_BITS(val,shift,bits)  (((val) >> (shift)) & ((1 << (bits))-1))
70e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
71e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* Mutex state:
72e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *
73e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * 0 for unlocked
74e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * 1 for locked, no waiters
75e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * 2 for locked, maybe waiters
76e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner */
77e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_SHIFT      0
78e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_LEN        2
79e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
80e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_MASK           FIELD_MASK(MUTEX_STATE_SHIFT, MUTEX_STATE_LEN)
81e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_FROM_BITS(v)   FIELD_FROM_BITS(v, MUTEX_STATE_SHIFT, MUTEX_STATE_LEN)
82e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_TO_BITS(v)     FIELD_TO_BITS(v, MUTEX_STATE_SHIFT, MUTEX_STATE_LEN)
83e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
84e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_UNLOCKED            0   /* must be 0 to match __PTHREAD_MUTEX_INIT_VALUE */
85e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_LOCKED_UNCONTENDED  1   /* must be 1 due to atomic dec in unlock operation */
86e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_LOCKED_CONTENDED    2   /* must be 1 + LOCKED_UNCONTENDED due to atomic dec */
87e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
88e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_FROM_BITS(v)    FIELD_FROM_BITS(v, MUTEX_STATE_SHIFT, MUTEX_STATE_LEN)
89e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_TO_BITS(v)      FIELD_TO_BITS(v, MUTEX_STATE_SHIFT, MUTEX_STATE_LEN)
90e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
91e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_BITS_UNLOCKED            MUTEX_STATE_TO_BITS(MUTEX_STATE_UNLOCKED)
92e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_BITS_LOCKED_UNCONTENDED  MUTEX_STATE_TO_BITS(MUTEX_STATE_LOCKED_UNCONTENDED)
93e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_BITS_LOCKED_CONTENDED    MUTEX_STATE_TO_BITS(MUTEX_STATE_LOCKED_CONTENDED)
94e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
95e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* return true iff the mutex if locked with no waiters */
96e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_BITS_IS_LOCKED_UNCONTENDED(v)  (((v) & MUTEX_STATE_MASK) == MUTEX_STATE_BITS_LOCKED_UNCONTENDED)
97e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
98e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* return true iff the mutex if locked with maybe waiters */
99e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_BITS_IS_LOCKED_CONTENDED(v)   (((v) & MUTEX_STATE_MASK) == MUTEX_STATE_BITS_LOCKED_CONTENDED)
100e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
101e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* used to flip from LOCKED_UNCONTENDED to LOCKED_CONTENDED */
102e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_STATE_BITS_FLIP_CONTENTION(v)      ((v) ^ (MUTEX_STATE_BITS_LOCKED_CONTENDED ^ MUTEX_STATE_BITS_LOCKED_UNCONTENDED))
103e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
104e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* Mutex counter:
105e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *
106e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * We need to check for overflow before incrementing, and we also need to
107e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * detect when the counter is 0
108e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner */
109e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_COUNTER_SHIFT         2
110e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_COUNTER_LEN           11
111e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_COUNTER_MASK          FIELD_MASK(MUTEX_COUNTER_SHIFT, MUTEX_COUNTER_LEN)
112e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
113e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_COUNTER_BITS_WILL_OVERFLOW(v)    (((v) & MUTEX_COUNTER_MASK) == MUTEX_COUNTER_MASK)
114e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_COUNTER_BITS_IS_ZERO(v)          (((v) & MUTEX_COUNTER_MASK) == 0)
115e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
116e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* Used to increment the counter directly after overflow has been checked */
117e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_COUNTER_BITS_ONE      FIELD_TO_BITS(1,MUTEX_COUNTER_SHIFT,MUTEX_COUNTER_LEN)
118e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
119e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* Returns true iff the counter is 0 */
120e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_COUNTER_BITS_ARE_ZERO(v)  (((v) & MUTEX_COUNTER_MASK) == 0)
1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
122e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* Mutex shared bit flag
123e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *
124e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * This flag is set to indicate that the mutex is shared among processes.
125e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * This changes the futex opcode we use for futex wait/wake operations
126e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * (non-shared operations are much faster).
127e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner */
128e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_SHARED_SHIFT    13
129e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_SHARED_MASK     FIELD_MASK(MUTEX_SHARED_SHIFT,1)
130e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
131e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* Mutex type:
132e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *
133e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * We support normal, recursive and errorcheck mutexes.
134e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *
135e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * The constants defined here *cannot* be changed because they must match
136e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * the C library ABI which defines the following initialization values in
137e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * <pthread.h>:
138e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *
139e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *   __PTHREAD_MUTEX_INIT_VALUE
140e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *   __PTHREAD_RECURSIVE_MUTEX_VALUE
141e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *   __PTHREAD_ERRORCHECK_MUTEX_INIT_VALUE
142e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner */
143e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_TYPE_SHIFT      14
144e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_TYPE_LEN        2
145e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_TYPE_MASK       FIELD_MASK(MUTEX_TYPE_SHIFT,MUTEX_TYPE_LEN)
146022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner
147e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_TYPE_NORMAL          0  /* Must be 0 to match __PTHREAD_MUTEX_INIT_VALUE */
148e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_TYPE_RECURSIVE       1
149e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_TYPE_ERRORCHECK      2
150e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
151e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_TYPE_TO_BITS(t)       FIELD_TO_BITS(t, MUTEX_TYPE_SHIFT, MUTEX_TYPE_LEN)
152e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
153e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_TYPE_BITS_NORMAL      MUTEX_TYPE_TO_BITS(MUTEX_TYPE_NORMAL)
154e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_TYPE_BITS_RECURSIVE   MUTEX_TYPE_TO_BITS(MUTEX_TYPE_RECURSIVE)
155e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_TYPE_BITS_ERRORCHECK  MUTEX_TYPE_TO_BITS(MUTEX_TYPE_ERRORCHECK)
156e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
157e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* Mutex owner field:
158e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *
159e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * This is only used for recursive and errorcheck mutexes. It holds the
16040eabe24e4e3ae8ebe437f1f4e43cf39cbba2e9eElliott Hughes * tid of the owning thread. Note that this works because the Linux
16140eabe24e4e3ae8ebe437f1f4e43cf39cbba2e9eElliott Hughes * kernel _only_ uses 16-bit values for tids.
162e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *
163e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * More specifically, it will wrap to 10000 when it reaches over 32768 for
164e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * application processes. You can check this by running the following inside
165e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * an adb shell session:
166e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *
167e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    OLDPID=$$;
168e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    while true; do
169e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    NEWPID=$(sh -c 'echo $$')
170e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if [ "$NEWPID" -gt 32768 ]; then
171e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        echo "AARGH: new PID $NEWPID is too high!"
172e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        exit 1
173e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    fi
174e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if [ "$NEWPID" -lt "$OLDPID" ]; then
175e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        echo "****** Wrapping from PID $OLDPID to $NEWPID. *******"
176e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    else
177e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        echo -n "$NEWPID!"
178e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    fi
179e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    OLDPID=$NEWPID
180e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    done
181e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
182e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * Note that you can run the same example on a desktop Linux system,
183e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * the wrapping will also happen at 32768, but will go back to 300 instead.
184e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner */
185e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_OWNER_SHIFT     16
186e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_OWNER_LEN       16
187e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
188e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_OWNER_FROM_BITS(v)    FIELD_FROM_BITS(v,MUTEX_OWNER_SHIFT,MUTEX_OWNER_LEN)
189e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner#define  MUTEX_OWNER_TO_BITS(v)      FIELD_TO_BITS(v,MUTEX_OWNER_SHIFT,MUTEX_OWNER_LEN)
190e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
191e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner/* Convenience macros.
192e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner *
193e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner * These are used to form or modify the bit pattern of a given mutex value
194e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner */
1951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
19888f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner/* a mutex attribute holds the following fields
19988f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner *
20088f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner * bits:     name       description
20188f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner * 0-3       type       type of mutex
20288f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner * 4         shared     process-shared flag
20388f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner */
20488f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner#define  MUTEXATTR_TYPE_MASK   0x000f
20588f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner#define  MUTEXATTR_SHARED_MASK 0x0010
2061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint pthread_mutexattr_init(pthread_mutexattr_t *attr)
2091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
2101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if (attr) {
2111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        *attr = PTHREAD_MUTEX_DEFAULT;
2121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return 0;
2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    } else {
2141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return EINVAL;
2151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
2201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if (attr) {
2211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        *attr = -1;
2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return 0;
2231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    } else {
2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return EINVAL;
2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
2261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
2271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type)
2291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
23088f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner    if (attr) {
23188f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner        int  atype = (*attr & MUTEXATTR_TYPE_MASK);
23288f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner
23388f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner         if (atype >= PTHREAD_MUTEX_NORMAL &&
23488f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner             atype <= PTHREAD_MUTEX_ERRORCHECK) {
23588f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner            *type = atype;
23688f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner            return 0;
23788f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner        }
2381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
2391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    return EINVAL;
2401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
2411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
2441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if (attr && type >= PTHREAD_MUTEX_NORMAL &&
2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                type <= PTHREAD_MUTEX_ERRORCHECK ) {
24688f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner        *attr = (*attr & ~MUTEXATTR_TYPE_MASK) | type;
2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return 0;
2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
2491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    return EINVAL;
2501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* process-shared mutexes are not supported at the moment */
2531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int  pshared)
2551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
2561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if (!attr)
2571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return EINVAL;
2581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
259b7681167cbe91c2bb95cccdc08f75184ed1fb839Mathias Agopian    switch (pshared) {
260b7681167cbe91c2bb95cccdc08f75184ed1fb839Mathias Agopian    case PTHREAD_PROCESS_PRIVATE:
26188f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner        *attr &= ~MUTEXATTR_SHARED_MASK;
26288f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner        return 0;
26388f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner
264b7681167cbe91c2bb95cccdc08f75184ed1fb839Mathias Agopian    case PTHREAD_PROCESS_SHARED:
265b7681167cbe91c2bb95cccdc08f75184ed1fb839Mathias Agopian        /* our current implementation of pthread actually supports shared
266b7681167cbe91c2bb95cccdc08f75184ed1fb839Mathias Agopian         * mutexes but won't cleanup if a process dies with the mutex held.
267b7681167cbe91c2bb95cccdc08f75184ed1fb839Mathias Agopian         * Nevertheless, it's better than nothing. Shared mutexes are used
268b7681167cbe91c2bb95cccdc08f75184ed1fb839Mathias Agopian         * by surfaceflinger and audioflinger.
269b7681167cbe91c2bb95cccdc08f75184ed1fb839Mathias Agopian         */
27088f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner        *attr |= MUTEXATTR_SHARED_MASK;
271b7681167cbe91c2bb95cccdc08f75184ed1fb839Mathias Agopian        return 0;
272b7681167cbe91c2bb95cccdc08f75184ed1fb839Mathias Agopian    }
27388f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner    return EINVAL;
2741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
2751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
276c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesint pthread_mutexattr_getpshared(const pthread_mutexattr_t* attr, int* pshared) {
27788f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner    if (!attr || !pshared)
2781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return EINVAL;
2791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
28088f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner    *pshared = (*attr & MUTEXATTR_SHARED_MASK) ? PTHREAD_PROCESS_SHARED
28188f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner                                               : PTHREAD_PROCESS_PRIVATE;
2821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    return 0;
2831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
2841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
285dff7203ee99ccac446b9a1c4371753a5216c6db4Elliott Hughesint pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* attr) {
286d4e753fea9345c24dcce89531dff9019bef14eb3Elliott Hughes    if (__predict_true(attr == NULL)) {
287e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        mutex->value = MUTEX_TYPE_BITS_NORMAL;
28888f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner        return 0;
289ba9c6f0989ae94778ba2b9f597adc827c9dc81e8David 'Digit' Turner    }
29088f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner
291dff7203ee99ccac446b9a1c4371753a5216c6db4Elliott Hughes    int value = 0;
292dff7203ee99ccac446b9a1c4371753a5216c6db4Elliott Hughes    if ((*attr & MUTEXATTR_SHARED_MASK) != 0) {
29388f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner        value |= MUTEX_SHARED_MASK;
294dff7203ee99ccac446b9a1c4371753a5216c6db4Elliott Hughes    }
29588f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner
29688f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner    switch (*attr & MUTEXATTR_TYPE_MASK) {
29788f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner    case PTHREAD_MUTEX_NORMAL:
298e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        value |= MUTEX_TYPE_BITS_NORMAL;
29988f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner        break;
30088f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner    case PTHREAD_MUTEX_RECURSIVE:
301e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        value |= MUTEX_TYPE_BITS_RECURSIVE;
30288f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner        break;
30388f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner    case PTHREAD_MUTEX_ERRORCHECK:
304e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        value |= MUTEX_TYPE_BITS_ERRORCHECK;
30588f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner        break;
30688f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner    default:
30788f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner        return EINVAL;
30888f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner    }
30988f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner
31088f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner    mutex->value = value;
31188f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner    return 0;
3121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
3131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
3161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Lock a non-recursive mutex.
3171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
3181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * As noted above, there are three states:
3191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *   0 (unlocked, no contention)
3201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *   1 (locked, no contention)
3211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *   2 (locked, contention)
3221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
3231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Non-recursive mutexes don't use the thread-id or counter fields, and the
3241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * "type" value is zero, so the only bits that will be set are the ones in
3251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * the lock state field.
3261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
3271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic __inline__ void
328022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner_normal_lock(pthread_mutex_t*  mutex, int shared)
3291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
330e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    /* convenience shortcuts */
331e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    const int unlocked           = shared | MUTEX_STATE_BITS_UNLOCKED;
332e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    const int locked_uncontended = shared | MUTEX_STATE_BITS_LOCKED_UNCONTENDED;
3338641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio    /*
3348641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio     * The common case is an unlocked mutex, so we begin by trying to
335e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * change the lock's state from 0 (UNLOCKED) to 1 (LOCKED).
336e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * __bionic_cmpxchg() returns 0 if it made the swap successfully.
337e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * If the result is nonzero, this lock is already held by another thread.
3388641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio     */
339e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if (__bionic_cmpxchg(unlocked, locked_uncontended, &mutex->value) != 0) {
340e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        const int locked_contended = shared | MUTEX_STATE_BITS_LOCKED_CONTENDED;
3411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /*
3428641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * We want to go to sleep until the mutex is available, which
343e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         * requires promoting it to state 2 (CONTENDED). We need to
344e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         * swap in the new state value and then wait until somebody wakes us up.
3458641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         *
346e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner         * __bionic_swap() returns the previous value.  We swap 2 in and
3478641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * see if we got zero back; if so, we have acquired the lock.  If
3488641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * not, another thread still holds the lock and we wait again.
3498641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         *
3508641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * The second argument to the __futex_wait() call is compared
3518641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * against the current value.  If it doesn't match, __futex_wait()
3528641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * returns immediately (otherwise, it sleeps for a time specified
3538641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * by the third argument; 0 means sleep forever).  This ensures
3548641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * that the mutex is in state 2 when we go to sleep on it, which
3558641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * guarantees a wake-up call.
3568641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         */
357e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        while (__bionic_swap(locked_contended, &mutex->value) != unlocked)
358e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            __futex_wait_ex(&mutex->value, shared, locked_contended, 0);
3591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
360fcd00ebbdf3e7f4e1e7782a65ae10fb0fc03a1aaAndy McFadden    ANDROID_MEMBAR_FULL();
3611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
3621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
3641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Release a non-recursive mutex.  The caller is responsible for determining
3651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * that we are in fact the owner of this lock.
3661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
3671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic __inline__ void
368022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner_normal_unlock(pthread_mutex_t*  mutex, int shared)
3691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
370fcd00ebbdf3e7f4e1e7782a65ae10fb0fc03a1aaAndy McFadden    ANDROID_MEMBAR_FULL();
371fcd00ebbdf3e7f4e1e7782a65ae10fb0fc03a1aaAndy McFadden
3728641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio    /*
37388f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner     * The mutex state will be 1 or (rarely) 2.  We use an atomic decrement
374e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner     * to release the lock.  __bionic_atomic_dec() returns the previous value;
3758641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio     * if it wasn't 1 we have to do some additional work.
3768641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio     */
377e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if (__bionic_atomic_dec(&mutex->value) != (shared|MUTEX_STATE_BITS_LOCKED_UNCONTENDED)) {
3781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /*
3798641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * Start by releasing the lock.  The decrement changed it from
3808641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * "contended lock" to "uncontended lock", which means we still
3818641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * hold it, and anybody who tries to sneak in will push it back
3828641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * to state 2.
3838641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         *
3848641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * Once we set it to zero the lock is up for grabs.  We follow
3858641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * this with a __futex_wake() to ensure that one of the waiting
3868641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * threads has a chance to grab it.
3878641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         *
3888641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * This doesn't cause a race with the swap/wait pair in
3898641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * _normal_lock(), because the __futex_wait() call there will
3908641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * return immediately if the mutex value isn't 2.
3918641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         */
39288f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner        mutex->value = shared;
3938641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio
3948641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio        /*
3958641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * Wake up one waiting thread.  We don't know which thread will be
3968641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * woken or when it'll start executing -- futexes make no guarantees
3978641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * here.  There may not even be a thread waiting.
3988641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         *
3998641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * The newly-woken thread will replace the 0 we just set above
4008641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * with 2, which means that when it eventually releases the mutex
4018641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * it will also call FUTEX_WAKE.  This results in one extra wake
4028641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * call whenever a lock is contended, but lets us avoid forgetting
4038641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * anyone without requiring us to track the number of sleepers.
4048641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         *
4058641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * It's possible for another thread to sneak in and grab the lock
4068641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * between the zero assignment above and the wake call below.  If
4078641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * the new thread is "slow" and holds the lock for a while, we'll
4088641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * wake up a sleeper, which will swap in a 2 and then go back to
4098641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * sleep since the lock is still held.  If the new thread is "fast",
4108641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * running to completion before we call wake, the thread we
4118641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * eventually wake will find an unlocked mutex and will execute.
4128641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * Either way we have correct behavior and nobody is orphaned on
4138641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         * the wait queue.
4148641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio         */
4156304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner        __futex_wake_ex(&mutex->value, shared, 1);
4161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
4171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
4181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
419022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner/* This common inlined function is used to increment the counter of an
420022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner * errorcheck or recursive mutex.
421022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner *
422022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner * For errorcheck mutexes, it will return EDEADLK
423022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner * If the counter overflows, it will return EAGAIN
424022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner * Otherwise, it atomically increments the counter and returns 0
425022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner * after providing an acquire barrier.
426022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner *
427022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner * mtype is the current mutex type
428022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner * mvalue is the current mutex value (already loaded)
429022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner * mutex pointers to the mutex.
430022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner */
431022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turnerstatic __inline__ __attribute__((always_inline)) int
432022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner_recursive_increment(pthread_mutex_t* mutex, int mvalue, int mtype)
433022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner{
434e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if (mtype == MUTEX_TYPE_BITS_ERRORCHECK) {
435022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner        /* trying to re-lock a mutex we already acquired */
436022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner        return EDEADLK;
437022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    }
438022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner
439022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    /* Detect recursive lock overflow and return EAGAIN.
440022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner     * This is safe because only the owner thread can modify the
441b57db7581cabb98651c4d8940d65c5c404b914adDavid 'Digit' Turner     * counter bits in the mutex value.
442022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner     */
443e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if (MUTEX_COUNTER_BITS_WILL_OVERFLOW(mvalue)) {
444022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner        return EAGAIN;
445022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    }
446022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner
447022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    /* We own the mutex, but other threads are able to change
448b57db7581cabb98651c4d8940d65c5c404b914adDavid 'Digit' Turner     * the lower bits (e.g. promoting it to "contended"), so we
449e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * need to use an atomic cmpxchg loop to update the counter.
450b57db7581cabb98651c4d8940d65c5c404b914adDavid 'Digit' Turner     */
451e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    for (;;) {
452e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        /* increment counter, overflow was already checked */
453e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        int newval = mvalue + MUTEX_COUNTER_BITS_ONE;
454d4e753fea9345c24dcce89531dff9019bef14eb3Elliott Hughes        if (__predict_true(__bionic_cmpxchg(mvalue, newval, &mutex->value) == 0)) {
455e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            /* mutex is still locked, not need for a memory barrier */
456e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            return 0;
457e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        }
458e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        /* the value was changed, this happens when another thread changes
459e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         * the lower state bits from 1 to 2 to indicate contention. This
460e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         * cannot change the counter, so simply reload and try again.
461e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         */
462e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        mvalue = mutex->value;
463e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    }
4641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
4651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4667c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian__LIBC_HIDDEN__
4677c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopianint pthread_mutex_lock_impl(pthread_mutex_t *mutex)
4681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
469a12c54454f3a6132988b68873903f6e9eed7f384Wink Saville    int mvalue, mtype, tid, shared;
47040e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
471022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    mvalue = mutex->value;
472022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    mtype = (mvalue & MUTEX_TYPE_MASK);
473022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    shared = (mvalue & MUTEX_SHARED_MASK);
47440e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
47540e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    /* Handle normal case first */
476d4e753fea9345c24dcce89531dff9019bef14eb3Elliott Hughes    if ( __predict_true(mtype == MUTEX_TYPE_BITS_NORMAL) ) {
477022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner        _normal_lock(mutex, shared);
47840e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner        return 0;
47940e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    }
48040e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
48140e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    /* Do we already own this recursive or error-check mutex ? */
48240eabe24e4e3ae8ebe437f1f4e43cf39cbba2e9eElliott Hughes    tid = __get_thread()->tid;
483e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if ( tid == MUTEX_OWNER_FROM_BITS(mvalue) )
484022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner        return _recursive_increment(mutex, mvalue, mtype);
48540e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
486e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    /* Add in shared state to avoid extra 'or' operations below */
4876304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner    mtype |= shared;
48888f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner
489e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    /* First, if the mutex is unlocked, try to quickly acquire it.
490e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * In the optimistic case where this works, set the state to 1 to
491e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * indicate locked with no contention */
492e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if (mvalue == mtype) {
493e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        int newval = MUTEX_OWNER_TO_BITS(tid) | mtype | MUTEX_STATE_BITS_LOCKED_UNCONTENDED;
494e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        if (__bionic_cmpxchg(mvalue, newval, &mutex->value) == 0) {
495e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            ANDROID_MEMBAR_FULL();
496e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            return 0;
49740e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner        }
498e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        /* argh, the value changed, reload before entering the loop */
499e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        mvalue = mutex->value;
500e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    }
50140e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
502e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    for (;;) {
503e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        int newval;
50440e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
505e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        /* if the mutex is unlocked, its value should be 'mtype' and
506e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         * we try to acquire it by setting its owner and state atomically.
507e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         * NOTE: We put the state to 2 since we _know_ there is contention
508e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         * when we are in this loop. This ensures all waiters will be
509e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         * unlocked.
51040e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner         */
511e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        if (mvalue == mtype) {
512e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            newval = MUTEX_OWNER_TO_BITS(tid) | mtype | MUTEX_STATE_BITS_LOCKED_CONTENDED;
513e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            /* TODO: Change this to __bionic_cmpxchg_acquire when we
514e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner             *        implement it to get rid of the explicit memory
515e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner             *        barrier below.
516e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner             */
517d4e753fea9345c24dcce89531dff9019bef14eb3Elliott Hughes            if (__predict_false(__bionic_cmpxchg(mvalue, newval, &mutex->value) != 0)) {
518e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner                mvalue = mutex->value;
519e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner                continue;
520e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            }
521e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            ANDROID_MEMBAR_FULL();
522e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            return 0;
523e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        }
524e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
525e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        /* the mutex is already locked by another thread, if its state is 1
526e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         * we will change it to 2 to indicate contention. */
527e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        if (MUTEX_STATE_BITS_IS_LOCKED_UNCONTENDED(mvalue)) {
528e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            newval = MUTEX_STATE_BITS_FLIP_CONTENTION(mvalue); /* locked state 1 => state 2 */
529d4e753fea9345c24dcce89531dff9019bef14eb3Elliott Hughes            if (__predict_false(__bionic_cmpxchg(mvalue, newval, &mutex->value) != 0)) {
530e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner                mvalue = mutex->value;
531e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner                continue;
532e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            }
533e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            mvalue = newval;
534e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        }
535e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
536e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        /* wait until the mutex is unlocked */
537e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        __futex_wait_ex(&mutex->value, shared, mvalue, NULL);
53840e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
539e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        mvalue = mutex->value;
54040e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    }
541e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    /* NOTREACHED */
5421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
5431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5447c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopianint pthread_mutex_lock(pthread_mutex_t *mutex)
5457c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian{
5467c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian    int err = pthread_mutex_lock_impl(mutex);
5477c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian    if (PTHREAD_DEBUG_ENABLED) {
5487c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian        if (!err) {
5497c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian            pthread_debug_mutex_lock_check(mutex);
5507c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian        }
5517c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian    }
5527c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian    return err;
5537c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian}
5541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5557c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian__LIBC_HIDDEN__
5567c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopianint pthread_mutex_unlock_impl(pthread_mutex_t *mutex)
5571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
558a12c54454f3a6132988b68873903f6e9eed7f384Wink Saville    int mvalue, mtype, tid, shared;
559ba9c6f0989ae94778ba2b9f597adc827c9dc81e8David 'Digit' Turner
560022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    mvalue = mutex->value;
561022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    mtype  = (mvalue & MUTEX_TYPE_MASK);
562022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    shared = (mvalue & MUTEX_SHARED_MASK);
56340e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
56440e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    /* Handle common case first */
565d4e753fea9345c24dcce89531dff9019bef14eb3Elliott Hughes    if (__predict_true(mtype == MUTEX_TYPE_BITS_NORMAL)) {
566022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner        _normal_unlock(mutex, shared);
5678641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio        return 0;
568ba9c6f0989ae94778ba2b9f597adc827c9dc81e8David 'Digit' Turner    }
56940e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
57040e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    /* Do we already own this recursive or error-check mutex ? */
57140eabe24e4e3ae8ebe437f1f4e43cf39cbba2e9eElliott Hughes    tid = __get_thread()->tid;
572e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if ( tid != MUTEX_OWNER_FROM_BITS(mvalue) )
57340e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner        return EPERM;
57440e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
575e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    /* If the counter is > 0, we can simply decrement it atomically.
576e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * Since other threads can mutate the lower state bits (and only the
577e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * lower state bits), use a cmpxchg to do it.
578e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     */
579e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if (!MUTEX_COUNTER_BITS_IS_ZERO(mvalue)) {
580e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        for (;;) {
581e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            int newval = mvalue - MUTEX_COUNTER_BITS_ONE;
582d4e753fea9345c24dcce89531dff9019bef14eb3Elliott Hughes            if (__predict_true(__bionic_cmpxchg(mvalue, newval, &mutex->value) == 0)) {
583e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner                /* success: we still own the mutex, so no memory barrier */
584e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner                return 0;
585e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            }
586e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            /* the value changed, so reload and loop */
587e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            mvalue = mutex->value;
588e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        }
58940e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    }
590e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
591e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    /* the counter is 0, so we're going to unlock the mutex by resetting
592e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * its value to 'unlocked'. We need to perform a swap in order
593e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * to read the current state, which will be 2 if there are waiters
594e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * to awake.
595e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     *
596e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * TODO: Change this to __bionic_swap_release when we implement it
597e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     *        to get rid of the explicit memory barrier below.
598e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     */
599e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    ANDROID_MEMBAR_FULL();  /* RELEASE BARRIER */
600e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    mvalue = __bionic_swap(mtype | shared | MUTEX_STATE_BITS_UNLOCKED, &mutex->value);
60140e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
60240e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    /* Wake one waiting thread, if any */
603e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if (MUTEX_STATE_BITS_IS_LOCKED_CONTENDED(mvalue)) {
6046304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner        __futex_wake_ex(&mutex->value, shared, 1);
60588f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner    }
60640e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    return 0;
6071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
6081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6097c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopianint pthread_mutex_unlock(pthread_mutex_t *mutex)
6107c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian{
6117c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian    if (PTHREAD_DEBUG_ENABLED) {
6127c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian        pthread_debug_mutex_unlock_check(mutex);
6137c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian    }
6147c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian    return pthread_mutex_unlock_impl(mutex);
6157c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian}
6161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6177c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian__LIBC_HIDDEN__
6187c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopianint pthread_mutex_trylock_impl(pthread_mutex_t *mutex)
6191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
620a12c54454f3a6132988b68873903f6e9eed7f384Wink Saville    int mvalue, mtype, tid, shared;
6211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
622022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    mvalue = mutex->value;
623022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    mtype  = (mvalue & MUTEX_TYPE_MASK);
624022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    shared = (mvalue & MUTEX_SHARED_MASK);
6251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
62640e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    /* Handle common case first */
627d4e753fea9345c24dcce89531dff9019bef14eb3Elliott Hughes    if ( __predict_true(mtype == MUTEX_TYPE_BITS_NORMAL) )
62840e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    {
629e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        if (__bionic_cmpxchg(shared|MUTEX_STATE_BITS_UNLOCKED,
630e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner                             shared|MUTEX_STATE_BITS_LOCKED_UNCONTENDED,
631e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner                             &mutex->value) == 0) {
632fcd00ebbdf3e7f4e1e7782a65ae10fb0fc03a1aaAndy McFadden            ANDROID_MEMBAR_FULL();
6338641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio            return 0;
634fcd00ebbdf3e7f4e1e7782a65ae10fb0fc03a1aaAndy McFadden        }
63540e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
63640e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner        return EBUSY;
63740e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    }
63840e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
63940e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    /* Do we already own this recursive or error-check mutex ? */
64040eabe24e4e3ae8ebe437f1f4e43cf39cbba2e9eElliott Hughes    tid = __get_thread()->tid;
641e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if ( tid == MUTEX_OWNER_FROM_BITS(mvalue) )
642022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner        return _recursive_increment(mutex, mvalue, mtype);
64340e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
644e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    /* Same as pthread_mutex_lock, except that we don't want to wait, and
645e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * the only operation that can succeed is a single cmpxchg to acquire the
646e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * lock if it is released / not owned by anyone. No need for a complex loop.
647e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     */
648e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    mtype |= shared | MUTEX_STATE_BITS_UNLOCKED;
649e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    mvalue = MUTEX_OWNER_TO_BITS(tid) | mtype | MUTEX_STATE_BITS_LOCKED_UNCONTENDED;
65040e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
651d4e753fea9345c24dcce89531dff9019bef14eb3Elliott Hughes    if (__predict_true(__bionic_cmpxchg(mtype, mvalue, &mutex->value) == 0)) {
652e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        ANDROID_MEMBAR_FULL();
653e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        return 0;
654e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    }
65540e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
656e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    return EBUSY;
6571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
6581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6597c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopianint pthread_mutex_trylock(pthread_mutex_t *mutex)
6607c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian{
6617c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian    int err = pthread_mutex_trylock_impl(mutex);
6627c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian    if (PTHREAD_DEBUG_ENABLED) {
6637c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian        if (!err) {
6647c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian            pthread_debug_mutex_lock_check(mutex);
6657c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian        }
6667c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian    }
6677c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian    return err;
6687c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian}
6691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6703f56b7f65adb9ee35cd0f878ca00b92011eec427David 'Digit' Turner/* initialize 'abstime' to the current time according to 'clock' plus 'msecs'
6713f56b7f65adb9ee35cd0f878ca00b92011eec427David 'Digit' Turner * milliseconds.
6723f56b7f65adb9ee35cd0f878ca00b92011eec427David 'Digit' Turner */
673c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesstatic void __timespec_to_relative_msec(timespec* abstime, unsigned msecs, clockid_t clock) {
6743f56b7f65adb9ee35cd0f878ca00b92011eec427David 'Digit' Turner    clock_gettime(clock, abstime);
6753f56b7f65adb9ee35cd0f878ca00b92011eec427David 'Digit' Turner    abstime->tv_sec  += msecs/1000;
6763f56b7f65adb9ee35cd0f878ca00b92011eec427David 'Digit' Turner    abstime->tv_nsec += (msecs%1000)*1000000;
6773f56b7f65adb9ee35cd0f878ca00b92011eec427David 'Digit' Turner    if (abstime->tv_nsec >= 1000000000) {
6783f56b7f65adb9ee35cd0f878ca00b92011eec427David 'Digit' Turner        abstime->tv_sec++;
6793f56b7f65adb9ee35cd0f878ca00b92011eec427David 'Digit' Turner        abstime->tv_nsec -= 1000000000;
6803f56b7f65adb9ee35cd0f878ca00b92011eec427David 'Digit' Turner    }
6813f56b7f65adb9ee35cd0f878ca00b92011eec427David 'Digit' Turner}
6823f56b7f65adb9ee35cd0f878ca00b92011eec427David 'Digit' Turner
6837c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian__LIBC_HIDDEN__
6847c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopianint pthread_mutex_lock_timeout_np_impl(pthread_mutex_t *mutex, unsigned msecs)
6853f56b7f65adb9ee35cd0f878ca00b92011eec427David 'Digit' Turner{
6863f56b7f65adb9ee35cd0f878ca00b92011eec427David 'Digit' Turner    clockid_t        clock = CLOCK_MONOTONIC;
687c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes    timespec  abstime;
688c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes    timespec  ts;
689a12c54454f3a6132988b68873903f6e9eed7f384Wink Saville    int               mvalue, mtype, tid, shared;
6903f56b7f65adb9ee35cd0f878ca00b92011eec427David 'Digit' Turner
6913f56b7f65adb9ee35cd0f878ca00b92011eec427David 'Digit' Turner    /* compute absolute expiration time */
6923f56b7f65adb9ee35cd0f878ca00b92011eec427David 'Digit' Turner    __timespec_to_relative_msec(&abstime, msecs, clock);
6933f56b7f65adb9ee35cd0f878ca00b92011eec427David 'Digit' Turner
694022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    mvalue = mutex->value;
695022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    mtype  = (mvalue & MUTEX_TYPE_MASK);
696022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner    shared = (mvalue & MUTEX_SHARED_MASK);
69740e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
69840e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    /* Handle common case first */
699d4e753fea9345c24dcce89531dff9019bef14eb3Elliott Hughes    if ( __predict_true(mtype == MUTEX_TYPE_BITS_NORMAL) )
700ba9c6f0989ae94778ba2b9f597adc827c9dc81e8David 'Digit' Turner    {
701e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        const int unlocked           = shared | MUTEX_STATE_BITS_UNLOCKED;
702e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        const int locked_uncontended = shared | MUTEX_STATE_BITS_LOCKED_UNCONTENDED;
703e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        const int locked_contended   = shared | MUTEX_STATE_BITS_LOCKED_CONTENDED;
704e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
705e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        /* fast path for uncontended lock. Note: MUTEX_TYPE_BITS_NORMAL is 0 */
706e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        if (__bionic_cmpxchg(unlocked, locked_uncontended, &mutex->value) == 0) {
707fcd00ebbdf3e7f4e1e7782a65ae10fb0fc03a1aaAndy McFadden            ANDROID_MEMBAR_FULL();
70840e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner            return 0;
709fcd00ebbdf3e7f4e1e7782a65ae10fb0fc03a1aaAndy McFadden        }
7108641833b62e3b319796dc80ea16eb1592c05edf6Fabrice Di Meglio
71140e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner        /* loop while needed */
712e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        while (__bionic_swap(locked_contended, &mutex->value) != unlocked) {
71340e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner            if (__timespec_to_absolute(&ts, &abstime, clock) < 0)
71440e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner                return EBUSY;
71540e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
716e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            __futex_wait_ex(&mutex->value, shared, locked_contended, &ts);
71740e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner        }
718fcd00ebbdf3e7f4e1e7782a65ae10fb0fc03a1aaAndy McFadden        ANDROID_MEMBAR_FULL();
71940e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner        return 0;
72040e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    }
7213f56b7f65adb9ee35cd0f878ca00b92011eec427David 'Digit' Turner
72240e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    /* Do we already own this recursive or error-check mutex ? */
72340eabe24e4e3ae8ebe437f1f4e43cf39cbba2e9eElliott Hughes    tid = __get_thread()->tid;
724e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if ( tid == MUTEX_OWNER_FROM_BITS(mvalue) )
725022d303116f742cd337852d37547e2ea24d97a25David 'Digit' Turner        return _recursive_increment(mutex, mvalue, mtype);
72640e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
727e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    /* the following implements the same loop than pthread_mutex_lock_impl
728e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * but adds checks to ensure that the operation never exceeds the
729e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner     * absolute expiration time.
73040e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner     */
731e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    mtype |= shared;
73240e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
733e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    /* first try a quick lock */
734e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    if (mvalue == mtype) {
735e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        mvalue = MUTEX_OWNER_TO_BITS(tid) | mtype | MUTEX_STATE_BITS_LOCKED_UNCONTENDED;
736d4e753fea9345c24dcce89531dff9019bef14eb3Elliott Hughes        if (__predict_true(__bionic_cmpxchg(mtype, mvalue, &mutex->value) == 0)) {
737e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            ANDROID_MEMBAR_FULL();
738e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            return 0;
739e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        }
740e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        mvalue = mutex->value;
741e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    }
74288f06cd84a70f8a5212cb03272ec2c7cf0017afaDavid 'Digit' Turner
74340e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner    for (;;) {
744c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes        timespec ts;
745e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner
746e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        /* if the value is 'unlocked', try to acquire it directly */
747e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        /* NOTE: put state to 2 since we know there is contention */
748e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        if (mvalue == mtype) /* unlocked */ {
749e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            mvalue = MUTEX_OWNER_TO_BITS(tid) | mtype | MUTEX_STATE_BITS_LOCKED_CONTENDED;
750e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            if (__bionic_cmpxchg(mtype, mvalue, &mutex->value) == 0) {
751e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner                ANDROID_MEMBAR_FULL();
752e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner                return 0;
753e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            }
754e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            /* the value changed before we could lock it. We need to check
755e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner             * the time to avoid livelocks, reload the value, then loop again. */
756e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            if (__timespec_to_absolute(&ts, &abstime, clock) < 0)
757e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner                return EBUSY;
75840e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
759e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            mvalue = mutex->value;
760e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            continue;
761e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        }
76240e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
763e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        /* The value is locked. If 'uncontended', try to switch its state
764e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         * to 'contented' to ensure we get woken up later. */
765e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        if (MUTEX_STATE_BITS_IS_LOCKED_UNCONTENDED(mvalue)) {
766e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            int newval = MUTEX_STATE_BITS_FLIP_CONTENTION(mvalue);
767e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            if (__bionic_cmpxchg(mvalue, newval, &mutex->value) != 0) {
768e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner                /* this failed because the value changed, reload it */
769e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner                mvalue = mutex->value;
770e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            } else {
771e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner                /* this succeeded, update mvalue */
772e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner                mvalue = newval;
773e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            }
774e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        }
77540e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
776e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        /* check time and update 'ts' */
77740e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner        if (__timespec_to_absolute(&ts, &abstime, clock) < 0)
77840e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner            return EBUSY;
77940e6b822866ee59f7823000384321bb899416cb1David 'Digit' Turner
780e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        /* Only wait to be woken up if the state is '2', otherwise we'll
781e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         * simply loop right now. This can happen when the second cmpxchg
782e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         * in our loop failed because the mutex was unlocked by another
783e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         * thread.
784e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner         */
785e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        if (MUTEX_STATE_BITS_IS_LOCKED_CONTENDED(mvalue)) {
786e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            if (__futex_wait_ex(&mutex->value, shared, mvalue, &ts) == ETIMEDOUT) {
787e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner                return EBUSY;
788e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            }
789e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner            mvalue = mutex->value;
790e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner        }
791ba9c6f0989ae94778ba2b9f597adc827c9dc81e8David 'Digit' Turner    }
792e1414aa96bb62057b1a25c6a9ea1797dd38dce59David 'Digit' Turner    /* NOTREACHED */
793ba9c6f0989ae94778ba2b9f597adc827c9dc81e8David 'Digit' Turner}
794ba9c6f0989ae94778ba2b9f597adc827c9dc81e8David 'Digit' Turner
7957c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopianint pthread_mutex_lock_timeout_np(pthread_mutex_t *mutex, unsigned msecs)
7967c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian{
7977c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian    int err = pthread_mutex_lock_timeout_np_impl(mutex, msecs);
7987c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian    if (PTHREAD_DEBUG_ENABLED) {
7997c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian        if (!err) {
8007c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian            pthread_debug_mutex_lock_check(mutex);
8017c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian        }
8027c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian    }
8037c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian    return err;
8047c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian}
8057c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian
8067c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopianint pthread_mutex_destroy(pthread_mutex_t *mutex)
8077c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian{
8087c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian    int ret;
8097c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian
8107c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian    /* use trylock to ensure that the mutex value is
8117c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian     * valid and is not already locked. */
8127c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian    ret = pthread_mutex_trylock_impl(mutex);
8137c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian    if (ret != 0)
8147c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian        return ret;
8157c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian
8167c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian    mutex->value = 0xdead10cc;
8177c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian    return 0;
8187c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian}
819