blob: 5f407a99067cdc62f296d081b7e0d5f6d46dd361 [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#define LOG_TAG "libutils.threads"
18
19#include <utils/threads.h>
20#include <utils/Log.h>
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <memory.h>
25#include <errno.h>
26#include <assert.h>
27#include <unistd.h>
28
29#if defined(HAVE_PTHREADS)
30# include <pthread.h>
31# include <sched.h>
32# include <sys/resource.h>
33#elif defined(HAVE_WIN32_THREADS)
34# include <windows.h>
35# include <stdint.h>
36# include <process.h>
37# define HAVE_CREATETHREAD // Cygwin, vs. HAVE__BEGINTHREADEX for MinGW
38#endif
39
40#if defined(HAVE_FUTEX)
41#include <private/utils/futex_synchro.h>
42#endif
43
44#if defined(HAVE_PRCTL)
45#include <sys/prctl.h>
46#endif
47
48/*
49 * ===========================================================================
50 * Thread wrappers
51 * ===========================================================================
52 */
53
54using namespace android;
55
56// ----------------------------------------------------------------------------
57#if defined(HAVE_PTHREADS)
58#if 0
59#pragma mark -
60#pragma mark PTHREAD
61#endif
62// ----------------------------------------------------------------------------
63
64/*
65 * Create and run a new thead.
66 *
67 * We create it "detached", so it cleans up after itself.
68 */
69
70typedef void* (*android_pthread_entry)(void*);
71
72struct thread_data_t {
73 thread_func_t entryFunction;
74 void* userData;
75 int priority;
76 char * threadName;
77
78 // we use this trampoline when we need to set the priority with
79 // nice/setpriority.
80 static int trampoline(const thread_data_t* t) {
81 thread_func_t f = t->entryFunction;
82 void* u = t->userData;
83 int prio = t->priority;
84 char * name = t->threadName;
85 delete t;
86 setpriority(PRIO_PROCESS, 0, prio);
87 if (name) {
88#if defined(HAVE_PRCTL)
89 // Mac OS doesn't have this, and we build libutil for the host too
90 int hasAt = 0;
91 int hasDot = 0;
92 char *s = name;
93 while (*s) {
94 if (*s == '.') hasDot = 1;
95 else if (*s == '@') hasAt = 1;
96 s++;
97 }
98 int len = s - name;
99 if (len < 15 || hasAt || !hasDot) {
100 s = name;
101 } else {
102 s = name + len - 15;
103 }
104 prctl(PR_SET_NAME, (unsigned long) s, 0, 0, 0);
105#endif
106 free(name);
107 }
108 return f(u);
109 }
110};
111
112int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
113 void *userData,
114 const char* threadName,
115 int32_t threadPriority,
116 size_t threadStackSize,
117 android_thread_id_t *threadId)
118{
119 pthread_attr_t attr;
120 pthread_attr_init(&attr);
121 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
122
123#ifdef HAVE_ANDROID_OS /* valgrind is rejecting RT-priority create reqs */
124 if (threadPriority != PRIORITY_DEFAULT || threadName != NULL) {
125 // We could avoid the trampoline if there was a way to get to the
126 // android_thread_id_t (pid) from pthread_t
127 thread_data_t* t = new thread_data_t;
128 t->priority = threadPriority;
129 t->threadName = threadName ? strdup(threadName) : NULL;
130 t->entryFunction = entryFunction;
131 t->userData = userData;
132 entryFunction = (android_thread_func_t)&thread_data_t::trampoline;
133 userData = t;
134 }
135#endif
136
137 if (threadStackSize) {
138 pthread_attr_setstacksize(&attr, threadStackSize);
139 }
140
141 errno = 0;
142 pthread_t thread;
143 int result = pthread_create(&thread, &attr,
144 (android_pthread_entry)entryFunction, userData);
145 if (result != 0) {
146 LOGE("androidCreateRawThreadEtc failed (entry=%p, res=%d, errno=%d)\n"
147 "(android threadPriority=%d)",
148 entryFunction, result, errno, threadPriority);
149 return 0;
150 }
151
152 if (threadId != NULL) {
153 *threadId = (android_thread_id_t)thread; // XXX: this is not portable
154 }
155 return 1;
156}
157
158android_thread_id_t androidGetThreadId()
159{
160 return (android_thread_id_t)pthread_self();
161}
162
163// ----------------------------------------------------------------------------
164#elif defined(HAVE_WIN32_THREADS)
165#if 0
166#pragma mark -
167#pragma mark WIN32_THREADS
168#endif
169// ----------------------------------------------------------------------------
170
171/*
172 * Trampoline to make us __stdcall-compliant.
173 *
174 * We're expected to delete "vDetails" when we're done.
175 */
176struct threadDetails {
177 int (*func)(void*);
178 void* arg;
179};
180static __stdcall unsigned int threadIntermediary(void* vDetails)
181{
182 struct threadDetails* pDetails = (struct threadDetails*) vDetails;
183 int result;
184
185 result = (*(pDetails->func))(pDetails->arg);
186
187 delete pDetails;
188
189 LOG(LOG_VERBOSE, "thread", "thread exiting\n");
190 return (unsigned int) result;
191}
192
193/*
194 * Create and run a new thread.
195 */
196static bool doCreateThread(android_thread_func_t fn, void* arg, android_thread_id_t *id)
197{
198 HANDLE hThread;
199 struct threadDetails* pDetails = new threadDetails; // must be on heap
200 unsigned int thrdaddr;
201
202 pDetails->func = fn;
203 pDetails->arg = arg;
204
205#if defined(HAVE__BEGINTHREADEX)
206 hThread = (HANDLE) _beginthreadex(NULL, 0, threadIntermediary, pDetails, 0,
207 &thrdaddr);
208 if (hThread == 0)
209#elif defined(HAVE_CREATETHREAD)
210 hThread = CreateThread(NULL, 0,
211 (LPTHREAD_START_ROUTINE) threadIntermediary,
212 (void*) pDetails, 0, (DWORD*) &thrdaddr);
213 if (hThread == NULL)
214#endif
215 {
216 LOG(LOG_WARN, "thread", "WARNING: thread create failed\n");
217 return false;
218 }
219
220#if defined(HAVE_CREATETHREAD)
221 /* close the management handle */
222 CloseHandle(hThread);
223#endif
224
225 if (id != NULL) {
226 *id = (android_thread_id_t)thrdaddr;
227 }
228
229 return true;
230}
231
232int androidCreateRawThreadEtc(android_thread_func_t fn,
233 void *userData,
234 const char* threadName,
235 int32_t threadPriority,
236 size_t threadStackSize,
237 android_thread_id_t *threadId)
238{
239 return doCreateThread( fn, userData, threadId);
240}
241
242android_thread_id_t androidGetThreadId()
243{
244 return (android_thread_id_t)GetCurrentThreadId();
245}
246
247// ----------------------------------------------------------------------------
248#else
249#error "Threads not supported"
250#endif
251
252// ----------------------------------------------------------------------------
253
254#if 0
255#pragma mark -
256#pragma mark Common Thread functions
257#endif
258
259int androidCreateThread(android_thread_func_t fn, void* arg)
260{
261 return createThreadEtc(fn, arg);
262}
263
264int androidCreateThreadGetID(android_thread_func_t fn, void *arg, android_thread_id_t *id)
265{
266 return createThreadEtc(fn, arg, "android:unnamed_thread",
267 PRIORITY_DEFAULT, 0, id);
268}
269
270static android_create_thread_fn gCreateThreadFn = androidCreateRawThreadEtc;
271
272int androidCreateThreadEtc(android_thread_func_t entryFunction,
273 void *userData,
274 const char* threadName,
275 int32_t threadPriority,
276 size_t threadStackSize,
277 android_thread_id_t *threadId)
278{
279 return gCreateThreadFn(entryFunction, userData, threadName,
280 threadPriority, threadStackSize, threadId);
281}
282
283void androidSetCreateThreadFunc(android_create_thread_fn func)
284{
285 gCreateThreadFn = func;
286}
287
288namespace android {
289
290/*
291 * ===========================================================================
292 * Mutex class
293 * ===========================================================================
294 */
295
296#if 0
297#pragma mark -
298#pragma mark Mutex
299#endif
300
301#if defined(HAVE_PTHREADS) && !defined(HAVE_FUTEX)
302/*
303 * Simple pthread wrapper.
304 */
305
306Mutex::Mutex()
307{
308 _init();
309}
310
311Mutex::Mutex(const char* name)
312{
313 // XXX: name not used for now
314 _init();
315}
316
317void Mutex::_init()
318{
319 pthread_mutex_t* pMutex = new pthread_mutex_t;
320 pthread_mutex_init(pMutex, NULL);
321 mState = pMutex;
322}
323
324Mutex::~Mutex()
325{
326 delete (pthread_mutex_t*) mState;
327}
328
329status_t Mutex::lock()
330{
331 int res;
332 while ((res=pthread_mutex_lock((pthread_mutex_t*) mState)) == EINTR) ;
333 return -res;
334}
335
336void Mutex::unlock()
337{
338 pthread_mutex_unlock((pthread_mutex_t*) mState);
339}
340
341status_t Mutex::tryLock()
342{
343 int res;
344 while ((res=pthread_mutex_trylock((pthread_mutex_t*) mState)) == EINTR) ;
345 return -res;
346}
347
348#elif defined(HAVE_FUTEX)
349#if 0
350#pragma mark -
351#endif
352
353#define STATE ((futex_mutex_t*) (&mState))
354
355Mutex::Mutex()
356{
357 _init();
358}
359
360Mutex::Mutex(const char* name)
361{
362 _init();
363}
364
365void
366Mutex::_init()
367{
368 futex_mutex_init(STATE);
369}
370
371Mutex::~Mutex()
372{
373}
374
375status_t Mutex::lock()
376{
377 int res;
378 while ((res=futex_mutex_lock(STATE, FUTEX_WAIT_INFINITE)) == EINTR) ;
379 return -res;
380}
381
382void Mutex::unlock()
383{
384 futex_mutex_unlock(STATE);
385}
386
387status_t Mutex::tryLock()
388{
389 int res;
390 while ((res=futex_mutex_trylock(STATE)) == EINTR) ;
391 return -res;
392}
393#undef STATE
394
395#elif defined(HAVE_WIN32_THREADS)
396#if 0
397#pragma mark -
398#endif
399
400Mutex::Mutex()
401{
402 HANDLE hMutex;
403
404 assert(sizeof(hMutex) == sizeof(mState));
405
406 hMutex = CreateMutex(NULL, FALSE, NULL);
407 mState = (void*) hMutex;
408}
409
410Mutex::Mutex(const char* name)
411{
412 // XXX: name not used for now
413 HANDLE hMutex;
414
415 hMutex = CreateMutex(NULL, FALSE, NULL);
416 mState = (void*) hMutex;
417}
418
419Mutex::~Mutex()
420{
421 CloseHandle((HANDLE) mState);
422}
423
424status_t Mutex::lock()
425{
426 DWORD dwWaitResult;
427 dwWaitResult = WaitForSingleObject((HANDLE) mState, INFINITE);
428 return dwWaitResult != WAIT_OBJECT_0 ? -1 : NO_ERROR;
429}
430
431void Mutex::unlock()
432{
433 if (!ReleaseMutex((HANDLE) mState))
434 LOG(LOG_WARN, "thread", "WARNING: bad result from unlocking mutex\n");
435}
436
437status_t Mutex::tryLock()
438{
439 DWORD dwWaitResult;
440
441 dwWaitResult = WaitForSingleObject((HANDLE) mState, 0);
442 if (dwWaitResult != WAIT_OBJECT_0 && dwWaitResult != WAIT_TIMEOUT)
443 LOG(LOG_WARN, "thread", "WARNING: bad result from try-locking mutex\n");
444 return (dwWaitResult == WAIT_OBJECT_0) ? 0 : -1;
445}
446
447#else
448#error "Somebody forgot to implement threads for this platform."
449#endif
450
451
452/*
453 * ===========================================================================
454 * Condition class
455 * ===========================================================================
456 */
457
458#if 0
459#pragma mark -
460#pragma mark Condition
461#endif
462
463#if defined(HAVE_PTHREADS) && !defined(HAVE_FUTEX)
464
465/*
466 * Constructor. This is a simple pthread wrapper.
467 */
468Condition::Condition()
469{
470 pthread_cond_t* pCond = new pthread_cond_t;
471
472 pthread_cond_init(pCond, NULL);
473 mState = pCond;
474}
475
476/*
477 * Destructor.
478 */
479Condition::~Condition()
480{
481 pthread_cond_destroy((pthread_cond_t*) mState);
482 delete (pthread_cond_t*) mState;
483}
484
485/*
486 * Wait on a condition variable. Lock the mutex before calling.
487 */
488
489status_t Condition::wait(Mutex& mutex)
490{
491 assert(mutex.mState != NULL);
492
493 int cc;
494 while ((cc = pthread_cond_wait((pthread_cond_t*)mState,
495 (pthread_mutex_t*) mutex.mState)) == EINTR) ;
496 return -cc;
497}
498
499status_t Condition::wait(Mutex& mutex, nsecs_t abstime)
500{
501 assert(mutex.mState != NULL);
502
503 struct timespec ts;
504 ts.tv_sec = abstime/1000000000;
505 ts.tv_nsec = abstime-(ts.tv_sec*1000000000);
506
507 int cc;
508 while ((cc = pthread_cond_timedwait((pthread_cond_t*)mState,
509 (pthread_mutex_t*) mutex.mState, &ts)) == EINTR) ;
510 return -cc;
511}
512
513status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime)
514{
515 return wait(mutex, systemTime()+reltime);
516}
517
518/*
519 * Signal the condition variable, allowing one thread to continue.
520 */
521void Condition::signal()
522{
523 pthread_cond_signal((pthread_cond_t*) mState);
524}
525
526/*
527 * Signal the condition variable, allowing all threads to continue.
528 */
529void Condition::broadcast()
530{
531 pthread_cond_broadcast((pthread_cond_t*) mState);
532}
533
534#elif defined(HAVE_FUTEX)
535#if 0
536#pragma mark -
537#endif
538
539#define STATE ((futex_cond_t*) (&mState))
540
541/*
542 * Constructor. This is a simple pthread wrapper.
543 */
544Condition::Condition()
545{
546 futex_cond_init(STATE);
547}
548
549/*
550 * Destructor.
551 */
552Condition::~Condition()
553{
554}
555
556/*
557 * Wait on a condition variable. Lock the mutex before calling.
558 */
559
560status_t Condition::wait(Mutex& mutex)
561{
562 assert(mutex.mState != NULL);
563
564 int res;
565 while ((res = futex_cond_wait(STATE,
566 (futex_mutex_t*)(&mutex.mState), FUTEX_WAIT_INFINITE)) == -EINTR) ;
567
568 return -res;
569}
570
571status_t Condition::wait(Mutex& mutex, nsecs_t abstime)
572{
573 nsecs_t reltime = abstime - systemTime();
574 if (reltime <= 0) return true;
575 return waitRelative(mutex, reltime);
576}
577
578status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime)
579{
580 assert(mutex.mState != NULL);
581 int res;
582 unsigned msec = ns2ms(reltime);
583 if(msec == 0)
584 return true;
585 // This code will not time out at the correct time if interrupted by signals
586 while ((res = futex_cond_wait(STATE,
587 (futex_mutex_t*)(&mutex.mState), msec)) == -EINTR) ;
588 return res;
589}
590
591/*
592 * Signal the condition variable, allowing one thread to continue.
593 */
594void Condition::signal()
595{
596 futex_cond_signal(STATE);
597}
598
599/*
600 * Signal the condition variable, allowing all threads to continue.
601 */
602void Condition::broadcast()
603{
604 futex_cond_broadcast(STATE);
605}
606
607#undef STATE
608
609#elif defined(HAVE_WIN32_THREADS)
610#if 0
611#pragma mark -
612#endif
613
614/*
615 * Windows doesn't have a condition variable solution. It's possible
616 * to create one, but it's easy to get it wrong. For a discussion, and
617 * the origin of this implementation, see:
618 *
619 * http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
620 *
621 * The implementation shown on the page does NOT follow POSIX semantics.
622 * As an optimization they require acquiring the external mutex before
623 * calling signal() and broadcast(), whereas POSIX only requires grabbing
624 * it before calling wait(). The implementation here has been un-optimized
625 * to have the correct behavior.
626 */
627typedef struct WinCondition {
628 // Number of waiting threads.
629 int waitersCount;
630
631 // Serialize access to waitersCount.
632 CRITICAL_SECTION waitersCountLock;
633
634 // Semaphore used to queue up threads waiting for the condition to
635 // become signaled.
636 HANDLE sema;
637
638 // An auto-reset event used by the broadcast/signal thread to wait
639 // for all the waiting thread(s) to wake up and be released from
640 // the semaphore.
641 HANDLE waitersDone;
642
643 // This mutex wouldn't be necessary if we required that the caller
644 // lock the external mutex before calling signal() and broadcast().
645 // I'm trying to mimic pthread semantics though.
646 HANDLE internalMutex;
647
648 // Keeps track of whether we were broadcasting or signaling. This
649 // allows us to optimize the code if we're just signaling.
650 bool wasBroadcast;
651
652 status_t wait(WinCondition* condState, HANDLE hMutex, nsecs_t* abstime)
653 {
654 // Increment the wait count, avoiding race conditions.
655 EnterCriticalSection(&condState->waitersCountLock);
656 condState->waitersCount++;
657 //printf("+++ wait: incr waitersCount to %d (tid=%ld)\n",
658 // condState->waitersCount, getThreadId());
659 LeaveCriticalSection(&condState->waitersCountLock);
660
661 DWORD timeout = INFINITE;
662 if (abstime) {
663 nsecs_t reltime = *abstime - systemTime();
664 if (reltime < 0)
665 reltime = 0;
666 timeout = reltime/1000000;
667 }
668
669 // Atomically release the external mutex and wait on the semaphore.
670 DWORD res =
671 SignalObjectAndWait(hMutex, condState->sema, timeout, FALSE);
672
673 //printf("+++ wait: awake (tid=%ld)\n", getThreadId());
674
675 // Reacquire lock to avoid race conditions.
676 EnterCriticalSection(&condState->waitersCountLock);
677
678 // No longer waiting.
679 condState->waitersCount--;
680
681 // Check to see if we're the last waiter after a broadcast.
682 bool lastWaiter = (condState->wasBroadcast && condState->waitersCount == 0);
683
684 //printf("+++ wait: lastWaiter=%d (wasBc=%d wc=%d)\n",
685 // lastWaiter, condState->wasBroadcast, condState->waitersCount);
686
687 LeaveCriticalSection(&condState->waitersCountLock);
688
689 // If we're the last waiter thread during this particular broadcast
690 // then signal broadcast() that we're all awake. It'll drop the
691 // internal mutex.
692 if (lastWaiter) {
693 // Atomically signal the "waitersDone" event and wait until we
694 // can acquire the internal mutex. We want to do this in one step
695 // because it ensures that everybody is in the mutex FIFO before
696 // any thread has a chance to run. Without it, another thread
697 // could wake up, do work, and hop back in ahead of us.
698 SignalObjectAndWait(condState->waitersDone, condState->internalMutex,
699 INFINITE, FALSE);
700 } else {
701 // Grab the internal mutex.
702 WaitForSingleObject(condState->internalMutex, INFINITE);
703 }
704
705 // Release the internal and grab the external.
706 ReleaseMutex(condState->internalMutex);
707 WaitForSingleObject(hMutex, INFINITE);
708
709 return res == WAIT_OBJECT_0 ? NO_ERROR : -1;
710 }
711} WinCondition;
712
713/*
714 * Constructor. Set up the WinCondition stuff.
715 */
716Condition::Condition()
717{
718 WinCondition* condState = new WinCondition;
719
720 condState->waitersCount = 0;
721 condState->wasBroadcast = false;
722 // semaphore: no security, initial value of 0
723 condState->sema = CreateSemaphore(NULL, 0, 0x7fffffff, NULL);
724 InitializeCriticalSection(&condState->waitersCountLock);
725 // auto-reset event, not signaled initially
726 condState->waitersDone = CreateEvent(NULL, FALSE, FALSE, NULL);
727 // used so we don't have to lock external mutex on signal/broadcast
728 condState->internalMutex = CreateMutex(NULL, FALSE, NULL);
729
730 mState = condState;
731}
732
733/*
734 * Destructor. Free Windows resources as well as our allocated storage.
735 */
736Condition::~Condition()
737{
738 WinCondition* condState = (WinCondition*) mState;
739 if (condState != NULL) {
740 CloseHandle(condState->sema);
741 CloseHandle(condState->waitersDone);
742 delete condState;
743 }
744}
745
746
747status_t Condition::wait(Mutex& mutex)
748{
749 WinCondition* condState = (WinCondition*) mState;
750 HANDLE hMutex = (HANDLE) mutex.mState;
751
752 return ((WinCondition*)mState)->wait(condState, hMutex, NULL);
753}
754
755status_t Condition::wait(Mutex& mutex, nsecs_t abstime)
756{
757 WinCondition* condState = (WinCondition*) mState;
758 HANDLE hMutex = (HANDLE) mutex.mState;
759
760 return ((WinCondition*)mState)->wait(condState, hMutex, &abstime);
761}
762
763status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime)
764{
765 return wait(mutex, systemTime()+reltime);
766}
767
768/*
769 * Signal the condition variable, allowing one thread to continue.
770 */
771void Condition::signal()
772{
773 WinCondition* condState = (WinCondition*) mState;
774
775 // Lock the internal mutex. This ensures that we don't clash with
776 // broadcast().
777 WaitForSingleObject(condState->internalMutex, INFINITE);
778
779 EnterCriticalSection(&condState->waitersCountLock);
780 bool haveWaiters = (condState->waitersCount > 0);
781 LeaveCriticalSection(&condState->waitersCountLock);
782
783 // If no waiters, then this is a no-op. Otherwise, knock the semaphore
784 // down a notch.
785 if (haveWaiters)
786 ReleaseSemaphore(condState->sema, 1, 0);
787
788 // Release internal mutex.
789 ReleaseMutex(condState->internalMutex);
790}
791
792/*
793 * Signal the condition variable, allowing all threads to continue.
794 *
795 * First we have to wake up all threads waiting on the semaphore, then
796 * we wait until all of the threads have actually been woken before
797 * releasing the internal mutex. This ensures that all threads are woken.
798 */
799void Condition::broadcast()
800{
801 WinCondition* condState = (WinCondition*) mState;
802
803 // Lock the internal mutex. This keeps the guys we're waking up
804 // from getting too far.
805 WaitForSingleObject(condState->internalMutex, INFINITE);
806
807 EnterCriticalSection(&condState->waitersCountLock);
808 bool haveWaiters = false;
809
810 if (condState->waitersCount > 0) {
811 haveWaiters = true;
812 condState->wasBroadcast = true;
813 }
814
815 if (haveWaiters) {
816 // Wake up all the waiters.
817 ReleaseSemaphore(condState->sema, condState->waitersCount, 0);
818
819 LeaveCriticalSection(&condState->waitersCountLock);
820
821 // Wait for all awakened threads to acquire the counting semaphore.
822 // The last guy who was waiting sets this.
823 WaitForSingleObject(condState->waitersDone, INFINITE);
824
825 // Reset wasBroadcast. (No crit section needed because nobody
826 // else can wake up to poke at it.)
827 condState->wasBroadcast = 0;
828 } else {
829 // nothing to do
830 LeaveCriticalSection(&condState->waitersCountLock);
831 }
832
833 // Release internal mutex.
834 ReleaseMutex(condState->internalMutex);
835}
836
837#else
838#error "condition variables not supported on this platform"
839#endif
840
841
842/*
843 * ===========================================================================
844 * ReadWriteLock class
845 * ===========================================================================
846 */
847
848#if 0
849#pragma mark -
850#pragma mark ReadWriteLock
851#endif
852
853/*
854 * Add a reader. Readers are nice. They share.
855 */
856void ReadWriteLock::lockForRead()
857{
858 mLock.lock();
859 while (mNumWriters > 0) {
860 LOG(LOG_DEBUG, "thread", "+++ lockForRead: waiting\n");
861 mReadWaiter.wait(mLock);
862 }
863 assert(mNumWriters == 0);
864 mNumReaders++;
865#if defined(PRINT_RENDER_TIMES)
866 if (mNumReaders == 1)
867 mDebugTimer.start();
868#endif
869 mLock.unlock();
870}
871
872/*
873 * Try to add a reader. If it doesn't work right away, return "false".
874 */
875bool ReadWriteLock::tryLockForRead()
876{
877 mLock.lock();
878 if (mNumWriters > 0) {
879 mLock.unlock();
880 return false;
881 }
882 assert(mNumWriters == 0);
883 mNumReaders++;
884#if defined(PRINT_RENDER_TIMES)
885 if (mNumReaders == 1)
886 mDebugTimer.start();
887#endif
888 mLock.unlock();
889 return true;
890}
891
892/*
893 * Remove a reader.
894 */
895void ReadWriteLock::unlockForRead()
896{
897 mLock.lock();
898 if (mNumReaders == 0) {
899 mLock.unlock();
900 LOG(LOG_WARN, "thread",
901 "WARNING: unlockForRead requested, but not locked\n");
902 return;
903 }
904 assert(mNumReaders > 0);
905 assert(mNumWriters == 0);
906 mNumReaders--;
907 if (mNumReaders == 0) { // last reader?
908#if defined(PRINT_RENDER_TIMES)
909 mDebugTimer.stop();
910 printf(" rdlk held %.3f msec\n",
911 (double) mDebugTimer.durationUsecs() / 1000.0);
912#endif
913 //printf("+++ signaling writers (if any)\n");
914 mWriteWaiter.signal(); // wake one writer (if any)
915 }
916 mLock.unlock();
917}
918
919/*
920 * Add a writer. This requires exclusive access to the object.
921 */
922void ReadWriteLock::lockForWrite()
923{
924 mLock.lock();
925 while (mNumReaders > 0 || mNumWriters > 0) {
926 LOG(LOG_DEBUG, "thread", "+++ lockForWrite: waiting\n");
927 mWriteWaiter.wait(mLock);
928 }
929 assert(mNumReaders == 0);
930 assert(mNumWriters == 0);
931 mNumWriters++;
932#if defined(PRINT_RENDER_TIMES)
933 mDebugTimer.start();
934#endif
935 mLock.unlock();
936}
937
938/*
939 * Try to add a writer. If it doesn't work right away, return "false".
940 */
941bool ReadWriteLock::tryLockForWrite()
942{
943 mLock.lock();
944 if (mNumReaders > 0 || mNumWriters > 0) {
945 mLock.unlock();
946 return false;
947 }
948 assert(mNumReaders == 0);
949 assert(mNumWriters == 0);
950 mNumWriters++;
951#if defined(PRINT_RENDER_TIMES)
952 mDebugTimer.start();
953#endif
954 mLock.unlock();
955 return true;
956}
957
958/*
959 * Remove a writer.
960 */
961void ReadWriteLock::unlockForWrite()
962{
963 mLock.lock();
964 if (mNumWriters == 0) {
965 mLock.unlock();
966 LOG(LOG_WARN, "thread",
967 "WARNING: unlockForWrite requested, but not locked\n");
968 return;
969 }
970 assert(mNumWriters == 1);
971 mNumWriters--;
972#if defined(PRINT_RENDER_TIMES)
973 mDebugTimer.stop();
974 //printf(" wrlk held %.3f msec\n",
975 // (double) mDebugTimer.durationUsecs() / 1000.0);
976#endif
977 mWriteWaiter.signal(); // should other writers get first dibs?
978 //printf("+++ signaling readers (if any)\n");
979 mReadWaiter.broadcast(); // wake all readers (if any)
980 mLock.unlock();
981}
982
983// ----------------------------------------------------------------------------
984
985#if 0
986#pragma mark -
987#pragma mark Thread::Thread
988#endif
989
990/*
991 * This is our thread object!
992 */
993
994Thread::Thread(bool canCallJava)
995 : mCanCallJava(canCallJava),
996 mThread(thread_id_t(-1)),
997 mLock("Thread::mLock"),
998 mStatus(NO_ERROR),
999 mExitPending(false), mRunning(false)
1000{
1001}
1002
1003Thread::~Thread()
1004{
1005}
1006
1007status_t Thread::readyToRun()
1008{
1009 return NO_ERROR;
1010}
1011
1012status_t Thread::run(const char* name, int32_t priority, size_t stack)
1013{
1014 Mutex::Autolock _l(mLock);
1015
1016 if (mRunning) {
1017 // thread already started
1018 return INVALID_OPERATION;
1019 }
1020
1021 // reset status and exitPending to their default value, so we can
1022 // try again after an error happened (either below, or in readyToRun())
1023 mStatus = NO_ERROR;
1024 mExitPending = false;
1025 mThread = thread_id_t(-1);
1026
1027 // hold a strong reference on ourself
1028 mHoldSelf = this;
1029
1030 bool res;
1031 if (mCanCallJava) {
1032 res = createThreadEtc(_threadLoop,
1033 this, name, priority, stack, &mThread);
1034 } else {
1035 res = androidCreateRawThreadEtc(_threadLoop,
1036 this, name, priority, stack, &mThread);
1037 }
1038
1039 if (res == false) {
1040 mStatus = UNKNOWN_ERROR; // something happened!
1041 mRunning = false;
1042 mThread = thread_id_t(-1);
1043 }
1044
1045 if (mStatus < 0) {
1046 // something happened, don't leak
1047 mHoldSelf.clear();
1048 }
1049
1050 return mStatus;
1051}
1052
1053int Thread::_threadLoop(void* user)
1054{
1055 Thread* const self = static_cast<Thread*>(user);
1056 sp<Thread> strong(self->mHoldSelf);
1057 wp<Thread> weak(strong);
1058 self->mHoldSelf.clear();
1059
1060 // we're about to run...
1061 self->mStatus = self->readyToRun();
1062 if (self->mStatus!=NO_ERROR || self->mExitPending) {
1063 // pretend the thread never started...
1064 self->mExitPending = false;
1065 self->mRunning = false;
1066 return 0;
1067 }
1068
1069 // thread is running now
1070 self->mRunning = true;
1071
1072 do {
1073 bool result = self->threadLoop();
1074 if (result == false || self->mExitPending) {
1075 self->mExitPending = true;
1076 self->mLock.lock();
1077 self->mRunning = false;
1078 self->mThreadExitedCondition.signal();
1079 self->mLock.unlock();
1080 break;
1081 }
1082
1083 // Release our strong reference, to let a chance to the thread
1084 // to die a peaceful death.
1085 strong.clear();
1086 // And immediately, reacquire a strong reference for the next loop
1087 strong = weak.promote();
1088 } while(strong != 0);
1089
1090 return 0;
1091}
1092
1093void Thread::requestExit()
1094{
1095 mExitPending = true;
1096}
1097
1098status_t Thread::requestExitAndWait()
1099{
1100 if (mStatus == OK) {
1101
1102 if (mThread == getThreadId()) {
1103 LOGW(
1104 "Thread (this=%p): don't call waitForExit() from this "
1105 "Thread object's thread. It's a guaranteed deadlock!",
1106 this);
1107 return WOULD_BLOCK;
1108 }
1109
1110 requestExit();
1111
1112 Mutex::Autolock _l(mLock);
1113 while (mRunning == true) {
1114 mThreadExitedCondition.wait(mLock);
1115 }
1116 mExitPending = false;
1117 }
1118 return mStatus;
1119}
1120
1121bool Thread::exitPending() const
1122{
1123 return mExitPending;
1124}
1125
1126
1127
1128}; // namespace android