Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 54466bc4 authored by Michael Lentine's avatar Michael Lentine
Browse files

Remove lock around ref count check in terminate.

Replace the global lock in terminate for the ref count check with atomics and a
local lock.

Bug: 19072064

Change-Id: I0cfd6564e227a75b8387a8788b16381d5bc2cc88
parent ef1c17ae
Loading
Loading
Loading
Loading
+144 −119
Original line number Original line Diff line number Diff line
@@ -57,7 +57,7 @@ static bool findExtension(const char* exts, const char* name, size_t nameLen) {
egl_display_t egl_display_t::sDisplay[NUM_DISPLAYS];
egl_display_t egl_display_t::sDisplay[NUM_DISPLAYS];


egl_display_t::egl_display_t() :
egl_display_t::egl_display_t() :
    magic('_dpy'), finishOnSwap(false), traceGpuCompletion(false), refs(0) {
    magic('_dpy'), finishOnSwap(false), traceGpuCompletion(false), refs(0), eglIsInitialized(false) {
}
}


egl_display_t::~egl_display_t() {
egl_display_t::~egl_display_t() {
@@ -120,17 +120,25 @@ EGLDisplay egl_display_t::getDisplay(EGLNativeDisplayType display) {


EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) {
EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) {


    Mutex::Autolock _l(lock);
    {
        Mutex::Autolock _rf(refLock);


    if (refs > 0) {
        refs++;
        if (refs > 1) {
            if (major != NULL)
            if (major != NULL)
                *major = VERSION_MAJOR;
                *major = VERSION_MAJOR;
            if (minor != NULL)
            if (minor != NULL)
                *minor = VERSION_MINOR;
                *minor = VERSION_MINOR;
        refs++;
            while(!eglIsInitialized) refCond.wait(refLock);
            return EGL_TRUE;
            return EGL_TRUE;
        }
        }


        while(eglIsInitialized) refCond.wait(refLock);
    }

    {
        Mutex::Autolock _l(lock);

#if EGL_TRACE
#if EGL_TRACE


        // Called both at early_init time and at this time. (Early_init is pre-zygote, so
        // Called both at early_init time and at this time. (Early_init is pre-zygote, so
@@ -214,21 +222,27 @@ EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) {
            traceGpuCompletion = true;
            traceGpuCompletion = true;
        }
        }


    refs++;
        if (major != NULL)
        if (major != NULL)
            *major = VERSION_MAJOR;
            *major = VERSION_MAJOR;
        if (minor != NULL)
        if (minor != NULL)
            *minor = VERSION_MINOR;
            *minor = VERSION_MINOR;


        mHibernation.setDisplayValid(true);
        mHibernation.setDisplayValid(true);
    }

    {
        Mutex::Autolock _rf(refLock);
        eglIsInitialized = true;
        refCond.broadcast();
    }


    return EGL_TRUE;
    return EGL_TRUE;
}
}


EGLBoolean egl_display_t::terminate() {
EGLBoolean egl_display_t::terminate() {


    Mutex::Autolock _l(lock);
    {

        Mutex::Autolock _rl(refLock);
        if (refs == 0) {
        if (refs == 0) {
            /*
            /*
             * From the EGL spec (3.2):
             * From the EGL spec (3.2):
@@ -240,12 +254,17 @@ EGLBoolean egl_display_t::terminate() {
        }
        }


        // this is specific to Android, display termination is ref-counted.
        // this is specific to Android, display termination is ref-counted.
    if (refs > 1) {
        refs--;
        refs--;
        if (refs > 0) {
            return EGL_TRUE;
            return EGL_TRUE;
        }
        }
    }


    EGLBoolean res = EGL_FALSE;
    EGLBoolean res = EGL_FALSE;

    {
        Mutex::Autolock _l(lock);

        egl_connection_t* const cnx = &gEGLImpl;
        egl_connection_t* const cnx = &gEGLImpl;
        if (cnx->dso && disp.state == egl_display_t::INITIALIZED) {
        if (cnx->dso && disp.state == egl_display_t::INITIALIZED) {
            if (cnx->egl.eglTerminate(disp.dpy) == EGL_FALSE) {
            if (cnx->egl.eglTerminate(disp.dpy) == EGL_FALSE) {
@@ -275,8 +294,14 @@ EGLBoolean egl_display_t::terminate() {


        // this marks all object handles are "terminated"
        // this marks all object handles are "terminated"
        objects.clear();
        objects.clear();
    }

    {
        Mutex::Autolock _rl(refLock);
        eglIsInitialized = false;
        refCond.broadcast();
    }


    refs--;
    return res;
    return res;
}
}


+3 −1
Original line number Original line Diff line number Diff line
@@ -131,7 +131,9 @@ private:
    void leave() { return mHibernation.decWakeCount(HibernationMachine::WEAK); }
    void leave() { return mHibernation.decWakeCount(HibernationMachine::WEAK); }


            uint32_t                    refs;
            uint32_t                    refs;
    mutable Mutex                       lock;
            bool                        eglIsInitialized;
    mutable Mutex                       lock, refLock;
    mutable Condition                   refCond;
            SortedVector<egl_object_t*> objects;
            SortedVector<egl_object_t*> objects;
            String8 mVendorString;
            String8 mVendorString;
            String8 mVersionString;
            String8 mVersionString;