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

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     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>
    24 #if defined(HAVE_PTHREADS)
    25 # include <pthread.h>
    26 #endif
    28 // ------------------------------------------------------------------
    29 // C API
    31 #ifdef __cplusplus
    32 extern "C" {
    33 #endif
    35 typedef void* android_thread_id_t;
    37 typedef int (*android_thread_func_t)(void*);
    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,
    56     /* use for background tasks */
    57     ANDROID_PRIORITY_BACKGROUND     =  10,
    59     /* most threads run at normal priority */
    60     ANDROID_PRIORITY_NORMAL         =   0,
    62     /* threads currently running a UI that the user is interacting with */
    63     ANDROID_PRIORITY_FOREGROUND     =  -2,
    65     /* the main UI thread has a slightly more favorable priority */
    66     ANDROID_PRIORITY_DISPLAY        =  -4,
    68     /* ui service treads might want to run at a urgent display (uncommon) */
    69     ANDROID_PRIORITY_URGENT_DISPLAY =  -8,
    71     /* all normal audio threads */
    72     ANDROID_PRIORITY_AUDIO          = -16,
    74     /* service audio threads (uncommon) */
    75     ANDROID_PRIORITY_URGENT_AUDIO   = -19,
    77     /* should never be used in practice. regular process might not 
    78      * be allowed to use this level */
    79     ANDROID_PRIORITY_HIGHEST        = -20,
    81     ANDROID_PRIORITY_DEFAULT        = ANDROID_PRIORITY_NORMAL,
    82     ANDROID_PRIORITY_MORE_FAVORABLE = -1,
    83     ANDROID_PRIORITY_LESS_FAVORABLE = +1,
    84 };
    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 };
    93 // Create and run a new thread.
    94 extern int androidCreateThread(android_thread_func_t, void *);
    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);
   104 // Get some sort of unique identifier for the current thread.
   105 extern android_thread_id_t androidGetThreadId();
   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);
   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);
   125 extern void androidSetCreateThreadFunc(android_create_thread_fn func);
   127 // ------------------------------------------------------------------
   128 // Extra functions working with raw pids.
   130 // Get pid for the current thread.
   131 extern pid_t androidGetTid();
   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);
   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);
   145 #ifdef __cplusplus
   146 }
   147 #endif
   149 // ------------------------------------------------------------------
   150 // C++ API
   152 #ifdef __cplusplus
   154 #include <utils/Errors.h>
   155 #include <utils/RefBase.h>
   156 #include <utils/Timers.h>
   158 namespace android {
   160 typedef android_thread_id_t thread_id_t;
   162 typedef android_thread_func_t thread_func_t;
   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 };
   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 }
   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 }
   196 // Get some sort of unique identifier for the current thread.
   197 inline thread_id_t getThreadId() {
   198     return androidGetThreadId();
   199 }
   201 /*****************************************************************************/
   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     };
   216                 Mutex();
   217                 Mutex(const char* name);
   218                 Mutex(int type, const char* name = NULL);
   219                 ~Mutex();
   221     // lock or unlock the mutex
   222     status_t    lock();
   223     void        unlock();
   225     // lock if possible; returns 0 on success, error otherwise
   226     status_t    tryLock();
   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     };
   239 private:
   240     friend class Condition;
   242     // A mutex cannot be copied
   243                 Mutex(const Mutex&);
   244     Mutex&      operator = (const Mutex&);
   246 #if defined(HAVE_PTHREADS)
   247     pthread_mutex_t mMutex;
   248 #else
   249     void    _init();
   250     void*   mState;
   251 #endif
   252 };
   254 #if defined(HAVE_PTHREADS)
   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 }
   286 #endif // HAVE_PTHREADS
   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  */
   294 typedef Mutex::Autolock AutoMutex;
   296 /*****************************************************************************/
   298 #if defined(HAVE_PTHREADS)
   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     };
   313                 RWLock();
   314                 RWLock(const char* name);
   315                 RWLock(int type, const char* name = NULL);
   316                 ~RWLock();
   318     status_t    readLock();
   319     status_t    tryReadLock();
   320     status_t    writeLock();
   321     status_t    tryWriteLock();
   322     void        unlock();
   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     };
   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     };
   340 private:
   341     // A RWLock cannot be copied
   342                 RWLock(const RWLock&);
   343    RWLock&      operator = (const RWLock&);
   345    pthread_rwlock_t mRWLock;
   346 };
   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 }
   384 #endif // HAVE_PTHREADS
   386 /*****************************************************************************/
   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     };
   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();
   415 private:
   416 #if defined(HAVE_PTHREADS)
   417     pthread_cond_t mCond;
   418 #else
   419     void*   mState;
   420 #endif
   421 };
   423 #if defined(HAVE_PTHREADS)
   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 }
   478 #endif // HAVE_PTHREADS
   480 /*****************************************************************************/
   482 /*
   483  * This is our spiffy thread object!
   484  */
   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();
   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);
   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();
   504     // Good place to do one-time initializations
   505     virtual status_t    readyToRun();
   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();
   513 protected:
   514     // exitPending() returns true if requestExit() has been called.
   515             bool        exitPending() const;
   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;
   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 };
   542 }; // namespace android
   544 #endif  // __cplusplus
   546 #endif // _LIBS_UTILS_THREADS_H

mercurial