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_internal.h"
     30 
     31 #include <errno.h>
     32 #include <linux/time.h>
     33 #include <stdio.h>
     34 #include <string.h>
     35 
     36 // Normal (i.e. non-SIGEV_THREAD) timers are created directly by the kernel
     37 // and are passed as is to/from the caller.
     38 //
     39 // This file also implements the support required for SIGEV_THREAD ("POSIX interval")
     40 // timers. See the following pages for additional details:
     41 //
     42 // www.opengroup.org/onlinepubs/000095399/functions/timer_create.html
     43 // www.opengroup.org/onlinepubs/000095399/functions/timer_settime.html
     44 // www.opengroup.org/onlinepubs/000095399/functions/xsh_chap02_04.html#tag_02_04_01
     45 //
     46 // The Linux kernel doesn't support these, so we need to implement them in the
     47 // C library. We use a very basic scheme where each timer is associated to a
     48 // thread that will loop, waiting for timeouts or messages from the program
     49 // corresponding to calls to timer_settime() and timer_delete().
     50 //
     51 // Note also an important thing: Posix mandates that in the case of fork(),
     52 // the timers of the child process should be disarmed, but not deleted.
     53 // this is implemented by providing a fork() wrapper (see bionic/fork.c) which
     54 // stops all timers before the fork, and only re-start them in case of error
     55 // or in the parent process.
     56 //
     57 // This stop/start is implemented by the __timer_table_start_stop() function
     58 // below.
     59 //
     60 // A SIGEV_THREAD timer ID will always have its TIMER_ID_WRAP_BIT
     61 // set to 1. In this implementation, this is always bit 31, which is
     62 // guaranteed to never be used by kernel-provided timer ids
     63 //
     64 // (See code in <kernel>/lib/idr.c, used to manage IDs, to see why.)
     65 
     66 #define  TIMER_ID_WRAP_BIT        0x80000000
     67 #define  TIMER_ID_WRAP(id)        ((timer_t)((id) |  TIMER_ID_WRAP_BIT))
     68 #define  TIMER_ID_UNWRAP(id)      ((timer_t)((id) & ~TIMER_ID_WRAP_BIT))
     69 #define  TIMER_ID_IS_WRAPPED(id)  (((id) & TIMER_ID_WRAP_BIT) != 0)
     70 
     71 /* this value is used internally to indicate a 'free' or 'zombie'
     72  * thr_timer structure. Here, 'zombie' means that timer_delete()
     73  * has been called, but that the corresponding thread hasn't
     74  * exited yet.
     75  */
     76 #define  TIMER_ID_NONE            ((timer_t)0xffffffff)
     77 
     78 /* True iff a timer id is valid */
     79 #define  TIMER_ID_IS_VALID(id)    ((id) != TIMER_ID_NONE)
     80 
     81 /* the maximum value of overrun counters */
     82 #define  DELAYTIMER_MAX    0x7fffffff
     83 
     84 #define  __likely(x)   __builtin_expect(!!(x),1)
     85 #define  __unlikely(x) __builtin_expect(!!(x),0)
     86 
     87 typedef struct thr_timer          thr_timer_t;
     88 typedef struct thr_timer_table    thr_timer_table_t;
     89 
     90 /* The Posix spec says the function receives an unsigned parameter, but
     91  * it's really a 'union sigval' a.k.a. sigval_t */
     92 typedef void (*thr_timer_func_t)( sigval_t );
     93 
     94 struct thr_timer {
     95     thr_timer_t*       next;     /* next in free list */
     96     timer_t            id;       /* TIMER_ID_NONE iff free or dying */
     97     clockid_t          clock;
     98     pthread_t          thread;
     99     pthread_attr_t     attributes;
    100     thr_timer_func_t   callback;
    101     sigval_t           value;
    102 
    103     /* the following are used to communicate between
    104      * the timer thread and the timer_XXX() functions
    105      */
    106     pthread_mutex_t           mutex;     /* lock */
    107     pthread_cond_t            cond;      /* signal a state change to thread */
    108     int volatile              done;      /* set by timer_delete */
    109     int volatile              stopped;   /* set by _start_stop() */
    110     struct timespec volatile  expires;   /* next expiration time, or 0 */
    111     struct timespec volatile  period;    /* reload value, or 0 */
    112     int volatile              overruns;  /* current number of overruns */
    113 };
    114 
    115 #define  MAX_THREAD_TIMERS  32
    116 
    117 struct thr_timer_table {
    118     pthread_mutex_t  lock;
    119     thr_timer_t*     free_timer;
    120     thr_timer_t      timers[ MAX_THREAD_TIMERS ];
    121 };
    122 
    123 /** GLOBAL TABLE OF THREAD TIMERS
    124  **/
    125 
    126 static void
    127 thr_timer_table_init( thr_timer_table_t*  t )
    128 {
    129     int  nn;
    130 
    131     memset(t, 0, sizeof *t);
    132     pthread_mutex_init( &t->lock, NULL );
    133 
    134     for (nn = 0; nn < MAX_THREAD_TIMERS; nn++)
    135         t->timers[nn].id = TIMER_ID_NONE;
    136 
    137     t->free_timer = &t->timers[0];
    138     for (nn = 1; nn < MAX_THREAD_TIMERS; nn++)
    139         t->timers[nn-1].next = &t->timers[nn];
    140 }
    141 
    142 
    143 static thr_timer_t*
    144 thr_timer_table_alloc( thr_timer_table_t*  t )
    145 {
    146     thr_timer_t*  timer;
    147 
    148     if (t == NULL)
    149         return NULL;
    150 
    151     pthread_mutex_lock(&t->lock);
    152     timer = t->free_timer;
    153     if (timer != NULL) {
    154         t->free_timer = timer->next;
    155         timer->next   = NULL;
    156         timer->id     = TIMER_ID_WRAP((timer - t->timers));
    157     }
    158     pthread_mutex_unlock(&t->lock);
    159     return timer;
    160 }
    161 
    162 
    163 static void
    164 thr_timer_table_free( thr_timer_table_t*  t, thr_timer_t*  timer )
    165 {
    166     pthread_mutex_lock( &t->lock );
    167     timer->id     = TIMER_ID_NONE;
    168     timer->thread = 0;
    169     timer->next   = t->free_timer;
    170     t->free_timer = timer;
    171     pthread_mutex_unlock( &t->lock );
    172 }
    173 
    174 
    175 static void thr_timer_table_start_stop(thr_timer_table_t* t, int stop) {
    176   if (t == NULL) {
    177     return;
    178   }
    179 
    180   pthread_mutex_lock(&t->lock);
    181   for (int nn = 0; nn < MAX_THREAD_TIMERS; ++nn) {
    182     thr_timer_t*  timer  = &t->timers[nn];
    183     if (TIMER_ID_IS_VALID(timer->id)) {
    184       // Tell the thread to start/stop.
    185       pthread_mutex_lock(&timer->mutex);
    186       timer->stopped = stop;
    187       pthread_cond_signal( &timer->cond );
    188       pthread_mutex_unlock(&timer->mutex);
    189     }
    190   }
    191   pthread_mutex_unlock(&t->lock);
    192 }
    193 
    194 
    195 /* convert a timer_id into the corresponding thr_timer_t* pointer
    196  * returns NULL if the id is not wrapped or is invalid/free
    197  */
    198 static thr_timer_t*
    199 thr_timer_table_from_id( thr_timer_table_t*  t,
    200                          timer_t             id,
    201                          int                 remove )
    202 {
    203     unsigned      index;
    204     thr_timer_t*  timer;
    205 
    206     if (t == NULL || !TIMER_ID_IS_WRAPPED(id))
    207         return NULL;
    208 
    209     index = (unsigned) TIMER_ID_UNWRAP(id);
    210     if (index >= MAX_THREAD_TIMERS)
    211         return NULL;
    212 
    213     pthread_mutex_lock(&t->lock);
    214 
    215     timer = &t->timers[index];
    216 
    217     if (!TIMER_ID_IS_VALID(timer->id)) {
    218         timer = NULL;
    219     } else {
    220         /* if we're removing this timer, clear the id
    221          * right now to prevent another thread to
    222          * use the same id after the unlock */
    223         if (remove)
    224             timer->id = TIMER_ID_NONE;
    225     }
    226     pthread_mutex_unlock(&t->lock);
    227 
    228     return timer;
    229 }
    230 
    231 /* the static timer table - we only create it if the process
    232  * really wants to use SIGEV_THREAD timers, which should be
    233  * pretty infrequent
    234  */
    235 
    236 static pthread_once_t __timer_table_once = PTHREAD_ONCE_INIT;
    237 static thr_timer_table_t* __timer_table;
    238 
    239 static void __timer_table_init(void) {
    240   __timer_table = calloc(1, sizeof(*__timer_table));
    241   if (__timer_table != NULL) {
    242     thr_timer_table_init(__timer_table);
    243   }
    244 }
    245 
    246 static thr_timer_table_t* __timer_table_get(void) {
    247   pthread_once(&__timer_table_once, __timer_table_init);
    248   return __timer_table;
    249 }
    250 
    251 /** POSIX THREAD TIMERS CLEANUP ON FORK
    252  **
    253  ** this should be called from the 'fork()' wrapper to stop/start
    254  ** all active thread timers. this is used to implement a Posix
    255  ** requirements: the timers of fork child processes must be
    256  ** disarmed but not deleted.
    257  **/
    258 __LIBC_HIDDEN__ void __timer_table_start_stop(int stop) {
    259   // We access __timer_table directly so we don't create it if it doesn't yet exist.
    260   thr_timer_table_start_stop(__timer_table, stop);
    261 }
    262 
    263 static thr_timer_t*
    264 thr_timer_from_id( timer_t   id )
    265 {
    266     thr_timer_table_t*  table = __timer_table_get();
    267     thr_timer_t*        timer = thr_timer_table_from_id( table, id, 0 );
    268 
    269     return timer;
    270 }
    271 
    272 
    273 static __inline__ void
    274 thr_timer_lock( thr_timer_t*  t )
    275 {
    276     pthread_mutex_lock(&t->mutex);
    277 }
    278 
    279 static __inline__ void
    280 thr_timer_unlock( thr_timer_t*  t )
    281 {
    282     pthread_mutex_unlock(&t->mutex);
    283 }
    284 
    285 /** POSIX TIMERS APIs */
    286 
    287 extern int __timer_create(clockid_t, struct sigevent*, timer_t*);
    288 extern int __timer_delete(timer_t);
    289 extern int __timer_gettime(timer_t, struct itimerspec*);
    290 extern int __timer_settime(timer_t, int, const struct itimerspec*, struct itimerspec*);
    291 extern int __timer_getoverrun(timer_t);
    292 
    293 static void* timer_thread_start(void*);
    294 
    295 int timer_create(clockid_t clock_id, struct sigevent* evp, timer_t* timer_id) {
    296   // If not a SIGEV_THREAD timer, the kernel can handle it without our help.
    297   if (__likely(evp == NULL || evp->sigev_notify != SIGEV_THREAD)) {
    298     return __timer_create(clock_id, evp, timer_id);
    299   }
    300 
    301   // Check arguments.
    302   if (evp->sigev_notify_function == NULL) {
    303     errno = EINVAL;
    304     return -1;
    305   }
    306 
    307   // Check that the clock id is supported by the kernel.
    308   struct timespec dummy;
    309   if (clock_gettime(clock_id, &dummy) < 0 && errno == EINVAL) {
    310     return -1;
    311   }
    312 
    313   // Create a new timer and its thread.
    314   // TODO: use a single global thread for all timers.
    315   thr_timer_table_t* table = __timer_table_get();
    316   thr_timer_t* timer = thr_timer_table_alloc(table);
    317   if (timer == NULL) {
    318     errno = ENOMEM;
    319     return -1;
    320   }
    321 
    322   // Copy the thread attributes.
    323   if (evp->sigev_notify_attributes == NULL) {
    324     pthread_attr_init(&timer->attributes);
    325   } else {
    326     timer->attributes = ((pthread_attr_t*) evp->sigev_notify_attributes)[0];
    327   }
    328 
    329   // Posix says that the default is PTHREAD_CREATE_DETACHED and
    330   // that PTHREAD_CREATE_JOINABLE has undefined behavior.
    331   // So simply always use DETACHED :-)
    332   pthread_attr_setdetachstate(&timer->attributes, PTHREAD_CREATE_DETACHED);
    333 
    334   timer->callback = evp->sigev_notify_function;
    335   timer->value = evp->sigev_value;
    336   timer->clock = clock_id;
    337 
    338   pthread_mutex_init(&timer->mutex, NULL);
    339   pthread_cond_init(&timer->cond, NULL);
    340 
    341   timer->done = 0;
    342   timer->stopped = 0;
    343   timer->expires.tv_sec = timer->expires.tv_nsec = 0;
    344   timer->period.tv_sec = timer->period.tv_nsec  = 0;
    345   timer->overruns = 0;
    346 
    347   // Create the thread.
    348   int rc = pthread_create(&timer->thread, &timer->attributes, timer_thread_start, timer);
    349   if (rc != 0) {
    350     thr_timer_table_free(table, timer);
    351     errno = rc;
    352     return -1;
    353   }
    354 
    355   *timer_id = timer->id;
    356   return 0;
    357 }
    358 
    359 
    360 int
    361 timer_delete( timer_t  id )
    362 {
    363     if ( __likely(!TIMER_ID_IS_WRAPPED(id)) )
    364         return __timer_delete( id );
    365     else
    366     {
    367         thr_timer_table_t*  table = __timer_table_get();
    368         thr_timer_t*        timer = thr_timer_table_from_id(table, id, 1);
    369 
    370         if (timer == NULL) {
    371             errno = EINVAL;
    372             return -1;
    373         }
    374 
    375         /* tell the timer's thread to stop */
    376         thr_timer_lock(timer);
    377         timer->done = 1;
    378         pthread_cond_signal( &timer->cond );
    379         thr_timer_unlock(timer);
    380 
    381         /* NOTE: the thread will call __timer_table_free() to free the
    382          * timer object. the '1' parameter to thr_timer_table_from_id
    383          * above ensured that the object and its timer_id cannot be
    384          * reused before that.
    385          */
    386         return 0;
    387     }
    388 }
    389 
    390 /* return the relative time until the next expiration, or 0 if
    391  * the timer is disarmed */
    392 static void
    393 timer_gettime_internal( thr_timer_t*        timer,
    394                         struct itimerspec*  spec)
    395 {
    396     struct timespec  diff;
    397 
    398     diff = timer->expires;
    399     if (!timespec_is_zero(&diff))
    400     {
    401         struct timespec  now;
    402 
    403         clock_gettime( timer->clock, &now );
    404         timespec_sub(&diff, &now);
    405 
    406         /* in case of overrun, return 0 */
    407         if (timespec_cmp0(&diff) < 0) {
    408             timespec_zero(&diff);
    409         }
    410     }
    411 
    412     spec->it_value    = diff;
    413     spec->it_interval = timer->period;
    414 }
    415 
    416 
    417 int
    418 timer_gettime( timer_t  id, struct itimerspec*  ospec )
    419 {
    420     if (ospec == NULL) {
    421         errno = EINVAL;
    422         return -1;
    423     }
    424 
    425     if ( __likely(!TIMER_ID_IS_WRAPPED(id)) ) {
    426         return __timer_gettime( id, ospec );
    427     } else {
    428         thr_timer_t*  timer = thr_timer_from_id(id);
    429 
    430         if (timer == NULL) {
    431             errno = EINVAL;
    432             return -1;
    433         }
    434         thr_timer_lock(timer);
    435         timer_gettime_internal( timer, ospec );
    436         thr_timer_unlock(timer);
    437     }
    438     return 0;
    439 }
    440 
    441 
    442 int
    443 timer_settime( timer_t                   id,
    444                int                       flags,
    445                const struct itimerspec*  spec,
    446                struct itimerspec*        ospec )
    447 {
    448     if (spec == NULL) {
    449         errno = EINVAL;
    450         return -1;
    451     }
    452 
    453     if ( __likely(!TIMER_ID_IS_WRAPPED(id)) ) {
    454         return __timer_settime( id, flags, spec, ospec );
    455     } else {
    456         thr_timer_t*        timer = thr_timer_from_id(id);
    457         struct timespec     expires, now;
    458 
    459         if (timer == NULL) {
    460             errno = EINVAL;
    461             return -1;
    462         }
    463         thr_timer_lock(timer);
    464 
    465         /* return current timer value if ospec isn't NULL */
    466         if (ospec != NULL) {
    467             timer_gettime_internal(timer, ospec );
    468         }
    469 
    470         /* compute next expiration time. note that if the
    471          * new it_interval is 0, we should disarm the timer
    472          */
    473         expires = spec->it_value;
    474         if (!timespec_is_zero(&expires)) {
    475             clock_gettime( timer->clock, &now );
    476             if (!(flags & TIMER_ABSTIME)) {
    477                 timespec_add(&expires, &now);
    478             } else {
    479                 if (timespec_cmp(&expires, &now) < 0)
    480                     expires = now;
    481             }
    482         }
    483         timer->expires = expires;
    484         timer->period  = spec->it_interval;
    485         thr_timer_unlock( timer );
    486 
    487         /* signal the change to the thread */
    488         pthread_cond_signal( &timer->cond );
    489     }
    490     return 0;
    491 }
    492 
    493 
    494 int
    495 timer_getoverrun(timer_t  id)
    496 {
    497     if ( __likely(!TIMER_ID_IS_WRAPPED(id)) ) {
    498         return __timer_getoverrun( id );
    499     } else {
    500         thr_timer_t*  timer = thr_timer_from_id(id);
    501         int           result;
    502 
    503         if (timer == NULL) {
    504             errno = EINVAL;
    505             return -1;
    506         }
    507 
    508         thr_timer_lock(timer);
    509         result = timer->overruns;
    510         thr_timer_unlock(timer);
    511 
    512         return result;
    513     }
    514 }
    515 
    516 
    517 static void* timer_thread_start(void* arg) {
    518   thr_timer_t* timer = arg;
    519 
    520   thr_timer_lock(timer);
    521 
    522   // Give this thread a meaningful name.
    523   char name[32];
    524   snprintf(name, sizeof(name), "POSIX interval timer 0x%08x", timer->id);
    525   pthread_setname_np(pthread_self(), name);
    526 
    527   // We loop until timer->done is set in timer_delete().
    528   while (!timer->done) {
    529     struct timespec expires = timer->expires;
    530     struct timespec period = timer->period;
    531 
    532     // If the timer is stopped or disarmed, wait indefinitely
    533     // for a state change from timer_settime/_delete/_start_stop.
    534     if (timer->stopped || timespec_is_zero(&expires)) {
    535       pthread_cond_wait(&timer->cond, &timer->mutex);
    536       continue;
    537     }
    538 
    539     // Otherwise, we need to do a timed wait until either a
    540     // state change of the timer expiration time.
    541     struct timespec now;
    542     clock_gettime(timer->clock, &now);
    543 
    544     if (timespec_cmp(&expires, &now) > 0) {
    545       // Cool, there was no overrun, so compute the
    546       // relative timeout as 'expires - now', then wait.
    547       struct timespec diff = expires;
    548       timespec_sub(&diff, &now);
    549 
    550       int ret = __pthread_cond_timedwait_relative(&timer->cond, &timer->mutex, &diff);
    551 
    552       // If we didn't time out, it means that a state change
    553       // occurred, so loop to take care of it.
    554       if (ret != ETIMEDOUT) {
    555         continue;
    556       }
    557     } else {
    558       // Overrun was detected before we could wait!
    559       if (!timespec_is_zero(&period)) {
    560         // For periodic timers, compute total overrun count.
    561         do {
    562           timespec_add(&expires, &period);
    563           if (timer->overruns < DELAYTIMER_MAX) {
    564             timer->overruns += 1;
    565           }
    566         } while (timespec_cmp(&expires, &now) < 0);
    567 
    568         // Backtrack the last one, because we're going to
    569         // add the same value just a bit later.
    570         timespec_sub(&expires, &period);
    571       } else {
    572         // For non-periodic timers, things are simple.
    573         timer->overruns = 1;
    574       }
    575     }
    576 
    577     // If we get here, a timeout was detected.
    578     // First reload/disarm the timer as needed.
    579     if (!timespec_is_zero(&period)) {
    580       timespec_add(&expires, &period);
    581     } else {
    582       timespec_zero(&expires);
    583     }
    584     timer->expires = expires;
    585 
    586     // Now call the timer callback function. Release the
    587     // lock to allow the function to modify the timer setting
    588     // or call timer_getoverrun().
    589     // NOTE: at this point we trust the callback not to be a
    590     //      total moron and pthread_kill() the timer thread
    591     thr_timer_unlock(timer);
    592     timer->callback(timer->value);
    593     thr_timer_lock(timer);
    594 
    595     // Now clear the overruns counter. it only makes sense
    596     // within the callback.
    597     timer->overruns = 0;
    598   }
    599 
    600   thr_timer_unlock(timer);
    601 
    602   // Free the timer object.
    603   thr_timer_table_free(__timer_table_get(), timer);
    604 
    605   return NULL;
    606 }
    607