blob: c84a9b448c7e3eff0629888c66969e21b6b173ca [file] [log] [blame]
The Android Open Source Projectedbf3b62009-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 Agopiana11499a2011-08-09 18:57:37 -070023#include <system/graphics.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080024
Mathias Agopianec0f1f62009-07-12 23:11:20 -070025#if defined(HAVE_PTHREADS)
26# include <pthread.h>
27#endif
28
The Android Open Source Projectedbf3b62009-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 Agopiana11499a2011-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 Projectedbf3b62009-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 Agopiana11499a2011-08-09 18:57:37 -070070 ANDROID_PRIORITY_URGENT_DISPLAY = HAL_PRIORITY_URGENT_DISPLAY,
The Android Open Source Projectedbf3b62009-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 Mehat046cda42009-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 Projectedbf3b62009-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 Hackborn8c6cedc2009-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 Kastence633962011-06-22 17:42:23 -0700137// the operation failed. Thread ID zero means current thread.
Dianne Hackborn8c6cedc2009-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 Kastence633962011-06-22 17:42:23 -0700143// in either case errno is set. Thread ID zero means current thread.
Dianne Hackborn8c6cedc2009-12-07 17:59:37 -0800144extern int androidSetThreadPriority(pid_t tid, int prio);
145
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800146#ifdef __cplusplus
147}
148#endif
149
150// ------------------------------------------------------------------
151// C++ API
152
153#ifdef __cplusplus
154
155#include <utils/Errors.h>
156#include <utils/RefBase.h>
157#include <utils/Timers.h>
158
159namespace android {
160
161typedef android_thread_id_t thread_id_t;
162
163typedef android_thread_func_t thread_func_t;
164
165enum {
166 PRIORITY_LOWEST = ANDROID_PRIORITY_LOWEST,
167 PRIORITY_BACKGROUND = ANDROID_PRIORITY_BACKGROUND,
168 PRIORITY_NORMAL = ANDROID_PRIORITY_NORMAL,
169 PRIORITY_FOREGROUND = ANDROID_PRIORITY_FOREGROUND,
170 PRIORITY_DISPLAY = ANDROID_PRIORITY_DISPLAY,
171 PRIORITY_URGENT_DISPLAY = ANDROID_PRIORITY_URGENT_DISPLAY,
172 PRIORITY_AUDIO = ANDROID_PRIORITY_AUDIO,
173 PRIORITY_URGENT_AUDIO = ANDROID_PRIORITY_URGENT_AUDIO,
174 PRIORITY_HIGHEST = ANDROID_PRIORITY_HIGHEST,
175 PRIORITY_DEFAULT = ANDROID_PRIORITY_DEFAULT,
176 PRIORITY_MORE_FAVORABLE = ANDROID_PRIORITY_MORE_FAVORABLE,
177 PRIORITY_LESS_FAVORABLE = ANDROID_PRIORITY_LESS_FAVORABLE,
178};
179
180// Create and run a new thread.
181inline bool createThread(thread_func_t f, void *a) {
182 return androidCreateThread(f, a) ? true : false;
183}
184
185// Create thread with lots of parameters
186inline bool createThreadEtc(thread_func_t entryFunction,
187 void *userData,
188 const char* threadName = "android:unnamed_thread",
189 int32_t threadPriority = PRIORITY_DEFAULT,
190 size_t threadStackSize = 0,
191 thread_id_t *threadId = 0)
192{
193 return androidCreateThreadEtc(entryFunction, userData, threadName,
194 threadPriority, threadStackSize, threadId) ? true : false;
195}
196
197// Get some sort of unique identifier for the current thread.
198inline thread_id_t getThreadId() {
199 return androidGetThreadId();
200}
201
Mathias Agopianec0f1f62009-07-12 23:11:20 -0700202/*****************************************************************************/
203
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800204/*
205 * Simple mutex class. The implementation is system-dependent.
206 *
207 * The mutex must be unlocked by the thread that locked it. They are not
208 * recursive, i.e. the same thread can't lock it multiple times.
209 */
210class Mutex {
211public:
Mathias Agopianeb9fd682009-07-13 21:59:37 -0700212 enum {
Mathias Agopian26d24422010-03-19 16:14:13 -0700213 PRIVATE = 0,
Mathias Agopianeb9fd682009-07-13 21:59:37 -0700214 SHARED = 1
215 };
216
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800217 Mutex();
218 Mutex(const char* name);
Mathias Agopianeb9fd682009-07-13 21:59:37 -0700219 Mutex(int type, const char* name = NULL);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800220 ~Mutex();
221
222 // lock or unlock the mutex
223 status_t lock();
224 void unlock();
225
226 // lock if possible; returns 0 on success, error otherwise
227 status_t tryLock();
228
229 // Manages the mutex automatically. It'll be locked when Autolock is
230 // constructed and released when Autolock goes out of scope.
231 class Autolock {
232 public:
Mathias Agopian83c04462009-05-22 19:00:22 -0700233 inline Autolock(Mutex& mutex) : mLock(mutex) { mLock.lock(); }
234 inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
235 inline ~Autolock() { mLock.unlock(); }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800236 private:
Mathias Agopian83c04462009-05-22 19:00:22 -0700237 Mutex& mLock;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800238 };
239
240private:
241 friend class Condition;
242
243 // A mutex cannot be copied
244 Mutex(const Mutex&);
245 Mutex& operator = (const Mutex&);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800246
Mathias Agopianec0f1f62009-07-12 23:11:20 -0700247#if defined(HAVE_PTHREADS)
248 pthread_mutex_t mMutex;
249#else
250 void _init();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800251 void* mState;
Mathias Agopianec0f1f62009-07-12 23:11:20 -0700252#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800253};
254
Mathias Agopianec0f1f62009-07-12 23:11:20 -0700255#if defined(HAVE_PTHREADS)
256
257inline Mutex::Mutex() {
258 pthread_mutex_init(&mMutex, NULL);
259}
260inline Mutex::Mutex(const char* name) {
261 pthread_mutex_init(&mMutex, NULL);
262}
Mathias Agopianeb9fd682009-07-13 21:59:37 -0700263inline Mutex::Mutex(int type, const char* name) {
264 if (type == SHARED) {
265 pthread_mutexattr_t attr;
266 pthread_mutexattr_init(&attr);
267 pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
268 pthread_mutex_init(&mMutex, &attr);
269 pthread_mutexattr_destroy(&attr);
270 } else {
271 pthread_mutex_init(&mMutex, NULL);
272 }
273}
Mathias Agopianec0f1f62009-07-12 23:11:20 -0700274inline Mutex::~Mutex() {
275 pthread_mutex_destroy(&mMutex);
276}
277inline status_t Mutex::lock() {
278 return -pthread_mutex_lock(&mMutex);
279}
280inline void Mutex::unlock() {
281 pthread_mutex_unlock(&mMutex);
282}
283inline status_t Mutex::tryLock() {
284 return -pthread_mutex_trylock(&mMutex);
285}
286
287#endif // HAVE_PTHREADS
288
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800289/*
290 * Automatic mutex. Declare one of these at the top of a function.
291 * When the function returns, it will go out of scope, and release the
292 * mutex.
293 */
294
295typedef Mutex::Autolock AutoMutex;
296
Mathias Agopianec0f1f62009-07-12 23:11:20 -0700297/*****************************************************************************/
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800298
Mathias Agopiandcf01e62010-05-19 15:11:00 -0700299#if defined(HAVE_PTHREADS)
300
301/*
302 * Simple mutex class. The implementation is system-dependent.
303 *
304 * The mutex must be unlocked by the thread that locked it. They are not
305 * recursive, i.e. the same thread can't lock it multiple times.
306 */
307class RWLock {
308public:
309 enum {
310 PRIVATE = 0,
311 SHARED = 1
312 };
313
314 RWLock();
315 RWLock(const char* name);
316 RWLock(int type, const char* name = NULL);
317 ~RWLock();
318
319 status_t readLock();
320 status_t tryReadLock();
321 status_t writeLock();
322 status_t tryWriteLock();
323 void unlock();
324
325 class AutoRLock {
326 public:
327 inline AutoRLock(RWLock& rwlock) : mLock(rwlock) { mLock.readLock(); }
328 inline ~AutoRLock() { mLock.unlock(); }
329 private:
330 RWLock& mLock;
331 };
332
333 class AutoWLock {
334 public:
335 inline AutoWLock(RWLock& rwlock) : mLock(rwlock) { mLock.writeLock(); }
336 inline ~AutoWLock() { mLock.unlock(); }
337 private:
338 RWLock& mLock;
339 };
340
341private:
342 // A RWLock cannot be copied
343 RWLock(const RWLock&);
344 RWLock& operator = (const RWLock&);
345
346 pthread_rwlock_t mRWLock;
347};
348
349inline RWLock::RWLock() {
350 pthread_rwlock_init(&mRWLock, NULL);
351}
352inline RWLock::RWLock(const char* name) {
353 pthread_rwlock_init(&mRWLock, NULL);
354}
355inline RWLock::RWLock(int type, const char* name) {
356 if (type == SHARED) {
357 pthread_rwlockattr_t attr;
358 pthread_rwlockattr_init(&attr);
359 pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
360 pthread_rwlock_init(&mRWLock, &attr);
361 pthread_rwlockattr_destroy(&attr);
362 } else {
363 pthread_rwlock_init(&mRWLock, NULL);
364 }
365}
366inline RWLock::~RWLock() {
367 pthread_rwlock_destroy(&mRWLock);
368}
369inline status_t RWLock::readLock() {
370 return -pthread_rwlock_rdlock(&mRWLock);
371}
372inline status_t RWLock::tryReadLock() {
373 return -pthread_rwlock_tryrdlock(&mRWLock);
374}
375inline status_t RWLock::writeLock() {
376 return -pthread_rwlock_wrlock(&mRWLock);
377}
378inline status_t RWLock::tryWriteLock() {
379 return -pthread_rwlock_trywrlock(&mRWLock);
380}
381inline void RWLock::unlock() {
382 pthread_rwlock_unlock(&mRWLock);
383}
384
385#endif // HAVE_PTHREADS
386
387/*****************************************************************************/
388
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800389/*
390 * Condition variable class. The implementation is system-dependent.
391 *
392 * Condition variables are paired up with mutexes. Lock the mutex,
393 * call wait(), then either re-wait() if things aren't quite what you want,
394 * or unlock the mutex and continue. All threads calling wait() must
395 * use the same mutex for a given Condition.
396 */
397class Condition {
398public:
Mathias Agopian26d24422010-03-19 16:14:13 -0700399 enum {
400 PRIVATE = 0,
401 SHARED = 1
402 };
403
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800404 Condition();
Mathias Agopian26d24422010-03-19 16:14:13 -0700405 Condition(int type);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800406 ~Condition();
407 // Wait on the condition variable. Lock the mutex before calling.
408 status_t wait(Mutex& mutex);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800409 // same with relative timeout
410 status_t waitRelative(Mutex& mutex, nsecs_t reltime);
411 // Signal the condition variable, allowing one thread to continue.
412 void signal();
413 // Signal the condition variable, allowing all threads to continue.
414 void broadcast();
415
416private:
Mathias Agopianec0f1f62009-07-12 23:11:20 -0700417#if defined(HAVE_PTHREADS)
418 pthread_cond_t mCond;
419#else
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800420 void* mState;
Mathias Agopianec0f1f62009-07-12 23:11:20 -0700421#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800422};
423
Mathias Agopianec0f1f62009-07-12 23:11:20 -0700424#if defined(HAVE_PTHREADS)
425
426inline Condition::Condition() {
427 pthread_cond_init(&mCond, NULL);
428}
Mathias Agopian26d24422010-03-19 16:14:13 -0700429inline Condition::Condition(int type) {
430 if (type == SHARED) {
431 pthread_condattr_t attr;
432 pthread_condattr_init(&attr);
433 pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
434 pthread_cond_init(&mCond, &attr);
435 pthread_condattr_destroy(&attr);
436 } else {
437 pthread_cond_init(&mCond, NULL);
438 }
439}
Mathias Agopianec0f1f62009-07-12 23:11:20 -0700440inline Condition::~Condition() {
441 pthread_cond_destroy(&mCond);
442}
443inline status_t Condition::wait(Mutex& mutex) {
444 return -pthread_cond_wait(&mCond, &mutex.mMutex);
445}
446inline status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) {
447#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)
448 struct timespec ts;
449 ts.tv_sec = reltime/1000000000;
450 ts.tv_nsec = reltime%1000000000;
451 return -pthread_cond_timedwait_relative_np(&mCond, &mutex.mMutex, &ts);
452#else // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
453 struct timespec ts;
454#if defined(HAVE_POSIX_CLOCKS)
455 clock_gettime(CLOCK_REALTIME, &ts);
456#else // HAVE_POSIX_CLOCKS
457 // we don't support the clocks here.
458 struct timeval t;
459 gettimeofday(&t, NULL);
460 ts.tv_sec = t.tv_sec;
461 ts.tv_nsec= t.tv_usec*1000;
462#endif // HAVE_POSIX_CLOCKS
463 ts.tv_sec += reltime/1000000000;
464 ts.tv_nsec+= reltime%1000000000;
465 if (ts.tv_nsec >= 1000000000) {
466 ts.tv_nsec -= 1000000000;
467 ts.tv_sec += 1;
468 }
469 return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts);
470#endif // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
471}
472inline void Condition::signal() {
473 pthread_cond_signal(&mCond);
474}
475inline void Condition::broadcast() {
476 pthread_cond_broadcast(&mCond);
477}
478
479#endif // HAVE_PTHREADS
480
481/*****************************************************************************/
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800482
483/*
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800484 * This is our spiffy thread object!
485 */
486
487class Thread : virtual public RefBase
488{
489public:
490 // Create a Thread object, but doesn't create or start the associated
491 // thread. See the run() method.
492 Thread(bool canCallJava = true);
493 virtual ~Thread();
494
495 // Start the thread in threadLoop() which needs to be implemented.
496 virtual status_t run( const char* name = 0,
497 int32_t priority = PRIORITY_DEFAULT,
498 size_t stack = 0);
499
500 // Ask this object's thread to exit. This function is asynchronous, when the
501 // function returns the thread might still be running. Of course, this
502 // function can be called from a different thread.
503 virtual void requestExit();
504
505 // Good place to do one-time initializations
506 virtual status_t readyToRun();
507
508 // Call requestExit() and wait until this object's thread exits.
509 // BE VERY CAREFUL of deadlocks. In particular, it would be silly to call
510 // this function from this object's thread. Will return WOULD_BLOCK in
511 // that case.
512 status_t requestExitAndWait();
513
Glenn Kasten58e012d2011-06-23 12:55:29 -0700514 // Wait until this object's thread exits. Returns immediately if not yet running.
515 // Do not call from this object's thread; will return WOULD_BLOCK in that case.
516 status_t join();
517
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800518protected:
519 // exitPending() returns true if requestExit() has been called.
520 bool exitPending() const;
521
522private:
Mathias Agopian83c04462009-05-22 19:00:22 -0700523 // Derived class must implement threadLoop(). The thread starts its life
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800524 // here. There are two ways of using the Thread object:
525 // 1) loop: if threadLoop() returns true, it will be called again if
526 // requestExit() wasn't called.
527 // 2) once: if threadLoop() returns false, the thread will exit upon return.
528 virtual bool threadLoop() = 0;
529
530private:
531 Thread& operator=(const Thread&);
532 static int _threadLoop(void* user);
533 const bool mCanCallJava;
Glenn Kastend9e1bb72011-06-02 08:59:28 -0700534 // always hold mLock when reading or writing
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800535 thread_id_t mThread;
Glenn Kasten7e453a52011-02-01 11:32:29 -0800536 mutable Mutex mLock;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800537 Condition mThreadExitedCondition;
538 status_t mStatus;
Glenn Kasten7e453a52011-02-01 11:32:29 -0800539 // note that all accesses of mExitPending and mRunning need to hold mLock
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800540 volatile bool mExitPending;
541 volatile bool mRunning;
542 sp<Thread> mHoldSelf;
Mathias Agopian4de4ebf2009-09-09 02:38:13 -0700543#if HAVE_ANDROID_OS
544 int mTid;
545#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800546};
547
548
549}; // namespace android
550
551#endif // __cplusplus
552
553#endif // _LIBS_UTILS_THREADS_H