|
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. |
|
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. |
|
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: |
|
244 inline Autolock(Mutex& mutex) : mLock(mutex) { mLock.lock(); } |
|
245 inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); } |
|
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 |
|
268 inline Mutex::Mutex() { |
|
269 pthread_mutex_init(&mMutex, NULL); |
|
270 } |
|
271 inline Mutex::Mutex(const char* name) { |
|
272 pthread_mutex_init(&mMutex, NULL); |
|
273 } |
|
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 } |
|
285 inline Mutex::~Mutex() { |
|
286 pthread_mutex_destroy(&mMutex); |
|
287 } |
|
288 inline status_t Mutex::lock() { |
|
289 return -pthread_mutex_lock(&mMutex); |
|
290 } |
|
291 inline void Mutex::unlock() { |
|
292 pthread_mutex_unlock(&mMutex); |
|
293 } |
|
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: |
|
338 inline AutoRLock(RWLock& rwlock) : mLock(rwlock) { mLock.readLock(); } |
|
339 inline ~AutoRLock() { mLock.unlock(); } |
|
340 private: |
|
341 RWLock& mLock; |
|
342 }; |
|
343 |
|
344 class AutoWLock { |
|
345 public: |
|
346 inline AutoWLock(RWLock& rwlock) : mLock(rwlock) { mLock.writeLock(); } |
|
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 |
|
360 inline RWLock::RWLock() { |
|
361 pthread_rwlock_init(&mRWLock, NULL); |
|
362 } |
|
363 inline RWLock::RWLock(const char* name) { |
|
364 pthread_rwlock_init(&mRWLock, NULL); |
|
365 } |
|
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 } |
|
377 inline RWLock::~RWLock() { |
|
378 pthread_rwlock_destroy(&mRWLock); |
|
379 } |
|
380 inline status_t RWLock::readLock() { |
|
381 return -pthread_rwlock_rdlock(&mRWLock); |
|
382 } |
|
383 inline status_t RWLock::tryReadLock() { |
|
384 return -pthread_rwlock_tryrdlock(&mRWLock); |
|
385 } |
|
386 inline status_t RWLock::writeLock() { |
|
387 return -pthread_rwlock_wrlock(&mRWLock); |
|
388 } |
|
389 inline status_t RWLock::tryWriteLock() { |
|
390 return -pthread_rwlock_trywrlock(&mRWLock); |
|
391 } |
|
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 |
|
437 inline Condition::Condition() { |
|
438 pthread_cond_init(&mCond, NULL); |
|
439 } |
|
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 } |
|
451 inline Condition::~Condition() { |
|
452 pthread_cond_destroy(&mCond); |
|
453 } |
|
454 inline status_t Condition::wait(Mutex& mutex) { |
|
455 return -pthread_cond_wait(&mCond, &mutex.mMutex); |
|
456 } |
|
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 } |
|
483 inline void Condition::signal() { |
|
484 pthread_cond_signal(&mCond); |
|
485 } |
|
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 |