blob: 1bcfaede67aaebd09d9204bb88c16f1bc2f76c7c [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>
23
Mathias Agopianb1c4ca52009-07-12 23:11:20 -070024#if defined(HAVE_PTHREADS)
25# include <pthread.h>
26#endif
27
The Android Open Source Project9066cfe2009-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 Mehate9d376b2009-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 Project9066cfe2009-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 Hackborn887f3552009-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
136// the operation failed.
137extern 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;
142// in either case errno is set.
143extern int androidSetThreadPriority(pid_t tid, int prio);
144
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145#ifdef __cplusplus
146}
147#endif
148
149// ------------------------------------------------------------------
150// C++ API
151
152#ifdef __cplusplus
153
154#include <utils/Errors.h>
155#include <utils/RefBase.h>
156#include <utils/Timers.h>
157
158namespace android {
159
160typedef android_thread_id_t thread_id_t;
161
162typedef android_thread_func_t thread_func_t;
163
164enum {
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};
178
179// Create and run a new thread.
180inline bool createThread(thread_func_t f, void *a) {
181 return androidCreateThread(f, a) ? true : false;
182}
183
184// Create thread with lots of parameters
185inline 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}
195
196// Get some sort of unique identifier for the current thread.
197inline thread_id_t getThreadId() {
198 return androidGetThreadId();
199}
200
Mathias Agopianb1c4ca52009-07-12 23:11:20 -0700201/*****************************************************************************/
202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203/*
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 */
209class Mutex {
210public:
Mathias Agopianfb4f2662009-07-13 21:59:37 -0700211 enum {
Mathias Agopiana729f972010-03-19 16:14:13 -0700212 PRIVATE = 0,
Mathias Agopianfb4f2662009-07-13 21:59:37 -0700213 SHARED = 1
214 };
215
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 Mutex();
217 Mutex(const char* name);
Mathias Agopianfb4f2662009-07-13 21:59:37 -0700218 Mutex(int type, const char* name = NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219 ~Mutex();
220
221 // lock or unlock the mutex
222 status_t lock();
223 void unlock();
224
225 // lock if possible; returns 0 on success, error otherwise
226 status_t tryLock();
227
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:
Mathias Agopianaaf834a2009-05-22 19:00:22 -0700232 inline Autolock(Mutex& mutex) : mLock(mutex) { mLock.lock(); }
233 inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
234 inline ~Autolock() { mLock.unlock(); }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 private:
Mathias Agopianaaf834a2009-05-22 19:00:22 -0700236 Mutex& mLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237 };
238
239private:
240 friend class Condition;
241
242 // A mutex cannot be copied
243 Mutex(const Mutex&);
244 Mutex& operator = (const Mutex&);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800245
Mathias Agopianb1c4ca52009-07-12 23:11:20 -0700246#if defined(HAVE_PTHREADS)
247 pthread_mutex_t mMutex;
248#else
249 void _init();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250 void* mState;
Mathias Agopianb1c4ca52009-07-12 23:11:20 -0700251#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252};
253
Mathias Agopianb1c4ca52009-07-12 23:11:20 -0700254#if defined(HAVE_PTHREADS)
255
256inline Mutex::Mutex() {
257 pthread_mutex_init(&mMutex, NULL);
258}
259inline Mutex::Mutex(const char* name) {
260 pthread_mutex_init(&mMutex, NULL);
261}
Mathias Agopianfb4f2662009-07-13 21:59:37 -0700262inline 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}
Mathias Agopianb1c4ca52009-07-12 23:11:20 -0700273inline Mutex::~Mutex() {
274 pthread_mutex_destroy(&mMutex);
275}
276inline status_t Mutex::lock() {
277 return -pthread_mutex_lock(&mMutex);
278}
279inline void Mutex::unlock() {
280 pthread_mutex_unlock(&mMutex);
281}
282inline status_t Mutex::tryLock() {
283 return -pthread_mutex_trylock(&mMutex);
284}
285
286#endif // HAVE_PTHREADS
287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288/*
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 */
293
294typedef Mutex::Autolock AutoMutex;
295
Mathias Agopianb1c4ca52009-07-12 23:11:20 -0700296/*****************************************************************************/
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297
Mathias Agopian66c46a62010-05-19 15:11:00 -0700298#if defined(HAVE_PTHREADS)
299
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 */
306class RWLock {
307public:
308 enum {
309 PRIVATE = 0,
310 SHARED = 1
311 };
312
313 RWLock();
314 RWLock(const char* name);
315 RWLock(int type, const char* name = NULL);
316 ~RWLock();
317
318 status_t readLock();
319 status_t tryReadLock();
320 status_t writeLock();
321 status_t tryWriteLock();
322 void unlock();
323
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 };
331
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 };
339
340private:
341 // A RWLock cannot be copied
342 RWLock(const RWLock&);
343 RWLock& operator = (const RWLock&);
344
345 pthread_rwlock_t mRWLock;
346};
347
348inline RWLock::RWLock() {
349 pthread_rwlock_init(&mRWLock, NULL);
350}
351inline RWLock::RWLock(const char* name) {
352 pthread_rwlock_init(&mRWLock, NULL);
353}
354inline 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}
365inline RWLock::~RWLock() {
366 pthread_rwlock_destroy(&mRWLock);
367}
368inline status_t RWLock::readLock() {
369 return -pthread_rwlock_rdlock(&mRWLock);
370}
371inline status_t RWLock::tryReadLock() {
372 return -pthread_rwlock_tryrdlock(&mRWLock);
373}
374inline status_t RWLock::writeLock() {
375 return -pthread_rwlock_wrlock(&mRWLock);
376}
377inline status_t RWLock::tryWriteLock() {
378 return -pthread_rwlock_trywrlock(&mRWLock);
379}
380inline void RWLock::unlock() {
381 pthread_rwlock_unlock(&mRWLock);
382}
383
384#endif // HAVE_PTHREADS
385
386/*****************************************************************************/
387
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800388/*
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 */
396class Condition {
397public:
Mathias Agopiana729f972010-03-19 16:14:13 -0700398 enum {
399 PRIVATE = 0,
400 SHARED = 1
401 };
402
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800403 Condition();
Mathias Agopiana729f972010-03-19 16:14:13 -0700404 Condition(int type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 ~Condition();
406 // Wait on the condition variable. Lock the mutex before calling.
407 status_t wait(Mutex& mutex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800408 // 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();
414
415private:
Mathias Agopianb1c4ca52009-07-12 23:11:20 -0700416#if defined(HAVE_PTHREADS)
417 pthread_cond_t mCond;
418#else
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419 void* mState;
Mathias Agopianb1c4ca52009-07-12 23:11:20 -0700420#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421};
422
Mathias Agopianb1c4ca52009-07-12 23:11:20 -0700423#if defined(HAVE_PTHREADS)
424
425inline Condition::Condition() {
426 pthread_cond_init(&mCond, NULL);
427}
Mathias Agopiana729f972010-03-19 16:14:13 -0700428inline 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}
Mathias Agopianb1c4ca52009-07-12 23:11:20 -0700439inline Condition::~Condition() {
440 pthread_cond_destroy(&mCond);
441}
442inline status_t Condition::wait(Mutex& mutex) {
443 return -pthread_cond_wait(&mCond, &mutex.mMutex);
444}
445inline 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}
471inline void Condition::signal() {
472 pthread_cond_signal(&mCond);
473}
474inline void Condition::broadcast() {
475 pthread_cond_broadcast(&mCond);
476}
477
478#endif // HAVE_PTHREADS
479
480/*****************************************************************************/
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481
482/*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800483 * This is our spiffy thread object!
484 */
485
486class Thread : virtual public RefBase
487{
488public:
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();
493
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);
498
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();
503
504 // Good place to do one-time initializations
505 virtual status_t readyToRun();
506
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();
512
513protected:
514 // exitPending() returns true if requestExit() has been called.
515 bool exitPending() const;
516
517private:
Mathias Agopianaaf834a2009-05-22 19:00:22 -0700518 // Derived class must implement threadLoop(). The thread starts its life
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800519 // 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;
524
525private:
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;
Mathias Agopiand42bd872009-09-09 02:38:13 -0700536#if HAVE_ANDROID_OS
537 int mTid;
538#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800539};
540
541
542}; // namespace android
543
544#endif // __cplusplus
545
546#endif // _LIBS_UTILS_THREADS_H