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