blob: 79e02ebb350c996ee7e016dfa1a367b29db8438b [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>
23
Mathias Agopianec0f1f62009-07-12 23:11:20 -070024#if defined(HAVE_PTHREADS)
25# include <pthread.h>
26#endif
27
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080028// ------------------------------------------------------------------
29// C API
30
31#ifdef __cplusplus
32extern "C" {
33#endif
34
35typedef void* android_thread_id_t;
36
37typedef int (*android_thread_func_t)(void*);
38
39enum {
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,
55
56 /* use for background tasks */
57 ANDROID_PRIORITY_BACKGROUND = 10,
58
59 /* most threads run at normal priority */
60 ANDROID_PRIORITY_NORMAL = 0,
61
62 /* threads currently running a UI that the user is interacting with */
63 ANDROID_PRIORITY_FOREGROUND = -2,
64
65 /* the main UI thread has a slightly more favorable priority */
66 ANDROID_PRIORITY_DISPLAY = -4,
67
68 /* ui service treads might want to run at a urgent display (uncommon) */
69 ANDROID_PRIORITY_URGENT_DISPLAY = -8,
70
71 /* all normal audio threads */
72 ANDROID_PRIORITY_AUDIO = -16,
73
74 /* service audio threads (uncommon) */
75 ANDROID_PRIORITY_URGENT_AUDIO = -19,
76
77 /* should never be used in practice. regular process might not
78 * be allowed to use this level */
79 ANDROID_PRIORITY_HIGHEST = -20,
80
81 ANDROID_PRIORITY_DEFAULT = ANDROID_PRIORITY_NORMAL,
82 ANDROID_PRIORITY_MORE_FAVORABLE = -1,
83 ANDROID_PRIORITY_LESS_FAVORABLE = +1,
84};
85
San Mehat046cda42009-04-21 14:06:36 -070086enum {
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};
92
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080093// Create and run a new thread.
94extern int androidCreateThread(android_thread_func_t, void *);
95
96// Create thread with lots of parameters
97extern 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);
103
104// Get some sort of unique identifier for the current thread.
105extern android_thread_id_t androidGetThreadId();
106
107// Low-level thread creation -- never creates threads that can
108// interact with the Java VM.
109extern 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);
115
116// Used by the Java Runtime to control how threads are created, so that
117// they can be proper and lovely Java threads.
118typedef 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);
124
125extern void androidSetCreateThreadFunc(android_create_thread_fn func);
126
Dianne Hackborn8c6cedc2009-12-07 17:59:37 -0800127// ------------------------------------------------------------------
128// Extra functions working with raw pids.
129
130// Get pid for the current thread.
131extern pid_t androidGetTid();
132
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
Glenn Kastence633962011-06-22 17:42:23 -0700136// the operation failed. Thread ID zero means current thread.
Dianne Hackborn8c6cedc2009-12-07 17:59:37 -0800137extern int androidSetThreadSchedulingGroup(pid_t tid, int grp);
138
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;
Glenn Kastence633962011-06-22 17:42:23 -0700142// in either case errno is set. Thread ID zero means current thread.
Dianne Hackborn8c6cedc2009-12-07 17:59:37 -0800143extern int androidSetThreadPriority(pid_t tid, int prio);
144
Glenn Kasten4fb24272011-06-22 16:20:37 -0700145// Get the current scheduling group of a particular thread. Normally returns
146// one of the ANDROID_TGROUP constants other than ANDROID_TGROUP_DEFAULT.
147// Returns ANDROID_TGROUP_DEFAULT if no pthread support (e.g. on host) or if
148// scheduling groups are disabled. Returns INVALID_OPERATION if unexpected error.
149// Thread ID zero means current thread.
150extern int androidGetThreadSchedulingGroup(pid_t tid);
151
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800152#ifdef __cplusplus
153}
154#endif
155
156// ------------------------------------------------------------------
157// C++ API
158
159#ifdef __cplusplus
160
161#include <utils/Errors.h>
162#include <utils/RefBase.h>
163#include <utils/Timers.h>
164
165namespace android {
166
167typedef android_thread_id_t thread_id_t;
168
169typedef android_thread_func_t thread_func_t;
170
171enum {
172 PRIORITY_LOWEST = ANDROID_PRIORITY_LOWEST,
173 PRIORITY_BACKGROUND = ANDROID_PRIORITY_BACKGROUND,
174 PRIORITY_NORMAL = ANDROID_PRIORITY_NORMAL,
175 PRIORITY_FOREGROUND = ANDROID_PRIORITY_FOREGROUND,
176 PRIORITY_DISPLAY = ANDROID_PRIORITY_DISPLAY,
177 PRIORITY_URGENT_DISPLAY = ANDROID_PRIORITY_URGENT_DISPLAY,
178 PRIORITY_AUDIO = ANDROID_PRIORITY_AUDIO,
179 PRIORITY_URGENT_AUDIO = ANDROID_PRIORITY_URGENT_AUDIO,
180 PRIORITY_HIGHEST = ANDROID_PRIORITY_HIGHEST,
181 PRIORITY_DEFAULT = ANDROID_PRIORITY_DEFAULT,
182 PRIORITY_MORE_FAVORABLE = ANDROID_PRIORITY_MORE_FAVORABLE,
183 PRIORITY_LESS_FAVORABLE = ANDROID_PRIORITY_LESS_FAVORABLE,
184};
185
186// Create and run a new thread.
187inline bool createThread(thread_func_t f, void *a) {
188 return androidCreateThread(f, a) ? true : false;
189}
190
191// Create thread with lots of parameters
192inline bool createThreadEtc(thread_func_t entryFunction,
193 void *userData,
194 const char* threadName = "android:unnamed_thread",
195 int32_t threadPriority = PRIORITY_DEFAULT,
196 size_t threadStackSize = 0,
197 thread_id_t *threadId = 0)
198{
199 return androidCreateThreadEtc(entryFunction, userData, threadName,
200 threadPriority, threadStackSize, threadId) ? true : false;
201}
202
203// Get some sort of unique identifier for the current thread.
204inline thread_id_t getThreadId() {
205 return androidGetThreadId();
206}
207
Mathias Agopianec0f1f62009-07-12 23:11:20 -0700208/*****************************************************************************/
209
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800210/*
211 * Simple mutex class. The implementation is system-dependent.
212 *
213 * The mutex must be unlocked by the thread that locked it. They are not
214 * recursive, i.e. the same thread can't lock it multiple times.
215 */
216class Mutex {
217public:
Mathias Agopianeb9fd682009-07-13 21:59:37 -0700218 enum {
Mathias Agopian26d24422010-03-19 16:14:13 -0700219 PRIVATE = 0,
Mathias Agopianeb9fd682009-07-13 21:59:37 -0700220 SHARED = 1
221 };
222
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800223 Mutex();
224 Mutex(const char* name);
Mathias Agopianeb9fd682009-07-13 21:59:37 -0700225 Mutex(int type, const char* name = NULL);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800226 ~Mutex();
227
228 // lock or unlock the mutex
229 status_t lock();
230 void unlock();
231
232 // lock if possible; returns 0 on success, error otherwise
233 status_t tryLock();
234
235 // Manages the mutex automatically. It'll be locked when Autolock is
236 // constructed and released when Autolock goes out of scope.
237 class Autolock {
238 public:
Mathias Agopian83c04462009-05-22 19:00:22 -0700239 inline Autolock(Mutex& mutex) : mLock(mutex) { mLock.lock(); }
240 inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
241 inline ~Autolock() { mLock.unlock(); }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800242 private:
Mathias Agopian83c04462009-05-22 19:00:22 -0700243 Mutex& mLock;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800244 };
245
246private:
247 friend class Condition;
248
249 // A mutex cannot be copied
250 Mutex(const Mutex&);
251 Mutex& operator = (const Mutex&);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800252
Mathias Agopianec0f1f62009-07-12 23:11:20 -0700253#if defined(HAVE_PTHREADS)
254 pthread_mutex_t mMutex;
255#else
256 void _init();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800257 void* mState;
Mathias Agopianec0f1f62009-07-12 23:11:20 -0700258#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800259};
260
Mathias Agopianec0f1f62009-07-12 23:11:20 -0700261#if defined(HAVE_PTHREADS)
262
263inline Mutex::Mutex() {
264 pthread_mutex_init(&mMutex, NULL);
265}
266inline Mutex::Mutex(const char* name) {
267 pthread_mutex_init(&mMutex, NULL);
268}
Mathias Agopianeb9fd682009-07-13 21:59:37 -0700269inline Mutex::Mutex(int type, const char* name) {
270 if (type == SHARED) {
271 pthread_mutexattr_t attr;
272 pthread_mutexattr_init(&attr);
273 pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
274 pthread_mutex_init(&mMutex, &attr);
275 pthread_mutexattr_destroy(&attr);
276 } else {
277 pthread_mutex_init(&mMutex, NULL);
278 }
279}
Mathias Agopianec0f1f62009-07-12 23:11:20 -0700280inline Mutex::~Mutex() {
281 pthread_mutex_destroy(&mMutex);
282}
283inline status_t Mutex::lock() {
284 return -pthread_mutex_lock(&mMutex);
285}
286inline void Mutex::unlock() {
287 pthread_mutex_unlock(&mMutex);
288}
289inline status_t Mutex::tryLock() {
290 return -pthread_mutex_trylock(&mMutex);
291}
292
293#endif // HAVE_PTHREADS
294
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800295/*
296 * Automatic mutex. Declare one of these at the top of a function.
297 * When the function returns, it will go out of scope, and release the
298 * mutex.
299 */
300
301typedef Mutex::Autolock AutoMutex;
302
Mathias Agopianec0f1f62009-07-12 23:11:20 -0700303/*****************************************************************************/
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800304
Mathias Agopiandcf01e62010-05-19 15:11:00 -0700305#if defined(HAVE_PTHREADS)
306
307/*
308 * Simple mutex class. The implementation is system-dependent.
309 *
310 * The mutex must be unlocked by the thread that locked it. They are not
311 * recursive, i.e. the same thread can't lock it multiple times.
312 */
313class RWLock {
314public:
315 enum {
316 PRIVATE = 0,
317 SHARED = 1
318 };
319
320 RWLock();
321 RWLock(const char* name);
322 RWLock(int type, const char* name = NULL);
323 ~RWLock();
324
325 status_t readLock();
326 status_t tryReadLock();
327 status_t writeLock();
328 status_t tryWriteLock();
329 void unlock();
330
331 class AutoRLock {
332 public:
333 inline AutoRLock(RWLock& rwlock) : mLock(rwlock) { mLock.readLock(); }
334 inline ~AutoRLock() { mLock.unlock(); }
335 private:
336 RWLock& mLock;
337 };
338
339 class AutoWLock {
340 public:
341 inline AutoWLock(RWLock& rwlock) : mLock(rwlock) { mLock.writeLock(); }
342 inline ~AutoWLock() { mLock.unlock(); }
343 private:
344 RWLock& mLock;
345 };
346
347private:
348 // A RWLock cannot be copied
349 RWLock(const RWLock&);
350 RWLock& operator = (const RWLock&);
351
352 pthread_rwlock_t mRWLock;
353};
354
355inline RWLock::RWLock() {
356 pthread_rwlock_init(&mRWLock, NULL);
357}
358inline RWLock::RWLock(const char* name) {
359 pthread_rwlock_init(&mRWLock, NULL);
360}
361inline RWLock::RWLock(int type, const char* name) {
362 if (type == SHARED) {
363 pthread_rwlockattr_t attr;
364 pthread_rwlockattr_init(&attr);
365 pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
366 pthread_rwlock_init(&mRWLock, &attr);
367 pthread_rwlockattr_destroy(&attr);
368 } else {
369 pthread_rwlock_init(&mRWLock, NULL);
370 }
371}
372inline RWLock::~RWLock() {
373 pthread_rwlock_destroy(&mRWLock);
374}
375inline status_t RWLock::readLock() {
376 return -pthread_rwlock_rdlock(&mRWLock);
377}
378inline status_t RWLock::tryReadLock() {
379 return -pthread_rwlock_tryrdlock(&mRWLock);
380}
381inline status_t RWLock::writeLock() {
382 return -pthread_rwlock_wrlock(&mRWLock);
383}
384inline status_t RWLock::tryWriteLock() {
385 return -pthread_rwlock_trywrlock(&mRWLock);
386}
387inline void RWLock::unlock() {
388 pthread_rwlock_unlock(&mRWLock);
389}
390
391#endif // HAVE_PTHREADS
392
393/*****************************************************************************/
394
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800395/*
396 * Condition variable class. The implementation is system-dependent.
397 *
398 * Condition variables are paired up with mutexes. Lock the mutex,
399 * call wait(), then either re-wait() if things aren't quite what you want,
400 * or unlock the mutex and continue. All threads calling wait() must
401 * use the same mutex for a given Condition.
402 */
403class Condition {
404public:
Mathias Agopian26d24422010-03-19 16:14:13 -0700405 enum {
406 PRIVATE = 0,
407 SHARED = 1
408 };
409
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800410 Condition();
Mathias Agopian26d24422010-03-19 16:14:13 -0700411 Condition(int type);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800412 ~Condition();
413 // Wait on the condition variable. Lock the mutex before calling.
414 status_t wait(Mutex& mutex);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800415 // same with relative timeout
416 status_t waitRelative(Mutex& mutex, nsecs_t reltime);
417 // Signal the condition variable, allowing one thread to continue.
418 void signal();
419 // Signal the condition variable, allowing all threads to continue.
420 void broadcast();
421
422private:
Mathias Agopianec0f1f62009-07-12 23:11:20 -0700423#if defined(HAVE_PTHREADS)
424 pthread_cond_t mCond;
425#else
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800426 void* mState;
Mathias Agopianec0f1f62009-07-12 23:11:20 -0700427#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800428};
429
Mathias Agopianec0f1f62009-07-12 23:11:20 -0700430#if defined(HAVE_PTHREADS)
431
432inline Condition::Condition() {
433 pthread_cond_init(&mCond, NULL);
434}
Mathias Agopian26d24422010-03-19 16:14:13 -0700435inline Condition::Condition(int type) {
436 if (type == SHARED) {
437 pthread_condattr_t attr;
438 pthread_condattr_init(&attr);
439 pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
440 pthread_cond_init(&mCond, &attr);
441 pthread_condattr_destroy(&attr);
442 } else {
443 pthread_cond_init(&mCond, NULL);
444 }
445}
Mathias Agopianec0f1f62009-07-12 23:11:20 -0700446inline Condition::~Condition() {
447 pthread_cond_destroy(&mCond);
448}
449inline status_t Condition::wait(Mutex& mutex) {
450 return -pthread_cond_wait(&mCond, &mutex.mMutex);
451}
452inline status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) {
453#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)
454 struct timespec ts;
455 ts.tv_sec = reltime/1000000000;
456 ts.tv_nsec = reltime%1000000000;
457 return -pthread_cond_timedwait_relative_np(&mCond, &mutex.mMutex, &ts);
458#else // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
459 struct timespec ts;
460#if defined(HAVE_POSIX_CLOCKS)
461 clock_gettime(CLOCK_REALTIME, &ts);
462#else // HAVE_POSIX_CLOCKS
463 // we don't support the clocks here.
464 struct timeval t;
465 gettimeofday(&t, NULL);
466 ts.tv_sec = t.tv_sec;
467 ts.tv_nsec= t.tv_usec*1000;
468#endif // HAVE_POSIX_CLOCKS
469 ts.tv_sec += reltime/1000000000;
470 ts.tv_nsec+= reltime%1000000000;
471 if (ts.tv_nsec >= 1000000000) {
472 ts.tv_nsec -= 1000000000;
473 ts.tv_sec += 1;
474 }
475 return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts);
476#endif // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
477}
478inline void Condition::signal() {
479 pthread_cond_signal(&mCond);
480}
481inline void Condition::broadcast() {
482 pthread_cond_broadcast(&mCond);
483}
484
485#endif // HAVE_PTHREADS
486
487/*****************************************************************************/
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800488
489/*
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800490 * This is our spiffy thread object!
491 */
492
493class Thread : virtual public RefBase
494{
495public:
496 // Create a Thread object, but doesn't create or start the associated
497 // thread. See the run() method.
498 Thread(bool canCallJava = true);
499 virtual ~Thread();
500
501 // Start the thread in threadLoop() which needs to be implemented.
502 virtual status_t run( const char* name = 0,
503 int32_t priority = PRIORITY_DEFAULT,
504 size_t stack = 0);
505
506 // Ask this object's thread to exit. This function is asynchronous, when the
507 // function returns the thread might still be running. Of course, this
508 // function can be called from a different thread.
509 virtual void requestExit();
510
511 // Good place to do one-time initializations
512 virtual status_t readyToRun();
513
514 // Call requestExit() and wait until this object's thread exits.
515 // BE VERY CAREFUL of deadlocks. In particular, it would be silly to call
516 // this function from this object's thread. Will return WOULD_BLOCK in
517 // that case.
518 status_t requestExitAndWait();
519
Glenn Kasten58e012d2011-06-23 12:55:29 -0700520 // Wait until this object's thread exits. Returns immediately if not yet running.
521 // Do not call from this object's thread; will return WOULD_BLOCK in that case.
522 status_t join();
523
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800524protected:
525 // exitPending() returns true if requestExit() has been called.
526 bool exitPending() const;
527
528private:
Mathias Agopian83c04462009-05-22 19:00:22 -0700529 // Derived class must implement threadLoop(). The thread starts its life
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800530 // here. There are two ways of using the Thread object:
531 // 1) loop: if threadLoop() returns true, it will be called again if
532 // requestExit() wasn't called.
533 // 2) once: if threadLoop() returns false, the thread will exit upon return.
534 virtual bool threadLoop() = 0;
535
536private:
537 Thread& operator=(const Thread&);
538 static int _threadLoop(void* user);
539 const bool mCanCallJava;
Glenn Kastend9e1bb72011-06-02 08:59:28 -0700540 // always hold mLock when reading or writing
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800541 thread_id_t mThread;
Glenn Kasten7e453a52011-02-01 11:32:29 -0800542 mutable Mutex mLock;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800543 Condition mThreadExitedCondition;
544 status_t mStatus;
Glenn Kasten7e453a52011-02-01 11:32:29 -0800545 // note that all accesses of mExitPending and mRunning need to hold mLock
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800546 volatile bool mExitPending;
547 volatile bool mRunning;
548 sp<Thread> mHoldSelf;
Mathias Agopian4de4ebf2009-09-09 02:38:13 -0700549#if HAVE_ANDROID_OS
550 int mTid;
551#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800552};
553
554
555}; // namespace android
556
557#endif // __cplusplus
558
559#endif // _LIBS_UTILS_THREADS_H