threads.h revision 4fb24275919aab88d0ce346f530c9911d6c08422
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#ifndef _LIBS_UTILS_THREADS_H 18#define _LIBS_UTILS_THREADS_H 19 20#include <stdint.h> 21#include <sys/types.h> 22#include <time.h> 23 24#if defined(HAVE_PTHREADS) 25# include <pthread.h> 26#endif 27 28// ------------------------------------------------------------------ 29// C API 30 31#ifdef __cplusplus 32extern "C" { 33#endif 34 35typedef void* android_thread_id_t; 36 37typedef int (*android_thread_func_t)(void*); 38 39enum { 40 /* 41 * *********************************************** 42 * ** Keep in sync with android.os.Process.java ** 43 * *********************************************** 44 * 45 * This maps directly to the "nice" priorites we use in Android. 46 * A thread priority should be chosen inverse-proportinally to 47 * the amount of work the thread is expected to do. The more work 48 * a thread will do, the less favorable priority it should get so that 49 * it doesn't starve the system. Threads not behaving properly might 50 * be "punished" by the kernel. 51 * Use the levels below when appropriate. Intermediate values are 52 * acceptable, preferably use the {MORE|LESS}_FAVORABLE constants below. 53 */ 54 ANDROID_PRIORITY_LOWEST = 19, 55 56 /* use for background tasks */ 57 ANDROID_PRIORITY_BACKGROUND = 10, 58 59 /* most threads run at normal priority */ 60 ANDROID_PRIORITY_NORMAL = 0, 61 62 /* threads currently running a UI that the user is interacting with */ 63 ANDROID_PRIORITY_FOREGROUND = -2, 64 65 /* the main UI thread has a slightly more favorable priority */ 66 ANDROID_PRIORITY_DISPLAY = -4, 67 68 /* ui service treads might want to run at a urgent display (uncommon) */ 69 ANDROID_PRIORITY_URGENT_DISPLAY = -8, 70 71 /* all normal audio threads */ 72 ANDROID_PRIORITY_AUDIO = -16, 73 74 /* service audio threads (uncommon) */ 75 ANDROID_PRIORITY_URGENT_AUDIO = -19, 76 77 /* should never be used in practice. regular process might not 78 * be allowed to use this level */ 79 ANDROID_PRIORITY_HIGHEST = -20, 80 81 ANDROID_PRIORITY_DEFAULT = ANDROID_PRIORITY_NORMAL, 82 ANDROID_PRIORITY_MORE_FAVORABLE = -1, 83 ANDROID_PRIORITY_LESS_FAVORABLE = +1, 84}; 85 86enum { 87 ANDROID_TGROUP_DEFAULT = 0, 88 ANDROID_TGROUP_BG_NONINTERACT = 1, 89 ANDROID_TGROUP_FG_BOOST = 2, 90 ANDROID_TGROUP_MAX = ANDROID_TGROUP_FG_BOOST, 91}; 92 93// Create and run a new thread. 94extern int androidCreateThread(android_thread_func_t, void *); 95 96// Create thread with lots of parameters 97extern int androidCreateThreadEtc(android_thread_func_t entryFunction, 98 void *userData, 99 const char* threadName, 100 int32_t threadPriority, 101 size_t threadStackSize, 102 android_thread_id_t *threadId); 103 104// Get some sort of unique identifier for the current thread. 105extern android_thread_id_t androidGetThreadId(); 106 107// Low-level thread creation -- never creates threads that can 108// interact with the Java VM. 109extern int androidCreateRawThreadEtc(android_thread_func_t entryFunction, 110 void *userData, 111 const char* threadName, 112 int32_t threadPriority, 113 size_t threadStackSize, 114 android_thread_id_t *threadId); 115 116// Used by the Java Runtime to control how threads are created, so that 117// they can be proper and lovely Java threads. 118typedef int (*android_create_thread_fn)(android_thread_func_t entryFunction, 119 void *userData, 120 const char* threadName, 121 int32_t threadPriority, 122 size_t threadStackSize, 123 android_thread_id_t *threadId); 124 125extern void androidSetCreateThreadFunc(android_create_thread_fn func); 126 127// ------------------------------------------------------------------ 128// Extra functions working with raw pids. 129 130// Get pid for the current thread. 131extern pid_t androidGetTid(); 132 133// Change the scheduling group of a particular thread. The group 134// should be one of the ANDROID_TGROUP constants. Returns BAD_VALUE if 135// grp is out of range, else another non-zero value with errno set if 136// the operation failed. Thread ID zero means current thread. 137extern int androidSetThreadSchedulingGroup(pid_t tid, int grp); 138 139// Change the priority AND scheduling group of a particular thread. The priority 140// should be one of the ANDROID_PRIORITY constants. Returns INVALID_OPERATION 141// if the priority set failed, else another value if just the group set failed; 142// in either case errno is set. Thread ID zero means current thread. 143extern int androidSetThreadPriority(pid_t tid, int prio); 144 145// Get the current scheduling group of a particular thread. Normally returns 146// one of the ANDROID_TGROUP constants other than ANDROID_TGROUP_DEFAULT. 147// Returns ANDROID_TGROUP_DEFAULT if no pthread support (e.g. on host) or if 148// scheduling groups are disabled. Returns INVALID_OPERATION if unexpected error. 149// Thread ID zero means current thread. 150extern int androidGetThreadSchedulingGroup(pid_t tid); 151 152#ifdef __cplusplus 153} 154#endif 155 156// ------------------------------------------------------------------ 157// C++ API 158 159#ifdef __cplusplus 160 161#include <utils/Errors.h> 162#include <utils/RefBase.h> 163#include <utils/Timers.h> 164 165namespace android { 166 167typedef android_thread_id_t thread_id_t; 168 169typedef android_thread_func_t thread_func_t; 170 171enum { 172 PRIORITY_LOWEST = ANDROID_PRIORITY_LOWEST, 173 PRIORITY_BACKGROUND = ANDROID_PRIORITY_BACKGROUND, 174 PRIORITY_NORMAL = ANDROID_PRIORITY_NORMAL, 175 PRIORITY_FOREGROUND = ANDROID_PRIORITY_FOREGROUND, 176 PRIORITY_DISPLAY = ANDROID_PRIORITY_DISPLAY, 177 PRIORITY_URGENT_DISPLAY = ANDROID_PRIORITY_URGENT_DISPLAY, 178 PRIORITY_AUDIO = ANDROID_PRIORITY_AUDIO, 179 PRIORITY_URGENT_AUDIO = ANDROID_PRIORITY_URGENT_AUDIO, 180 PRIORITY_HIGHEST = ANDROID_PRIORITY_HIGHEST, 181 PRIORITY_DEFAULT = ANDROID_PRIORITY_DEFAULT, 182 PRIORITY_MORE_FAVORABLE = ANDROID_PRIORITY_MORE_FAVORABLE, 183 PRIORITY_LESS_FAVORABLE = ANDROID_PRIORITY_LESS_FAVORABLE, 184}; 185 186// Create and run a new thread. 187inline bool createThread(thread_func_t f, void *a) { 188 return androidCreateThread(f, a) ? true : false; 189} 190 191// Create thread with lots of parameters 192inline bool createThreadEtc(thread_func_t entryFunction, 193 void *userData, 194 const char* threadName = "android:unnamed_thread", 195 int32_t threadPriority = PRIORITY_DEFAULT, 196 size_t threadStackSize = 0, 197 thread_id_t *threadId = 0) 198{ 199 return androidCreateThreadEtc(entryFunction, userData, threadName, 200 threadPriority, threadStackSize, threadId) ? true : false; 201} 202 203// Get some sort of unique identifier for the current thread. 204inline thread_id_t getThreadId() { 205 return androidGetThreadId(); 206} 207 208/*****************************************************************************/ 209 210/* 211 * Simple mutex class. The implementation is system-dependent. 212 * 213 * The mutex must be unlocked by the thread that locked it. They are not 214 * recursive, i.e. the same thread can't lock it multiple times. 215 */ 216class Mutex { 217public: 218 enum { 219 PRIVATE = 0, 220 SHARED = 1 221 }; 222 223 Mutex(); 224 Mutex(const char* name); 225 Mutex(int type, const char* name = NULL); 226 ~Mutex(); 227 228 // lock or unlock the mutex 229 status_t lock(); 230 void unlock(); 231 232 // lock if possible; returns 0 on success, error otherwise 233 status_t tryLock(); 234 235 // Manages the mutex automatically. It'll be locked when Autolock is 236 // constructed and released when Autolock goes out of scope. 237 class Autolock { 238 public: 239 inline Autolock(Mutex& mutex) : mLock(mutex) { mLock.lock(); } 240 inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); } 241 inline ~Autolock() { mLock.unlock(); } 242 private: 243 Mutex& mLock; 244 }; 245 246private: 247 friend class Condition; 248 249 // A mutex cannot be copied 250 Mutex(const Mutex&); 251 Mutex& operator = (const Mutex&); 252 253#if defined(HAVE_PTHREADS) 254 pthread_mutex_t mMutex; 255#else 256 void _init(); 257 void* mState; 258#endif 259}; 260 261#if defined(HAVE_PTHREADS) 262 263inline Mutex::Mutex() { 264 pthread_mutex_init(&mMutex, NULL); 265} 266inline Mutex::Mutex(const char* name) { 267 pthread_mutex_init(&mMutex, NULL); 268} 269inline Mutex::Mutex(int type, const char* name) { 270 if (type == SHARED) { 271 pthread_mutexattr_t attr; 272 pthread_mutexattr_init(&attr); 273 pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); 274 pthread_mutex_init(&mMutex, &attr); 275 pthread_mutexattr_destroy(&attr); 276 } else { 277 pthread_mutex_init(&mMutex, NULL); 278 } 279} 280inline Mutex::~Mutex() { 281 pthread_mutex_destroy(&mMutex); 282} 283inline status_t Mutex::lock() { 284 return -pthread_mutex_lock(&mMutex); 285} 286inline void Mutex::unlock() { 287 pthread_mutex_unlock(&mMutex); 288} 289inline status_t Mutex::tryLock() { 290 return -pthread_mutex_trylock(&mMutex); 291} 292 293#endif // HAVE_PTHREADS 294 295/* 296 * Automatic mutex. Declare one of these at the top of a function. 297 * When the function returns, it will go out of scope, and release the 298 * mutex. 299 */ 300 301typedef Mutex::Autolock AutoMutex; 302 303/*****************************************************************************/ 304 305#if defined(HAVE_PTHREADS) 306 307/* 308 * Simple mutex class. The implementation is system-dependent. 309 * 310 * The mutex must be unlocked by the thread that locked it. They are not 311 * recursive, i.e. the same thread can't lock it multiple times. 312 */ 313class RWLock { 314public: 315 enum { 316 PRIVATE = 0, 317 SHARED = 1 318 }; 319 320 RWLock(); 321 RWLock(const char* name); 322 RWLock(int type, const char* name = NULL); 323 ~RWLock(); 324 325 status_t readLock(); 326 status_t tryReadLock(); 327 status_t writeLock(); 328 status_t tryWriteLock(); 329 void unlock(); 330 331 class AutoRLock { 332 public: 333 inline AutoRLock(RWLock& rwlock) : mLock(rwlock) { mLock.readLock(); } 334 inline ~AutoRLock() { mLock.unlock(); } 335 private: 336 RWLock& mLock; 337 }; 338 339 class AutoWLock { 340 public: 341 inline AutoWLock(RWLock& rwlock) : mLock(rwlock) { mLock.writeLock(); } 342 inline ~AutoWLock() { mLock.unlock(); } 343 private: 344 RWLock& mLock; 345 }; 346 347private: 348 // A RWLock cannot be copied 349 RWLock(const RWLock&); 350 RWLock& operator = (const RWLock&); 351 352 pthread_rwlock_t mRWLock; 353}; 354 355inline RWLock::RWLock() { 356 pthread_rwlock_init(&mRWLock, NULL); 357} 358inline RWLock::RWLock(const char* name) { 359 pthread_rwlock_init(&mRWLock, NULL); 360} 361inline RWLock::RWLock(int type, const char* name) { 362 if (type == SHARED) { 363 pthread_rwlockattr_t attr; 364 pthread_rwlockattr_init(&attr); 365 pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); 366 pthread_rwlock_init(&mRWLock, &attr); 367 pthread_rwlockattr_destroy(&attr); 368 } else { 369 pthread_rwlock_init(&mRWLock, NULL); 370 } 371} 372inline RWLock::~RWLock() { 373 pthread_rwlock_destroy(&mRWLock); 374} 375inline status_t RWLock::readLock() { 376 return -pthread_rwlock_rdlock(&mRWLock); 377} 378inline status_t RWLock::tryReadLock() { 379 return -pthread_rwlock_tryrdlock(&mRWLock); 380} 381inline status_t RWLock::writeLock() { 382 return -pthread_rwlock_wrlock(&mRWLock); 383} 384inline status_t RWLock::tryWriteLock() { 385 return -pthread_rwlock_trywrlock(&mRWLock); 386} 387inline void RWLock::unlock() { 388 pthread_rwlock_unlock(&mRWLock); 389} 390 391#endif // HAVE_PTHREADS 392 393/*****************************************************************************/ 394 395/* 396 * Condition variable class. The implementation is system-dependent. 397 * 398 * Condition variables are paired up with mutexes. Lock the mutex, 399 * call wait(), then either re-wait() if things aren't quite what you want, 400 * or unlock the mutex and continue. All threads calling wait() must 401 * use the same mutex for a given Condition. 402 */ 403class Condition { 404public: 405 enum { 406 PRIVATE = 0, 407 SHARED = 1 408 }; 409 410 Condition(); 411 Condition(int type); 412 ~Condition(); 413 // Wait on the condition variable. Lock the mutex before calling. 414 status_t wait(Mutex& mutex); 415 // same with relative timeout 416 status_t waitRelative(Mutex& mutex, nsecs_t reltime); 417 // Signal the condition variable, allowing one thread to continue. 418 void signal(); 419 // Signal the condition variable, allowing all threads to continue. 420 void broadcast(); 421 422private: 423#if defined(HAVE_PTHREADS) 424 pthread_cond_t mCond; 425#else 426 void* mState; 427#endif 428}; 429 430#if defined(HAVE_PTHREADS) 431 432inline Condition::Condition() { 433 pthread_cond_init(&mCond, NULL); 434} 435inline Condition::Condition(int type) { 436 if (type == SHARED) { 437 pthread_condattr_t attr; 438 pthread_condattr_init(&attr); 439 pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); 440 pthread_cond_init(&mCond, &attr); 441 pthread_condattr_destroy(&attr); 442 } else { 443 pthread_cond_init(&mCond, NULL); 444 } 445} 446inline Condition::~Condition() { 447 pthread_cond_destroy(&mCond); 448} 449inline status_t Condition::wait(Mutex& mutex) { 450 return -pthread_cond_wait(&mCond, &mutex.mMutex); 451} 452inline status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) { 453#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE) 454 struct timespec ts; 455 ts.tv_sec = reltime/1000000000; 456 ts.tv_nsec = reltime%1000000000; 457 return -pthread_cond_timedwait_relative_np(&mCond, &mutex.mMutex, &ts); 458#else // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE 459 struct timespec ts; 460#if defined(HAVE_POSIX_CLOCKS) 461 clock_gettime(CLOCK_REALTIME, &ts); 462#else // HAVE_POSIX_CLOCKS 463 // we don't support the clocks here. 464 struct timeval t; 465 gettimeofday(&t, NULL); 466 ts.tv_sec = t.tv_sec; 467 ts.tv_nsec= t.tv_usec*1000; 468#endif // HAVE_POSIX_CLOCKS 469 ts.tv_sec += reltime/1000000000; 470 ts.tv_nsec+= reltime%1000000000; 471 if (ts.tv_nsec >= 1000000000) { 472 ts.tv_nsec -= 1000000000; 473 ts.tv_sec += 1; 474 } 475 return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts); 476#endif // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE 477} 478inline void Condition::signal() { 479 pthread_cond_signal(&mCond); 480} 481inline void Condition::broadcast() { 482 pthread_cond_broadcast(&mCond); 483} 484 485#endif // HAVE_PTHREADS 486 487/*****************************************************************************/ 488 489/* 490 * This is our spiffy thread object! 491 */ 492 493class Thread : virtual public RefBase 494{ 495public: 496 // Create a Thread object, but doesn't create or start the associated 497 // thread. See the run() method. 498 Thread(bool canCallJava = true); 499 virtual ~Thread(); 500 501 // Start the thread in threadLoop() which needs to be implemented. 502 virtual status_t run( const char* name = 0, 503 int32_t priority = PRIORITY_DEFAULT, 504 size_t stack = 0); 505 506 // Ask this object's thread to exit. This function is asynchronous, when the 507 // function returns the thread might still be running. Of course, this 508 // function can be called from a different thread. 509 virtual void requestExit(); 510 511 // Good place to do one-time initializations 512 virtual status_t readyToRun(); 513 514 // Call requestExit() and wait until this object's thread exits. 515 // BE VERY CAREFUL of deadlocks. In particular, it would be silly to call 516 // this function from this object's thread. Will return WOULD_BLOCK in 517 // that case. 518 status_t requestExitAndWait(); 519 520 // Wait until this object's thread exits. Returns immediately if not yet running. 521 // Do not call from this object's thread; will return WOULD_BLOCK in that case. 522 status_t join(); 523 524protected: 525 // exitPending() returns true if requestExit() has been called. 526 bool exitPending() const; 527 528private: 529 // Derived class must implement threadLoop(). The thread starts its life 530 // here. There are two ways of using the Thread object: 531 // 1) loop: if threadLoop() returns true, it will be called again if 532 // requestExit() wasn't called. 533 // 2) once: if threadLoop() returns false, the thread will exit upon return. 534 virtual bool threadLoop() = 0; 535 536private: 537 Thread& operator=(const Thread&); 538 static int _threadLoop(void* user); 539 const bool mCanCallJava; 540 // always hold mLock when reading or writing 541 thread_id_t mThread; 542 mutable Mutex mLock; 543 Condition mThreadExitedCondition; 544 status_t mStatus; 545 // note that all accesses of mExitPending and mRunning need to hold mLock 546 volatile bool mExitPending; 547 volatile bool mRunning; 548 sp<Thread> mHoldSelf; 549#if HAVE_ANDROID_OS 550 int mTid; 551#endif 552}; 553 554 555}; // namespace android 556 557#endif // __cplusplus 558 559#endif // _LIBS_UTILS_THREADS_H 560