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
87typedef struct thr_timer          thr_timer_t;
88typedef 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 */
92typedef void (*thr_timer_func_t)( sigval_t );
93
94struct 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
117struct 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
126static void
127thr_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
143static thr_timer_t*
144thr_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
163static void
164thr_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
175static 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 */
198static thr_timer_t*
199thr_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
236static pthread_once_t __timer_table_once = PTHREAD_ONCE_INIT;
237static thr_timer_table_t* __timer_table;
238
239static 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
246static 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
263static thr_timer_t*
264thr_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
273static __inline__ void
274thr_timer_lock( thr_timer_t*  t )
275{
276    pthread_mutex_lock(&t->mutex);
277}
278
279static __inline__ void
280thr_timer_unlock( thr_timer_t*  t )
281{
282    pthread_mutex_unlock(&t->mutex);
283}
284
285/** POSIX TIMERS APIs */
286
287extern int __timer_create(clockid_t, struct sigevent*, timer_t*);
288extern int __timer_delete(timer_t);
289extern int __timer_gettime(timer_t, struct itimerspec*);
290extern int __timer_settime(timer_t, int, const struct itimerspec*, struct itimerspec*);
291extern int __timer_getoverrun(timer_t);
292
293static void* timer_thread_start(void*);
294
295int 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
360int
361timer_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 */
392static void
393timer_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
417int
418timer_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
442int
443timer_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
494int
495timer_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
517static 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