media/omx-plugin/include/ics/utils/threads.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial