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