Home | History | Annotate | Download | only in bionic
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *  * Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *  * Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in
     12  *    the documentation and/or other materials provided with the
     13  *    distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
     22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <pthread.h>
     30 
     31 #include <errno.h>
     32 #include <limits.h>
     33 #include <stdatomic.h>
     34 #include <sys/mman.h>
     35 #include <time.h>
     36 #include <unistd.h>
     37 
     38 #include "pthread_internal.h"
     39 
     40 #include "private/bionic_futex.h"
     41 #include "private/bionic_time_conversions.h"
     42 #include "private/bionic_tls.h"
     43 
     44 // XXX *technically* there is a race condition that could allow
     45 // XXX a signal to be missed.  If thread A is preempted in _wait()
     46 // XXX after unlocking the mutex and before waiting, and if other
     47 // XXX threads call signal or broadcast UINT_MAX/2 times (exactly),
     48 // XXX before thread A is scheduled again and calls futex_wait(),
     49 // XXX then the signal will be lost.
     50 
     51 // We use one bit in pthread_condattr_t (long) values as the 'shared' flag
     52 // and one bit for the clock type (CLOCK_REALTIME is 0 and
     53 // CLOCK_MONOTONIC is 1). The rest of the bits are a counter.
     54 //
     55 // The 'value' field in pthread_cond_t has the same layout.
     56 
     57 #define COND_SHARED_MASK 0x0001
     58 #define COND_CLOCK_MASK 0x0002
     59 #define COND_COUNTER_STEP 0x0004
     60 #define COND_FLAGS_MASK (COND_SHARED_MASK | COND_CLOCK_MASK)
     61 #define COND_COUNTER_MASK (~COND_FLAGS_MASK)
     62 
     63 #define COND_IS_SHARED(c) (((c) & COND_SHARED_MASK) != 0)
     64 #define COND_GET_CLOCK(c) (((c) & COND_CLOCK_MASK) >> 1)
     65 #define COND_SET_CLOCK(attr, c) ((attr) | (c << 1))
     66 
     67 int pthread_condattr_init(pthread_condattr_t* attr) {
     68   *attr = 0;
     69   *attr |= PTHREAD_PROCESS_PRIVATE;
     70   *attr |= (CLOCK_REALTIME << 1);
     71   return 0;
     72 }
     73 
     74 int pthread_condattr_getpshared(const pthread_condattr_t* attr, int* pshared) {
     75   *pshared = static_cast<int>(COND_IS_SHARED(*attr));
     76   return 0;
     77 }
     78 
     79 int pthread_condattr_setpshared(pthread_condattr_t* attr, int pshared) {
     80   if (pshared != PTHREAD_PROCESS_SHARED && pshared != PTHREAD_PROCESS_PRIVATE) {
     81     return EINVAL;
     82   }
     83 
     84   *attr |= pshared;
     85   return 0;
     86 }
     87 
     88 int pthread_condattr_getclock(const pthread_condattr_t* attr, clockid_t* clock) {
     89   *clock = COND_GET_CLOCK(*attr);
     90   return 0;
     91 }
     92 
     93 int pthread_condattr_setclock(pthread_condattr_t* attr, clockid_t clock) {
     94   if (clock != CLOCK_MONOTONIC && clock != CLOCK_REALTIME) {
     95     return EINVAL;
     96   }
     97 
     98   *attr = COND_SET_CLOCK(*attr, clock);
     99   return 0;
    100 }
    101 
    102 int pthread_condattr_destroy(pthread_condattr_t* attr) {
    103   *attr = 0xdeada11d;
    104   return 0;
    105 }
    106 
    107 struct pthread_cond_internal_t {
    108   atomic_uint state;
    109 
    110   bool process_shared() {
    111     return COND_IS_SHARED(atomic_load_explicit(&state, memory_order_relaxed));
    112   }
    113 
    114   bool use_realtime_clock() {
    115     return COND_GET_CLOCK(atomic_load_explicit(&state, memory_order_relaxed)) == CLOCK_REALTIME;
    116   }
    117 
    118 #if defined(__LP64__)
    119   char __reserved[44];
    120 #endif
    121 };
    122 
    123 static_assert(sizeof(pthread_cond_t) == sizeof(pthread_cond_internal_t),
    124               "pthread_cond_t should actually be pthread_cond_internal_t in implementation.");
    125 
    126 // For binary compatibility with old version of pthread_cond_t, we can't use more strict alignment
    127 // than 4-byte alignment.
    128 static_assert(alignof(pthread_cond_t) == 4,
    129               "pthread_cond_t should fulfill the alignment requirement of pthread_cond_internal_t.");
    130 
    131 static pthread_cond_internal_t* __get_internal_cond(pthread_cond_t* cond_interface) {
    132   return reinterpret_cast<pthread_cond_internal_t*>(cond_interface);
    133 }
    134 
    135 int pthread_cond_init(pthread_cond_t* cond_interface, const pthread_condattr_t* attr) {
    136   pthread_cond_internal_t* cond = __get_internal_cond(cond_interface);
    137 
    138   unsigned int init_state = 0;
    139   if (attr != NULL) {
    140     init_state = (*attr & COND_FLAGS_MASK);
    141   }
    142   atomic_init(&cond->state, init_state);
    143 
    144   return 0;
    145 }
    146 
    147 int pthread_cond_destroy(pthread_cond_t* cond_interface) {
    148   pthread_cond_internal_t* cond = __get_internal_cond(cond_interface);
    149   atomic_store_explicit(&cond->state, 0xdeadc04d, memory_order_relaxed);
    150   return 0;
    151 }
    152 
    153 // This function is used by pthread_cond_broadcast and
    154 // pthread_cond_signal to atomically decrement the counter
    155 // then wake up thread_count threads.
    156 static int __pthread_cond_pulse(pthread_cond_internal_t* cond, int thread_count) {
    157   // We don't use a release/seq_cst fence here. Because pthread_cond_wait/signal can't be
    158   // used as a method for memory synchronization by itself. It should always be used with
    159   // pthread mutexes. Note that Spurious wakeups from pthread_cond_wait/timedwait may occur,
    160   // so when using condition variables there is always a boolean predicate involving shared
    161   // variables associated with each condition wait that is true if the thread should proceed.
    162   // If the predicate is seen true before a condition wait, pthread_cond_wait/timedwait will
    163   // not be called. That's why pthread_wait/signal pair can't be used as a method for memory
    164   // synchronization. And it doesn't help even if we use any fence here.
    165 
    166   // The increase of value should leave flags alone, even if the value can overflows.
    167   atomic_fetch_add_explicit(&cond->state, COND_COUNTER_STEP, memory_order_relaxed);
    168 
    169   __futex_wake_ex(&cond->state, cond->process_shared(), thread_count);
    170   return 0;
    171 }
    172 
    173 static int __pthread_cond_timedwait(pthread_cond_internal_t* cond, pthread_mutex_t* mutex,
    174                                     bool use_realtime_clock, const timespec* abs_timeout_or_null) {
    175   int result = check_timespec(abs_timeout_or_null, true);
    176   if (result != 0) {
    177     return result;
    178   }
    179 
    180   unsigned int old_state = atomic_load_explicit(&cond->state, memory_order_relaxed);
    181   pthread_mutex_unlock(mutex);
    182   int status = __futex_wait_ex(&cond->state, cond->process_shared(), old_state,
    183                                use_realtime_clock, abs_timeout_or_null);
    184   pthread_mutex_lock(mutex);
    185 
    186   if (status == -ETIMEDOUT) {
    187     return ETIMEDOUT;
    188   }
    189   return 0;
    190 }
    191 
    192 int pthread_cond_broadcast(pthread_cond_t* cond_interface) {
    193   return __pthread_cond_pulse(__get_internal_cond(cond_interface), INT_MAX);
    194 }
    195 
    196 int pthread_cond_signal(pthread_cond_t* cond_interface) {
    197   return __pthread_cond_pulse(__get_internal_cond(cond_interface), 1);
    198 }
    199 
    200 int pthread_cond_wait(pthread_cond_t* cond_interface, pthread_mutex_t* mutex) {
    201   pthread_cond_internal_t* cond = __get_internal_cond(cond_interface);
    202   return __pthread_cond_timedwait(cond, mutex, false, nullptr);
    203 }
    204 
    205 int pthread_cond_timedwait(pthread_cond_t *cond_interface, pthread_mutex_t * mutex,
    206                            const timespec *abstime) {
    207 
    208   pthread_cond_internal_t* cond = __get_internal_cond(cond_interface);
    209   return __pthread_cond_timedwait(cond, mutex, cond->use_realtime_clock(), abstime);
    210 }
    211 
    212 extern "C" int pthread_cond_timedwait_monotonic_np(pthread_cond_t* cond_interface,
    213                                                    pthread_mutex_t* mutex,
    214                                                    const timespec* abs_timeout) {
    215   return __pthread_cond_timedwait(__get_internal_cond(cond_interface), mutex, false, abs_timeout);
    216 }
    217 
    218 #if !defined(__LP64__)
    219 // TODO: this exists only for backward binary compatibility on 32 bit platforms.
    220 extern "C" int pthread_cond_timedwait_monotonic(pthread_cond_t* cond_interface,
    221                                                 pthread_mutex_t* mutex,
    222                                                 const timespec* abs_timeout) {
    223   return pthread_cond_timedwait_monotonic_np(cond_interface, mutex, abs_timeout);
    224 }
    225 
    226 // Force this function using CLOCK_MONOTONIC because it was always using
    227 // CLOCK_MONOTONIC in history.
    228 extern "C" int pthread_cond_timedwait_relative_np(pthread_cond_t* cond_interface,
    229                                                   pthread_mutex_t* mutex,
    230                                                   const timespec* rel_timeout) {
    231   timespec ts;
    232   timespec* abs_timeout = nullptr;
    233   if (rel_timeout != nullptr) {
    234     absolute_timespec_from_timespec(ts, *rel_timeout, CLOCK_MONOTONIC);
    235     abs_timeout = &ts;
    236   }
    237   return __pthread_cond_timedwait(__get_internal_cond(cond_interface), mutex, false, abs_timeout);
    238 }
    239 
    240 extern "C" int pthread_cond_timeout_np(pthread_cond_t* cond_interface,
    241                                        pthread_mutex_t* mutex, unsigned ms) {
    242   timespec ts;
    243   timespec_from_ms(ts, ms);
    244   return pthread_cond_timedwait_relative_np(cond_interface, mutex, &ts);
    245 }
    246 #endif // !defined(__LP64__)
    247