blob: 5c039659607465547ef68396644f889360edf93c [file] [log] [blame]
The Android Open Source Projectcbb10112009-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 Agopian15554362009-07-12 23:11:20 -070024#if defined(HAVE_PTHREADS)
25# include <pthread.h>
26#endif
27
The Android Open Source Projectcbb10112009-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 Mehat624a35e2009-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 Projectcbb10112009-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
127#ifdef __cplusplus
128}
129#endif
130
131// ------------------------------------------------------------------
132// C++ API
133
134#ifdef __cplusplus
135
136#include <utils/Errors.h>
137#include <utils/RefBase.h>
138#include <utils/Timers.h>
139
140namespace android {
141
142typedef android_thread_id_t thread_id_t;
143
144typedef android_thread_func_t thread_func_t;
145
146enum {
147 PRIORITY_LOWEST = ANDROID_PRIORITY_LOWEST,
148 PRIORITY_BACKGROUND = ANDROID_PRIORITY_BACKGROUND,
149 PRIORITY_NORMAL = ANDROID_PRIORITY_NORMAL,
150 PRIORITY_FOREGROUND = ANDROID_PRIORITY_FOREGROUND,
151 PRIORITY_DISPLAY = ANDROID_PRIORITY_DISPLAY,
152 PRIORITY_URGENT_DISPLAY = ANDROID_PRIORITY_URGENT_DISPLAY,
153 PRIORITY_AUDIO = ANDROID_PRIORITY_AUDIO,
154 PRIORITY_URGENT_AUDIO = ANDROID_PRIORITY_URGENT_AUDIO,
155 PRIORITY_HIGHEST = ANDROID_PRIORITY_HIGHEST,
156 PRIORITY_DEFAULT = ANDROID_PRIORITY_DEFAULT,
157 PRIORITY_MORE_FAVORABLE = ANDROID_PRIORITY_MORE_FAVORABLE,
158 PRIORITY_LESS_FAVORABLE = ANDROID_PRIORITY_LESS_FAVORABLE,
159};
160
161// Create and run a new thread.
162inline bool createThread(thread_func_t f, void *a) {
163 return androidCreateThread(f, a) ? true : false;
164}
165
166// Create thread with lots of parameters
167inline bool createThreadEtc(thread_func_t entryFunction,
168 void *userData,
169 const char* threadName = "android:unnamed_thread",
170 int32_t threadPriority = PRIORITY_DEFAULT,
171 size_t threadStackSize = 0,
172 thread_id_t *threadId = 0)
173{
174 return androidCreateThreadEtc(entryFunction, userData, threadName,
175 threadPriority, threadStackSize, threadId) ? true : false;
176}
177
178// Get some sort of unique identifier for the current thread.
179inline thread_id_t getThreadId() {
180 return androidGetThreadId();
181}
182
Mathias Agopian15554362009-07-12 23:11:20 -0700183/*****************************************************************************/
184
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800185/*
186 * Simple mutex class. The implementation is system-dependent.
187 *
188 * The mutex must be unlocked by the thread that locked it. They are not
189 * recursive, i.e. the same thread can't lock it multiple times.
190 */
191class Mutex {
192public:
193 Mutex();
194 Mutex(const char* name);
195 ~Mutex();
196
197 // lock or unlock the mutex
198 status_t lock();
199 void unlock();
200
201 // lock if possible; returns 0 on success, error otherwise
202 status_t tryLock();
203
204 // Manages the mutex automatically. It'll be locked when Autolock is
205 // constructed and released when Autolock goes out of scope.
206 class Autolock {
207 public:
Mathias Agopiand0ef3d42009-05-22 19:00:22 -0700208 inline Autolock(Mutex& mutex) : mLock(mutex) { mLock.lock(); }
209 inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
210 inline ~Autolock() { mLock.unlock(); }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800211 private:
Mathias Agopiand0ef3d42009-05-22 19:00:22 -0700212 Mutex& mLock;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800213 };
214
215private:
216 friend class Condition;
217
218 // A mutex cannot be copied
219 Mutex(const Mutex&);
220 Mutex& operator = (const Mutex&);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800221
Mathias Agopian15554362009-07-12 23:11:20 -0700222#if defined(HAVE_PTHREADS)
223 pthread_mutex_t mMutex;
224#else
225 void _init();
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800226 void* mState;
Mathias Agopian15554362009-07-12 23:11:20 -0700227#endif
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800228};
229
Mathias Agopian15554362009-07-12 23:11:20 -0700230#if defined(HAVE_PTHREADS)
231
232inline Mutex::Mutex() {
233 pthread_mutex_init(&mMutex, NULL);
234}
235inline Mutex::Mutex(const char* name) {
236 pthread_mutex_init(&mMutex, NULL);
237}
238inline Mutex::~Mutex() {
239 pthread_mutex_destroy(&mMutex);
240}
241inline status_t Mutex::lock() {
242 return -pthread_mutex_lock(&mMutex);
243}
244inline void Mutex::unlock() {
245 pthread_mutex_unlock(&mMutex);
246}
247inline status_t Mutex::tryLock() {
248 return -pthread_mutex_trylock(&mMutex);
249}
250
251#endif // HAVE_PTHREADS
252
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800253/*
254 * Automatic mutex. Declare one of these at the top of a function.
255 * When the function returns, it will go out of scope, and release the
256 * mutex.
257 */
258
259typedef Mutex::Autolock AutoMutex;
260
Mathias Agopian15554362009-07-12 23:11:20 -0700261/*****************************************************************************/
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800262
263/*
264 * Condition variable class. The implementation is system-dependent.
265 *
266 * Condition variables are paired up with mutexes. Lock the mutex,
267 * call wait(), then either re-wait() if things aren't quite what you want,
268 * or unlock the mutex and continue. All threads calling wait() must
269 * use the same mutex for a given Condition.
270 */
271class Condition {
272public:
273 Condition();
274 ~Condition();
275 // Wait on the condition variable. Lock the mutex before calling.
276 status_t wait(Mutex& mutex);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800277 // same with relative timeout
278 status_t waitRelative(Mutex& mutex, nsecs_t reltime);
279 // Signal the condition variable, allowing one thread to continue.
280 void signal();
281 // Signal the condition variable, allowing all threads to continue.
282 void broadcast();
283
284private:
Mathias Agopian15554362009-07-12 23:11:20 -0700285#if defined(HAVE_PTHREADS)
286 pthread_cond_t mCond;
287#else
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800288 void* mState;
Mathias Agopian15554362009-07-12 23:11:20 -0700289#endif
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800290};
291
Mathias Agopian15554362009-07-12 23:11:20 -0700292#if defined(HAVE_PTHREADS)
293
294inline Condition::Condition() {
295 pthread_cond_init(&mCond, NULL);
296}
297inline Condition::~Condition() {
298 pthread_cond_destroy(&mCond);
299}
300inline status_t Condition::wait(Mutex& mutex) {
301 return -pthread_cond_wait(&mCond, &mutex.mMutex);
302}
303inline status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) {
304#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)
305 struct timespec ts;
306 ts.tv_sec = reltime/1000000000;
307 ts.tv_nsec = reltime%1000000000;
308 return -pthread_cond_timedwait_relative_np(&mCond, &mutex.mMutex, &ts);
309#else // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
310 struct timespec ts;
311#if defined(HAVE_POSIX_CLOCKS)
312 clock_gettime(CLOCK_REALTIME, &ts);
313#else // HAVE_POSIX_CLOCKS
314 // we don't support the clocks here.
315 struct timeval t;
316 gettimeofday(&t, NULL);
317 ts.tv_sec = t.tv_sec;
318 ts.tv_nsec= t.tv_usec*1000;
319#endif // HAVE_POSIX_CLOCKS
320 ts.tv_sec += reltime/1000000000;
321 ts.tv_nsec+= reltime%1000000000;
322 if (ts.tv_nsec >= 1000000000) {
323 ts.tv_nsec -= 1000000000;
324 ts.tv_sec += 1;
325 }
326 return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts);
327#endif // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
328}
329inline void Condition::signal() {
330 pthread_cond_signal(&mCond);
331}
332inline void Condition::broadcast() {
333 pthread_cond_broadcast(&mCond);
334}
335
336#endif // HAVE_PTHREADS
337
338/*****************************************************************************/
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800339
340/*
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800341 * This is our spiffy thread object!
342 */
343
344class Thread : virtual public RefBase
345{
346public:
347 // Create a Thread object, but doesn't create or start the associated
348 // thread. See the run() method.
349 Thread(bool canCallJava = true);
350 virtual ~Thread();
351
352 // Start the thread in threadLoop() which needs to be implemented.
353 virtual status_t run( const char* name = 0,
354 int32_t priority = PRIORITY_DEFAULT,
355 size_t stack = 0);
356
357 // Ask this object's thread to exit. This function is asynchronous, when the
358 // function returns the thread might still be running. Of course, this
359 // function can be called from a different thread.
360 virtual void requestExit();
361
362 // Good place to do one-time initializations
363 virtual status_t readyToRun();
364
365 // Call requestExit() and wait until this object's thread exits.
366 // BE VERY CAREFUL of deadlocks. In particular, it would be silly to call
367 // this function from this object's thread. Will return WOULD_BLOCK in
368 // that case.
369 status_t requestExitAndWait();
370
371protected:
372 // exitPending() returns true if requestExit() has been called.
373 bool exitPending() const;
374
375private:
Mathias Agopiand0ef3d42009-05-22 19:00:22 -0700376 // Derived class must implement threadLoop(). The thread starts its life
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800377 // here. There are two ways of using the Thread object:
378 // 1) loop: if threadLoop() returns true, it will be called again if
379 // requestExit() wasn't called.
380 // 2) once: if threadLoop() returns false, the thread will exit upon return.
381 virtual bool threadLoop() = 0;
382
383private:
384 Thread& operator=(const Thread&);
385 static int _threadLoop(void* user);
386 const bool mCanCallJava;
387 thread_id_t mThread;
388 Mutex mLock;
389 Condition mThreadExitedCondition;
390 status_t mStatus;
391 volatile bool mExitPending;
392 volatile bool mRunning;
393 sp<Thread> mHoldSelf;
394};
395
396
397}; // namespace android
398
399#endif // __cplusplus
400
401#endif // _LIBS_UTILS_THREADS_H