Threads.cpp revision 7c1b96a165f970a09ed239bb4fb3f1b0d8f2a407
1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#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        LOG(LOG_WARN, "thread",
900            "WARNING: unlockForRead requested, but not locked\n");
901        return;
902    }
903    assert(mNumReaders > 0);
904    assert(mNumWriters == 0);
905    mNumReaders--;
906    if (mNumReaders == 0) {           // last reader?
907#if defined(PRINT_RENDER_TIMES)
908        mDebugTimer.stop();
909        printf(" rdlk held %.3f msec\n",
910            (double) mDebugTimer.durationUsecs() / 1000.0);
911#endif
912        //printf("+++ signaling writers (if any)\n");
913        mWriteWaiter.signal();      // wake one writer (if any)
914    }
915    mLock.unlock();
916}
917
918/*
919 * Add a writer.  This requires exclusive access to the object.
920 */
921void ReadWriteLock::lockForWrite()
922{
923    mLock.lock();
924    while (mNumReaders > 0 || mNumWriters > 0) {
925        LOG(LOG_DEBUG, "thread", "+++ lockForWrite: waiting\n");
926        mWriteWaiter.wait(mLock);
927    }
928    assert(mNumReaders == 0);
929    assert(mNumWriters == 0);
930    mNumWriters++;
931#if defined(PRINT_RENDER_TIMES)
932    mDebugTimer.start();
933#endif
934    mLock.unlock();
935}
936
937/*
938 * Try to add a writer.  If it doesn't work right away, return "false".
939 */
940bool ReadWriteLock::tryLockForWrite()
941{
942    mLock.lock();
943    if (mNumReaders > 0 || mNumWriters > 0) {
944        mLock.unlock();
945        return false;
946    }
947    assert(mNumReaders == 0);
948    assert(mNumWriters == 0);
949    mNumWriters++;
950#if defined(PRINT_RENDER_TIMES)
951    mDebugTimer.start();
952#endif
953    mLock.unlock();
954    return true;
955}
956
957/*
958 * Remove a writer.
959 */
960void ReadWriteLock::unlockForWrite()
961{
962    mLock.lock();
963    if (mNumWriters == 0) {
964        LOG(LOG_WARN, "thread",
965            "WARNING: unlockForWrite requested, but not locked\n");
966        return;
967    }
968    assert(mNumWriters == 1);
969    mNumWriters--;
970#if defined(PRINT_RENDER_TIMES)
971    mDebugTimer.stop();
972    //printf(" wrlk held %.3f msec\n",
973    //    (double) mDebugTimer.durationUsecs() / 1000.0);
974#endif
975    // mWriteWaiter.signal();       // should other writers get first dibs?
976    //printf("+++ signaling readers (if any)\n");
977    mReadWaiter.broadcast();        // wake all readers (if any)
978    mLock.unlock();
979}
980
981// ----------------------------------------------------------------------------
982
983#if 0
984#pragma mark -
985#pragma mark Thread::Thread
986#endif
987
988/*
989 * This is our thread object!
990 */
991
992Thread::Thread(bool canCallJava)
993    :   mCanCallJava(canCallJava),
994        mThread(thread_id_t(-1)),
995        mLock("Thread::mLock"),
996        mStatus(NO_ERROR),
997        mExitPending(false), mRunning(false)
998{
999}
1000
1001Thread::~Thread()
1002{
1003}
1004
1005status_t Thread::readyToRun()
1006{
1007    return NO_ERROR;
1008}
1009
1010status_t Thread::run(const char* name, int32_t priority, size_t stack)
1011{
1012    Mutex::Autolock _l(mLock);
1013
1014    if (mRunning) {
1015        // thread already started
1016        return INVALID_OPERATION;
1017    }
1018
1019    // reset status and exitPending to their default value, so we can
1020    // try again after an error happened (either below, or in readyToRun())
1021    mStatus = NO_ERROR;
1022    mExitPending = false;
1023    mThread = thread_id_t(-1);
1024
1025    // hold a strong reference on ourself
1026    mHoldSelf = this;
1027
1028    bool res;
1029    if (mCanCallJava) {
1030        res = createThreadEtc(_threadLoop,
1031                this, name, priority, stack, &mThread);
1032    } else {
1033        res = androidCreateRawThreadEtc(_threadLoop,
1034                this, name, priority, stack, &mThread);
1035    }
1036
1037    if (res == false) {
1038        mStatus = UNKNOWN_ERROR;   // something happened!
1039        mRunning = false;
1040        mThread = thread_id_t(-1);
1041    }
1042
1043    if (mStatus < 0) {
1044        // something happened, don't leak
1045        mHoldSelf.clear();
1046    }
1047
1048    return mStatus;
1049}
1050
1051int Thread::_threadLoop(void* user)
1052{
1053    Thread* const self = static_cast<Thread*>(user);
1054    sp<Thread> strong(self->mHoldSelf);
1055    wp<Thread> weak(strong);
1056    self->mHoldSelf.clear();
1057
1058    // we're about to run...
1059    self->mStatus = self->readyToRun();
1060    if (self->mStatus!=NO_ERROR || self->mExitPending) {
1061        // pretend the thread never started...
1062        self->mExitPending = false;
1063        self->mRunning = false;
1064        return 0;
1065    }
1066
1067    // thread is running now
1068    self->mRunning = true;
1069
1070    do {
1071        bool result = self->threadLoop();
1072        if (result == false || self->mExitPending) {
1073            self->mExitPending = true;
1074            self->mLock.lock();
1075            self->mRunning = false;
1076            self->mThreadExitedCondition.signal();
1077            self->mLock.unlock();
1078            break;
1079        }
1080
1081        // Release our strong reference, to let a chance to the thread
1082        // to die a peaceful death.
1083        strong.clear();
1084        // And immediately, reacquire a strong reference for the next loop
1085        strong = weak.promote();
1086    } while(strong != 0);
1087
1088    return 0;
1089}
1090
1091void Thread::requestExit()
1092{
1093    mExitPending = true;
1094}
1095
1096status_t Thread::requestExitAndWait()
1097{
1098    if (mStatus == OK) {
1099
1100        if (mThread == getThreadId()) {
1101            LOGW(
1102            "Thread (this=%p): don't call waitForExit() from this "
1103            "Thread object's thread. It's a guaranteed deadlock!",
1104            this);
1105            return WOULD_BLOCK;
1106        }
1107
1108        requestExit();
1109
1110        Mutex::Autolock _l(mLock);
1111        while (mRunning == true) {
1112            mThreadExitedCondition.wait(mLock);
1113        }
1114        mExitPending = false;
1115    }
1116    return mStatus;
1117}
1118
1119bool Thread::exitPending() const
1120{
1121    return mExitPending;
1122}
1123
1124
1125
1126};  // namespace android
1127