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