blob: c685625055604f4f94acef2f9c5071342887692c [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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>
Mathias Agopian14788362011-08-09 18:57:37 -070023#include <system/graphics.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024
Mathias Agopianb1c4ca52009-07-12 23:11:20 -070025#if defined(HAVE_PTHREADS)
26# include <pthread.h>
27#endif
28
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029// ------------------------------------------------------------------
30// C API
31
32#ifdef __cplusplus
33extern "C" {
34#endif
35
36typedef void* android_thread_id_t;
37
38typedef int (*android_thread_func_t)(void*);
39
40enum {
41 /*
42 * ***********************************************
43 * ** Keep in sync with android.os.Process.java **
44 * ***********************************************
45 *
Mathias Agopian14788362011-08-09 18:57:37 -070046 * This maps directly to the "nice" priorities we use in Android.
47 * A thread priority should be chosen inverse-proportionally to
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048 * 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) */
Mathias Agopian14788362011-08-09 18:57:37 -070070 ANDROID_PRIORITY_URGENT_DISPLAY = HAL_PRIORITY_URGENT_DISPLAY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071
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
San Mehate9d376b2009-04-21 14:06:36 -070087enum {
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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094// Create and run a new thread.
95extern int androidCreateThread(android_thread_func_t, void *);
96
97// Create thread with lots of parameters
98extern 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.
106extern android_thread_id_t androidGetThreadId();
107
108// Low-level thread creation -- never creates threads that can
109// interact with the Java VM.
110extern 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.
119typedef 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
126extern void androidSetCreateThreadFunc(android_create_thread_fn func);
127
Dianne Hackborn887f3552009-12-07 17:59:37 -0800128// ------------------------------------------------------------------
129// Extra functions working with raw pids.
130
131// Get pid for the current thread.
132extern 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
Glenn Kasten60d47792011-06-22 17:42:23 -0700137// the operation failed. Thread ID zero means current thread.
Dianne Hackborn887f3552009-12-07 17:59:37 -0800138extern 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;
Glenn Kasten60d47792011-06-22 17:42:23 -0700143// in either case errno is set. Thread ID zero means current thread.
Dianne Hackborn887f3552009-12-07 17:59:37 -0800144extern int androidSetThreadPriority(pid_t tid, int prio);
145
Glenn Kasten33eafef2011-06-22 16:20:37 -0700146// Get the current scheduling group of a particular thread. Normally returns
147// one of the ANDROID_TGROUP constants other than ANDROID_TGROUP_DEFAULT.
148// Returns ANDROID_TGROUP_DEFAULT if no pthread support (e.g. on host) or if
149// scheduling groups are disabled. Returns INVALID_OPERATION if unexpected error.
150// Thread ID zero means current thread.
151extern int androidGetThreadSchedulingGroup(pid_t tid);
152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153#ifdef __cplusplus
154}
155#endif
156
157// ------------------------------------------------------------------
158// C++ API
159
160#ifdef __cplusplus
161
162#include <utils/Errors.h>
163#include <utils/RefBase.h>
164#include <utils/Timers.h>
165
166namespace android {
167
168typedef android_thread_id_t thread_id_t;
169
170typedef android_thread_func_t thread_func_t;
171
172enum {
173 PRIORITY_LOWEST = ANDROID_PRIORITY_LOWEST,
174 PRIORITY_BACKGROUND = ANDROID_PRIORITY_BACKGROUND,
175 PRIORITY_NORMAL = ANDROID_PRIORITY_NORMAL,
176 PRIORITY_FOREGROUND = ANDROID_PRIORITY_FOREGROUND,
177 PRIORITY_DISPLAY = ANDROID_PRIORITY_DISPLAY,
178 PRIORITY_URGENT_DISPLAY = ANDROID_PRIORITY_URGENT_DISPLAY,
179 PRIORITY_AUDIO = ANDROID_PRIORITY_AUDIO,
180 PRIORITY_URGENT_AUDIO = ANDROID_PRIORITY_URGENT_AUDIO,
181 PRIORITY_HIGHEST = ANDROID_PRIORITY_HIGHEST,
182 PRIORITY_DEFAULT = ANDROID_PRIORITY_DEFAULT,
183 PRIORITY_MORE_FAVORABLE = ANDROID_PRIORITY_MORE_FAVORABLE,
184 PRIORITY_LESS_FAVORABLE = ANDROID_PRIORITY_LESS_FAVORABLE,
185};
186
187// Create and run a new thread.
188inline bool createThread(thread_func_t f, void *a) {
189 return androidCreateThread(f, a) ? true : false;
190}
191
192// Create thread with lots of parameters
193inline bool createThreadEtc(thread_func_t entryFunction,
194 void *userData,
195 const char* threadName = "android:unnamed_thread",
196 int32_t threadPriority = PRIORITY_DEFAULT,
197 size_t threadStackSize = 0,
198 thread_id_t *threadId = 0)
199{
200 return androidCreateThreadEtc(entryFunction, userData, threadName,
201 threadPriority, threadStackSize, threadId) ? true : false;
202}
203
204// Get some sort of unique identifier for the current thread.
205inline thread_id_t getThreadId() {
206 return androidGetThreadId();
207}
208
Mathias Agopianb1c4ca52009-07-12 23:11:20 -0700209/*****************************************************************************/
210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211/*
212 * Simple mutex class. The implementation is system-dependent.
213 *
214 * The mutex must be unlocked by the thread that locked it. They are not
215 * recursive, i.e. the same thread can't lock it multiple times.
216 */
217class Mutex {
218public:
Mathias Agopianfb4f2662009-07-13 21:59:37 -0700219 enum {
Mathias Agopiana729f972010-03-19 16:14:13 -0700220 PRIVATE = 0,
Mathias Agopianfb4f2662009-07-13 21:59:37 -0700221 SHARED = 1
222 };
223
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 Mutex();
225 Mutex(const char* name);
Mathias Agopianfb4f2662009-07-13 21:59:37 -0700226 Mutex(int type, const char* name = NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227 ~Mutex();
228
229 // lock or unlock the mutex
230 status_t lock();
231 void unlock();
232
233 // lock if possible; returns 0 on success, error otherwise
234 status_t tryLock();
235
236 // Manages the mutex automatically. It'll be locked when Autolock is
237 // constructed and released when Autolock goes out of scope.
238 class Autolock {
239 public:
Mathias Agopianaaf834a2009-05-22 19:00:22 -0700240 inline Autolock(Mutex& mutex) : mLock(mutex) { mLock.lock(); }
241 inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
242 inline ~Autolock() { mLock.unlock(); }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243 private:
Mathias Agopianaaf834a2009-05-22 19:00:22 -0700244 Mutex& mLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800245 };
246
247private:
248 friend class Condition;
249
250 // A mutex cannot be copied
251 Mutex(const Mutex&);
252 Mutex& operator = (const Mutex&);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253
Mathias Agopianb1c4ca52009-07-12 23:11:20 -0700254#if defined(HAVE_PTHREADS)
255 pthread_mutex_t mMutex;
256#else
257 void _init();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800258 void* mState;
Mathias Agopianb1c4ca52009-07-12 23:11:20 -0700259#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260};
261
Mathias Agopianb1c4ca52009-07-12 23:11:20 -0700262#if defined(HAVE_PTHREADS)
263
264inline Mutex::Mutex() {
265 pthread_mutex_init(&mMutex, NULL);
266}
267inline Mutex::Mutex(const char* name) {
268 pthread_mutex_init(&mMutex, NULL);
269}
Mathias Agopianfb4f2662009-07-13 21:59:37 -0700270inline Mutex::Mutex(int type, const char* name) {
271 if (type == SHARED) {
272 pthread_mutexattr_t attr;
273 pthread_mutexattr_init(&attr);
274 pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
275 pthread_mutex_init(&mMutex, &attr);
276 pthread_mutexattr_destroy(&attr);
277 } else {
278 pthread_mutex_init(&mMutex, NULL);
279 }
280}
Mathias Agopianb1c4ca52009-07-12 23:11:20 -0700281inline Mutex::~Mutex() {
282 pthread_mutex_destroy(&mMutex);
283}
284inline status_t Mutex::lock() {
285 return -pthread_mutex_lock(&mMutex);
286}
287inline void Mutex::unlock() {
288 pthread_mutex_unlock(&mMutex);
289}
290inline status_t Mutex::tryLock() {
291 return -pthread_mutex_trylock(&mMutex);
292}
293
294#endif // HAVE_PTHREADS
295
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800296/*
297 * Automatic mutex. Declare one of these at the top of a function.
298 * When the function returns, it will go out of scope, and release the
299 * mutex.
300 */
301
302typedef Mutex::Autolock AutoMutex;
303
Mathias Agopianb1c4ca52009-07-12 23:11:20 -0700304/*****************************************************************************/
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305
Mathias Agopian66c46a62010-05-19 15:11:00 -0700306#if defined(HAVE_PTHREADS)
307
308/*
309 * Simple mutex class. The implementation is system-dependent.
310 *
311 * The mutex must be unlocked by the thread that locked it. They are not
312 * recursive, i.e. the same thread can't lock it multiple times.
313 */
314class RWLock {
315public:
316 enum {
317 PRIVATE = 0,
318 SHARED = 1
319 };
320
321 RWLock();
322 RWLock(const char* name);
323 RWLock(int type, const char* name = NULL);
324 ~RWLock();
325
326 status_t readLock();
327 status_t tryReadLock();
328 status_t writeLock();
329 status_t tryWriteLock();
330 void unlock();
331
332 class AutoRLock {
333 public:
334 inline AutoRLock(RWLock& rwlock) : mLock(rwlock) { mLock.readLock(); }
335 inline ~AutoRLock() { mLock.unlock(); }
336 private:
337 RWLock& mLock;
338 };
339
340 class AutoWLock {
341 public:
342 inline AutoWLock(RWLock& rwlock) : mLock(rwlock) { mLock.writeLock(); }
343 inline ~AutoWLock() { mLock.unlock(); }
344 private:
345 RWLock& mLock;
346 };
347
348private:
349 // A RWLock cannot be copied
350 RWLock(const RWLock&);
351 RWLock& operator = (const RWLock&);
352
353 pthread_rwlock_t mRWLock;
354};
355
356inline RWLock::RWLock() {
357 pthread_rwlock_init(&mRWLock, NULL);
358}
359inline RWLock::RWLock(const char* name) {
360 pthread_rwlock_init(&mRWLock, NULL);
361}
362inline RWLock::RWLock(int type, const char* name) {
363 if (type == SHARED) {
364 pthread_rwlockattr_t attr;
365 pthread_rwlockattr_init(&attr);
366 pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
367 pthread_rwlock_init(&mRWLock, &attr);
368 pthread_rwlockattr_destroy(&attr);
369 } else {
370 pthread_rwlock_init(&mRWLock, NULL);
371 }
372}
373inline RWLock::~RWLock() {
374 pthread_rwlock_destroy(&mRWLock);
375}
376inline status_t RWLock::readLock() {
377 return -pthread_rwlock_rdlock(&mRWLock);
378}
379inline status_t RWLock::tryReadLock() {
380 return -pthread_rwlock_tryrdlock(&mRWLock);
381}
382inline status_t RWLock::writeLock() {
383 return -pthread_rwlock_wrlock(&mRWLock);
384}
385inline status_t RWLock::tryWriteLock() {
386 return -pthread_rwlock_trywrlock(&mRWLock);
387}
388inline void RWLock::unlock() {
389 pthread_rwlock_unlock(&mRWLock);
390}
391
392#endif // HAVE_PTHREADS
393
394/*****************************************************************************/
395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800396/*
397 * Condition variable class. The implementation is system-dependent.
398 *
399 * Condition variables are paired up with mutexes. Lock the mutex,
400 * call wait(), then either re-wait() if things aren't quite what you want,
401 * or unlock the mutex and continue. All threads calling wait() must
402 * use the same mutex for a given Condition.
403 */
404class Condition {
405public:
Mathias Agopiana729f972010-03-19 16:14:13 -0700406 enum {
407 PRIVATE = 0,
408 SHARED = 1
409 };
410
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800411 Condition();
Mathias Agopiana729f972010-03-19 16:14:13 -0700412 Condition(int type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800413 ~Condition();
414 // Wait on the condition variable. Lock the mutex before calling.
415 status_t wait(Mutex& mutex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800416 // same with relative timeout
417 status_t waitRelative(Mutex& mutex, nsecs_t reltime);
418 // Signal the condition variable, allowing one thread to continue.
419 void signal();
420 // Signal the condition variable, allowing all threads to continue.
421 void broadcast();
422
423private:
Mathias Agopianb1c4ca52009-07-12 23:11:20 -0700424#if defined(HAVE_PTHREADS)
425 pthread_cond_t mCond;
426#else
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800427 void* mState;
Mathias Agopianb1c4ca52009-07-12 23:11:20 -0700428#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429};
430
Mathias Agopianb1c4ca52009-07-12 23:11:20 -0700431#if defined(HAVE_PTHREADS)
432
433inline Condition::Condition() {
434 pthread_cond_init(&mCond, NULL);
435}
Mathias Agopiana729f972010-03-19 16:14:13 -0700436inline Condition::Condition(int type) {
437 if (type == SHARED) {
438 pthread_condattr_t attr;
439 pthread_condattr_init(&attr);
440 pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
441 pthread_cond_init(&mCond, &attr);
442 pthread_condattr_destroy(&attr);
443 } else {
444 pthread_cond_init(&mCond, NULL);
445 }
446}
Mathias Agopianb1c4ca52009-07-12 23:11:20 -0700447inline Condition::~Condition() {
448 pthread_cond_destroy(&mCond);
449}
450inline status_t Condition::wait(Mutex& mutex) {
451 return -pthread_cond_wait(&mCond, &mutex.mMutex);
452}
453inline status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) {
454#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)
455 struct timespec ts;
456 ts.tv_sec = reltime/1000000000;
457 ts.tv_nsec = reltime%1000000000;
458 return -pthread_cond_timedwait_relative_np(&mCond, &mutex.mMutex, &ts);
459#else // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
460 struct timespec ts;
461#if defined(HAVE_POSIX_CLOCKS)
462 clock_gettime(CLOCK_REALTIME, &ts);
463#else // HAVE_POSIX_CLOCKS
464 // we don't support the clocks here.
465 struct timeval t;
466 gettimeofday(&t, NULL);
467 ts.tv_sec = t.tv_sec;
468 ts.tv_nsec= t.tv_usec*1000;
469#endif // HAVE_POSIX_CLOCKS
470 ts.tv_sec += reltime/1000000000;
471 ts.tv_nsec+= reltime%1000000000;
472 if (ts.tv_nsec >= 1000000000) {
473 ts.tv_nsec -= 1000000000;
474 ts.tv_sec += 1;
475 }
476 return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts);
477#endif // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
478}
479inline void Condition::signal() {
480 pthread_cond_signal(&mCond);
481}
482inline void Condition::broadcast() {
483 pthread_cond_broadcast(&mCond);
484}
485
486#endif // HAVE_PTHREADS
487
488/*****************************************************************************/
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800489
490/*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800491 * This is our spiffy thread object!
492 */
493
494class Thread : virtual public RefBase
495{
496public:
497 // Create a Thread object, but doesn't create or start the associated
498 // thread. See the run() method.
499 Thread(bool canCallJava = true);
500 virtual ~Thread();
501
502 // Start the thread in threadLoop() which needs to be implemented.
503 virtual status_t run( const char* name = 0,
504 int32_t priority = PRIORITY_DEFAULT,
505 size_t stack = 0);
506
507 // Ask this object's thread to exit. This function is asynchronous, when the
508 // function returns the thread might still be running. Of course, this
509 // function can be called from a different thread.
510 virtual void requestExit();
511
512 // Good place to do one-time initializations
513 virtual status_t readyToRun();
514
515 // Call requestExit() and wait until this object's thread exits.
516 // BE VERY CAREFUL of deadlocks. In particular, it would be silly to call
517 // this function from this object's thread. Will return WOULD_BLOCK in
518 // that case.
519 status_t requestExitAndWait();
520
Glenn Kasten697283e2011-06-23 12:55:29 -0700521 // Wait until this object's thread exits. Returns immediately if not yet running.
522 // Do not call from this object's thread; will return WOULD_BLOCK in that case.
523 status_t join();
524
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800525protected:
526 // exitPending() returns true if requestExit() has been called.
527 bool exitPending() const;
528
529private:
Mathias Agopianaaf834a2009-05-22 19:00:22 -0700530 // Derived class must implement threadLoop(). The thread starts its life
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800531 // here. There are two ways of using the Thread object:
532 // 1) loop: if threadLoop() returns true, it will be called again if
533 // requestExit() wasn't called.
534 // 2) once: if threadLoop() returns false, the thread will exit upon return.
535 virtual bool threadLoop() = 0;
536
537private:
538 Thread& operator=(const Thread&);
539 static int _threadLoop(void* user);
540 const bool mCanCallJava;
Glenn Kasten9dbd7d82011-06-02 08:59:28 -0700541 // always hold mLock when reading or writing
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800542 thread_id_t mThread;
Glenn Kastenc2b3cda02011-02-01 11:32:29 -0800543 mutable Mutex mLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800544 Condition mThreadExitedCondition;
545 status_t mStatus;
Glenn Kastenc2b3cda02011-02-01 11:32:29 -0800546 // note that all accesses of mExitPending and mRunning need to hold mLock
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800547 volatile bool mExitPending;
548 volatile bool mRunning;
549 sp<Thread> mHoldSelf;
Mathias Agopiand42bd872009-09-09 02:38:13 -0700550#if HAVE_ANDROID_OS
551 int mTid;
552#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800553};
554
555
556}; // namespace android
557
558#endif // __cplusplus
559
560#endif // _LIBS_UTILS_THREADS_H