blob: bc1c285f3af37d5047b792f8a2ae6e003faa5230 [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
The Android Open Source Project9adf84a2009-03-05 14:34:35 -080017// #define LOG_NDEBUG 0
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080018#define LOG_TAG "libutils.threads"
19
20#include <utils/threads.h>
21#include <utils/Log.h>
22
Dianne Hackborn8c6cedc2009-12-07 17:59:37 -080023#include <cutils/sched_policy.h>
Dianne Hackborn7b0d45c2010-09-03 17:07:07 -070024#include <cutils/properties.h>
Dianne Hackborn8c6cedc2009-12-07 17:59:37 -080025
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080026#include <stdio.h>
27#include <stdlib.h>
28#include <memory.h>
29#include <errno.h>
30#include <assert.h>
31#include <unistd.h>
32
33#if defined(HAVE_PTHREADS)
34# include <pthread.h>
35# include <sched.h>
36# include <sys/resource.h>
Glenn Kastenba699cb2011-07-11 15:59:22 -070037#ifdef HAVE_ANDROID_OS
38# include <bionic_pthread.h>
39#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080040#elif defined(HAVE_WIN32_THREADS)
41# include <windows.h>
42# include <stdint.h>
43# include <process.h>
44# define HAVE_CREATETHREAD // Cygwin, vs. HAVE__BEGINTHREADEX for MinGW
45#endif
46
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080047#if defined(HAVE_PRCTL)
48#include <sys/prctl.h>
49#endif
50
51/*
52 * ===========================================================================
53 * Thread wrappers
54 * ===========================================================================
55 */
56
57using namespace android;
58
59// ----------------------------------------------------------------------------
60#if defined(HAVE_PTHREADS)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080061// ----------------------------------------------------------------------------
62
63/*
Dianne Hackborn7b0d45c2010-09-03 17:07:07 -070064 * Create and run a new thread.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080065 *
66 * We create it "detached", so it cleans up after itself.
67 */
68
69typedef void* (*android_pthread_entry)(void*);
70
Dianne Hackborn9c82c482010-09-09 15:50:18 -070071static pthread_once_t gDoSchedulingGroupOnce = PTHREAD_ONCE_INIT;
72static bool gDoSchedulingGroup = true;
73
74static void checkDoSchedulingGroup(void) {
75 char buf[PROPERTY_VALUE_MAX];
76 int len = property_get("debug.sys.noschedgroups", buf, "");
77 if (len > 0) {
78 int temp;
79 if (sscanf(buf, "%d", &temp) == 1) {
80 gDoSchedulingGroup = temp == 0;
81 }
82 }
83}
84
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080085struct thread_data_t {
86 thread_func_t entryFunction;
87 void* userData;
88 int priority;
89 char * threadName;
90
91 // we use this trampoline when we need to set the priority with
Glenn Kastenba699cb2011-07-11 15:59:22 -070092 // nice/setpriority, and name with prctl.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080093 static int trampoline(const thread_data_t* t) {
94 thread_func_t f = t->entryFunction;
95 void* u = t->userData;
96 int prio = t->priority;
97 char * name = t->threadName;
98 delete t;
99 setpriority(PRIO_PROCESS, 0, prio);
Dianne Hackborn9c82c482010-09-09 15:50:18 -0700100 pthread_once(&gDoSchedulingGroupOnce, checkDoSchedulingGroup);
101 if (gDoSchedulingGroup) {
102 if (prio >= ANDROID_PRIORITY_BACKGROUND) {
103 set_sched_policy(androidGetTid(), SP_BACKGROUND);
104 } else {
105 set_sched_policy(androidGetTid(), SP_FOREGROUND);
106 }
107 }
108
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800109 if (name) {
110#if defined(HAVE_PRCTL)
111 // Mac OS doesn't have this, and we build libutil for the host too
112 int hasAt = 0;
113 int hasDot = 0;
114 char *s = name;
115 while (*s) {
116 if (*s == '.') hasDot = 1;
117 else if (*s == '@') hasAt = 1;
118 s++;
119 }
120 int len = s - name;
121 if (len < 15 || hasAt || !hasDot) {
122 s = name;
123 } else {
124 s = name + len - 15;
125 }
126 prctl(PR_SET_NAME, (unsigned long) s, 0, 0, 0);
127#endif
128 free(name);
129 }
130 return f(u);
131 }
132};
133
134int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
135 void *userData,
136 const char* threadName,
137 int32_t threadPriority,
138 size_t threadStackSize,
139 android_thread_id_t *threadId)
140{
141 pthread_attr_t attr;
142 pthread_attr_init(&attr);
143 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
144
145#ifdef HAVE_ANDROID_OS /* valgrind is rejecting RT-priority create reqs */
146 if (threadPriority != PRIORITY_DEFAULT || threadName != NULL) {
Glenn Kastenba699cb2011-07-11 15:59:22 -0700147 // Now that the pthread_t has a method to find the associated
148 // android_thread_id_t (pid) from pthread_t, it would be possible to avoid
149 // this trampoline in some cases as the parent could set the properties
150 // for the child. However, there would be a race condition because the
151 // child becomes ready immediately, and it doesn't work for the name.
152 // prctl(PR_SET_NAME) only works for self; prctl(PR_SET_THREAD_NAME) was
153 // proposed but not yet accepted.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800154 thread_data_t* t = new thread_data_t;
155 t->priority = threadPriority;
156 t->threadName = threadName ? strdup(threadName) : NULL;
157 t->entryFunction = entryFunction;
158 t->userData = userData;
159 entryFunction = (android_thread_func_t)&thread_data_t::trampoline;
160 userData = t;
161 }
162#endif
163
164 if (threadStackSize) {
165 pthread_attr_setstacksize(&attr, threadStackSize);
166 }
167
168 errno = 0;
169 pthread_t thread;
170 int result = pthread_create(&thread, &attr,
171 (android_pthread_entry)entryFunction, userData);
Le-Chun Wu39199502011-07-14 14:27:18 -0700172 pthread_attr_destroy(&attr);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800173 if (result != 0) {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000174 ALOGE("androidCreateRawThreadEtc failed (entry=%p, res=%d, errno=%d)\n"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800175 "(android threadPriority=%d)",
176 entryFunction, result, errno, threadPriority);
177 return 0;
178 }
179
Glenn Kastend9e1bb72011-06-02 08:59:28 -0700180 // Note that *threadID is directly available to the parent only, as it is
181 // assigned after the child starts. Use memory barrier / lock if the child
182 // or other threads also need access.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800183 if (threadId != NULL) {
184 *threadId = (android_thread_id_t)thread; // XXX: this is not portable
185 }
186 return 1;
187}
188
Glenn Kastenba699cb2011-07-11 15:59:22 -0700189#ifdef HAVE_ANDROID_OS
190static pthread_t android_thread_id_t_to_pthread(android_thread_id_t thread)
191{
192 return (pthread_t) thread;
193}
194#endif
195
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800196android_thread_id_t androidGetThreadId()
197{
198 return (android_thread_id_t)pthread_self();
199}
200
201// ----------------------------------------------------------------------------
202#elif defined(HAVE_WIN32_THREADS)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800203// ----------------------------------------------------------------------------
204
205/*
206 * Trampoline to make us __stdcall-compliant.
207 *
208 * We're expected to delete "vDetails" when we're done.
209 */
210struct threadDetails {
211 int (*func)(void*);
212 void* arg;
213};
214static __stdcall unsigned int threadIntermediary(void* vDetails)
215{
216 struct threadDetails* pDetails = (struct threadDetails*) vDetails;
217 int result;
218
219 result = (*(pDetails->func))(pDetails->arg);
220
221 delete pDetails;
222
Steve Block9f760152011-10-12 17:27:03 +0100223 ALOG(LOG_VERBOSE, "thread", "thread exiting\n");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800224 return (unsigned int) result;
225}
226
227/*
228 * Create and run a new thread.
229 */
230static bool doCreateThread(android_thread_func_t fn, void* arg, android_thread_id_t *id)
231{
232 HANDLE hThread;
233 struct threadDetails* pDetails = new threadDetails; // must be on heap
234 unsigned int thrdaddr;
235
236 pDetails->func = fn;
237 pDetails->arg = arg;
238
239#if defined(HAVE__BEGINTHREADEX)
240 hThread = (HANDLE) _beginthreadex(NULL, 0, threadIntermediary, pDetails, 0,
241 &thrdaddr);
242 if (hThread == 0)
243#elif defined(HAVE_CREATETHREAD)
244 hThread = CreateThread(NULL, 0,
245 (LPTHREAD_START_ROUTINE) threadIntermediary,
246 (void*) pDetails, 0, (DWORD*) &thrdaddr);
247 if (hThread == NULL)
248#endif
249 {
Steve Block9f760152011-10-12 17:27:03 +0100250 ALOG(LOG_WARN, "thread", "WARNING: thread create failed\n");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800251 return false;
252 }
253
254#if defined(HAVE_CREATETHREAD)
255 /* close the management handle */
256 CloseHandle(hThread);
257#endif
258
259 if (id != NULL) {
260 *id = (android_thread_id_t)thrdaddr;
261 }
262
263 return true;
264}
265
266int androidCreateRawThreadEtc(android_thread_func_t fn,
267 void *userData,
268 const char* threadName,
269 int32_t threadPriority,
270 size_t threadStackSize,
271 android_thread_id_t *threadId)
272{
273 return doCreateThread( fn, userData, threadId);
274}
275
276android_thread_id_t androidGetThreadId()
277{
278 return (android_thread_id_t)GetCurrentThreadId();
279}
280
281// ----------------------------------------------------------------------------
282#else
283#error "Threads not supported"
284#endif
285
286// ----------------------------------------------------------------------------
287
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800288int androidCreateThread(android_thread_func_t fn, void* arg)
289{
290 return createThreadEtc(fn, arg);
291}
292
293int androidCreateThreadGetID(android_thread_func_t fn, void *arg, android_thread_id_t *id)
294{
295 return createThreadEtc(fn, arg, "android:unnamed_thread",
296 PRIORITY_DEFAULT, 0, id);
297}
298
299static android_create_thread_fn gCreateThreadFn = androidCreateRawThreadEtc;
300
301int androidCreateThreadEtc(android_thread_func_t entryFunction,
302 void *userData,
303 const char* threadName,
304 int32_t threadPriority,
305 size_t threadStackSize,
306 android_thread_id_t *threadId)
307{
308 return gCreateThreadFn(entryFunction, userData, threadName,
309 threadPriority, threadStackSize, threadId);
310}
311
312void androidSetCreateThreadFunc(android_create_thread_fn func)
313{
314 gCreateThreadFn = func;
315}
316
Dianne Hackborn8c6cedc2009-12-07 17:59:37 -0800317pid_t androidGetTid()
318{
319#ifdef HAVE_GETTID
320 return gettid();
321#else
322 return getpid();
323#endif
324}
325
Jeff Brown0818b092012-03-16 22:18:39 -0700326#ifdef HAVE_ANDROID_OS
Dianne Hackborn8c6cedc2009-12-07 17:59:37 -0800327int androidSetThreadPriority(pid_t tid, int pri)
328{
329 int rc = 0;
Dianne Hackbornd0aecce2009-12-08 19:45:59 -0800330
331#if defined(HAVE_PTHREADS)
Dianne Hackborn8c6cedc2009-12-07 17:59:37 -0800332 int lasterr = 0;
333
Dianne Hackborn7b0d45c2010-09-03 17:07:07 -0700334 pthread_once(&gDoSchedulingGroupOnce, checkDoSchedulingGroup);
335 if (gDoSchedulingGroup) {
Glenn Kastenf0c41252011-06-14 10:35:34 -0700336 // set_sched_policy does not support tid == 0
337 int policy_tid;
338 if (tid == 0) {
339 policy_tid = androidGetTid();
340 } else {
341 policy_tid = tid;
342 }
Dianne Hackborn7b0d45c2010-09-03 17:07:07 -0700343 if (pri >= ANDROID_PRIORITY_BACKGROUND) {
Glenn Kastenf0c41252011-06-14 10:35:34 -0700344 rc = set_sched_policy(policy_tid, SP_BACKGROUND);
Dianne Hackborn7b0d45c2010-09-03 17:07:07 -0700345 } else if (getpriority(PRIO_PROCESS, tid) >= ANDROID_PRIORITY_BACKGROUND) {
Glenn Kastenf0c41252011-06-14 10:35:34 -0700346 rc = set_sched_policy(policy_tid, SP_FOREGROUND);
Dianne Hackborn7b0d45c2010-09-03 17:07:07 -0700347 }
Dianne Hackborn8c6cedc2009-12-07 17:59:37 -0800348 }
349
350 if (rc) {
351 lasterr = errno;
352 }
353
354 if (setpriority(PRIO_PROCESS, tid, pri) < 0) {
355 rc = INVALID_OPERATION;
356 } else {
357 errno = lasterr;
358 }
Dianne Hackbornc5b13892009-12-08 16:38:01 -0800359#endif
Dianne Hackborn8c6cedc2009-12-07 17:59:37 -0800360
361 return rc;
362}
363
Andreas Huber1d60b962011-09-15 12:21:40 -0700364int androidGetThreadPriority(pid_t tid) {
Andreas Huber9dbb77d2011-09-16 11:47:13 -0700365#if defined(HAVE_PTHREADS)
Andreas Huber1d60b962011-09-15 12:21:40 -0700366 return getpriority(PRIO_PROCESS, tid);
Andreas Huber9dbb77d2011-09-16 11:47:13 -0700367#else
368 return ANDROID_PRIORITY_NORMAL;
369#endif
Andreas Huber1d60b962011-09-15 12:21:40 -0700370}
371
Jeff Brown0818b092012-03-16 22:18:39 -0700372#endif
Glenn Kasten4fb24272011-06-22 16:20:37 -0700373
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800374namespace android {
375
376/*
377 * ===========================================================================
378 * Mutex class
379 * ===========================================================================
380 */
381
Mathias Agopianec0f1f62009-07-12 23:11:20 -0700382#if defined(HAVE_PTHREADS)
383// implemented as inlines in threads.h
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800384#elif defined(HAVE_WIN32_THREADS)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800385
386Mutex::Mutex()
387{
388 HANDLE hMutex;
389
390 assert(sizeof(hMutex) == sizeof(mState));
391
392 hMutex = CreateMutex(NULL, FALSE, NULL);
393 mState = (void*) hMutex;
394}
395
396Mutex::Mutex(const char* name)
397{
398 // XXX: name not used for now
399 HANDLE hMutex;
400
David 'Digit' Turner429db152009-08-01 00:20:17 +0200401 assert(sizeof(hMutex) == sizeof(mState));
402
403 hMutex = CreateMutex(NULL, FALSE, NULL);
404 mState = (void*) hMutex;
405}
406
407Mutex::Mutex(int type, const char* name)
408{
409 // XXX: type and name not used for now
410 HANDLE hMutex;
411
412 assert(sizeof(hMutex) == sizeof(mState));
413
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800414 hMutex = CreateMutex(NULL, FALSE, NULL);
415 mState = (void*) hMutex;
416}
417
418Mutex::~Mutex()
419{
420 CloseHandle((HANDLE) mState);
421}
422
423status_t Mutex::lock()
424{
425 DWORD dwWaitResult;
426 dwWaitResult = WaitForSingleObject((HANDLE) mState, INFINITE);
427 return dwWaitResult != WAIT_OBJECT_0 ? -1 : NO_ERROR;
428}
429
430void Mutex::unlock()
431{
432 if (!ReleaseMutex((HANDLE) mState))
Steve Block9f760152011-10-12 17:27:03 +0100433 ALOG(LOG_WARN, "thread", "WARNING: bad result from unlocking mutex\n");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800434}
435
436status_t Mutex::tryLock()
437{
438 DWORD dwWaitResult;
439
440 dwWaitResult = WaitForSingleObject((HANDLE) mState, 0);
441 if (dwWaitResult != WAIT_OBJECT_0 && dwWaitResult != WAIT_TIMEOUT)
Steve Block9f760152011-10-12 17:27:03 +0100442 ALOG(LOG_WARN, "thread", "WARNING: bad result from try-locking mutex\n");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800443 return (dwWaitResult == WAIT_OBJECT_0) ? 0 : -1;
444}
445
446#else
447#error "Somebody forgot to implement threads for this platform."
448#endif
449
450
451/*
452 * ===========================================================================
453 * Condition class
454 * ===========================================================================
455 */
456
Mathias Agopianec0f1f62009-07-12 23:11:20 -0700457#if defined(HAVE_PTHREADS)
458// implemented as inlines in threads.h
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800459#elif defined(HAVE_WIN32_THREADS)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800460
461/*
462 * Windows doesn't have a condition variable solution. It's possible
463 * to create one, but it's easy to get it wrong. For a discussion, and
464 * the origin of this implementation, see:
465 *
466 * http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
467 *
468 * The implementation shown on the page does NOT follow POSIX semantics.
469 * As an optimization they require acquiring the external mutex before
470 * calling signal() and broadcast(), whereas POSIX only requires grabbing
471 * it before calling wait(). The implementation here has been un-optimized
472 * to have the correct behavior.
473 */
474typedef struct WinCondition {
475 // Number of waiting threads.
476 int waitersCount;
477
478 // Serialize access to waitersCount.
479 CRITICAL_SECTION waitersCountLock;
480
481 // Semaphore used to queue up threads waiting for the condition to
482 // become signaled.
483 HANDLE sema;
484
485 // An auto-reset event used by the broadcast/signal thread to wait
486 // for all the waiting thread(s) to wake up and be released from
487 // the semaphore.
488 HANDLE waitersDone;
489
490 // This mutex wouldn't be necessary if we required that the caller
491 // lock the external mutex before calling signal() and broadcast().
492 // I'm trying to mimic pthread semantics though.
493 HANDLE internalMutex;
494
495 // Keeps track of whether we were broadcasting or signaling. This
496 // allows us to optimize the code if we're just signaling.
497 bool wasBroadcast;
498
499 status_t wait(WinCondition* condState, HANDLE hMutex, nsecs_t* abstime)
500 {
501 // Increment the wait count, avoiding race conditions.
502 EnterCriticalSection(&condState->waitersCountLock);
503 condState->waitersCount++;
504 //printf("+++ wait: incr waitersCount to %d (tid=%ld)\n",
505 // condState->waitersCount, getThreadId());
506 LeaveCriticalSection(&condState->waitersCountLock);
507
508 DWORD timeout = INFINITE;
509 if (abstime) {
510 nsecs_t reltime = *abstime - systemTime();
511 if (reltime < 0)
512 reltime = 0;
513 timeout = reltime/1000000;
514 }
515
516 // Atomically release the external mutex and wait on the semaphore.
517 DWORD res =
518 SignalObjectAndWait(hMutex, condState->sema, timeout, FALSE);
519
520 //printf("+++ wait: awake (tid=%ld)\n", getThreadId());
521
522 // Reacquire lock to avoid race conditions.
523 EnterCriticalSection(&condState->waitersCountLock);
524
525 // No longer waiting.
526 condState->waitersCount--;
527
528 // Check to see if we're the last waiter after a broadcast.
529 bool lastWaiter = (condState->wasBroadcast && condState->waitersCount == 0);
530
531 //printf("+++ wait: lastWaiter=%d (wasBc=%d wc=%d)\n",
532 // lastWaiter, condState->wasBroadcast, condState->waitersCount);
533
534 LeaveCriticalSection(&condState->waitersCountLock);
535
536 // If we're the last waiter thread during this particular broadcast
537 // then signal broadcast() that we're all awake. It'll drop the
538 // internal mutex.
539 if (lastWaiter) {
540 // Atomically signal the "waitersDone" event and wait until we
541 // can acquire the internal mutex. We want to do this in one step
542 // because it ensures that everybody is in the mutex FIFO before
543 // any thread has a chance to run. Without it, another thread
544 // could wake up, do work, and hop back in ahead of us.
545 SignalObjectAndWait(condState->waitersDone, condState->internalMutex,
546 INFINITE, FALSE);
547 } else {
548 // Grab the internal mutex.
549 WaitForSingleObject(condState->internalMutex, INFINITE);
550 }
551
552 // Release the internal and grab the external.
553 ReleaseMutex(condState->internalMutex);
554 WaitForSingleObject(hMutex, INFINITE);
555
556 return res == WAIT_OBJECT_0 ? NO_ERROR : -1;
557 }
558} WinCondition;
559
560/*
561 * Constructor. Set up the WinCondition stuff.
562 */
563Condition::Condition()
564{
565 WinCondition* condState = new WinCondition;
566
567 condState->waitersCount = 0;
568 condState->wasBroadcast = false;
569 // semaphore: no security, initial value of 0
570 condState->sema = CreateSemaphore(NULL, 0, 0x7fffffff, NULL);
571 InitializeCriticalSection(&condState->waitersCountLock);
572 // auto-reset event, not signaled initially
573 condState->waitersDone = CreateEvent(NULL, FALSE, FALSE, NULL);
574 // used so we don't have to lock external mutex on signal/broadcast
575 condState->internalMutex = CreateMutex(NULL, FALSE, NULL);
576
577 mState = condState;
578}
579
580/*
581 * Destructor. Free Windows resources as well as our allocated storage.
582 */
583Condition::~Condition()
584{
585 WinCondition* condState = (WinCondition*) mState;
586 if (condState != NULL) {
587 CloseHandle(condState->sema);
588 CloseHandle(condState->waitersDone);
589 delete condState;
590 }
591}
592
593
594status_t Condition::wait(Mutex& mutex)
595{
596 WinCondition* condState = (WinCondition*) mState;
597 HANDLE hMutex = (HANDLE) mutex.mState;
598
599 return ((WinCondition*)mState)->wait(condState, hMutex, NULL);
600}
601
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800602status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime)
603{
David 'Digit' Turner429db152009-08-01 00:20:17 +0200604 WinCondition* condState = (WinCondition*) mState;
605 HANDLE hMutex = (HANDLE) mutex.mState;
606 nsecs_t absTime = systemTime()+reltime;
607
608 return ((WinCondition*)mState)->wait(condState, hMutex, &absTime);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800609}
610
611/*
612 * Signal the condition variable, allowing one thread to continue.
613 */
614void Condition::signal()
615{
616 WinCondition* condState = (WinCondition*) mState;
617
618 // Lock the internal mutex. This ensures that we don't clash with
619 // broadcast().
620 WaitForSingleObject(condState->internalMutex, INFINITE);
621
622 EnterCriticalSection(&condState->waitersCountLock);
623 bool haveWaiters = (condState->waitersCount > 0);
624 LeaveCriticalSection(&condState->waitersCountLock);
625
626 // If no waiters, then this is a no-op. Otherwise, knock the semaphore
627 // down a notch.
628 if (haveWaiters)
629 ReleaseSemaphore(condState->sema, 1, 0);
630
631 // Release internal mutex.
632 ReleaseMutex(condState->internalMutex);
633}
634
635/*
636 * Signal the condition variable, allowing all threads to continue.
637 *
638 * First we have to wake up all threads waiting on the semaphore, then
639 * we wait until all of the threads have actually been woken before
640 * releasing the internal mutex. This ensures that all threads are woken.
641 */
642void Condition::broadcast()
643{
644 WinCondition* condState = (WinCondition*) mState;
645
646 // Lock the internal mutex. This keeps the guys we're waking up
647 // from getting too far.
648 WaitForSingleObject(condState->internalMutex, INFINITE);
649
650 EnterCriticalSection(&condState->waitersCountLock);
651 bool haveWaiters = false;
652
653 if (condState->waitersCount > 0) {
654 haveWaiters = true;
655 condState->wasBroadcast = true;
656 }
657
658 if (haveWaiters) {
659 // Wake up all the waiters.
660 ReleaseSemaphore(condState->sema, condState->waitersCount, 0);
661
662 LeaveCriticalSection(&condState->waitersCountLock);
663
664 // Wait for all awakened threads to acquire the counting semaphore.
665 // The last guy who was waiting sets this.
666 WaitForSingleObject(condState->waitersDone, INFINITE);
667
668 // Reset wasBroadcast. (No crit section needed because nobody
669 // else can wake up to poke at it.)
670 condState->wasBroadcast = 0;
671 } else {
672 // nothing to do
673 LeaveCriticalSection(&condState->waitersCountLock);
674 }
675
676 // Release internal mutex.
677 ReleaseMutex(condState->internalMutex);
678}
679
680#else
681#error "condition variables not supported on this platform"
682#endif
683
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800684// ----------------------------------------------------------------------------
685
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800686/*
687 * This is our thread object!
688 */
689
690Thread::Thread(bool canCallJava)
691 : mCanCallJava(canCallJava),
692 mThread(thread_id_t(-1)),
693 mLock("Thread::mLock"),
694 mStatus(NO_ERROR),
695 mExitPending(false), mRunning(false)
Glenn Kasten7e453a52011-02-01 11:32:29 -0800696#ifdef HAVE_ANDROID_OS
697 , mTid(-1)
698#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800699{
700}
701
702Thread::~Thread()
703{
704}
705
706status_t Thread::readyToRun()
707{
708 return NO_ERROR;
709}
710
711status_t Thread::run(const char* name, int32_t priority, size_t stack)
712{
713 Mutex::Autolock _l(mLock);
714
715 if (mRunning) {
716 // thread already started
717 return INVALID_OPERATION;
718 }
719
720 // reset status and exitPending to their default value, so we can
721 // try again after an error happened (either below, or in readyToRun())
722 mStatus = NO_ERROR;
723 mExitPending = false;
724 mThread = thread_id_t(-1);
725
726 // hold a strong reference on ourself
727 mHoldSelf = this;
728
The Android Open Source Project9adf84a2009-03-05 14:34:35 -0800729 mRunning = true;
730
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800731 bool res;
732 if (mCanCallJava) {
733 res = createThreadEtc(_threadLoop,
734 this, name, priority, stack, &mThread);
735 } else {
736 res = androidCreateRawThreadEtc(_threadLoop,
737 this, name, priority, stack, &mThread);
738 }
739
740 if (res == false) {
741 mStatus = UNKNOWN_ERROR; // something happened!
742 mRunning = false;
743 mThread = thread_id_t(-1);
The Android Open Source Project9adf84a2009-03-05 14:34:35 -0800744 mHoldSelf.clear(); // "this" may have gone away after this.
745
746 return UNKNOWN_ERROR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800747 }
748
The Android Open Source Project9adf84a2009-03-05 14:34:35 -0800749 // Do not refer to mStatus here: The thread is already running (may, in fact
750 // already have exited with a valid mStatus result). The NO_ERROR indication
751 // here merely indicates successfully starting the thread and does not
752 // imply successful termination/execution.
753 return NO_ERROR;
Glenn Kasten7e453a52011-02-01 11:32:29 -0800754
755 // Exiting scope of mLock is a memory barrier and allows new thread to run
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800756}
757
758int Thread::_threadLoop(void* user)
759{
760 Thread* const self = static_cast<Thread*>(user);
Glenn Kasten7e453a52011-02-01 11:32:29 -0800761
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800762 sp<Thread> strong(self->mHoldSelf);
763 wp<Thread> weak(strong);
764 self->mHoldSelf.clear();
765
Kenny Rootaf1cf072011-02-16 10:13:53 -0800766#ifdef HAVE_ANDROID_OS
Mathias Agopian4de4ebf2009-09-09 02:38:13 -0700767 // this is very useful for debugging with gdb
768 self->mTid = gettid();
769#endif
770
The Android Open Source Project9adf84a2009-03-05 14:34:35 -0800771 bool first = true;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800772
773 do {
The Android Open Source Project9adf84a2009-03-05 14:34:35 -0800774 bool result;
775 if (first) {
776 first = false;
777 self->mStatus = self->readyToRun();
778 result = (self->mStatus == NO_ERROR);
779
Glenn Kasten7e453a52011-02-01 11:32:29 -0800780 if (result && !self->exitPending()) {
The Android Open Source Project9adf84a2009-03-05 14:34:35 -0800781 // Binder threads (and maybe others) rely on threadLoop
782 // running at least once after a successful ::readyToRun()
783 // (unless, of course, the thread has already been asked to exit
784 // at that point).
785 // This is because threads are essentially used like this:
786 // (new ThreadSubclass())->run();
787 // The caller therefore does not retain a strong reference to
788 // the thread and the thread would simply disappear after the
789 // successful ::readyToRun() call instead of entering the
790 // threadLoop at least once.
791 result = self->threadLoop();
792 }
793 } else {
794 result = self->threadLoop();
795 }
796
Glenn Kasten7e453a52011-02-01 11:32:29 -0800797 // establish a scope for mLock
798 {
799 Mutex::Autolock _l(self->mLock);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800800 if (result == false || self->mExitPending) {
801 self->mExitPending = true;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800802 self->mRunning = false;
Eric Laurenta017d5b2011-01-04 11:58:04 -0800803 // clear thread ID so that requestExitAndWait() does not exit if
804 // called by a new thread using the same thread ID as this one.
805 self->mThread = thread_id_t(-1);
Glenn Kasten7e453a52011-02-01 11:32:29 -0800806 // note that interested observers blocked in requestExitAndWait are
807 // awoken by broadcast, but blocked on mLock until break exits scope
Mathias Agopian4de4ebf2009-09-09 02:38:13 -0700808 self->mThreadExitedCondition.broadcast();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800809 break;
810 }
Glenn Kasten7e453a52011-02-01 11:32:29 -0800811 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800812
813 // Release our strong reference, to let a chance to the thread
814 // to die a peaceful death.
815 strong.clear();
Mathias Agopian4de4ebf2009-09-09 02:38:13 -0700816 // And immediately, re-acquire a strong reference for the next loop
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800817 strong = weak.promote();
818 } while(strong != 0);
819
820 return 0;
821}
822
823void Thread::requestExit()
824{
Glenn Kasten7e453a52011-02-01 11:32:29 -0800825 Mutex::Autolock _l(mLock);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800826 mExitPending = true;
827}
828
829status_t Thread::requestExitAndWait()
830{
Glenn Kastend9e1bb72011-06-02 08:59:28 -0700831 Mutex::Autolock _l(mLock);
The Android Open Source Project9adf84a2009-03-05 14:34:35 -0800832 if (mThread == getThreadId()) {
Steve Block32397c12012-01-05 23:22:43 +0000833 ALOGW(
The Android Open Source Project9adf84a2009-03-05 14:34:35 -0800834 "Thread (this=%p): don't call waitForExit() from this "
835 "Thread object's thread. It's a guaranteed deadlock!",
836 this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800837
The Android Open Source Project9adf84a2009-03-05 14:34:35 -0800838 return WOULD_BLOCK;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800839 }
The Android Open Source Project9adf84a2009-03-05 14:34:35 -0800840
Glenn Kastend9e1bb72011-06-02 08:59:28 -0700841 mExitPending = true;
The Android Open Source Project9adf84a2009-03-05 14:34:35 -0800842
The Android Open Source Project9adf84a2009-03-05 14:34:35 -0800843 while (mRunning == true) {
844 mThreadExitedCondition.wait(mLock);
845 }
Glenn Kasten7e453a52011-02-01 11:32:29 -0800846 // This next line is probably not needed any more, but is being left for
847 // historical reference. Note that each interested party will clear flag.
The Android Open Source Project9adf84a2009-03-05 14:34:35 -0800848 mExitPending = false;
849
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800850 return mStatus;
851}
852
Glenn Kasten58e012d2011-06-23 12:55:29 -0700853status_t Thread::join()
854{
855 Mutex::Autolock _l(mLock);
856 if (mThread == getThreadId()) {
Steve Block32397c12012-01-05 23:22:43 +0000857 ALOGW(
Glenn Kasten58e012d2011-06-23 12:55:29 -0700858 "Thread (this=%p): don't call join() from this "
859 "Thread object's thread. It's a guaranteed deadlock!",
860 this);
861
862 return WOULD_BLOCK;
863 }
864
865 while (mRunning == true) {
866 mThreadExitedCondition.wait(mLock);
867 }
868
869 return mStatus;
870}
871
Glenn Kastenba699cb2011-07-11 15:59:22 -0700872#ifdef HAVE_ANDROID_OS
873pid_t Thread::getTid() const
874{
875 // mTid is not defined until the child initializes it, and the caller may need it earlier
876 Mutex::Autolock _l(mLock);
877 pid_t tid;
878 if (mRunning) {
879 pthread_t pthread = android_thread_id_t_to_pthread(mThread);
880 tid = __pthread_gettid(pthread);
881 } else {
882 ALOGW("Thread (this=%p): getTid() is undefined before run()", this);
883 tid = -1;
884 }
885 return tid;
886}
887#endif
888
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800889bool Thread::exitPending() const
890{
Glenn Kasten7e453a52011-02-01 11:32:29 -0800891 Mutex::Autolock _l(mLock);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800892 return mExitPending;
893}
894
895
896
897}; // namespace android