blob: ff74914cbb34613c25092620c480983b18869a03 [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
The Android Open Source Project7a4c8392009-03-05 14:34:35 -080017// #define LOG_NDEBUG 0
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080018#define LOG_TAG "libutils.threads"
19
20#include <utils/threads.h>
21#include <utils/Log.h>
22
Dianne Hackborn235af972009-12-07 17:59:37 -080023#include <cutils/sched_policy.h>
24
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080025#include <stdio.h>
26#include <stdlib.h>
27#include <memory.h>
28#include <errno.h>
29#include <assert.h>
30#include <unistd.h>
31
32#if defined(HAVE_PTHREADS)
33# include <pthread.h>
34# include <sched.h>
35# include <sys/resource.h>
Glenn Kastend731f072011-07-11 15:59:22 -070036#ifdef HAVE_ANDROID_OS
37# include <bionic_pthread.h>
38#endif
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080039#elif defined(HAVE_WIN32_THREADS)
40# include <windows.h>
41# include <stdint.h>
42# include <process.h>
43# define HAVE_CREATETHREAD // Cygwin, vs. HAVE__BEGINTHREADEX for MinGW
44#endif
45
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080046#if defined(HAVE_PRCTL)
47#include <sys/prctl.h>
48#endif
49
50/*
51 * ===========================================================================
52 * Thread wrappers
53 * ===========================================================================
54 */
55
56using namespace android;
57
58// ----------------------------------------------------------------------------
59#if defined(HAVE_PTHREADS)
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080060// ----------------------------------------------------------------------------
61
62/*
Dianne Hackborn16d217e2010-09-03 17:07:07 -070063 * Create and run a new thread.
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080064 *
65 * We create it "detached", so it cleans up after itself.
66 */
67
68typedef void* (*android_pthread_entry)(void*);
69
70struct thread_data_t {
71 thread_func_t entryFunction;
72 void* userData;
73 int priority;
74 char * threadName;
75
76 // we use this trampoline when we need to set the priority with
Glenn Kastend731f072011-07-11 15:59:22 -070077 // nice/setpriority, and name with prctl.
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080078 static int trampoline(const thread_data_t* t) {
79 thread_func_t f = t->entryFunction;
80 void* u = t->userData;
81 int prio = t->priority;
82 char * name = t->threadName;
83 delete t;
84 setpriority(PRIO_PROCESS, 0, prio);
Glenn Kastenfe34e452012-04-30 16:03:30 -070085 if (prio >= ANDROID_PRIORITY_BACKGROUND) {
86 set_sched_policy(0, SP_BACKGROUND);
87 } else {
88 set_sched_policy(0, SP_FOREGROUND);
Dianne Hackborna78bab02010-09-09 15:50:18 -070089 }
90
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080091 if (name) {
Mathias Agopian6090df82013-03-07 15:34:28 -080092 androidSetThreadName(name);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080093 free(name);
94 }
95 return f(u);
96 }
97};
98
Mathias Agopian6090df82013-03-07 15:34:28 -080099void androidSetThreadName(const char* name) {
100#if defined(HAVE_PRCTL)
101 // Mac OS doesn't have this, and we build libutil for the host too
102 int hasAt = 0;
103 int hasDot = 0;
104 const char *s = name;
105 while (*s) {
106 if (*s == '.') hasDot = 1;
107 else if (*s == '@') hasAt = 1;
108 s++;
109 }
110 int len = s - name;
111 if (len < 15 || hasAt || !hasDot) {
112 s = name;
113 } else {
114 s = name + len - 15;
115 }
116 prctl(PR_SET_NAME, (unsigned long) s, 0, 0, 0);
117#endif
118}
119
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800120int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
121 void *userData,
122 const char* threadName,
123 int32_t threadPriority,
124 size_t threadStackSize,
125 android_thread_id_t *threadId)
126{
127 pthread_attr_t attr;
128 pthread_attr_init(&attr);
129 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
130
131#ifdef HAVE_ANDROID_OS /* valgrind is rejecting RT-priority create reqs */
132 if (threadPriority != PRIORITY_DEFAULT || threadName != NULL) {
Glenn Kastend731f072011-07-11 15:59:22 -0700133 // Now that the pthread_t has a method to find the associated
134 // android_thread_id_t (pid) from pthread_t, it would be possible to avoid
135 // this trampoline in some cases as the parent could set the properties
136 // for the child. However, there would be a race condition because the
137 // child becomes ready immediately, and it doesn't work for the name.
138 // prctl(PR_SET_NAME) only works for self; prctl(PR_SET_THREAD_NAME) was
139 // proposed but not yet accepted.
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800140 thread_data_t* t = new thread_data_t;
141 t->priority = threadPriority;
142 t->threadName = threadName ? strdup(threadName) : NULL;
143 t->entryFunction = entryFunction;
144 t->userData = userData;
145 entryFunction = (android_thread_func_t)&thread_data_t::trampoline;
146 userData = t;
147 }
148#endif
149
150 if (threadStackSize) {
151 pthread_attr_setstacksize(&attr, threadStackSize);
152 }
153
154 errno = 0;
155 pthread_t thread;
156 int result = pthread_create(&thread, &attr,
157 (android_pthread_entry)entryFunction, userData);
Le-Chun Wud8734d12011-07-14 14:27:18 -0700158 pthread_attr_destroy(&attr);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800159 if (result != 0) {
Steve Block1b781ab2012-01-06 19:20:56 +0000160 ALOGE("androidCreateRawThreadEtc failed (entry=%p, res=%d, errno=%d)\n"
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800161 "(android threadPriority=%d)",
162 entryFunction, result, errno, threadPriority);
163 return 0;
164 }
165
Glenn Kastena538e262011-06-02 08:59:28 -0700166 // Note that *threadID is directly available to the parent only, as it is
167 // assigned after the child starts. Use memory barrier / lock if the child
168 // or other threads also need access.
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800169 if (threadId != NULL) {
170 *threadId = (android_thread_id_t)thread; // XXX: this is not portable
171 }
172 return 1;
173}
174
Glenn Kastend731f072011-07-11 15:59:22 -0700175#ifdef HAVE_ANDROID_OS
176static pthread_t android_thread_id_t_to_pthread(android_thread_id_t thread)
177{
178 return (pthread_t) thread;
179}
180#endif
181
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800182android_thread_id_t androidGetThreadId()
183{
184 return (android_thread_id_t)pthread_self();
185}
186
187// ----------------------------------------------------------------------------
188#elif defined(HAVE_WIN32_THREADS)
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800189// ----------------------------------------------------------------------------
190
191/*
192 * Trampoline to make us __stdcall-compliant.
193 *
194 * We're expected to delete "vDetails" when we're done.
195 */
196struct threadDetails {
197 int (*func)(void*);
198 void* arg;
199};
200static __stdcall unsigned int threadIntermediary(void* vDetails)
201{
202 struct threadDetails* pDetails = (struct threadDetails*) vDetails;
203 int result;
204
205 result = (*(pDetails->func))(pDetails->arg);
206
207 delete pDetails;
208
Steve Block8b4cf772011-10-12 17:27:03 +0100209 ALOG(LOG_VERBOSE, "thread", "thread exiting\n");
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800210 return (unsigned int) result;
211}
212
213/*
214 * Create and run a new thread.
215 */
216static bool doCreateThread(android_thread_func_t fn, void* arg, android_thread_id_t *id)
217{
218 HANDLE hThread;
219 struct threadDetails* pDetails = new threadDetails; // must be on heap
220 unsigned int thrdaddr;
221
222 pDetails->func = fn;
223 pDetails->arg = arg;
224
225#if defined(HAVE__BEGINTHREADEX)
226 hThread = (HANDLE) _beginthreadex(NULL, 0, threadIntermediary, pDetails, 0,
227 &thrdaddr);
228 if (hThread == 0)
229#elif defined(HAVE_CREATETHREAD)
230 hThread = CreateThread(NULL, 0,
231 (LPTHREAD_START_ROUTINE) threadIntermediary,
232 (void*) pDetails, 0, (DWORD*) &thrdaddr);
233 if (hThread == NULL)
234#endif
235 {
Steve Block8b4cf772011-10-12 17:27:03 +0100236 ALOG(LOG_WARN, "thread", "WARNING: thread create failed\n");
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800237 return false;
238 }
239
240#if defined(HAVE_CREATETHREAD)
241 /* close the management handle */
242 CloseHandle(hThread);
243#endif
244
245 if (id != NULL) {
246 *id = (android_thread_id_t)thrdaddr;
247 }
248
249 return true;
250}
251
252int androidCreateRawThreadEtc(android_thread_func_t fn,
253 void *userData,
254 const char* threadName,
255 int32_t threadPriority,
256 size_t threadStackSize,
257 android_thread_id_t *threadId)
258{
259 return doCreateThread( fn, userData, threadId);
260}
261
262android_thread_id_t androidGetThreadId()
263{
264 return (android_thread_id_t)GetCurrentThreadId();
265}
266
267// ----------------------------------------------------------------------------
268#else
269#error "Threads not supported"
270#endif
271
272// ----------------------------------------------------------------------------
273
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800274int androidCreateThread(android_thread_func_t fn, void* arg)
275{
276 return createThreadEtc(fn, arg);
277}
278
279int androidCreateThreadGetID(android_thread_func_t fn, void *arg, android_thread_id_t *id)
280{
281 return createThreadEtc(fn, arg, "android:unnamed_thread",
282 PRIORITY_DEFAULT, 0, id);
283}
284
285static android_create_thread_fn gCreateThreadFn = androidCreateRawThreadEtc;
286
287int androidCreateThreadEtc(android_thread_func_t entryFunction,
288 void *userData,
289 const char* threadName,
290 int32_t threadPriority,
291 size_t threadStackSize,
292 android_thread_id_t *threadId)
293{
294 return gCreateThreadFn(entryFunction, userData, threadName,
295 threadPriority, threadStackSize, threadId);
296}
297
298void androidSetCreateThreadFunc(android_create_thread_fn func)
299{
300 gCreateThreadFn = func;
301}
302
Dianne Hackborn235af972009-12-07 17:59:37 -0800303pid_t androidGetTid()
304{
305#ifdef HAVE_GETTID
306 return gettid();
307#else
308 return getpid();
309#endif
310}
311
Jeff Brown27e6eaa2012-03-16 22:18:39 -0700312#ifdef HAVE_ANDROID_OS
Dianne Hackborn235af972009-12-07 17:59:37 -0800313int androidSetThreadPriority(pid_t tid, int pri)
314{
315 int rc = 0;
Dianne Hackbornaaa7ef82009-12-08 19:45:59 -0800316
317#if defined(HAVE_PTHREADS)
Dianne Hackborn235af972009-12-07 17:59:37 -0800318 int lasterr = 0;
319
Glenn Kastenfe34e452012-04-30 16:03:30 -0700320 if (pri >= ANDROID_PRIORITY_BACKGROUND) {
321 rc = set_sched_policy(tid, SP_BACKGROUND);
322 } else if (getpriority(PRIO_PROCESS, tid) >= ANDROID_PRIORITY_BACKGROUND) {
323 rc = set_sched_policy(tid, SP_FOREGROUND);
Dianne Hackborn235af972009-12-07 17:59:37 -0800324 }
325
326 if (rc) {
327 lasterr = errno;
328 }
329
330 if (setpriority(PRIO_PROCESS, tid, pri) < 0) {
331 rc = INVALID_OPERATION;
332 } else {
333 errno = lasterr;
334 }
Dianne Hackborn3432efa2009-12-08 16:38:01 -0800335#endif
Dianne Hackborn235af972009-12-07 17:59:37 -0800336
337 return rc;
338}
339
Andreas Huber8ddbed92011-09-15 12:21:40 -0700340int androidGetThreadPriority(pid_t tid) {
Andreas Huber7b4ce612011-09-16 11:47:13 -0700341#if defined(HAVE_PTHREADS)
Andreas Huber8ddbed92011-09-15 12:21:40 -0700342 return getpriority(PRIO_PROCESS, tid);
Andreas Huber7b4ce612011-09-16 11:47:13 -0700343#else
344 return ANDROID_PRIORITY_NORMAL;
345#endif
Andreas Huber8ddbed92011-09-15 12:21:40 -0700346}
347
Jeff Brown27e6eaa2012-03-16 22:18:39 -0700348#endif
Glenn Kasten6fbe0a82011-06-22 16:20:37 -0700349
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800350namespace android {
351
352/*
353 * ===========================================================================
354 * Mutex class
355 * ===========================================================================
356 */
357
Mathias Agopian15554362009-07-12 23:11:20 -0700358#if defined(HAVE_PTHREADS)
359// implemented as inlines in threads.h
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800360#elif defined(HAVE_WIN32_THREADS)
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800361
362Mutex::Mutex()
363{
364 HANDLE hMutex;
365
366 assert(sizeof(hMutex) == sizeof(mState));
367
368 hMutex = CreateMutex(NULL, FALSE, NULL);
369 mState = (void*) hMutex;
370}
371
372Mutex::Mutex(const char* name)
373{
374 // XXX: name not used for now
375 HANDLE hMutex;
376
David 'Digit' Turner9bafd122009-08-01 00:20:17 +0200377 assert(sizeof(hMutex) == sizeof(mState));
378
379 hMutex = CreateMutex(NULL, FALSE, NULL);
380 mState = (void*) hMutex;
381}
382
383Mutex::Mutex(int type, const char* name)
384{
385 // XXX: type and name not used for now
386 HANDLE hMutex;
387
388 assert(sizeof(hMutex) == sizeof(mState));
389
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800390 hMutex = CreateMutex(NULL, FALSE, NULL);
391 mState = (void*) hMutex;
392}
393
394Mutex::~Mutex()
395{
396 CloseHandle((HANDLE) mState);
397}
398
399status_t Mutex::lock()
400{
401 DWORD dwWaitResult;
402 dwWaitResult = WaitForSingleObject((HANDLE) mState, INFINITE);
403 return dwWaitResult != WAIT_OBJECT_0 ? -1 : NO_ERROR;
404}
405
406void Mutex::unlock()
407{
408 if (!ReleaseMutex((HANDLE) mState))
Steve Block8b4cf772011-10-12 17:27:03 +0100409 ALOG(LOG_WARN, "thread", "WARNING: bad result from unlocking mutex\n");
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800410}
411
412status_t Mutex::tryLock()
413{
414 DWORD dwWaitResult;
415
416 dwWaitResult = WaitForSingleObject((HANDLE) mState, 0);
417 if (dwWaitResult != WAIT_OBJECT_0 && dwWaitResult != WAIT_TIMEOUT)
Steve Block8b4cf772011-10-12 17:27:03 +0100418 ALOG(LOG_WARN, "thread", "WARNING: bad result from try-locking mutex\n");
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800419 return (dwWaitResult == WAIT_OBJECT_0) ? 0 : -1;
420}
421
422#else
423#error "Somebody forgot to implement threads for this platform."
424#endif
425
426
427/*
428 * ===========================================================================
429 * Condition class
430 * ===========================================================================
431 */
432
Mathias Agopian15554362009-07-12 23:11:20 -0700433#if defined(HAVE_PTHREADS)
434// implemented as inlines in threads.h
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800435#elif defined(HAVE_WIN32_THREADS)
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800436
437/*
438 * Windows doesn't have a condition variable solution. It's possible
439 * to create one, but it's easy to get it wrong. For a discussion, and
440 * the origin of this implementation, see:
441 *
442 * http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
443 *
444 * The implementation shown on the page does NOT follow POSIX semantics.
445 * As an optimization they require acquiring the external mutex before
446 * calling signal() and broadcast(), whereas POSIX only requires grabbing
447 * it before calling wait(). The implementation here has been un-optimized
448 * to have the correct behavior.
449 */
450typedef struct WinCondition {
451 // Number of waiting threads.
452 int waitersCount;
453
454 // Serialize access to waitersCount.
455 CRITICAL_SECTION waitersCountLock;
456
457 // Semaphore used to queue up threads waiting for the condition to
458 // become signaled.
459 HANDLE sema;
460
461 // An auto-reset event used by the broadcast/signal thread to wait
462 // for all the waiting thread(s) to wake up and be released from
463 // the semaphore.
464 HANDLE waitersDone;
465
466 // This mutex wouldn't be necessary if we required that the caller
467 // lock the external mutex before calling signal() and broadcast().
468 // I'm trying to mimic pthread semantics though.
469 HANDLE internalMutex;
470
471 // Keeps track of whether we were broadcasting or signaling. This
472 // allows us to optimize the code if we're just signaling.
473 bool wasBroadcast;
474
475 status_t wait(WinCondition* condState, HANDLE hMutex, nsecs_t* abstime)
476 {
477 // Increment the wait count, avoiding race conditions.
478 EnterCriticalSection(&condState->waitersCountLock);
479 condState->waitersCount++;
480 //printf("+++ wait: incr waitersCount to %d (tid=%ld)\n",
481 // condState->waitersCount, getThreadId());
482 LeaveCriticalSection(&condState->waitersCountLock);
483
484 DWORD timeout = INFINITE;
485 if (abstime) {
486 nsecs_t reltime = *abstime - systemTime();
487 if (reltime < 0)
488 reltime = 0;
489 timeout = reltime/1000000;
490 }
491
492 // Atomically release the external mutex and wait on the semaphore.
493 DWORD res =
494 SignalObjectAndWait(hMutex, condState->sema, timeout, FALSE);
495
496 //printf("+++ wait: awake (tid=%ld)\n", getThreadId());
497
498 // Reacquire lock to avoid race conditions.
499 EnterCriticalSection(&condState->waitersCountLock);
500
501 // No longer waiting.
502 condState->waitersCount--;
503
504 // Check to see if we're the last waiter after a broadcast.
505 bool lastWaiter = (condState->wasBroadcast && condState->waitersCount == 0);
506
507 //printf("+++ wait: lastWaiter=%d (wasBc=%d wc=%d)\n",
508 // lastWaiter, condState->wasBroadcast, condState->waitersCount);
509
510 LeaveCriticalSection(&condState->waitersCountLock);
511
512 // If we're the last waiter thread during this particular broadcast
513 // then signal broadcast() that we're all awake. It'll drop the
514 // internal mutex.
515 if (lastWaiter) {
516 // Atomically signal the "waitersDone" event and wait until we
517 // can acquire the internal mutex. We want to do this in one step
518 // because it ensures that everybody is in the mutex FIFO before
519 // any thread has a chance to run. Without it, another thread
520 // could wake up, do work, and hop back in ahead of us.
521 SignalObjectAndWait(condState->waitersDone, condState->internalMutex,
522 INFINITE, FALSE);
523 } else {
524 // Grab the internal mutex.
525 WaitForSingleObject(condState->internalMutex, INFINITE);
526 }
527
528 // Release the internal and grab the external.
529 ReleaseMutex(condState->internalMutex);
530 WaitForSingleObject(hMutex, INFINITE);
531
532 return res == WAIT_OBJECT_0 ? NO_ERROR : -1;
533 }
534} WinCondition;
535
536/*
537 * Constructor. Set up the WinCondition stuff.
538 */
539Condition::Condition()
540{
541 WinCondition* condState = new WinCondition;
542
543 condState->waitersCount = 0;
544 condState->wasBroadcast = false;
545 // semaphore: no security, initial value of 0
546 condState->sema = CreateSemaphore(NULL, 0, 0x7fffffff, NULL);
547 InitializeCriticalSection(&condState->waitersCountLock);
548 // auto-reset event, not signaled initially
549 condState->waitersDone = CreateEvent(NULL, FALSE, FALSE, NULL);
550 // used so we don't have to lock external mutex on signal/broadcast
551 condState->internalMutex = CreateMutex(NULL, FALSE, NULL);
552
553 mState = condState;
554}
555
556/*
557 * Destructor. Free Windows resources as well as our allocated storage.
558 */
559Condition::~Condition()
560{
561 WinCondition* condState = (WinCondition*) mState;
562 if (condState != NULL) {
563 CloseHandle(condState->sema);
564 CloseHandle(condState->waitersDone);
565 delete condState;
566 }
567}
568
569
570status_t Condition::wait(Mutex& mutex)
571{
572 WinCondition* condState = (WinCondition*) mState;
573 HANDLE hMutex = (HANDLE) mutex.mState;
574
575 return ((WinCondition*)mState)->wait(condState, hMutex, NULL);
576}
577
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800578status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime)
579{
David 'Digit' Turner9bafd122009-08-01 00:20:17 +0200580 WinCondition* condState = (WinCondition*) mState;
581 HANDLE hMutex = (HANDLE) mutex.mState;
582 nsecs_t absTime = systemTime()+reltime;
583
584 return ((WinCondition*)mState)->wait(condState, hMutex, &absTime);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800585}
586
587/*
588 * Signal the condition variable, allowing one thread to continue.
589 */
590void Condition::signal()
591{
592 WinCondition* condState = (WinCondition*) mState;
593
594 // Lock the internal mutex. This ensures that we don't clash with
595 // broadcast().
596 WaitForSingleObject(condState->internalMutex, INFINITE);
597
598 EnterCriticalSection(&condState->waitersCountLock);
599 bool haveWaiters = (condState->waitersCount > 0);
600 LeaveCriticalSection(&condState->waitersCountLock);
601
602 // If no waiters, then this is a no-op. Otherwise, knock the semaphore
603 // down a notch.
604 if (haveWaiters)
605 ReleaseSemaphore(condState->sema, 1, 0);
606
607 // Release internal mutex.
608 ReleaseMutex(condState->internalMutex);
609}
610
611/*
612 * Signal the condition variable, allowing all threads to continue.
613 *
614 * First we have to wake up all threads waiting on the semaphore, then
615 * we wait until all of the threads have actually been woken before
616 * releasing the internal mutex. This ensures that all threads are woken.
617 */
618void Condition::broadcast()
619{
620 WinCondition* condState = (WinCondition*) mState;
621
622 // Lock the internal mutex. This keeps the guys we're waking up
623 // from getting too far.
624 WaitForSingleObject(condState->internalMutex, INFINITE);
625
626 EnterCriticalSection(&condState->waitersCountLock);
627 bool haveWaiters = false;
628
629 if (condState->waitersCount > 0) {
630 haveWaiters = true;
631 condState->wasBroadcast = true;
632 }
633
634 if (haveWaiters) {
635 // Wake up all the waiters.
636 ReleaseSemaphore(condState->sema, condState->waitersCount, 0);
637
638 LeaveCriticalSection(&condState->waitersCountLock);
639
640 // Wait for all awakened threads to acquire the counting semaphore.
641 // The last guy who was waiting sets this.
642 WaitForSingleObject(condState->waitersDone, INFINITE);
643
644 // Reset wasBroadcast. (No crit section needed because nobody
645 // else can wake up to poke at it.)
646 condState->wasBroadcast = 0;
647 } else {
648 // nothing to do
649 LeaveCriticalSection(&condState->waitersCountLock);
650 }
651
652 // Release internal mutex.
653 ReleaseMutex(condState->internalMutex);
654}
655
656#else
657#error "condition variables not supported on this platform"
658#endif
659
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800660// ----------------------------------------------------------------------------
661
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800662/*
663 * This is our thread object!
664 */
665
666Thread::Thread(bool canCallJava)
667 : mCanCallJava(canCallJava),
668 mThread(thread_id_t(-1)),
669 mLock("Thread::mLock"),
670 mStatus(NO_ERROR),
671 mExitPending(false), mRunning(false)
Glenn Kasten966a48f2011-02-01 11:32:29 -0800672#ifdef HAVE_ANDROID_OS
673 , mTid(-1)
674#endif
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800675{
676}
677
678Thread::~Thread()
679{
680}
681
682status_t Thread::readyToRun()
683{
684 return NO_ERROR;
685}
686
687status_t Thread::run(const char* name, int32_t priority, size_t stack)
688{
689 Mutex::Autolock _l(mLock);
690
691 if (mRunning) {
692 // thread already started
693 return INVALID_OPERATION;
694 }
695
696 // reset status and exitPending to their default value, so we can
697 // try again after an error happened (either below, or in readyToRun())
698 mStatus = NO_ERROR;
699 mExitPending = false;
700 mThread = thread_id_t(-1);
701
702 // hold a strong reference on ourself
703 mHoldSelf = this;
704
The Android Open Source Project7a4c8392009-03-05 14:34:35 -0800705 mRunning = true;
706
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800707 bool res;
708 if (mCanCallJava) {
709 res = createThreadEtc(_threadLoop,
710 this, name, priority, stack, &mThread);
711 } else {
712 res = androidCreateRawThreadEtc(_threadLoop,
713 this, name, priority, stack, &mThread);
714 }
715
716 if (res == false) {
717 mStatus = UNKNOWN_ERROR; // something happened!
718 mRunning = false;
719 mThread = thread_id_t(-1);
The Android Open Source Project7a4c8392009-03-05 14:34:35 -0800720 mHoldSelf.clear(); // "this" may have gone away after this.
721
722 return UNKNOWN_ERROR;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800723 }
724
The Android Open Source Project7a4c8392009-03-05 14:34:35 -0800725 // Do not refer to mStatus here: The thread is already running (may, in fact
726 // already have exited with a valid mStatus result). The NO_ERROR indication
727 // here merely indicates successfully starting the thread and does not
728 // imply successful termination/execution.
729 return NO_ERROR;
Glenn Kasten966a48f2011-02-01 11:32:29 -0800730
731 // Exiting scope of mLock is a memory barrier and allows new thread to run
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800732}
733
734int Thread::_threadLoop(void* user)
735{
736 Thread* const self = static_cast<Thread*>(user);
Glenn Kasten966a48f2011-02-01 11:32:29 -0800737
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800738 sp<Thread> strong(self->mHoldSelf);
739 wp<Thread> weak(strong);
740 self->mHoldSelf.clear();
741
Kenny Rootdafff0b2011-02-16 10:13:53 -0800742#ifdef HAVE_ANDROID_OS
Mathias Agopian51ce3ad2009-09-09 02:38:13 -0700743 // this is very useful for debugging with gdb
744 self->mTid = gettid();
745#endif
746
The Android Open Source Project7a4c8392009-03-05 14:34:35 -0800747 bool first = true;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800748
749 do {
The Android Open Source Project7a4c8392009-03-05 14:34:35 -0800750 bool result;
751 if (first) {
752 first = false;
753 self->mStatus = self->readyToRun();
754 result = (self->mStatus == NO_ERROR);
755
Glenn Kasten966a48f2011-02-01 11:32:29 -0800756 if (result && !self->exitPending()) {
The Android Open Source Project7a4c8392009-03-05 14:34:35 -0800757 // Binder threads (and maybe others) rely on threadLoop
758 // running at least once after a successful ::readyToRun()
759 // (unless, of course, the thread has already been asked to exit
760 // at that point).
761 // This is because threads are essentially used like this:
762 // (new ThreadSubclass())->run();
763 // The caller therefore does not retain a strong reference to
764 // the thread and the thread would simply disappear after the
765 // successful ::readyToRun() call instead of entering the
766 // threadLoop at least once.
767 result = self->threadLoop();
768 }
769 } else {
770 result = self->threadLoop();
771 }
772
Glenn Kasten966a48f2011-02-01 11:32:29 -0800773 // establish a scope for mLock
774 {
775 Mutex::Autolock _l(self->mLock);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800776 if (result == false || self->mExitPending) {
777 self->mExitPending = true;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800778 self->mRunning = false;
Eric Laurentfe2c4632011-01-04 11:58:04 -0800779 // clear thread ID so that requestExitAndWait() does not exit if
780 // called by a new thread using the same thread ID as this one.
781 self->mThread = thread_id_t(-1);
Glenn Kasten966a48f2011-02-01 11:32:29 -0800782 // note that interested observers blocked in requestExitAndWait are
783 // awoken by broadcast, but blocked on mLock until break exits scope
Mathias Agopian51ce3ad2009-09-09 02:38:13 -0700784 self->mThreadExitedCondition.broadcast();
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800785 break;
786 }
Glenn Kasten966a48f2011-02-01 11:32:29 -0800787 }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800788
789 // Release our strong reference, to let a chance to the thread
790 // to die a peaceful death.
791 strong.clear();
Mathias Agopian51ce3ad2009-09-09 02:38:13 -0700792 // And immediately, re-acquire a strong reference for the next loop
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800793 strong = weak.promote();
794 } while(strong != 0);
795
796 return 0;
797}
798
799void Thread::requestExit()
800{
Glenn Kasten966a48f2011-02-01 11:32:29 -0800801 Mutex::Autolock _l(mLock);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800802 mExitPending = true;
803}
804
805status_t Thread::requestExitAndWait()
806{
Glenn Kastena538e262011-06-02 08:59:28 -0700807 Mutex::Autolock _l(mLock);
The Android Open Source Project7a4c8392009-03-05 14:34:35 -0800808 if (mThread == getThreadId()) {
Steve Block61d341b2012-01-05 23:22:43 +0000809 ALOGW(
The Android Open Source Project7a4c8392009-03-05 14:34:35 -0800810 "Thread (this=%p): don't call waitForExit() from this "
811 "Thread object's thread. It's a guaranteed deadlock!",
812 this);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800813
The Android Open Source Project7a4c8392009-03-05 14:34:35 -0800814 return WOULD_BLOCK;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800815 }
The Android Open Source Project7a4c8392009-03-05 14:34:35 -0800816
Glenn Kastena538e262011-06-02 08:59:28 -0700817 mExitPending = true;
The Android Open Source Project7a4c8392009-03-05 14:34:35 -0800818
The Android Open Source Project7a4c8392009-03-05 14:34:35 -0800819 while (mRunning == true) {
820 mThreadExitedCondition.wait(mLock);
821 }
Glenn Kasten966a48f2011-02-01 11:32:29 -0800822 // This next line is probably not needed any more, but is being left for
823 // historical reference. Note that each interested party will clear flag.
The Android Open Source Project7a4c8392009-03-05 14:34:35 -0800824 mExitPending = false;
825
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800826 return mStatus;
827}
828
Glenn Kasten6839e8e2011-06-23 12:55:29 -0700829status_t Thread::join()
830{
831 Mutex::Autolock _l(mLock);
832 if (mThread == getThreadId()) {
Steve Block61d341b2012-01-05 23:22:43 +0000833 ALOGW(
Glenn Kasten6839e8e2011-06-23 12:55:29 -0700834 "Thread (this=%p): don't call join() from this "
835 "Thread object's thread. It's a guaranteed deadlock!",
836 this);
837
838 return WOULD_BLOCK;
839 }
840
841 while (mRunning == true) {
842 mThreadExitedCondition.wait(mLock);
843 }
844
845 return mStatus;
846}
847
Romain Guy31ba37f2013-03-11 14:34:56 -0700848bool Thread::isRunning() const {
849 Mutex::Autolock _l(mLock);
850 return mRunning;
851}
852
Glenn Kastend731f072011-07-11 15:59:22 -0700853#ifdef HAVE_ANDROID_OS
854pid_t Thread::getTid() const
855{
856 // mTid is not defined until the child initializes it, and the caller may need it earlier
857 Mutex::Autolock _l(mLock);
858 pid_t tid;
859 if (mRunning) {
860 pthread_t pthread = android_thread_id_t_to_pthread(mThread);
861 tid = __pthread_gettid(pthread);
862 } else {
863 ALOGW("Thread (this=%p): getTid() is undefined before run()", this);
864 tid = -1;
865 }
866 return tid;
867}
868#endif
869
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800870bool Thread::exitPending() const
871{
Glenn Kasten966a48f2011-02-01 11:32:29 -0800872 Mutex::Autolock _l(mLock);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800873 return mExitPending;
874}
875
876
877
878}; // namespace android