Threads.cpp revision 4de4ebf6a25b5cf1819809ffcedea331d79823e0
1edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/*
2edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
4edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * you may not use this file except in compliance with the License.
6edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * You may obtain a copy of the License at
7edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
8edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
10edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * See the License for the specific language governing permissions and
14edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * limitations under the License.
15edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project */
16edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
179adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project// #define LOG_NDEBUG 0
18edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#define LOG_TAG "libutils.threads"
19edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
20edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <utils/threads.h>
21edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <utils/Log.h>
22edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
23edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <stdio.h>
24edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <stdlib.h>
25edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <memory.h>
26edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <errno.h>
27edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <assert.h>
28edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <unistd.h>
29edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
30edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#if defined(HAVE_PTHREADS)
31edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project# include <pthread.h>
32edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project# include <sched.h>
33edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project# include <sys/resource.h>
34edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#elif defined(HAVE_WIN32_THREADS)
35edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project# include <windows.h>
36edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project# include <stdint.h>
37edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project# include <process.h>
38edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project# define HAVE_CREATETHREAD  // Cygwin, vs. HAVE__BEGINTHREADEX for MinGW
39edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#endif
40edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
41edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#if defined(HAVE_PRCTL)
42edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <sys/prctl.h>
43edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#endif
44edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
45edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/*
46edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * ===========================================================================
47edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *      Thread wrappers
48edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * ===========================================================================
49edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project */
50edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
51edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectusing namespace android;
52edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
53edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ----------------------------------------------------------------------------
54edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#if defined(HAVE_PTHREADS)
55edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ----------------------------------------------------------------------------
56edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
57edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/*
58edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Create and run a new thead.
59edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
60edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * We create it "detached", so it cleans up after itself.
61edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project */
62edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
63edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projecttypedef void* (*android_pthread_entry)(void*);
64edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
65edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstruct thread_data_t {
66edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    thread_func_t   entryFunction;
67edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    void*           userData;
68edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    int             priority;
69edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    char *          threadName;
70edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
71edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // we use this trampoline when we need to set the priority with
72edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // nice/setpriority.
73edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    static int trampoline(const thread_data_t* t) {
74edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        thread_func_t f = t->entryFunction;
75edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        void* u = t->userData;
76edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        int prio = t->priority;
77edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        char * name = t->threadName;
78edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        delete t;
79edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        setpriority(PRIO_PROCESS, 0, prio);
80edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (name) {
81edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#if defined(HAVE_PRCTL)
82edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // Mac OS doesn't have this, and we build libutil for the host too
83edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            int hasAt = 0;
84edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            int hasDot = 0;
85edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            char *s = name;
86edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            while (*s) {
87edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                if (*s == '.') hasDot = 1;
88edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                else if (*s == '@') hasAt = 1;
89edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                s++;
90edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            }
91edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            int len = s - name;
92edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            if (len < 15 || hasAt || !hasDot) {
93edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                s = name;
94edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            } else {
95edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                s = name + len - 15;
96edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            }
97edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            prctl(PR_SET_NAME, (unsigned long) s, 0, 0, 0);
98edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#endif
99edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            free(name);
100edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        }
101edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        return f(u);
102edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
103edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project};
104edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
105edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectint androidCreateRawThreadEtc(android_thread_func_t entryFunction,
106edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                               void *userData,
107edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                               const char* threadName,
108edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                               int32_t threadPriority,
109edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                               size_t threadStackSize,
110edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                               android_thread_id_t *threadId)
111edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
112edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    pthread_attr_t attr;
113edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    pthread_attr_init(&attr);
114edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
115edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
116edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#ifdef HAVE_ANDROID_OS  /* valgrind is rejecting RT-priority create reqs */
117edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (threadPriority != PRIORITY_DEFAULT || threadName != NULL) {
118edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // We could avoid the trampoline if there was a way to get to the
119edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // android_thread_id_t (pid) from pthread_t
120edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        thread_data_t* t = new thread_data_t;
121edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        t->priority = threadPriority;
122edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        t->threadName = threadName ? strdup(threadName) : NULL;
123edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        t->entryFunction = entryFunction;
124edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        t->userData = userData;
125edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        entryFunction = (android_thread_func_t)&thread_data_t::trampoline;
126edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        userData = t;
127edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
128edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#endif
129edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
130edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (threadStackSize) {
131edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        pthread_attr_setstacksize(&attr, threadStackSize);
132edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
133edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
134edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    errno = 0;
135edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    pthread_t thread;
136edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    int result = pthread_create(&thread, &attr,
137edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    (android_pthread_entry)entryFunction, userData);
138edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (result != 0) {
139edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        LOGE("androidCreateRawThreadEtc failed (entry=%p, res=%d, errno=%d)\n"
140edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project             "(android threadPriority=%d)",
141edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            entryFunction, result, errno, threadPriority);
142edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        return 0;
143edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
144edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
145edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (threadId != NULL) {
146edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        *threadId = (android_thread_id_t)thread; // XXX: this is not portable
147edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
148edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return 1;
149edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
150edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
151edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectandroid_thread_id_t androidGetThreadId()
152edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
153edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return (android_thread_id_t)pthread_self();
154edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
155edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
156edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ----------------------------------------------------------------------------
157edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#elif defined(HAVE_WIN32_THREADS)
158edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ----------------------------------------------------------------------------
159edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
160edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/*
161edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Trampoline to make us __stdcall-compliant.
162edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
163edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * We're expected to delete "vDetails" when we're done.
164edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project */
165edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstruct threadDetails {
166edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    int (*func)(void*);
167edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    void* arg;
168edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project};
169edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatic __stdcall unsigned int threadIntermediary(void* vDetails)
170edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
171edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    struct threadDetails* pDetails = (struct threadDetails*) vDetails;
172edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    int result;
173edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
174edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    result = (*(pDetails->func))(pDetails->arg);
175edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
176edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    delete pDetails;
177edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
178edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    LOG(LOG_VERBOSE, "thread", "thread exiting\n");
179edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return (unsigned int) result;
180edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
181edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
182edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/*
183edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Create and run a new thread.
184edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project */
185edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatic bool doCreateThread(android_thread_func_t fn, void* arg, android_thread_id_t *id)
186edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
187edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    HANDLE hThread;
188edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    struct threadDetails* pDetails = new threadDetails; // must be on heap
189edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    unsigned int thrdaddr;
190edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
191edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    pDetails->func = fn;
192edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    pDetails->arg = arg;
193edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
194edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#if defined(HAVE__BEGINTHREADEX)
195edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    hThread = (HANDLE) _beginthreadex(NULL, 0, threadIntermediary, pDetails, 0,
196edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    &thrdaddr);
197edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (hThread == 0)
198edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#elif defined(HAVE_CREATETHREAD)
199edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    hThread = CreateThread(NULL, 0,
200edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    (LPTHREAD_START_ROUTINE) threadIntermediary,
201edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    (void*) pDetails, 0, (DWORD*) &thrdaddr);
202edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (hThread == NULL)
203edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#endif
204edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    {
205edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        LOG(LOG_WARN, "thread", "WARNING: thread create failed\n");
206edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        return false;
207edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
208edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
209edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#if defined(HAVE_CREATETHREAD)
210edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    /* close the management handle */
211edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    CloseHandle(hThread);
212edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#endif
213edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
214edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (id != NULL) {
215edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project      	*id = (android_thread_id_t)thrdaddr;
216edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
217edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
218edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return true;
219edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
220edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
221edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectint androidCreateRawThreadEtc(android_thread_func_t fn,
222edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                               void *userData,
223edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                               const char* threadName,
224edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                               int32_t threadPriority,
225edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                               size_t threadStackSize,
226edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                               android_thread_id_t *threadId)
227edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
228edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return doCreateThread(  fn, userData, threadId);
229edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
230edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
231edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectandroid_thread_id_t androidGetThreadId()
232edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
233edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return (android_thread_id_t)GetCurrentThreadId();
234edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
235edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
236edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ----------------------------------------------------------------------------
237edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#else
238edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#error "Threads not supported"
239edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#endif
240edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
241edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ----------------------------------------------------------------------------
242edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
243edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectint androidCreateThread(android_thread_func_t fn, void* arg)
244edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
245edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return createThreadEtc(fn, arg);
246edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
247edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
248edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectint androidCreateThreadGetID(android_thread_func_t fn, void *arg, android_thread_id_t *id)
249edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
250edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return createThreadEtc(fn, arg, "android:unnamed_thread",
251edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                           PRIORITY_DEFAULT, 0, id);
252edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
253edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
254edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatic android_create_thread_fn gCreateThreadFn = androidCreateRawThreadEtc;
255edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
256edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectint androidCreateThreadEtc(android_thread_func_t entryFunction,
257edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                            void *userData,
258edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                            const char* threadName,
259edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                            int32_t threadPriority,
260edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                            size_t threadStackSize,
261edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                            android_thread_id_t *threadId)
262edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
263edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return gCreateThreadFn(entryFunction, userData, threadName,
264edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        threadPriority, threadStackSize, threadId);
265edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
266edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
267edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid androidSetCreateThreadFunc(android_create_thread_fn func)
268edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
269edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    gCreateThreadFn = func;
270edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
271edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
272edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectnamespace android {
273edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
274edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/*
275edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * ===========================================================================
276edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *      Mutex class
277edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * ===========================================================================
278edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project */
279edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
280ec0f1f6720cd7ecffab54b0dfc2553b55a38e50fMathias Agopian#if defined(HAVE_PTHREADS)
281ec0f1f6720cd7ecffab54b0dfc2553b55a38e50fMathias Agopian// implemented as inlines in threads.h
282edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#elif defined(HAVE_WIN32_THREADS)
283edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
284edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectMutex::Mutex()
285edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
286edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    HANDLE hMutex;
287edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
288edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    assert(sizeof(hMutex) == sizeof(mState));
289edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
290edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    hMutex = CreateMutex(NULL, FALSE, NULL);
291edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    mState = (void*) hMutex;
292edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
293edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
294edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectMutex::Mutex(const char* name)
295edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
296edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // XXX: name not used for now
297edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    HANDLE hMutex;
298edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
299429db150affcc99b198fa0da52165fde4cd4cc7cDavid 'Digit' Turner    assert(sizeof(hMutex) == sizeof(mState));
300429db150affcc99b198fa0da52165fde4cd4cc7cDavid 'Digit' Turner
301429db150affcc99b198fa0da52165fde4cd4cc7cDavid 'Digit' Turner    hMutex = CreateMutex(NULL, FALSE, NULL);
302429db150affcc99b198fa0da52165fde4cd4cc7cDavid 'Digit' Turner    mState = (void*) hMutex;
303429db150affcc99b198fa0da52165fde4cd4cc7cDavid 'Digit' Turner}
304429db150affcc99b198fa0da52165fde4cd4cc7cDavid 'Digit' Turner
305429db150affcc99b198fa0da52165fde4cd4cc7cDavid 'Digit' TurnerMutex::Mutex(int type, const char* name)
306429db150affcc99b198fa0da52165fde4cd4cc7cDavid 'Digit' Turner{
307429db150affcc99b198fa0da52165fde4cd4cc7cDavid 'Digit' Turner    // XXX: type and name not used for now
308429db150affcc99b198fa0da52165fde4cd4cc7cDavid 'Digit' Turner    HANDLE hMutex;
309429db150affcc99b198fa0da52165fde4cd4cc7cDavid 'Digit' Turner
310429db150affcc99b198fa0da52165fde4cd4cc7cDavid 'Digit' Turner    assert(sizeof(hMutex) == sizeof(mState));
311429db150affcc99b198fa0da52165fde4cd4cc7cDavid 'Digit' Turner
312edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    hMutex = CreateMutex(NULL, FALSE, NULL);
313edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    mState = (void*) hMutex;
314edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
315edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
316edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectMutex::~Mutex()
317edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
318edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    CloseHandle((HANDLE) mState);
319edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
320edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
321edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatus_t Mutex::lock()
322edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
323edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    DWORD dwWaitResult;
324edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    dwWaitResult = WaitForSingleObject((HANDLE) mState, INFINITE);
325edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return dwWaitResult != WAIT_OBJECT_0 ? -1 : NO_ERROR;
326edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
327edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
328edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid Mutex::unlock()
329edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
330edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (!ReleaseMutex((HANDLE) mState))
331edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        LOG(LOG_WARN, "thread", "WARNING: bad result from unlocking mutex\n");
332edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
333edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
334edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatus_t Mutex::tryLock()
335edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
336edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    DWORD dwWaitResult;
337edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
338edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    dwWaitResult = WaitForSingleObject((HANDLE) mState, 0);
339edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (dwWaitResult != WAIT_OBJECT_0 && dwWaitResult != WAIT_TIMEOUT)
340edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        LOG(LOG_WARN, "thread", "WARNING: bad result from try-locking mutex\n");
341edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return (dwWaitResult == WAIT_OBJECT_0) ? 0 : -1;
342edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
343edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
344edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#else
345edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#error "Somebody forgot to implement threads for this platform."
346edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#endif
347edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
348edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
349edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/*
350edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * ===========================================================================
351edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *      Condition class
352edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * ===========================================================================
353edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project */
354edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
355ec0f1f6720cd7ecffab54b0dfc2553b55a38e50fMathias Agopian#if defined(HAVE_PTHREADS)
356ec0f1f6720cd7ecffab54b0dfc2553b55a38e50fMathias Agopian// implemented as inlines in threads.h
357edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#elif defined(HAVE_WIN32_THREADS)
358edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
359edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/*
360edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Windows doesn't have a condition variable solution.  It's possible
361edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * to create one, but it's easy to get it wrong.  For a discussion, and
362edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * the origin of this implementation, see:
363edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
364edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *  http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
365edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
366edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * The implementation shown on the page does NOT follow POSIX semantics.
367edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * As an optimization they require acquiring the external mutex before
368edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * calling signal() and broadcast(), whereas POSIX only requires grabbing
369edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * it before calling wait().  The implementation here has been un-optimized
370edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * to have the correct behavior.
371edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project */
372edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projecttypedef struct WinCondition {
373edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // Number of waiting threads.
374edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    int                 waitersCount;
375edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
376edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // Serialize access to waitersCount.
377edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    CRITICAL_SECTION    waitersCountLock;
378edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
379edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // Semaphore used to queue up threads waiting for the condition to
380edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // become signaled.
381edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    HANDLE              sema;
382edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
383edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // An auto-reset event used by the broadcast/signal thread to wait
384edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // for all the waiting thread(s) to wake up and be released from
385edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // the semaphore.
386edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    HANDLE              waitersDone;
387edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
388edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // This mutex wouldn't be necessary if we required that the caller
389edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // lock the external mutex before calling signal() and broadcast().
390edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // I'm trying to mimic pthread semantics though.
391edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    HANDLE              internalMutex;
392edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
393edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // Keeps track of whether we were broadcasting or signaling.  This
394edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // allows us to optimize the code if we're just signaling.
395edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    bool                wasBroadcast;
396edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
397edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    status_t wait(WinCondition* condState, HANDLE hMutex, nsecs_t* abstime)
398edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    {
399edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // Increment the wait count, avoiding race conditions.
400edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        EnterCriticalSection(&condState->waitersCountLock);
401edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        condState->waitersCount++;
402edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        //printf("+++ wait: incr waitersCount to %d (tid=%ld)\n",
403edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        //    condState->waitersCount, getThreadId());
404edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        LeaveCriticalSection(&condState->waitersCountLock);
405edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
406edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        DWORD timeout = INFINITE;
407edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (abstime) {
408edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            nsecs_t reltime = *abstime - systemTime();
409edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            if (reltime < 0)
410edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                reltime = 0;
411edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            timeout = reltime/1000000;
412edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        }
413edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
414edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // Atomically release the external mutex and wait on the semaphore.
415edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        DWORD res =
416edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            SignalObjectAndWait(hMutex, condState->sema, timeout, FALSE);
417edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
418edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        //printf("+++ wait: awake (tid=%ld)\n", getThreadId());
419edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
420edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // Reacquire lock to avoid race conditions.
421edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        EnterCriticalSection(&condState->waitersCountLock);
422edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
423edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // No longer waiting.
424edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        condState->waitersCount--;
425edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
426edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // Check to see if we're the last waiter after a broadcast.
427edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        bool lastWaiter = (condState->wasBroadcast && condState->waitersCount == 0);
428edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
429edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        //printf("+++ wait: lastWaiter=%d (wasBc=%d wc=%d)\n",
430edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        //    lastWaiter, condState->wasBroadcast, condState->waitersCount);
431edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
432edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        LeaveCriticalSection(&condState->waitersCountLock);
433edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
434edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // If we're the last waiter thread during this particular broadcast
435edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // then signal broadcast() that we're all awake.  It'll drop the
436edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // internal mutex.
437edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (lastWaiter) {
438edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // Atomically signal the "waitersDone" event and wait until we
439edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // can acquire the internal mutex.  We want to do this in one step
440edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // because it ensures that everybody is in the mutex FIFO before
441edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // any thread has a chance to run.  Without it, another thread
442edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // could wake up, do work, and hop back in ahead of us.
443edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            SignalObjectAndWait(condState->waitersDone, condState->internalMutex,
444edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                INFINITE, FALSE);
445edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        } else {
446edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // Grab the internal mutex.
447edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            WaitForSingleObject(condState->internalMutex, INFINITE);
448edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        }
449edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
450edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // Release the internal and grab the external.
451edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        ReleaseMutex(condState->internalMutex);
452edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        WaitForSingleObject(hMutex, INFINITE);
453edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
454edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        return res == WAIT_OBJECT_0 ? NO_ERROR : -1;
455edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
456edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} WinCondition;
457edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
458edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/*
459edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Constructor.  Set up the WinCondition stuff.
460edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project */
461edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectCondition::Condition()
462edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
463edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    WinCondition* condState = new WinCondition;
464edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
465edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    condState->waitersCount = 0;
466edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    condState->wasBroadcast = false;
467edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // semaphore: no security, initial value of 0
468edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    condState->sema = CreateSemaphore(NULL, 0, 0x7fffffff, NULL);
469edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    InitializeCriticalSection(&condState->waitersCountLock);
470edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // auto-reset event, not signaled initially
471edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    condState->waitersDone = CreateEvent(NULL, FALSE, FALSE, NULL);
472edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // used so we don't have to lock external mutex on signal/broadcast
473edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    condState->internalMutex = CreateMutex(NULL, FALSE, NULL);
474edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
475edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    mState = condState;
476edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
477edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
478edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/*
479edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Destructor.  Free Windows resources as well as our allocated storage.
480edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project */
481edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectCondition::~Condition()
482edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
483edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    WinCondition* condState = (WinCondition*) mState;
484edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (condState != NULL) {
485edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        CloseHandle(condState->sema);
486edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        CloseHandle(condState->waitersDone);
487edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        delete condState;
488edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
489edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
490edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
491edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
492edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatus_t Condition::wait(Mutex& mutex)
493edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
494edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    WinCondition* condState = (WinCondition*) mState;
495edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    HANDLE hMutex = (HANDLE) mutex.mState;
496edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
497edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return ((WinCondition*)mState)->wait(condState, hMutex, NULL);
498edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
499edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
500edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatus_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime)
501edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
502429db150affcc99b198fa0da52165fde4cd4cc7cDavid 'Digit' Turner    WinCondition* condState = (WinCondition*) mState;
503429db150affcc99b198fa0da52165fde4cd4cc7cDavid 'Digit' Turner    HANDLE hMutex = (HANDLE) mutex.mState;
504429db150affcc99b198fa0da52165fde4cd4cc7cDavid 'Digit' Turner    nsecs_t absTime = systemTime()+reltime;
505429db150affcc99b198fa0da52165fde4cd4cc7cDavid 'Digit' Turner
506429db150affcc99b198fa0da52165fde4cd4cc7cDavid 'Digit' Turner    return ((WinCondition*)mState)->wait(condState, hMutex, &absTime);
507edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
508edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
509edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/*
510edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Signal the condition variable, allowing one thread to continue.
511edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project */
512edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid Condition::signal()
513edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
514edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    WinCondition* condState = (WinCondition*) mState;
515edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
516edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // Lock the internal mutex.  This ensures that we don't clash with
517edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // broadcast().
518edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    WaitForSingleObject(condState->internalMutex, INFINITE);
519edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
520edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    EnterCriticalSection(&condState->waitersCountLock);
521edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    bool haveWaiters = (condState->waitersCount > 0);
522edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    LeaveCriticalSection(&condState->waitersCountLock);
523edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
524edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // If no waiters, then this is a no-op.  Otherwise, knock the semaphore
525edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // down a notch.
526edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (haveWaiters)
527edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        ReleaseSemaphore(condState->sema, 1, 0);
528edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
529edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // Release internal mutex.
530edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    ReleaseMutex(condState->internalMutex);
531edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
532edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
533edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/*
534edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Signal the condition variable, allowing all threads to continue.
535edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
536edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * First we have to wake up all threads waiting on the semaphore, then
537edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * we wait until all of the threads have actually been woken before
538edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * releasing the internal mutex.  This ensures that all threads are woken.
539edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project */
540edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid Condition::broadcast()
541edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
542edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    WinCondition* condState = (WinCondition*) mState;
543edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
544edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // Lock the internal mutex.  This keeps the guys we're waking up
545edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // from getting too far.
546edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    WaitForSingleObject(condState->internalMutex, INFINITE);
547edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
548edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    EnterCriticalSection(&condState->waitersCountLock);
549edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    bool haveWaiters = false;
550edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
551edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (condState->waitersCount > 0) {
552edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        haveWaiters = true;
553edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        condState->wasBroadcast = true;
554edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
555edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
556edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (haveWaiters) {
557edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // Wake up all the waiters.
558edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        ReleaseSemaphore(condState->sema, condState->waitersCount, 0);
559edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
560edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        LeaveCriticalSection(&condState->waitersCountLock);
561edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
562edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // Wait for all awakened threads to acquire the counting semaphore.
563edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // The last guy who was waiting sets this.
564edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        WaitForSingleObject(condState->waitersDone, INFINITE);
565edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
566edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // Reset wasBroadcast.  (No crit section needed because nobody
567edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // else can wake up to poke at it.)
568edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        condState->wasBroadcast = 0;
569edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    } else {
570edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // nothing to do
571edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        LeaveCriticalSection(&condState->waitersCountLock);
572edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
573edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
574edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // Release internal mutex.
575edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    ReleaseMutex(condState->internalMutex);
576edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
577edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
578edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#else
579edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#error "condition variables not supported on this platform"
580edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#endif
581edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
582edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ----------------------------------------------------------------------------
583edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
584edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/*
585edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * This is our thread object!
586edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project */
587edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
588edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectThread::Thread(bool canCallJava)
589edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    :   mCanCallJava(canCallJava),
590edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mThread(thread_id_t(-1)),
591edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mLock("Thread::mLock"),
592edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mStatus(NO_ERROR),
593edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mExitPending(false), mRunning(false)
594edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
595edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
596edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
597edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectThread::~Thread()
598edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
599edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
600edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
601edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatus_t Thread::readyToRun()
602edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
603edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return NO_ERROR;
604edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
605edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
606edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatus_t Thread::run(const char* name, int32_t priority, size_t stack)
607edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
608edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    Mutex::Autolock _l(mLock);
609edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
610edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (mRunning) {
611edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // thread already started
612edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        return INVALID_OPERATION;
613edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
614edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
615edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // reset status and exitPending to their default value, so we can
616edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // try again after an error happened (either below, or in readyToRun())
617edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    mStatus = NO_ERROR;
618edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    mExitPending = false;
619edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    mThread = thread_id_t(-1);
620edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
621edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // hold a strong reference on ourself
622edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    mHoldSelf = this;
623edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
6249adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project    mRunning = true;
6259adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project
626edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    bool res;
627edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (mCanCallJava) {
628edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        res = createThreadEtc(_threadLoop,
629edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                this, name, priority, stack, &mThread);
630edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    } else {
631edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        res = androidCreateRawThreadEtc(_threadLoop,
632edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                this, name, priority, stack, &mThread);
633edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
634edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
635edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (res == false) {
636edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mStatus = UNKNOWN_ERROR;   // something happened!
637edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mRunning = false;
638edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mThread = thread_id_t(-1);
6399adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project        mHoldSelf.clear();  // "this" may have gone away after this.
6409adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project
6419adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project        return UNKNOWN_ERROR;
642edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
643edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
6449adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project    // Do not refer to mStatus here: The thread is already running (may, in fact
6459adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project    // already have exited with a valid mStatus result). The NO_ERROR indication
6469adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project    // here merely indicates successfully starting the thread and does not
6479adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project    // imply successful termination/execution.
6489adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project    return NO_ERROR;
649edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
650edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
651edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectint Thread::_threadLoop(void* user)
652edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
653edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    Thread* const self = static_cast<Thread*>(user);
654edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    sp<Thread> strong(self->mHoldSelf);
655edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    wp<Thread> weak(strong);
656edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    self->mHoldSelf.clear();
657edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
6584de4ebf6a25b5cf1819809ffcedea331d79823e0Mathias Agopian#if HAVE_ANDROID_OS
6594de4ebf6a25b5cf1819809ffcedea331d79823e0Mathias Agopian    // this is very useful for debugging with gdb
6604de4ebf6a25b5cf1819809ffcedea331d79823e0Mathias Agopian    self->mTid = gettid();
6614de4ebf6a25b5cf1819809ffcedea331d79823e0Mathias Agopian#endif
6624de4ebf6a25b5cf1819809ffcedea331d79823e0Mathias Agopian
6639adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project    bool first = true;
664edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
665edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    do {
6669adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project        bool result;
6679adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project        if (first) {
6689adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project            first = false;
6699adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project            self->mStatus = self->readyToRun();
6709adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project            result = (self->mStatus == NO_ERROR);
6719adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project
6729adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project            if (result && !self->mExitPending) {
6739adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project                // Binder threads (and maybe others) rely on threadLoop
6749adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project                // running at least once after a successful ::readyToRun()
6759adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project                // (unless, of course, the thread has already been asked to exit
6769adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project                // at that point).
6779adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project                // This is because threads are essentially used like this:
6789adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project                //   (new ThreadSubclass())->run();
6799adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project                // The caller therefore does not retain a strong reference to
6809adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project                // the thread and the thread would simply disappear after the
6819adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project                // successful ::readyToRun() call instead of entering the
6829adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project                // threadLoop at least once.
6839adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project                result = self->threadLoop();
6849adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project            }
6859adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project        } else {
6869adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project            result = self->threadLoop();
6879adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project        }
6889adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project
689edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (result == false || self->mExitPending) {
690edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            self->mExitPending = true;
691edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            self->mLock.lock();
692edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            self->mRunning = false;
6934de4ebf6a25b5cf1819809ffcedea331d79823e0Mathias Agopian            self->mThreadExitedCondition.broadcast();
694edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            self->mLock.unlock();
695edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            break;
696edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        }
697edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
698edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // Release our strong reference, to let a chance to the thread
699edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // to die a peaceful death.
700edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        strong.clear();
7014de4ebf6a25b5cf1819809ffcedea331d79823e0Mathias Agopian        // And immediately, re-acquire a strong reference for the next loop
702edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        strong = weak.promote();
703edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    } while(strong != 0);
704edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
705edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return 0;
706edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
707edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
708edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid Thread::requestExit()
709edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
710edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    mExitPending = true;
711edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
712edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
713edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatus_t Thread::requestExitAndWait()
714edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
7159adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project    if (mThread == getThreadId()) {
7169adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project        LOGW(
7179adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project        "Thread (this=%p): don't call waitForExit() from this "
7189adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project        "Thread object's thread. It's a guaranteed deadlock!",
7199adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project        this);
720edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
7219adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project        return WOULD_BLOCK;
722edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
7239adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project
7249adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project    requestExit();
7259adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project
7269adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project    Mutex::Autolock _l(mLock);
7279adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project    while (mRunning == true) {
7289adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project        mThreadExitedCondition.wait(mLock);
7299adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project    }
7309adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project    mExitPending = false;
7319adf84a4b6735354893ff1e57c129f66d97d75eeThe Android Open Source Project
732edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return mStatus;
733edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
734edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
735edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectbool Thread::exitPending() const
736edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
737edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return mExitPending;
738edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
739edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
740edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
741edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
742edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project};  // namespace android
743