page6
我们看一下Thread的run函数的实现:
1 status_t Thread::run(const char* name, int32_t priority, size_t stack)
2 {
3 Mutex::Autolock _l(mLock);
4
5 if (mRunning) {
6 // thread already started
7 return INVALID_OPERATION;
8 }
9
10 // reset status and exitPending to their default value, so we can
11 // try again after an error happened (either below, or in readyToRun())
12 mStatus = NO_ERROR;
13 mExitPending = false;
14 mThread = thread_id_t(-1);
15
16 // hold a strong reference on ourself
17 mHoldSelf = this;
18
19 mRunning = true;
20
21 bool res;
22 if (mCanCallJava) {
23 res = createThreadEtc(_threadLoop,
24 this, name, priority, stack, &mThread);
25 } else {
26 res = androidCreateRawThreadEtc(_threadLoop,
27 this, name, priority, stack, &mThread);
28 }
29
30 if (res == false) {
31 mStatus = UNKNOWN_ERROR; // something happened!
32 mRunning = false;
33 mThread = thread_id_t(-1);
34 mHoldSelf.clear(); // "this" may have gone away after this.
35
36 return UNKNOWN_ERROR;
37 }
38
39 // Do not refer to mStatus here: The thread is already running (may, in fact
40 // already have exited with a valid mStatus result). The NO_ERROR indication
41 // here merely indicates successfully starting the thread and does not
42 // imply successful termination/execution.
43 return NO_ERROR;
44
45 // Exiting scope of mLock is a memory barrier and allows new thread to run
46 }
第22-24行(Thread->run)会调用createThreadEtc函数来创建一个
Lines 25-28 (Thread->run) will call the androidCreateRawThreadEtc function to create a thread. For a detailed analysis of the androidCreateRawThreadEtc function, please refer to the page7 file.
When a new thread is created, the thread will use the _threadLoop function as the entry point. Execution, for the detailed analysis of the _threadLoop function of Thread, please refer to the page8 file.
From the analysis of the _threadLoop function, we can know that the readyToRun function of SurfaceFlinger will be called first. For the detailed analysis of the readyToRun function of SurfaceFlinger, please refer to the page9 file.
page7
is here , Let's take a look at the implementation of Thread's androidCreateRawThreadEtc function:
1 int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
2 void *userData,
3 const char* threadName,
4 int32_t threadPriority,
5 size_t threadStackSize,
6 android_thread_id_t *threadId)
7 {
8 pthread_attr_t attr;
9 pthread_attr_init(&attr);
10 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11
12 #ifdef HAVE_ANDROID_OS /* valgrind is rejecting RT-priority create reqs */
13 if (threadPriority != PRIORITY_DEFAULT || threadName != NULL) {
14 // Now that the pthread_t has a method to find the associated
15 // android_thread_id_t (pid) from pthread_t, it would be possible to avoid
16 // this trampoline in some cases as the parent could set the properties
17 // for the child. However, there would be a race condition because the
18 // child becomes ready immediately, and it doesn't work for the name.
19 // prctl(PR_SET_NAME) only works for self; prctl(PR_SET_THREAD_NAME) was
20 // proposed but not yet accepted.
21 thread_data_t* t = new thread_data_t;
22 t->priority = threadPriority;
23 t->threadName = threadName ? strdup(threadName) : NULL;
24 t->entryFunction = entryFunction;
25 t->userData = userData;
26 entryFunction = (android_thread_func_t)&thread_data_t::trampoline;
27 userData = t;
28 }
29 #endif
30
31 if (threadStackSize) {
32 pthread_attr_setstacksize(&attr, threadStackSize);
33 }
34
35 errno = 0;
36 pthread_t thread;
37 int result = pthread_create(&thread, &attr,
38 (android_pthread_entry)entryFunction, userData);
39 pthread_attr_destroy(&attr);
40 if (result != 0) {
41 ALOGE("androidCreateRawThreadEtc failed (entry=%p, res=%d, errno=%d)\n"
42 "(android threadPriority=%d)",
43 entryFunction, result, errno, threadPriority);
44 return 0;
45 }
46
47 // Note that *threadID is directly available to the parent only, as it is
48 // assigned after the child starts. Use memory barrier / lock if the child
49 // or other threads also need access.
50 if (threadId != NULL) {
51 *threadId = (android_thread_id_t)thread; // XXX: this is not portable
52 }
53 return 1;
54 }
Lines 37-38 (Thread->androidCreateRawThreadEtc) will call the pthread_create function to create a Thread, and use entryFunction as the entry function of thread.
page8
In this article, we analyze the implementation of Thread's _threadLoop function:
1 int Thread::_threadLoop(void* user)
2 {
3 Thread* const self = static_cast<Thread*>(user);
4
5 sp<Thread> strong(self->mHoldSelf);
6 wp<Thread> weak(strong);
7 self->mHoldSelf.clear();
8
9 #ifdef HAVE_ANDROID_OS
10 // this is very useful for debugging with gdb
11 self->mTid = gettid();
12 #endif
13
14 bool first = true;
15
16 do {
17 bool result;
18 if (first) {
19 first = false;
20 self->mStatus = self->readyToRun();
21 result = (self->mStatus == NO_ERROR);
22
23 if (result && !self->exitPending()) {
24 // Binder threads (and maybe others) rely on threadLoop
25 // running at least once after a successful ::readyToRun()
26 // (unless, of course, the thread has already been asked to exit
27 // at that point).
28 // This is because threads are essentially used like this:
29 // (new ThreadSubclass())->run();
30 // The caller therefore does not retain a strong reference to
31 // the thread and the thread would simply disappear after the
32 // successful ::readyToRun() call instead of entering the
33 // threadLoop at least once.
34 result = self->threadLoop();
35 }
36 } else {
37 result = self->threadLoop();
38 }
39
40 // establish a scope for mLock
41 {
42 Mutex::Autolock _l(self->mLock);
43 if (result == false || self->mExitPending) {
44 self->mExitPending = true;
45 self->mRunning = false;
46 // clear thread ID so that requestExitAndWait() does not exit if
47 // called by a new thread using the same thread ID as this one.
48 self->mThread = thread_id_t(-1);
49 // note that interested observers blocked in requestExitAndWait are
50 // awoken by broadcast, but blocked on mLock until break exits scope
51 self->mThreadExitedCondition.broadcast();
52 break;
53 }
54 }
55
56 // Release our strong reference, to let a chance to the thread
57 // to die a peaceful death.
58 strong.clear();
59 // And immediately, re-acquire a strong reference for the next loop
60 strong = weak.promote();
61 } while(strong != 0);
62
63 return 0;
64 }
Lines 18-38 (Thread->_threadLoop) will judge that if the thread is executed for the first time, the readyToRun function will be executed first , and then the threadLoop function will be executed continuously.
page9
In this article, we analyze the implementation of SurfaceFlinger's readyToRun function:
1 status_t SurfaceFlinger::readyToRun()
2 {
3 ALOGI( "SurfaceFlinger's main thread ready to run. "
4 "Initializing graphics H/W...");
5
6 // initialize EGL for the default display
7 mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
8 eglInitialize(mEGLDisplay, NULL, NULL);
9
10 // Initialize the H/W composer object. There may or may not be an
11 // actual hardware composer underneath.
12 mHwc = new HWComposer(this,
13 *static_cast<HWComposer::EventHandler *>(this));
14
15 // initialize the config and context
16 EGLint format = mHwc->getVisualID();
17 mEGLConfig = selectEGLConfig(mEGLDisplay, format);
18 mEGLContext = createGLContext(mEGLDisplay, mEGLConfig);
19
20 LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
21 "couldn't create EGLContext");
22
23 // initialize our non-virtual displays
24 for (size_t i=0 ; i<DisplayDevice::NUM_DISPLAY_TYPES ; i++) {
25 DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
26 mDefaultDisplays[i] = new BBinder();
27 wp<IBinder> token = mDefaultDisplays[i];
28
29 // set-up the displays that are already connected
30 if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
31 // All non-virtual displays are currently considered secure.
32 bool isSecure = true;
33 mCurrentState.displays.add(token, DisplayDeviceState(type));
34 sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i);
35 sp<SurfaceTextureClient> stc = new SurfaceTextureClient(
36 static_cast< sp<ISurfaceTexture> >(fbs->getBufferQueue()));
37 sp<DisplayDevice> hw = new DisplayDevice(this,
38 type, isSecure, token, stc, fbs, mEGLConfig);
39 if (i > DisplayDevice::DISPLAY_PRIMARY) {
40 // FIXME: currently we don't get blank/unblank requests
41 // for displays other than the main display, so we always
42 // assume a connected display is unblanked.
43 ALOGD("marking display %d as acquired/unblanked", i);
44 hw->acquireScreen();
45 }
46 mDisplays.add(token, hw);
47 }
48 }
49
50 // we need a GL context current in a few places, when initializing
51 // OpenGL ES (see below), or creating a layer,
52 // or when a texture is (asynchronously) destroyed, and for that
53 // we need a valid surface, so it's convenient to use the main display
54 // for that.
55 sp<const DisplayDevice> hw(getDefaultDisplayDevice());
56
57 // initialize OpenGL ES
58 DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext);
59 initializeGL(mEGLDisplay);
60
61 // start the EventThread
62 mEventThread = new EventThread(this);
63 mEventQueue.setEventThread(mEventThread);
64
65 // initialize our drawing state
66 mDrawingState = mCurrentState;
67
68
69 // We're now ready to accept clients...
70 mReadyToRunBarrier.open();
71
72 // set initial conditions (e.g. unblank default device)
73 initializeDisplays();
74
75 // start boot animation
76 startBootAnim();
77
78 return NO_ERROR;
79 }
Lines 12-13 (SurfaceFlinger->readyToRun) will create a HWComposer object to initialize the member variable mHwc, mHwc is the underlying operation Fb file.
Lines 24-48 (SurfaceFlinger->readyToRun) will apply for a DisplayDevice for each display device Object,
line 62 (SurfaceFlinger->readyToRun) will create an EventThread object and initialize the member variable mEventThread. For the creation process of EventThread, please refer to the page10 file.
Because mEventThread is a member variable of type Sp, this will cause onFirstRef of EventThread For the function call, please refer to the page11 file for a detailed analysis of the onFirstRef function of the EventThread.
Line 63 (SurfaceFlinger->readyToRun) will call the setEventThread function of the MessageQueue to create a connection with the EventThread. For a detailed analysis of the setEventThread function of the MessageQueue, please refer to the page12 file .
page10In
this article, let's take a look at the creation process of EventThread. Let's first look at the inheritance system of the EventThread class:
class EventThread : public Thread
Obviously, EventThread is just a thread.
The definition of the constructor of the EventThread class is as follows:
1 EventThread::EventThread(const sp<SurfaceFlinger>& flinger)
2 : mFlinger(flinger),
3 mUseSoftwareVSync(false),
4 mDebugVsyncEnabled(false) {
5
6 for (int32_t i=0 ; i<HWC_DISPLAY_TYPES_SUPPORTED ; i++) {
7 mVSyncEvent[i].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
8 mVSyncEvent[i].header.id = 0;
9 mVSyncEvent[i].header.timestamp = 0;
10 mVSyncEvent[i].vsync.count = 0;
11 }
12 }
The startup of SurfaceFlinger of Android source code (2)
Guess you like
Origin http://43.154.161.224:23101/article/api/json?id=326228613&siteId=291194637
Recommended
Ranking