Threads.cpp revision 54b6cfa9a9e5b861a9930af873580d6dc20f773c
1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "libutils.threads" 18 19#include <utils/threads.h> 20#include <utils/Log.h> 21 22#include <stdio.h> 23#include <stdlib.h> 24#include <memory.h> 25#include <errno.h> 26#include <assert.h> 27#include <unistd.h> 28 29#if defined(HAVE_PTHREADS) 30# include <pthread.h> 31# include <sched.h> 32# include <sys/resource.h> 33#elif defined(HAVE_WIN32_THREADS) 34# include <windows.h> 35# include <stdint.h> 36# include <process.h> 37# define HAVE_CREATETHREAD // Cygwin, vs. HAVE__BEGINTHREADEX for MinGW 38#endif 39 40#if defined(HAVE_FUTEX) 41#include <private/utils/futex_synchro.h> 42#endif 43 44#if defined(HAVE_PRCTL) 45#include <sys/prctl.h> 46#endif 47 48/* 49 * =========================================================================== 50 * Thread wrappers 51 * =========================================================================== 52 */ 53 54using namespace android; 55 56// ---------------------------------------------------------------------------- 57#if defined(HAVE_PTHREADS) 58#if 0 59#pragma mark - 60#pragma mark PTHREAD 61#endif 62// ---------------------------------------------------------------------------- 63 64/* 65 * Create and run a new thead. 66 * 67 * We create it "detached", so it cleans up after itself. 68 */ 69 70typedef void* (*android_pthread_entry)(void*); 71 72struct thread_data_t { 73 thread_func_t entryFunction; 74 void* userData; 75 int priority; 76 char * threadName; 77 78 // we use this trampoline when we need to set the priority with 79 // nice/setpriority. 80 static int trampoline(const thread_data_t* t) { 81 thread_func_t f = t->entryFunction; 82 void* u = t->userData; 83 int prio = t->priority; 84 char * name = t->threadName; 85 delete t; 86 setpriority(PRIO_PROCESS, 0, prio); 87 if (name) { 88#if defined(HAVE_PRCTL) 89 // Mac OS doesn't have this, and we build libutil for the host too 90 int hasAt = 0; 91 int hasDot = 0; 92 char *s = name; 93 while (*s) { 94 if (*s == '.') hasDot = 1; 95 else if (*s == '@') hasAt = 1; 96 s++; 97 } 98 int len = s - name; 99 if (len < 15 || hasAt || !hasDot) { 100 s = name; 101 } else { 102 s = name + len - 15; 103 } 104 prctl(PR_SET_NAME, (unsigned long) s, 0, 0, 0); 105#endif 106 free(name); 107 } 108 return f(u); 109 } 110}; 111 112int androidCreateRawThreadEtc(android_thread_func_t entryFunction, 113 void *userData, 114 const char* threadName, 115 int32_t threadPriority, 116 size_t threadStackSize, 117 android_thread_id_t *threadId) 118{ 119 pthread_attr_t attr; 120 pthread_attr_init(&attr); 121 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 122 123#ifdef HAVE_ANDROID_OS /* valgrind is rejecting RT-priority create reqs */ 124 if (threadPriority != PRIORITY_DEFAULT || threadName != NULL) { 125 // We could avoid the trampoline if there was a way to get to the 126 // android_thread_id_t (pid) from pthread_t 127 thread_data_t* t = new thread_data_t; 128 t->priority = threadPriority; 129 t->threadName = threadName ? strdup(threadName) : NULL; 130 t->entryFunction = entryFunction; 131 t->userData = userData; 132 entryFunction = (android_thread_func_t)&thread_data_t::trampoline; 133 userData = t; 134 } 135#endif 136 137 if (threadStackSize) { 138 pthread_attr_setstacksize(&attr, threadStackSize); 139 } 140 141 errno = 0; 142 pthread_t thread; 143 int result = pthread_create(&thread, &attr, 144 (android_pthread_entry)entryFunction, userData); 145 if (result != 0) { 146 LOGE("androidCreateRawThreadEtc failed (entry=%p, res=%d, errno=%d)\n" 147 "(android threadPriority=%d)", 148 entryFunction, result, errno, threadPriority); 149 return 0; 150 } 151 152 if (threadId != NULL) { 153 *threadId = (android_thread_id_t)thread; // XXX: this is not portable 154 } 155 return 1; 156} 157 158android_thread_id_t androidGetThreadId() 159{ 160 return (android_thread_id_t)pthread_self(); 161} 162 163// ---------------------------------------------------------------------------- 164#elif defined(HAVE_WIN32_THREADS) 165#if 0 166#pragma mark - 167#pragma mark WIN32_THREADS 168#endif 169// ---------------------------------------------------------------------------- 170 171/* 172 * Trampoline to make us __stdcall-compliant. 173 * 174 * We're expected to delete "vDetails" when we're done. 175 */ 176struct threadDetails { 177 int (*func)(void*); 178 void* arg; 179}; 180static __stdcall unsigned int threadIntermediary(void* vDetails) 181{ 182 struct threadDetails* pDetails = (struct threadDetails*) vDetails; 183 int result; 184 185 result = (*(pDetails->func))(pDetails->arg); 186 187 delete pDetails; 188 189 LOG(LOG_VERBOSE, "thread", "thread exiting\n"); 190 return (unsigned int) result; 191} 192 193/* 194 * Create and run a new thread. 195 */ 196static bool doCreateThread(android_thread_func_t fn, void* arg, android_thread_id_t *id) 197{ 198 HANDLE hThread; 199 struct threadDetails* pDetails = new threadDetails; // must be on heap 200 unsigned int thrdaddr; 201 202 pDetails->func = fn; 203 pDetails->arg = arg; 204 205#if defined(HAVE__BEGINTHREADEX) 206 hThread = (HANDLE) _beginthreadex(NULL, 0, threadIntermediary, pDetails, 0, 207 &thrdaddr); 208 if (hThread == 0) 209#elif defined(HAVE_CREATETHREAD) 210 hThread = CreateThread(NULL, 0, 211 (LPTHREAD_START_ROUTINE) threadIntermediary, 212 (void*) pDetails, 0, (DWORD*) &thrdaddr); 213 if (hThread == NULL) 214#endif 215 { 216 LOG(LOG_WARN, "thread", "WARNING: thread create failed\n"); 217 return false; 218 } 219 220#if defined(HAVE_CREATETHREAD) 221 /* close the management handle */ 222 CloseHandle(hThread); 223#endif 224 225 if (id != NULL) { 226 *id = (android_thread_id_t)thrdaddr; 227 } 228 229 return true; 230} 231 232int androidCreateRawThreadEtc(android_thread_func_t fn, 233 void *userData, 234 const char* threadName, 235 int32_t threadPriority, 236 size_t threadStackSize, 237 android_thread_id_t *threadId) 238{ 239 return doCreateThread( fn, userData, threadId); 240} 241 242android_thread_id_t androidGetThreadId() 243{ 244 return (android_thread_id_t)GetCurrentThreadId(); 245} 246 247// ---------------------------------------------------------------------------- 248#else 249#error "Threads not supported" 250#endif 251 252// ---------------------------------------------------------------------------- 253 254#if 0 255#pragma mark - 256#pragma mark Common Thread functions 257#endif 258 259int androidCreateThread(android_thread_func_t fn, void* arg) 260{ 261 return createThreadEtc(fn, arg); 262} 263 264int androidCreateThreadGetID(android_thread_func_t fn, void *arg, android_thread_id_t *id) 265{ 266 return createThreadEtc(fn, arg, "android:unnamed_thread", 267 PRIORITY_DEFAULT, 0, id); 268} 269 270static android_create_thread_fn gCreateThreadFn = androidCreateRawThreadEtc; 271 272int androidCreateThreadEtc(android_thread_func_t entryFunction, 273 void *userData, 274 const char* threadName, 275 int32_t threadPriority, 276 size_t threadStackSize, 277 android_thread_id_t *threadId) 278{ 279 return gCreateThreadFn(entryFunction, userData, threadName, 280 threadPriority, threadStackSize, threadId); 281} 282 283void androidSetCreateThreadFunc(android_create_thread_fn func) 284{ 285 gCreateThreadFn = func; 286} 287 288namespace android { 289 290/* 291 * =========================================================================== 292 * Mutex class 293 * =========================================================================== 294 */ 295 296#if 0 297#pragma mark - 298#pragma mark Mutex 299#endif 300 301#if defined(HAVE_PTHREADS) && !defined(HAVE_FUTEX) 302/* 303 * Simple pthread wrapper. 304 */ 305 306Mutex::Mutex() 307{ 308 _init(); 309} 310 311Mutex::Mutex(const char* name) 312{ 313 // XXX: name not used for now 314 _init(); 315} 316 317void Mutex::_init() 318{ 319 pthread_mutex_t* pMutex = new pthread_mutex_t; 320 pthread_mutex_init(pMutex, NULL); 321 mState = pMutex; 322} 323 324Mutex::~Mutex() 325{ 326 delete (pthread_mutex_t*) mState; 327} 328 329status_t Mutex::lock() 330{ 331 int res; 332 while ((res=pthread_mutex_lock((pthread_mutex_t*) mState)) == EINTR) ; 333 return -res; 334} 335 336void Mutex::unlock() 337{ 338 pthread_mutex_unlock((pthread_mutex_t*) mState); 339} 340 341status_t Mutex::tryLock() 342{ 343 int res; 344 while ((res=pthread_mutex_trylock((pthread_mutex_t*) mState)) == EINTR) ; 345 return -res; 346} 347 348#elif defined(HAVE_FUTEX) 349#if 0 350#pragma mark - 351#endif 352 353#define STATE ((futex_mutex_t*) (&mState)) 354 355Mutex::Mutex() 356{ 357 _init(); 358} 359 360Mutex::Mutex(const char* name) 361{ 362 _init(); 363} 364 365void 366Mutex::_init() 367{ 368 futex_mutex_init(STATE); 369} 370 371Mutex::~Mutex() 372{ 373} 374 375status_t Mutex::lock() 376{ 377 int res; 378 while ((res=futex_mutex_lock(STATE, FUTEX_WAIT_INFINITE)) == EINTR) ; 379 return -res; 380} 381 382void Mutex::unlock() 383{ 384 futex_mutex_unlock(STATE); 385} 386 387status_t Mutex::tryLock() 388{ 389 int res; 390 while ((res=futex_mutex_trylock(STATE)) == EINTR) ; 391 return -res; 392} 393#undef STATE 394 395#elif defined(HAVE_WIN32_THREADS) 396#if 0 397#pragma mark - 398#endif 399 400Mutex::Mutex() 401{ 402 HANDLE hMutex; 403 404 assert(sizeof(hMutex) == sizeof(mState)); 405 406 hMutex = CreateMutex(NULL, FALSE, NULL); 407 mState = (void*) hMutex; 408} 409 410Mutex::Mutex(const char* name) 411{ 412 // XXX: name not used for now 413 HANDLE hMutex; 414 415 hMutex = CreateMutex(NULL, FALSE, NULL); 416 mState = (void*) hMutex; 417} 418 419Mutex::~Mutex() 420{ 421 CloseHandle((HANDLE) mState); 422} 423 424status_t Mutex::lock() 425{ 426 DWORD dwWaitResult; 427 dwWaitResult = WaitForSingleObject((HANDLE) mState, INFINITE); 428 return dwWaitResult != WAIT_OBJECT_0 ? -1 : NO_ERROR; 429} 430 431void Mutex::unlock() 432{ 433 if (!ReleaseMutex((HANDLE) mState)) 434 LOG(LOG_WARN, "thread", "WARNING: bad result from unlocking mutex\n"); 435} 436 437status_t Mutex::tryLock() 438{ 439 DWORD dwWaitResult; 440 441 dwWaitResult = WaitForSingleObject((HANDLE) mState, 0); 442 if (dwWaitResult != WAIT_OBJECT_0 && dwWaitResult != WAIT_TIMEOUT) 443 LOG(LOG_WARN, "thread", "WARNING: bad result from try-locking mutex\n"); 444 return (dwWaitResult == WAIT_OBJECT_0) ? 0 : -1; 445} 446 447#else 448#error "Somebody forgot to implement threads for this platform." 449#endif 450 451 452/* 453 * =========================================================================== 454 * Condition class 455 * =========================================================================== 456 */ 457 458#if 0 459#pragma mark - 460#pragma mark Condition 461#endif 462 463#if defined(HAVE_PTHREADS) && !defined(HAVE_FUTEX) 464 465/* 466 * Constructor. This is a simple pthread wrapper. 467 */ 468Condition::Condition() 469{ 470 pthread_cond_t* pCond = new pthread_cond_t; 471 472 pthread_cond_init(pCond, NULL); 473 mState = pCond; 474} 475 476/* 477 * Destructor. 478 */ 479Condition::~Condition() 480{ 481 pthread_cond_destroy((pthread_cond_t*) mState); 482 delete (pthread_cond_t*) mState; 483} 484 485/* 486 * Wait on a condition variable. Lock the mutex before calling. 487 */ 488 489status_t Condition::wait(Mutex& mutex) 490{ 491 assert(mutex.mState != NULL); 492 493 int cc; 494 while ((cc = pthread_cond_wait((pthread_cond_t*)mState, 495 (pthread_mutex_t*) mutex.mState)) == EINTR) ; 496 return -cc; 497} 498 499status_t Condition::wait(Mutex& mutex, nsecs_t abstime) 500{ 501 assert(mutex.mState != NULL); 502 503 struct timespec ts; 504 ts.tv_sec = abstime/1000000000; 505 ts.tv_nsec = abstime-(ts.tv_sec*1000000000); 506 507 int cc; 508 while ((cc = pthread_cond_timedwait((pthread_cond_t*)mState, 509 (pthread_mutex_t*) mutex.mState, &ts)) == EINTR) ; 510 return -cc; 511} 512 513status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) 514{ 515 return wait(mutex, systemTime()+reltime); 516} 517 518/* 519 * Signal the condition variable, allowing one thread to continue. 520 */ 521void Condition::signal() 522{ 523 pthread_cond_signal((pthread_cond_t*) mState); 524} 525 526/* 527 * Signal the condition variable, allowing all threads to continue. 528 */ 529void Condition::broadcast() 530{ 531 pthread_cond_broadcast((pthread_cond_t*) mState); 532} 533 534#elif defined(HAVE_FUTEX) 535#if 0 536#pragma mark - 537#endif 538 539#define STATE ((futex_cond_t*) (&mState)) 540 541/* 542 * Constructor. This is a simple pthread wrapper. 543 */ 544Condition::Condition() 545{ 546 futex_cond_init(STATE); 547} 548 549/* 550 * Destructor. 551 */ 552Condition::~Condition() 553{ 554} 555 556/* 557 * Wait on a condition variable. Lock the mutex before calling. 558 */ 559 560status_t Condition::wait(Mutex& mutex) 561{ 562 assert(mutex.mState != NULL); 563 564 int res; 565 while ((res = futex_cond_wait(STATE, 566 (futex_mutex_t*)(&mutex.mState), FUTEX_WAIT_INFINITE)) == -EINTR) ; 567 568 return -res; 569} 570 571status_t Condition::wait(Mutex& mutex, nsecs_t abstime) 572{ 573 nsecs_t reltime = abstime - systemTime(); 574 if (reltime <= 0) return true; 575 return waitRelative(mutex, reltime); 576} 577 578status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) 579{ 580 assert(mutex.mState != NULL); 581 int res; 582 unsigned msec = ns2ms(reltime); 583 if(msec == 0) 584 return true; 585 // This code will not time out at the correct time if interrupted by signals 586 while ((res = futex_cond_wait(STATE, 587 (futex_mutex_t*)(&mutex.mState), msec)) == -EINTR) ; 588 return res; 589} 590 591/* 592 * Signal the condition variable, allowing one thread to continue. 593 */ 594void Condition::signal() 595{ 596 futex_cond_signal(STATE); 597} 598 599/* 600 * Signal the condition variable, allowing all threads to continue. 601 */ 602void Condition::broadcast() 603{ 604 futex_cond_broadcast(STATE); 605} 606 607#undef STATE 608 609#elif defined(HAVE_WIN32_THREADS) 610#if 0 611#pragma mark - 612#endif 613 614/* 615 * Windows doesn't have a condition variable solution. It's possible 616 * to create one, but it's easy to get it wrong. For a discussion, and 617 * the origin of this implementation, see: 618 * 619 * http://www.cs.wustl.edu/~schmidt/win32-cv-1.html 620 * 621 * The implementation shown on the page does NOT follow POSIX semantics. 622 * As an optimization they require acquiring the external mutex before 623 * calling signal() and broadcast(), whereas POSIX only requires grabbing 624 * it before calling wait(). The implementation here has been un-optimized 625 * to have the correct behavior. 626 */ 627typedef struct WinCondition { 628 // Number of waiting threads. 629 int waitersCount; 630 631 // Serialize access to waitersCount. 632 CRITICAL_SECTION waitersCountLock; 633 634 // Semaphore used to queue up threads waiting for the condition to 635 // become signaled. 636 HANDLE sema; 637 638 // An auto-reset event used by the broadcast/signal thread to wait 639 // for all the waiting thread(s) to wake up and be released from 640 // the semaphore. 641 HANDLE waitersDone; 642 643 // This mutex wouldn't be necessary if we required that the caller 644 // lock the external mutex before calling signal() and broadcast(). 645 // I'm trying to mimic pthread semantics though. 646 HANDLE internalMutex; 647 648 // Keeps track of whether we were broadcasting or signaling. This 649 // allows us to optimize the code if we're just signaling. 650 bool wasBroadcast; 651 652 status_t wait(WinCondition* condState, HANDLE hMutex, nsecs_t* abstime) 653 { 654 // Increment the wait count, avoiding race conditions. 655 EnterCriticalSection(&condState->waitersCountLock); 656 condState->waitersCount++; 657 //printf("+++ wait: incr waitersCount to %d (tid=%ld)\n", 658 // condState->waitersCount, getThreadId()); 659 LeaveCriticalSection(&condState->waitersCountLock); 660 661 DWORD timeout = INFINITE; 662 if (abstime) { 663 nsecs_t reltime = *abstime - systemTime(); 664 if (reltime < 0) 665 reltime = 0; 666 timeout = reltime/1000000; 667 } 668 669 // Atomically release the external mutex and wait on the semaphore. 670 DWORD res = 671 SignalObjectAndWait(hMutex, condState->sema, timeout, FALSE); 672 673 //printf("+++ wait: awake (tid=%ld)\n", getThreadId()); 674 675 // Reacquire lock to avoid race conditions. 676 EnterCriticalSection(&condState->waitersCountLock); 677 678 // No longer waiting. 679 condState->waitersCount--; 680 681 // Check to see if we're the last waiter after a broadcast. 682 bool lastWaiter = (condState->wasBroadcast && condState->waitersCount == 0); 683 684 //printf("+++ wait: lastWaiter=%d (wasBc=%d wc=%d)\n", 685 // lastWaiter, condState->wasBroadcast, condState->waitersCount); 686 687 LeaveCriticalSection(&condState->waitersCountLock); 688 689 // If we're the last waiter thread during this particular broadcast 690 // then signal broadcast() that we're all awake. It'll drop the 691 // internal mutex. 692 if (lastWaiter) { 693 // Atomically signal the "waitersDone" event and wait until we 694 // can acquire the internal mutex. We want to do this in one step 695 // because it ensures that everybody is in the mutex FIFO before 696 // any thread has a chance to run. Without it, another thread 697 // could wake up, do work, and hop back in ahead of us. 698 SignalObjectAndWait(condState->waitersDone, condState->internalMutex, 699 INFINITE, FALSE); 700 } else { 701 // Grab the internal mutex. 702 WaitForSingleObject(condState->internalMutex, INFINITE); 703 } 704 705 // Release the internal and grab the external. 706 ReleaseMutex(condState->internalMutex); 707 WaitForSingleObject(hMutex, INFINITE); 708 709 return res == WAIT_OBJECT_0 ? NO_ERROR : -1; 710 } 711} WinCondition; 712 713/* 714 * Constructor. Set up the WinCondition stuff. 715 */ 716Condition::Condition() 717{ 718 WinCondition* condState = new WinCondition; 719 720 condState->waitersCount = 0; 721 condState->wasBroadcast = false; 722 // semaphore: no security, initial value of 0 723 condState->sema = CreateSemaphore(NULL, 0, 0x7fffffff, NULL); 724 InitializeCriticalSection(&condState->waitersCountLock); 725 // auto-reset event, not signaled initially 726 condState->waitersDone = CreateEvent(NULL, FALSE, FALSE, NULL); 727 // used so we don't have to lock external mutex on signal/broadcast 728 condState->internalMutex = CreateMutex(NULL, FALSE, NULL); 729 730 mState = condState; 731} 732 733/* 734 * Destructor. Free Windows resources as well as our allocated storage. 735 */ 736Condition::~Condition() 737{ 738 WinCondition* condState = (WinCondition*) mState; 739 if (condState != NULL) { 740 CloseHandle(condState->sema); 741 CloseHandle(condState->waitersDone); 742 delete condState; 743 } 744} 745 746 747status_t Condition::wait(Mutex& mutex) 748{ 749 WinCondition* condState = (WinCondition*) mState; 750 HANDLE hMutex = (HANDLE) mutex.mState; 751 752 return ((WinCondition*)mState)->wait(condState, hMutex, NULL); 753} 754 755status_t Condition::wait(Mutex& mutex, nsecs_t abstime) 756{ 757 WinCondition* condState = (WinCondition*) mState; 758 HANDLE hMutex = (HANDLE) mutex.mState; 759 760 return ((WinCondition*)mState)->wait(condState, hMutex, &abstime); 761} 762 763status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) 764{ 765 return wait(mutex, systemTime()+reltime); 766} 767 768/* 769 * Signal the condition variable, allowing one thread to continue. 770 */ 771void Condition::signal() 772{ 773 WinCondition* condState = (WinCondition*) mState; 774 775 // Lock the internal mutex. This ensures that we don't clash with 776 // broadcast(). 777 WaitForSingleObject(condState->internalMutex, INFINITE); 778 779 EnterCriticalSection(&condState->waitersCountLock); 780 bool haveWaiters = (condState->waitersCount > 0); 781 LeaveCriticalSection(&condState->waitersCountLock); 782 783 // If no waiters, then this is a no-op. Otherwise, knock the semaphore 784 // down a notch. 785 if (haveWaiters) 786 ReleaseSemaphore(condState->sema, 1, 0); 787 788 // Release internal mutex. 789 ReleaseMutex(condState->internalMutex); 790} 791 792/* 793 * Signal the condition variable, allowing all threads to continue. 794 * 795 * First we have to wake up all threads waiting on the semaphore, then 796 * we wait until all of the threads have actually been woken before 797 * releasing the internal mutex. This ensures that all threads are woken. 798 */ 799void Condition::broadcast() 800{ 801 WinCondition* condState = (WinCondition*) mState; 802 803 // Lock the internal mutex. This keeps the guys we're waking up 804 // from getting too far. 805 WaitForSingleObject(condState->internalMutex, INFINITE); 806 807 EnterCriticalSection(&condState->waitersCountLock); 808 bool haveWaiters = false; 809 810 if (condState->waitersCount > 0) { 811 haveWaiters = true; 812 condState->wasBroadcast = true; 813 } 814 815 if (haveWaiters) { 816 // Wake up all the waiters. 817 ReleaseSemaphore(condState->sema, condState->waitersCount, 0); 818 819 LeaveCriticalSection(&condState->waitersCountLock); 820 821 // Wait for all awakened threads to acquire the counting semaphore. 822 // The last guy who was waiting sets this. 823 WaitForSingleObject(condState->waitersDone, INFINITE); 824 825 // Reset wasBroadcast. (No crit section needed because nobody 826 // else can wake up to poke at it.) 827 condState->wasBroadcast = 0; 828 } else { 829 // nothing to do 830 LeaveCriticalSection(&condState->waitersCountLock); 831 } 832 833 // Release internal mutex. 834 ReleaseMutex(condState->internalMutex); 835} 836 837#else 838#error "condition variables not supported on this platform" 839#endif 840 841 842/* 843 * =========================================================================== 844 * ReadWriteLock class 845 * =========================================================================== 846 */ 847 848#if 0 849#pragma mark - 850#pragma mark ReadWriteLock 851#endif 852 853/* 854 * Add a reader. Readers are nice. They share. 855 */ 856void ReadWriteLock::lockForRead() 857{ 858 mLock.lock(); 859 while (mNumWriters > 0) { 860 LOG(LOG_DEBUG, "thread", "+++ lockForRead: waiting\n"); 861 mReadWaiter.wait(mLock); 862 } 863 assert(mNumWriters == 0); 864 mNumReaders++; 865#if defined(PRINT_RENDER_TIMES) 866 if (mNumReaders == 1) 867 mDebugTimer.start(); 868#endif 869 mLock.unlock(); 870} 871 872/* 873 * Try to add a reader. If it doesn't work right away, return "false". 874 */ 875bool ReadWriteLock::tryLockForRead() 876{ 877 mLock.lock(); 878 if (mNumWriters > 0) { 879 mLock.unlock(); 880 return false; 881 } 882 assert(mNumWriters == 0); 883 mNumReaders++; 884#if defined(PRINT_RENDER_TIMES) 885 if (mNumReaders == 1) 886 mDebugTimer.start(); 887#endif 888 mLock.unlock(); 889 return true; 890} 891 892/* 893 * Remove a reader. 894 */ 895void ReadWriteLock::unlockForRead() 896{ 897 mLock.lock(); 898 if (mNumReaders == 0) { 899 LOG(LOG_WARN, "thread", 900 "WARNING: unlockForRead requested, but not locked\n"); 901 return; 902 } 903 assert(mNumReaders > 0); 904 assert(mNumWriters == 0); 905 mNumReaders--; 906 if (mNumReaders == 0) { // last reader? 907#if defined(PRINT_RENDER_TIMES) 908 mDebugTimer.stop(); 909 printf(" rdlk held %.3f msec\n", 910 (double) mDebugTimer.durationUsecs() / 1000.0); 911#endif 912 //printf("+++ signaling writers (if any)\n"); 913 mWriteWaiter.signal(); // wake one writer (if any) 914 } 915 mLock.unlock(); 916} 917 918/* 919 * Add a writer. This requires exclusive access to the object. 920 */ 921void ReadWriteLock::lockForWrite() 922{ 923 mLock.lock(); 924 while (mNumReaders > 0 || mNumWriters > 0) { 925 LOG(LOG_DEBUG, "thread", "+++ lockForWrite: waiting\n"); 926 mWriteWaiter.wait(mLock); 927 } 928 assert(mNumReaders == 0); 929 assert(mNumWriters == 0); 930 mNumWriters++; 931#if defined(PRINT_RENDER_TIMES) 932 mDebugTimer.start(); 933#endif 934 mLock.unlock(); 935} 936 937/* 938 * Try to add a writer. If it doesn't work right away, return "false". 939 */ 940bool ReadWriteLock::tryLockForWrite() 941{ 942 mLock.lock(); 943 if (mNumReaders > 0 || mNumWriters > 0) { 944 mLock.unlock(); 945 return false; 946 } 947 assert(mNumReaders == 0); 948 assert(mNumWriters == 0); 949 mNumWriters++; 950#if defined(PRINT_RENDER_TIMES) 951 mDebugTimer.start(); 952#endif 953 mLock.unlock(); 954 return true; 955} 956 957/* 958 * Remove a writer. 959 */ 960void ReadWriteLock::unlockForWrite() 961{ 962 mLock.lock(); 963 if (mNumWriters == 0) { 964 LOG(LOG_WARN, "thread", 965 "WARNING: unlockForWrite requested, but not locked\n"); 966 return; 967 } 968 assert(mNumWriters == 1); 969 mNumWriters--; 970#if defined(PRINT_RENDER_TIMES) 971 mDebugTimer.stop(); 972 //printf(" wrlk held %.3f msec\n", 973 // (double) mDebugTimer.durationUsecs() / 1000.0); 974#endif 975 // mWriteWaiter.signal(); // should other writers get first dibs? 976 //printf("+++ signaling readers (if any)\n"); 977 mReadWaiter.broadcast(); // wake all readers (if any) 978 mLock.unlock(); 979} 980 981// ---------------------------------------------------------------------------- 982 983#if 0 984#pragma mark - 985#pragma mark Thread::Thread 986#endif 987 988/* 989 * This is our thread object! 990 */ 991 992Thread::Thread(bool canCallJava) 993 : mCanCallJava(canCallJava), 994 mThread(thread_id_t(-1)), 995 mLock("Thread::mLock"), 996 mStatus(NO_ERROR), 997 mExitPending(false), mRunning(false) 998{ 999} 1000 1001Thread::~Thread() 1002{ 1003} 1004 1005status_t Thread::readyToRun() 1006{ 1007 return NO_ERROR; 1008} 1009 1010status_t Thread::run(const char* name, int32_t priority, size_t stack) 1011{ 1012 Mutex::Autolock _l(mLock); 1013 1014 if (mRunning) { 1015 // thread already started 1016 return INVALID_OPERATION; 1017 } 1018 1019 // reset status and exitPending to their default value, so we can 1020 // try again after an error happened (either below, or in readyToRun()) 1021 mStatus = NO_ERROR; 1022 mExitPending = false; 1023 mThread = thread_id_t(-1); 1024 1025 // hold a strong reference on ourself 1026 mHoldSelf = this; 1027 1028 bool res; 1029 if (mCanCallJava) { 1030 res = createThreadEtc(_threadLoop, 1031 this, name, priority, stack, &mThread); 1032 } else { 1033 res = androidCreateRawThreadEtc(_threadLoop, 1034 this, name, priority, stack, &mThread); 1035 } 1036 1037 if (res == false) { 1038 mStatus = UNKNOWN_ERROR; // something happened! 1039 mRunning = false; 1040 mThread = thread_id_t(-1); 1041 } 1042 1043 if (mStatus < 0) { 1044 // something happened, don't leak 1045 mHoldSelf.clear(); 1046 } 1047 1048 return mStatus; 1049} 1050 1051int Thread::_threadLoop(void* user) 1052{ 1053 Thread* const self = static_cast<Thread*>(user); 1054 sp<Thread> strong(self->mHoldSelf); 1055 wp<Thread> weak(strong); 1056 self->mHoldSelf.clear(); 1057 1058 // we're about to run... 1059 self->mStatus = self->readyToRun(); 1060 if (self->mStatus!=NO_ERROR || self->mExitPending) { 1061 // pretend the thread never started... 1062 self->mExitPending = false; 1063 self->mRunning = false; 1064 return 0; 1065 } 1066 1067 // thread is running now 1068 self->mRunning = true; 1069 1070 do { 1071 bool result = self->threadLoop(); 1072 if (result == false || self->mExitPending) { 1073 self->mExitPending = true; 1074 self->mLock.lock(); 1075 self->mRunning = false; 1076 self->mThreadExitedCondition.signal(); 1077 self->mLock.unlock(); 1078 break; 1079 } 1080 1081 // Release our strong reference, to let a chance to the thread 1082 // to die a peaceful death. 1083 strong.clear(); 1084 // And immediately, reacquire a strong reference for the next loop 1085 strong = weak.promote(); 1086 } while(strong != 0); 1087 1088 return 0; 1089} 1090 1091void Thread::requestExit() 1092{ 1093 mExitPending = true; 1094} 1095 1096status_t Thread::requestExitAndWait() 1097{ 1098 if (mStatus == OK) { 1099 1100 if (mThread == getThreadId()) { 1101 LOGW( 1102 "Thread (this=%p): don't call waitForExit() from this " 1103 "Thread object's thread. It's a guaranteed deadlock!", 1104 this); 1105 return WOULD_BLOCK; 1106 } 1107 1108 requestExit(); 1109 1110 Mutex::Autolock _l(mLock); 1111 while (mRunning == true) { 1112 mThreadExitedCondition.wait(mLock); 1113 } 1114 mExitPending = false; 1115 } 1116 return mStatus; 1117} 1118 1119bool Thread::exitPending() const 1120{ 1121 return mExitPending; 1122} 1123 1124 1125 1126}; // namespace android 1127