• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <system/graphics.h>
24 
25 #if defined(HAVE_PTHREADS)
26 # include <pthread.h>
27 #endif
28 
29 // ------------------------------------------------------------------
30 // C API
31 
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35 
36 typedef void* android_thread_id_t;
37 
38 typedef int (*android_thread_func_t)(void*);
39 
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,
56 
57     /* use for background tasks */
58     ANDROID_PRIORITY_BACKGROUND     =  10,
59 
60     /* most threads run at normal priority */
61     ANDROID_PRIORITY_NORMAL         =   0,
62 
63     /* threads currently running a UI that the user is interacting with */
64     ANDROID_PRIORITY_FOREGROUND     =  -2,
65 
66     /* the main UI thread has a slightly more favorable priority */
67     ANDROID_PRIORITY_DISPLAY        =  -4,
68 
69     /* ui service treads might want to run at a urgent display (uncommon) */
70     ANDROID_PRIORITY_URGENT_DISPLAY =  HAL_PRIORITY_URGENT_DISPLAY,
71 
72     /* all normal audio threads */
73     ANDROID_PRIORITY_AUDIO          = -16,
74 
75     /* service audio threads (uncommon) */
76     ANDROID_PRIORITY_URGENT_AUDIO   = -19,
77 
78     /* should never be used in practice. regular process might not
79      * be allowed to use this level */
80     ANDROID_PRIORITY_HIGHEST        = -20,
81 
82     ANDROID_PRIORITY_DEFAULT        = ANDROID_PRIORITY_NORMAL,
83     ANDROID_PRIORITY_MORE_FAVORABLE = -1,
84     ANDROID_PRIORITY_LESS_FAVORABLE = +1,
85 };
86 
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 };
93 
94 // Create and run a new thread.
95 extern int androidCreateThread(android_thread_func_t, void *);
96 
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);
104 
105 // Get some sort of unique identifier for the current thread.
106 extern android_thread_id_t androidGetThreadId();
107 
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);
116 
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);
125 
126 extern void androidSetCreateThreadFunc(android_create_thread_fn func);
127 
128 // ------------------------------------------------------------------
129 // Extra functions working with raw pids.
130 
131 // Get pid for the current thread.
132 extern pid_t androidGetTid();
133 
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);
139 
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);
145 
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);
149 
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);
156 
157 #ifdef __cplusplus
158 }
159 #endif
160 
161 // ------------------------------------------------------------------
162 // C++ API
163 
164 #ifdef __cplusplus
165 
166 #include <utils/Errors.h>
167 #include <utils/RefBase.h>
168 #include <utils/Timers.h>
169 
170 namespace android {
171 
172 typedef android_thread_id_t thread_id_t;
173 
174 typedef android_thread_func_t thread_func_t;
175 
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 };
190 
191 // Create and run a new thread.
createThread(thread_func_t f,void * a)192 inline bool createThread(thread_func_t f, void *a) {
193     return androidCreateThread(f, a) ? true : false;
194 }
195 
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 }
207 
208 // Get some sort of unique identifier for the current thread.
getThreadId()209 inline thread_id_t getThreadId() {
210     return androidGetThreadId();
211 }
212 
213 /*****************************************************************************/
214 
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     };
227 
228                 Mutex();
229                 Mutex(const char* name);
230                 Mutex(int type, const char* name = NULL);
231                 ~Mutex();
232 
233     // lock or unlock the mutex
234     status_t    lock();
235     void        unlock();
236 
237     // lock if possible; returns 0 on success, error otherwise
238     status_t    tryLock();
239 
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:
Autolock(Mutex & mutex)244         inline Autolock(Mutex& mutex) : mLock(mutex)  { mLock.lock(); }
Autolock(Mutex * mutex)245         inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
~Autolock()246         inline ~Autolock() { mLock.unlock(); }
247     private:
248         Mutex& mLock;
249     };
250 
251 private:
252     friend class Condition;
253 
254     // A mutex cannot be copied
255                 Mutex(const Mutex&);
256     Mutex&      operator = (const Mutex&);
257 
258 #if defined(HAVE_PTHREADS)
259     pthread_mutex_t mMutex;
260 #else
261     void    _init();
262     void*   mState;
263 #endif
264 };
265 
266 #if defined(HAVE_PTHREADS)
267 
Mutex()268 inline Mutex::Mutex() {
269     pthread_mutex_init(&mMutex, NULL);
270 }
Mutex(const char * name)271 inline Mutex::Mutex(const char* name) {
272     pthread_mutex_init(&mMutex, NULL);
273 }
Mutex(int type,const char * name)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 }
~Mutex()285 inline Mutex::~Mutex() {
286     pthread_mutex_destroy(&mMutex);
287 }
lock()288 inline status_t Mutex::lock() {
289     return -pthread_mutex_lock(&mMutex);
290 }
unlock()291 inline void Mutex::unlock() {
292     pthread_mutex_unlock(&mMutex);
293 }
tryLock()294 inline status_t Mutex::tryLock() {
295     return -pthread_mutex_trylock(&mMutex);
296 }
297 
298 #endif // HAVE_PTHREADS
299 
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  */
305 
306 typedef Mutex::Autolock AutoMutex;
307 
308 /*****************************************************************************/
309 
310 #if defined(HAVE_PTHREADS)
311 
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     };
324 
325                 RWLock();
326                 RWLock(const char* name);
327                 RWLock(int type, const char* name = NULL);
328                 ~RWLock();
329 
330     status_t    readLock();
331     status_t    tryReadLock();
332     status_t    writeLock();
333     status_t    tryWriteLock();
334     void        unlock();
335 
336     class AutoRLock {
337     public:
AutoRLock(RWLock & rwlock)338         inline AutoRLock(RWLock& rwlock) : mLock(rwlock)  { mLock.readLock(); }
~AutoRLock()339         inline ~AutoRLock() { mLock.unlock(); }
340     private:
341         RWLock& mLock;
342     };
343 
344     class AutoWLock {
345     public:
AutoWLock(RWLock & rwlock)346         inline AutoWLock(RWLock& rwlock) : mLock(rwlock)  { mLock.writeLock(); }
~AutoWLock()347         inline ~AutoWLock() { mLock.unlock(); }
348     private:
349         RWLock& mLock;
350     };
351 
352 private:
353     // A RWLock cannot be copied
354                 RWLock(const RWLock&);
355    RWLock&      operator = (const RWLock&);
356 
357    pthread_rwlock_t mRWLock;
358 };
359 
RWLock()360 inline RWLock::RWLock() {
361     pthread_rwlock_init(&mRWLock, NULL);
362 }
RWLock(const char * name)363 inline RWLock::RWLock(const char* name) {
364     pthread_rwlock_init(&mRWLock, NULL);
365 }
RWLock(int type,const char * name)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 }
~RWLock()377 inline RWLock::~RWLock() {
378     pthread_rwlock_destroy(&mRWLock);
379 }
readLock()380 inline status_t RWLock::readLock() {
381     return -pthread_rwlock_rdlock(&mRWLock);
382 }
tryReadLock()383 inline status_t RWLock::tryReadLock() {
384     return -pthread_rwlock_tryrdlock(&mRWLock);
385 }
writeLock()386 inline status_t RWLock::writeLock() {
387     return -pthread_rwlock_wrlock(&mRWLock);
388 }
tryWriteLock()389 inline status_t RWLock::tryWriteLock() {
390     return -pthread_rwlock_trywrlock(&mRWLock);
391 }
unlock()392 inline void RWLock::unlock() {
393     pthread_rwlock_unlock(&mRWLock);
394 }
395 
396 #endif // HAVE_PTHREADS
397 
398 /*****************************************************************************/
399 
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     };
414 
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();
426 
427 private:
428 #if defined(HAVE_PTHREADS)
429     pthread_cond_t mCond;
430 #else
431     void*   mState;
432 #endif
433 };
434 
435 #if defined(HAVE_PTHREADS)
436 
Condition()437 inline Condition::Condition() {
438     pthread_cond_init(&mCond, NULL);
439 }
Condition(int type)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 }
~Condition()451 inline Condition::~Condition() {
452     pthread_cond_destroy(&mCond);
453 }
wait(Mutex & mutex)454 inline status_t Condition::wait(Mutex& mutex) {
455     return -pthread_cond_wait(&mCond, &mutex.mMutex);
456 }
waitRelative(Mutex & mutex,nsecs_t reltime)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 }
signal()483 inline void Condition::signal() {
484     pthread_cond_signal(&mCond);
485 }
broadcast()486 inline void Condition::broadcast() {
487     pthread_cond_broadcast(&mCond);
488 }
489 
490 #endif // HAVE_PTHREADS
491 
492 /*****************************************************************************/
493 
494 /*
495  * This is our spiffy thread object!
496  */
497 
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();
505 
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);
510 
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();
515 
516     // Good place to do one-time initializations
517     virtual status_t    readyToRun();
518 
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();
524 
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();
528 
529 protected:
530     // exitPending() returns true if requestExit() has been called.
531             bool        exitPending() const;
532 
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;
540 
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 };
558 
559 
560 }; // namespace android
561 
562 #endif  // __cplusplus
563 
564 #endif // _LIBS_UTILS_THREADS_H
565