|
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 |
|
24 #if defined(HAVE_PTHREADS) |
|
25 # include <pthread.h> |
|
26 #endif |
|
27 |
|
28 // ------------------------------------------------------------------ |
|
29 // C API |
|
30 |
|
31 #ifdef __cplusplus |
|
32 extern "C" { |
|
33 #endif |
|
34 |
|
35 typedef void* android_thread_id_t; |
|
36 |
|
37 typedef int (*android_thread_func_t)(void*); |
|
38 |
|
39 enum { |
|
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 |
|
86 enum { |
|
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 |
|
93 // Create and run a new thread. |
|
94 extern int androidCreateThread(android_thread_func_t, void *); |
|
95 |
|
96 // Create thread with lots of parameters |
|
97 extern 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. |
|
105 extern android_thread_id_t androidGetThreadId(); |
|
106 |
|
107 // Low-level thread creation -- never creates threads that can |
|
108 // interact with the Java VM. |
|
109 extern 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. |
|
118 typedef 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 |
|
125 extern void androidSetCreateThreadFunc(android_create_thread_fn func); |
|
126 |
|
127 // ------------------------------------------------------------------ |
|
128 // Extra functions working with raw pids. |
|
129 |
|
130 // Get pid for the current thread. |
|
131 extern 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. |
|
137 extern 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. |
|
143 extern int androidSetThreadPriority(pid_t tid, int prio); |
|
144 |
|
145 #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 |
|
158 namespace android { |
|
159 |
|
160 typedef android_thread_id_t thread_id_t; |
|
161 |
|
162 typedef android_thread_func_t thread_func_t; |
|
163 |
|
164 enum { |
|
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. |
|
180 inline bool createThread(thread_func_t f, void *a) { |
|
181 return androidCreateThread(f, a) ? true : false; |
|
182 } |
|
183 |
|
184 // Create thread with lots of parameters |
|
185 inline 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. |
|
197 inline thread_id_t getThreadId() { |
|
198 return androidGetThreadId(); |
|
199 } |
|
200 |
|
201 /*****************************************************************************/ |
|
202 |
|
203 /* |
|
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 */ |
|
209 class Mutex { |
|
210 public: |
|
211 enum { |
|
212 PRIVATE = 0, |
|
213 SHARED = 1 |
|
214 }; |
|
215 |
|
216 Mutex(); |
|
217 Mutex(const char* name); |
|
218 Mutex(int type, const char* name = NULL); |
|
219 ~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: |
|
232 inline Autolock(Mutex& mutex) : mLock(mutex) { mLock.lock(); } |
|
233 inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); } |
|
234 inline ~Autolock() { mLock.unlock(); } |
|
235 private: |
|
236 Mutex& mLock; |
|
237 }; |
|
238 |
|
239 private: |
|
240 friend class Condition; |
|
241 |
|
242 // A mutex cannot be copied |
|
243 Mutex(const Mutex&); |
|
244 Mutex& operator = (const Mutex&); |
|
245 |
|
246 #if defined(HAVE_PTHREADS) |
|
247 pthread_mutex_t mMutex; |
|
248 #else |
|
249 void _init(); |
|
250 void* mState; |
|
251 #endif |
|
252 }; |
|
253 |
|
254 #if defined(HAVE_PTHREADS) |
|
255 |
|
256 inline Mutex::Mutex() { |
|
257 pthread_mutex_init(&mMutex, NULL); |
|
258 } |
|
259 inline Mutex::Mutex(const char* name) { |
|
260 pthread_mutex_init(&mMutex, NULL); |
|
261 } |
|
262 inline 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 } |
|
273 inline Mutex::~Mutex() { |
|
274 pthread_mutex_destroy(&mMutex); |
|
275 } |
|
276 inline status_t Mutex::lock() { |
|
277 return -pthread_mutex_lock(&mMutex); |
|
278 } |
|
279 inline void Mutex::unlock() { |
|
280 pthread_mutex_unlock(&mMutex); |
|
281 } |
|
282 inline status_t Mutex::tryLock() { |
|
283 return -pthread_mutex_trylock(&mMutex); |
|
284 } |
|
285 |
|
286 #endif // HAVE_PTHREADS |
|
287 |
|
288 /* |
|
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 |
|
294 typedef Mutex::Autolock AutoMutex; |
|
295 |
|
296 /*****************************************************************************/ |
|
297 |
|
298 /* |
|
299 * Condition variable class. The implementation is system-dependent. |
|
300 * |
|
301 * Condition variables are paired up with mutexes. Lock the mutex, |
|
302 * call wait(), then either re-wait() if things aren't quite what you want, |
|
303 * or unlock the mutex and continue. All threads calling wait() must |
|
304 * use the same mutex for a given Condition. |
|
305 */ |
|
306 class Condition { |
|
307 public: |
|
308 enum { |
|
309 PRIVATE = 0, |
|
310 SHARED = 1 |
|
311 }; |
|
312 |
|
313 Condition(); |
|
314 Condition(int type); |
|
315 ~Condition(); |
|
316 // Wait on the condition variable. Lock the mutex before calling. |
|
317 status_t wait(Mutex& mutex); |
|
318 // same with relative timeout |
|
319 status_t waitRelative(Mutex& mutex, nsecs_t reltime); |
|
320 // Signal the condition variable, allowing one thread to continue. |
|
321 void signal(); |
|
322 // Signal the condition variable, allowing all threads to continue. |
|
323 void broadcast(); |
|
324 |
|
325 private: |
|
326 #if defined(HAVE_PTHREADS) |
|
327 pthread_cond_t mCond; |
|
328 #else |
|
329 void* mState; |
|
330 #endif |
|
331 }; |
|
332 |
|
333 #if defined(HAVE_PTHREADS) |
|
334 |
|
335 inline Condition::Condition() { |
|
336 pthread_cond_init(&mCond, NULL); |
|
337 } |
|
338 inline Condition::Condition(int type) { |
|
339 if (type == SHARED) { |
|
340 pthread_condattr_t attr; |
|
341 pthread_condattr_init(&attr); |
|
342 pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); |
|
343 pthread_cond_init(&mCond, &attr); |
|
344 pthread_condattr_destroy(&attr); |
|
345 } else { |
|
346 pthread_cond_init(&mCond, NULL); |
|
347 } |
|
348 } |
|
349 inline Condition::~Condition() { |
|
350 pthread_cond_destroy(&mCond); |
|
351 } |
|
352 inline status_t Condition::wait(Mutex& mutex) { |
|
353 return -pthread_cond_wait(&mCond, &mutex.mMutex); |
|
354 } |
|
355 inline status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) { |
|
356 #if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE) |
|
357 struct timespec ts; |
|
358 ts.tv_sec = reltime/1000000000; |
|
359 ts.tv_nsec = reltime%1000000000; |
|
360 return -pthread_cond_timedwait_relative_np(&mCond, &mutex.mMutex, &ts); |
|
361 #else // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE |
|
362 struct timespec ts; |
|
363 #if defined(HAVE_POSIX_CLOCKS) |
|
364 clock_gettime(CLOCK_REALTIME, &ts); |
|
365 #else // HAVE_POSIX_CLOCKS |
|
366 // we don't support the clocks here. |
|
367 struct timeval t; |
|
368 gettimeofday(&t, NULL); |
|
369 ts.tv_sec = t.tv_sec; |
|
370 ts.tv_nsec= t.tv_usec*1000; |
|
371 #endif // HAVE_POSIX_CLOCKS |
|
372 ts.tv_sec += reltime/1000000000; |
|
373 ts.tv_nsec+= reltime%1000000000; |
|
374 if (ts.tv_nsec >= 1000000000) { |
|
375 ts.tv_nsec -= 1000000000; |
|
376 ts.tv_sec += 1; |
|
377 } |
|
378 return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts); |
|
379 #endif // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE |
|
380 } |
|
381 inline void Condition::signal() { |
|
382 pthread_cond_signal(&mCond); |
|
383 } |
|
384 inline void Condition::broadcast() { |
|
385 pthread_cond_broadcast(&mCond); |
|
386 } |
|
387 |
|
388 #endif // HAVE_PTHREADS |
|
389 |
|
390 /*****************************************************************************/ |
|
391 |
|
392 /* |
|
393 * This is our spiffy thread object! |
|
394 */ |
|
395 |
|
396 class Thread : virtual public RefBase |
|
397 { |
|
398 public: |
|
399 // Create a Thread object, but doesn't create or start the associated |
|
400 // thread. See the run() method. |
|
401 Thread(bool canCallJava = true); |
|
402 virtual ~Thread(); |
|
403 |
|
404 // Start the thread in threadLoop() which needs to be implemented. |
|
405 virtual status_t run( const char* name = 0, |
|
406 int32_t priority = PRIORITY_DEFAULT, |
|
407 size_t stack = 0); |
|
408 |
|
409 // Ask this object's thread to exit. This function is asynchronous, when the |
|
410 // function returns the thread might still be running. Of course, this |
|
411 // function can be called from a different thread. |
|
412 virtual void requestExit(); |
|
413 |
|
414 // Good place to do one-time initializations |
|
415 virtual status_t readyToRun(); |
|
416 |
|
417 // Call requestExit() and wait until this object's thread exits. |
|
418 // BE VERY CAREFUL of deadlocks. In particular, it would be silly to call |
|
419 // this function from this object's thread. Will return WOULD_BLOCK in |
|
420 // that case. |
|
421 status_t requestExitAndWait(); |
|
422 |
|
423 protected: |
|
424 // exitPending() returns true if requestExit() has been called. |
|
425 bool exitPending() const; |
|
426 |
|
427 private: |
|
428 // Derived class must implement threadLoop(). The thread starts its life |
|
429 // here. There are two ways of using the Thread object: |
|
430 // 1) loop: if threadLoop() returns true, it will be called again if |
|
431 // requestExit() wasn't called. |
|
432 // 2) once: if threadLoop() returns false, the thread will exit upon return. |
|
433 virtual bool threadLoop() = 0; |
|
434 |
|
435 private: |
|
436 Thread& operator=(const Thread&); |
|
437 static int _threadLoop(void* user); |
|
438 const bool mCanCallJava; |
|
439 thread_id_t mThread; |
|
440 Mutex mLock; |
|
441 Condition mThreadExitedCondition; |
|
442 status_t mStatus; |
|
443 volatile bool mExitPending; |
|
444 volatile bool mRunning; |
|
445 sp<Thread> mHoldSelf; |
|
446 #if HAVE_ANDROID_OS |
|
447 int mTid; |
|
448 #endif |
|
449 }; |
|
450 |
|
451 |
|
452 }; // namespace android |
|
453 |
|
454 #endif // __cplusplus |
|
455 |
|
456 #endif // _LIBS_UTILS_THREADS_H |