Home | History | Annotate | Download | only in utils
      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
     32 extern "C" {
     33 #endif
     34 
     35 typedef void* android_thread_id_t;
     36 
     37 typedef int (*android_thread_func_t)(void*);
     38 
     39 enum {
     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 
     86 enum {
     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.
     94 extern int androidCreateThread(android_thread_func_t, void *);
     95 
     96 // Create thread with lots of parameters
     97 extern 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.
    105 extern android_thread_id_t androidGetThreadId();
    106 
    107 // Low-level thread creation -- never creates threads that can
    108 // interact with the Java VM.
    109 extern 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.
    118 typedef 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 
    125 extern void androidSetCreateThreadFunc(android_create_thread_fn func);
    126 
    127 // ------------------------------------------------------------------
    128 // Extra functions working with raw pids.
    129 
    130 // Get pid for the current thread.
    131 extern 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.
    137 extern 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.
    143 extern int androidSetThreadPriority(pid_t tid, int prio);
    144 
    145 #ifdef __cplusplus
    146 }
    147 #endif
    148 
    149 // ------------------------------------------------------------------
    150 // C++ API
    151 
    152 #ifdef __cplusplus
    153 
    154 #include <utils/Errors.h>
    155 #include <utils/RefBase.h>
    156 #include <utils/Timers.h>
    157 
    158 namespace android {
    159 
    160 typedef android_thread_id_t thread_id_t;
    161 
    162 typedef android_thread_func_t thread_func_t;
    163 
    164 enum {
    165     PRIORITY_LOWEST         = ANDROID_PRIORITY_LOWEST,
    166     PRIORITY_BACKGROUND     = ANDROID_PRIORITY_BACKGROUND,
    167     PRIORITY_NORMAL         = ANDROID_PRIORITY_NORMAL,
    168     PRIORITY_FOREGROUND     = ANDROID_PRIORITY_FOREGROUND,
    169     PRIORITY_DISPLAY        = ANDROID_PRIORITY_DISPLAY,
    170     PRIORITY_URGENT_DISPLAY = ANDROID_PRIORITY_URGENT_DISPLAY,
    171     PRIORITY_AUDIO          = ANDROID_PRIORITY_AUDIO,
    172     PRIORITY_URGENT_AUDIO   = ANDROID_PRIORITY_URGENT_AUDIO,
    173     PRIORITY_HIGHEST        = ANDROID_PRIORITY_HIGHEST,
    174     PRIORITY_DEFAULT        = ANDROID_PRIORITY_DEFAULT,
    175     PRIORITY_MORE_FAVORABLE = ANDROID_PRIORITY_MORE_FAVORABLE,
    176     PRIORITY_LESS_FAVORABLE = ANDROID_PRIORITY_LESS_FAVORABLE,
    177 };
    178 
    179 // Create and run a new thread.
    180 inline bool createThread(thread_func_t f, void *a) {
    181     return androidCreateThread(f, a) ? true : false;
    182 }
    183 
    184 // Create thread with lots of parameters
    185 inline bool createThreadEtc(thread_func_t entryFunction,
    186                             void *userData,
    187                             const char* threadName = "android:unnamed_thread",
    188                             int32_t threadPriority = PRIORITY_DEFAULT,
    189                             size_t threadStackSize = 0,
    190                             thread_id_t *threadId = 0)
    191 {
    192     return androidCreateThreadEtc(entryFunction, userData, threadName,
    193         threadPriority, threadStackSize, threadId) ? true : false;
    194 }
    195 
    196 // Get some sort of unique identifier for the current thread.
    197 inline thread_id_t getThreadId() {
    198     return androidGetThreadId();
    199 }
    200 
    201 /*****************************************************************************/
    202 
    203 /*
    204  * Simple mutex class.  The implementation is system-dependent.
    205  *
    206  * The mutex must be unlocked by the thread that locked it.  They are not
    207  * recursive, i.e. the same thread can't lock it multiple times.
    208  */
    209 class Mutex {
    210 public:
    211     enum {
    212         PRIVATE = 0,
    213         SHARED = 1
    214     };
    215 
    216                 Mutex();
    217                 Mutex(const char* name);
    218                 Mutex(int type, const char* name = NULL);
    219                 ~Mutex();
    220 
    221     // lock or unlock the mutex
    222     status_t    lock();
    223     void        unlock();
    224 
    225     // lock if possible; returns 0 on success, error otherwise
    226     status_t    tryLock();
    227 
    228     // Manages the mutex automatically. It'll be locked when Autolock is
    229     // constructed and released when Autolock goes out of scope.
    230     class Autolock {
    231     public:
    232         inline Autolock(Mutex& mutex) : mLock(mutex)  { mLock.lock(); }
    233         inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
    234         inline ~Autolock() { mLock.unlock(); }
    235     private:
    236         Mutex& mLock;
    237     };
    238 
    239 private:
    240     friend class Condition;
    241 
    242     // A mutex cannot be copied
    243                 Mutex(const Mutex&);
    244     Mutex&      operator = (const Mutex&);
    245 
    246 #if defined(HAVE_PTHREADS)
    247     pthread_mutex_t mMutex;
    248 #else
    249     void    _init();
    250     void*   mState;
    251 #endif
    252 };
    253 
    254 #if defined(HAVE_PTHREADS)
    255 
    256 inline Mutex::Mutex() {
    257     pthread_mutex_init(&mMutex, NULL);
    258 }
    259 inline Mutex::Mutex(const char* name) {
    260     pthread_mutex_init(&mMutex, NULL);
    261 }
    262 inline Mutex::Mutex(int type, const char* name) {
    263     if (type == SHARED) {
    264         pthread_mutexattr_t attr;
    265         pthread_mutexattr_init(&attr);
    266         pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
    267         pthread_mutex_init(&mMutex, &attr);
    268         pthread_mutexattr_destroy(&attr);
    269     } else {
    270         pthread_mutex_init(&mMutex, NULL);
    271     }
    272 }
    273 inline Mutex::~Mutex() {
    274     pthread_mutex_destroy(&mMutex);
    275 }
    276 inline status_t Mutex::lock() {
    277     return -pthread_mutex_lock(&mMutex);
    278 }
    279 inline void Mutex::unlock() {
    280     pthread_mutex_unlock(&mMutex);
    281 }
    282 inline status_t Mutex::tryLock() {
    283     return -pthread_mutex_trylock(&mMutex);
    284 }
    285 
    286 #endif // HAVE_PTHREADS
    287 
    288 /*
    289  * Automatic mutex.  Declare one of these at the top of a function.
    290  * When the function returns, it will go out of scope, and release the
    291  * mutex.
    292  */
    293 
    294 typedef Mutex::Autolock AutoMutex;
    295 
    296 /*****************************************************************************/
    297 
    298 #if defined(HAVE_PTHREADS)
    299 
    300 /*
    301  * Simple mutex class.  The implementation is system-dependent.
    302  *
    303  * The mutex must be unlocked by the thread that locked it.  They are not
    304  * recursive, i.e. the same thread can't lock it multiple times.
    305  */
    306 class RWLock {
    307 public:
    308     enum {
    309         PRIVATE = 0,
    310         SHARED = 1
    311     };
    312 
    313                 RWLock();
    314                 RWLock(const char* name);
    315                 RWLock(int type, const char* name = NULL);
    316                 ~RWLock();
    317 
    318     status_t    readLock();
    319     status_t    tryReadLock();
    320     status_t    writeLock();
    321     status_t    tryWriteLock();
    322     void        unlock();
    323 
    324     class AutoRLock {
    325     public:
    326         inline AutoRLock(RWLock& rwlock) : mLock(rwlock)  { mLock.readLock(); }
    327         inline ~AutoRLock() { mLock.unlock(); }
    328     private:
    329         RWLock& mLock;
    330     };
    331 
    332     class AutoWLock {
    333     public:
    334         inline AutoWLock(RWLock& rwlock) : mLock(rwlock)  { mLock.writeLock(); }
    335         inline ~AutoWLock() { mLock.unlock(); }
    336     private:
    337         RWLock& mLock;
    338     };
    339 
    340 private:
    341     // A RWLock cannot be copied
    342                 RWLock(const RWLock&);
    343    RWLock&      operator = (const RWLock&);
    344 
    345    pthread_rwlock_t mRWLock;
    346 };
    347 
    348 inline RWLock::RWLock() {
    349     pthread_rwlock_init(&mRWLock, NULL);
    350 }
    351 inline RWLock::RWLock(const char* name) {
    352     pthread_rwlock_init(&mRWLock, NULL);
    353 }
    354 inline RWLock::RWLock(int type, const char* name) {
    355     if (type == SHARED) {
    356         pthread_rwlockattr_t attr;
    357         pthread_rwlockattr_init(&attr);
    358         pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
    359         pthread_rwlock_init(&mRWLock, &attr);
    360         pthread_rwlockattr_destroy(&attr);
    361     } else {
    362         pthread_rwlock_init(&mRWLock, NULL);
    363     }
    364 }
    365 inline RWLock::~RWLock() {
    366     pthread_rwlock_destroy(&mRWLock);
    367 }
    368 inline status_t RWLock::readLock() {
    369     return -pthread_rwlock_rdlock(&mRWLock);
    370 }
    371 inline status_t RWLock::tryReadLock() {
    372     return -pthread_rwlock_tryrdlock(&mRWLock);
    373 }
    374 inline status_t RWLock::writeLock() {
    375     return -pthread_rwlock_wrlock(&mRWLock);
    376 }
    377 inline status_t RWLock::tryWriteLock() {
    378     return -pthread_rwlock_trywrlock(&mRWLock);
    379 }
    380 inline void RWLock::unlock() {
    381     pthread_rwlock_unlock(&mRWLock);
    382 }
    383 
    384 #endif // HAVE_PTHREADS
    385 
    386 /*****************************************************************************/
    387 
    388 /*
    389  * Condition variable class.  The implementation is system-dependent.
    390  *
    391  * Condition variables are paired up with mutexes.  Lock the mutex,
    392  * call wait(), then either re-wait() if things aren't quite what you want,
    393  * or unlock the mutex and continue.  All threads calling wait() must
    394  * use the same mutex for a given Condition.
    395  */
    396 class Condition {
    397 public:
    398     enum {
    399         PRIVATE = 0,
    400         SHARED = 1
    401     };
    402 
    403     Condition();
    404     Condition(int type);
    405     ~Condition();
    406     // Wait on the condition variable.  Lock the mutex before calling.
    407     status_t wait(Mutex& mutex);
    408     // same with relative timeout
    409     status_t waitRelative(Mutex& mutex, nsecs_t reltime);
    410     // Signal the condition variable, allowing one thread to continue.
    411     void signal();
    412     // Signal the condition variable, allowing all threads to continue.
    413     void broadcast();
    414 
    415 private:
    416 #if defined(HAVE_PTHREADS)
    417     pthread_cond_t mCond;
    418 #else
    419     void*   mState;
    420 #endif
    421 };
    422 
    423 #if defined(HAVE_PTHREADS)
    424 
    425 inline Condition::Condition() {
    426     pthread_cond_init(&mCond, NULL);
    427 }
    428 inline Condition::Condition(int type) {
    429     if (type == SHARED) {
    430         pthread_condattr_t attr;
    431         pthread_condattr_init(&attr);
    432         pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
    433         pthread_cond_init(&mCond, &attr);
    434         pthread_condattr_destroy(&attr);
    435     } else {
    436         pthread_cond_init(&mCond, NULL);
    437     }
    438 }
    439 inline Condition::~Condition() {
    440     pthread_cond_destroy(&mCond);
    441 }
    442 inline status_t Condition::wait(Mutex& mutex) {
    443     return -pthread_cond_wait(&mCond, &mutex.mMutex);
    444 }
    445 inline status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) {
    446 #if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)
    447     struct timespec ts;
    448     ts.tv_sec  = reltime/1000000000;
    449     ts.tv_nsec = reltime%1000000000;
    450     return -pthread_cond_timedwait_relative_np(&mCond, &mutex.mMutex, &ts);
    451 #else // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
    452     struct timespec ts;
    453 #if defined(HAVE_POSIX_CLOCKS)
    454     clock_gettime(CLOCK_REALTIME, &ts);
    455 #else // HAVE_POSIX_CLOCKS
    456     // we don't support the clocks here.
    457     struct timeval t;
    458     gettimeofday(&t, NULL);
    459     ts.tv_sec = t.tv_sec;
    460     ts.tv_nsec= t.tv_usec*1000;
    461 #endif // HAVE_POSIX_CLOCKS
    462     ts.tv_sec += reltime/1000000000;
    463     ts.tv_nsec+= reltime%1000000000;
    464     if (ts.tv_nsec >= 1000000000) {
    465         ts.tv_nsec -= 1000000000;
    466         ts.tv_sec  += 1;
    467     }
    468     return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts);
    469 #endif // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
    470 }
    471 inline void Condition::signal() {
    472     pthread_cond_signal(&mCond);
    473 }
    474 inline void Condition::broadcast() {
    475     pthread_cond_broadcast(&mCond);
    476 }
    477 
    478 #endif // HAVE_PTHREADS
    479 
    480 /*****************************************************************************/
    481 
    482 /*
    483  * This is our spiffy thread object!
    484  */
    485 
    486 class Thread : virtual public RefBase
    487 {
    488 public:
    489     // Create a Thread object, but doesn't create or start the associated
    490     // thread. See the run() method.
    491                         Thread(bool canCallJava = true);
    492     virtual             ~Thread();
    493 
    494     // Start the thread in threadLoop() which needs to be implemented.
    495     virtual status_t    run(    const char* name = 0,
    496                                 int32_t priority = PRIORITY_DEFAULT,
    497                                 size_t stack = 0);
    498 
    499     // Ask this object's thread to exit. This function is asynchronous, when the
    500     // function returns the thread might still be running. Of course, this
    501     // function can be called from a different thread.
    502     virtual void        requestExit();
    503 
    504     // Good place to do one-time initializations
    505     virtual status_t    readyToRun();
    506 
    507     // Call requestExit() and wait until this object's thread exits.
    508     // BE VERY CAREFUL of deadlocks. In particular, it would be silly to call
    509     // this function from this object's thread. Will return WOULD_BLOCK in
    510     // that case.
    511             status_t    requestExitAndWait();
    512 
    513 protected:
    514     // exitPending() returns true if requestExit() has been called.
    515             bool        exitPending() const;
    516 
    517 private:
    518     // Derived class must implement threadLoop(). The thread starts its life
    519     // here. There are two ways of using the Thread object:
    520     // 1) loop: if threadLoop() returns true, it will be called again if
    521     //          requestExit() wasn't called.
    522     // 2) once: if threadLoop() returns false, the thread will exit upon return.
    523     virtual bool        threadLoop() = 0;
    524 
    525 private:
    526     Thread& operator=(const Thread&);
    527     static  int             _threadLoop(void* user);
    528     const   bool            mCanCallJava;
    529             thread_id_t     mThread;
    530             Mutex           mLock;
    531             Condition       mThreadExitedCondition;
    532             status_t        mStatus;
    533     volatile bool           mExitPending;
    534     volatile bool           mRunning;
    535             sp<Thread>      mHoldSelf;
    536 #if HAVE_ANDROID_OS
    537             int             mTid;
    538 #endif
    539 };
    540 
    541 
    542 }; // namespace android
    543 
    544 #endif  // __cplusplus
    545 
    546 #endif // _LIBS_UTILS_THREADS_H
    547