[Libreoffice-commits] core.git: 3 commits - include/vcl vcl/headless vcl/inc vcl/osx vcl/qa vcl/source vcl/unx vcl/win

Michael Stahl mstahl at redhat.com
Fri Jun 26 14:21:07 PDT 2015


 include/vcl/svapp.hxx           |    8 +++++
 vcl/headless/svpinst.cxx        |    4 ++
 vcl/inc/headless/svpinst.hxx    |    2 -
 vcl/inc/osx/salinst.h           |    2 -
 vcl/inc/salinst.hxx             |    2 -
 vcl/inc/unx/gtk/gtkinst.hxx     |    2 -
 vcl/inc/unx/salinst.h           |    2 -
 vcl/inc/win/salinst.h           |   22 +++++++++++----
 vcl/osx/salinst.cxx             |    4 ++
 vcl/qa/cppunit/timer.cxx        |    2 -
 vcl/source/app/svapp.cxx        |   36 +++++++++++++++++++++----
 vcl/unx/generic/app/salinst.cxx |    4 ++
 vcl/unx/gtk/app/gtkinst.cxx     |    4 ++
 vcl/win/source/app/salinst.cxx  |   56 ++++++++++++++++++++++++++++------------
 14 files changed, 111 insertions(+), 39 deletions(-)

New commits:
commit 7790b6a4544cf2d5ba0bcdfae31346cf2f9a0041
Author: Michael Stahl <mstahl at redhat.com>
Date:   Fri Jun 26 23:09:29 2015 +0200

    vcl: convert some BOOLs
    
    Change-Id: I6d6d63a88ef125b12614f1daeab7afbab06c47ca

diff --git a/vcl/win/source/app/salinst.cxx b/vcl/win/source/app/salinst.cxx
index 227d6af..8a79471 100644
--- a/vcl/win/source/app/salinst.cxx
+++ b/vcl/win/source/app/salinst.cxx
@@ -223,17 +223,17 @@ void ImplSalYieldMutexAcquireWithWait()
     if ( pSalData->mnAppThreadId == nThreadId )
     {
         // wait till we get the Mutex
-        bool bAcquire = FALSE;
+        bool bAcquire = false;
         do
         {
             if ( pInst->mpSalYieldMutex->tryToAcquire() )
-                bAcquire = TRUE;
+                bAcquire = true;
             else
             {
                 pInst->mpSalWaitMutex->acquire();
                 if ( pInst->mpSalYieldMutex->tryToAcquire() )
                 {
-                    bAcquire = TRUE;
+                    bAcquire = true;
                     pInst->mpSalWaitMutex->release();
                 }
                 else
@@ -273,7 +273,7 @@ bool ImplSalYieldMutexTryToAcquire()
     if ( pInst )
         return pInst->mpSalYieldMutex->tryToAcquire();
     else
-        return FALSE;
+        return false;
 }
 
 void ImplSalYieldMutexRelease()
@@ -398,16 +398,16 @@ SalData::SalData()
     mnStockBrushCount = 0;      // count of static brushes
     mnSalObjWantKeyEvt = 0;     // KeyEvent for the SalObj hook
     mnCacheDCInUse = 0;         // count of CacheDC in use
-    mbObjClassInit = FALSE;     // is SALOBJECTCLASS initialised
-    mbInPalChange = FALSE;      // is in WM_QUERYNEWPALETTE
+    mbObjClassInit = false;     // is SALOBJECTCLASS initialised
+    mbInPalChange = false;      // is in WM_QUERYNEWPALETTE
     mnAppThreadId = 0;          // Id from Applikation-Thread
     mbScrSvrEnabled = FALSE;    // ScreenSaver enabled
     mnSageStatus = 0;           // status of Sage-DLL (DISABLE_AGENT == not available)
     mpSageEnableProc = 0;       // funktion to deactivate the system agent
     mpFirstIcon = 0;            // icon cache, points to first icon, NULL if none
     mpTempFontItem = 0;
-    mbThemeChanged = FALSE;     // true if visual theme was changed: throw away theme handles
-    mbThemeMenuSupport = FALSE;
+    mbThemeChanged = false;     // true if visual theme was changed: throw away theme handles
+    mbThemeMenuSupport = false;
 
     // init with NULL
     gdiplusToken = 0;
@@ -905,7 +905,7 @@ bool WinSalInstance::AnyInput( VclInputFlags nType )
         }
     }
 
-    return FALSE;
+    return false;
 }
 
 void SalTimer::Start( sal_uLong nMS )
commit ea2be4ef9ecaacffb36e48bd678a4fe8916c617c
Author: Michael Stahl <mstahl at redhat.com>
Date:   Fri Jun 26 23:06:25 2015 +0200

    vcl: document the non-obvious WinSalInstance's WaitMutex members
    
    Change-Id: I004f082c9e4a17aeb7a8bd778bf45dff93e47ee8

diff --git a/vcl/inc/win/salinst.h b/vcl/inc/win/salinst.h
index b3337ac..6eab9b3 100644
--- a/vcl/inc/win/salinst.h
+++ b/vcl/inc/win/salinst.h
@@ -27,11 +27,21 @@ class SalYieldMutex;
 class WinSalInstance : public SalInstance
 {
 public:
-    HINSTANCE           mhInst;                 // Instance Handle
-    HWND                mhComWnd;               // window, for communication (between threads and the main thread)
-    SalYieldMutex*      mpSalYieldMutex;        // Sal-Yield-Mutex
-    osl::Mutex*         mpSalWaitMutex;         // Sal-Wait-Mutex
-    sal_uInt16              mnYieldWaitCount;       // Wait-Count
+    /// Instance Handle
+    HINSTANCE           mhInst;
+    /// invisible Window so non-main threads can SendMessage() the main thread
+    HWND                mhComWnd;
+    /// The Yield mutex ensures that only one thread calls into VCL
+    SalYieldMutex*      mpSalYieldMutex;
+    /// The Wait mutex ensures increment of mnYieldWaitCount and acquisition
+    /// or release of mpSalYieldMutex is atomic
+    osl::Mutex*         mpSalWaitMutex;
+    /// count main thread's pending ImplSalYieldMutexAcquireWithWait() calls
+    /// (it's not clear to me if this will be > 1 in practice; it would be
+    /// possible if main thread's handling of SAL_MSG_* sent by other threads
+    /// via SendMessage() ends up calling ImplSalYieldMutexAcquireWithWait())
+    sal_uInt16          mnYieldWaitCount;
+
 public:
     WinSalInstance();
     virtual ~WinSalInstance();
diff --git a/vcl/win/source/app/salinst.cxx b/vcl/win/source/app/salinst.cxx
index 36b93ff..227d6af 100644
--- a/vcl/win/source/app/salinst.cxx
+++ b/vcl/win/source/app/salinst.cxx
@@ -159,6 +159,8 @@ void SalYieldMutex::release()
                 // Java clients doesn't come in the right order
                 GdiFlush();
 
+                // lock here to ensure that the test of mnYieldWaitCount and
+                // m_mutex.release() is atomic
                 mpInstData->mpSalWaitMutex->acquire();
                 if ( mpInstData->mnYieldWaitCount )
                     PostMessageW( mpInstData->mhComWnd, SAL_MSG_RELEASEWAITYIELD, 0, 0 );
@@ -203,16 +205,19 @@ sal_uLong SalYieldMutex::GetAcquireCount( sal_uLong nThreadId )
         return 0;
 }
 
+/// note: while VCL is fully up and running (other threads started and
+/// before shutdown), the main thread must acquire SolarMutex only via
+/// this function to avoid deadlock
 void ImplSalYieldMutexAcquireWithWait()
 {
     WinSalInstance* pInst = GetSalData()->mpFirstInstance;
     if ( !pInst )
         return;
 
-    // If we are the main thread, then we must wait with wait, because
-    // in if we don't reschedule, then we create deadlocks if a Windows
-    // Function is called from another thread. If we aren't the main thread,
-    // than we call acquire directly.
+    // If this is the main thread, then we must wait with GetMessage(),
+    // because if we don't reschedule, then we create deadlocks if a Window's
+    // create/destroy is called via SendMessage() from another thread.
+    // If this is not the main thread, call acquire directly.
     DWORD nThreadId = GetCurrentThreadId();
     SalData* pSalData = GetSalData();
     if ( pSalData->mnAppThreadId == nThreadId )
@@ -233,13 +238,26 @@ void ImplSalYieldMutexAcquireWithWait()
                 }
                 else
                 {
+                    // other threads must not observe mnYieldWaitCount == 0
+                    // while main thread is blocked in GetMessage()
                     pInst->mnYieldWaitCount++;
                     pInst->mpSalWaitMutex->release();
                     MSG aTmpMsg;
+                    // this call exists because it dispatches SendMessage() msg!
                     GetMessageW( &aTmpMsg, pInst->mhComWnd, SAL_MSG_RELEASEWAITYIELD, SAL_MSG_RELEASEWAITYIELD );
+                    // it is possible that another thread acquires and releases
+                    // mpSalYieldMutex after the GetMessage call returns,
+                    // observes mnYieldWaitCount != 0 and sends an extra
+                    // SAL_MSG_RELEASEWAITYIELD - but that appears unproblematic
+                    // as it will just cause the next Yield to do an extra
+                    // iteration of the while loop here
                     pInst->mnYieldWaitCount--;
                     if ( pInst->mnYieldWaitCount )
+                    {
+                        // repeat the message so that the next instance of this
+                        // function further up the call stack is unblocked too
                         PostMessageW( pInst->mhComWnd, SAL_MSG_RELEASEWAITYIELD, 0, 0 );
+                    }
                 }
             }
         }
@@ -701,6 +719,8 @@ LRESULT CALLBACK SalComWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lPar
         case SAL_MSG_RELEASEWAITYIELD:
             {
             WinSalInstance* pInst = GetSalData()->mpFirstInstance;
+            // this test does not need mpSalWaitMutex locked because
+            // it can only happen on the main thread
             if ( pInst && pInst->mnYieldWaitCount )
                 PostMessageW( hWnd, SAL_MSG_RELEASEWAITYIELD, wParam, lParam );
             }
commit 482c52e91fe41a52e68827e9bf64a9736427d517
Author: Michael Stahl <mstahl at redhat.com>
Date:   Fri Jun 26 13:01:51 2015 +0200

    vcl: fix Win32 deadlocks from SolarMutexReleaser
    
    To create and destroy thread-affine Win32 Windows and DCs, non-main
    threads SendMessage() special messages like SAL_MSG_CREATEFRAME.
    
    The main thread must handle these messages and return the result to
    un-block the other thread.
    
    This works fine as long as the main thread is in its message loop anyway
    and blocked on GetMessage(); however if the main blocks trying to acquire
    the SolarMutex that is held by the sending thread, deadlock results.
    
    In order to work around this, there is some peculiar code in
    ImplSalYieldMutexAcquireWithWait() to avoid blocking the main thread on
    mpSalYieldMutex but instead block in GetMessage().
    
    The crucial detail is that GetMessage() will immediately dispatch any
    message sent via SendMessage(), which avoids the deadlock.
    
    https://msdn.microsoft.com/en-us/library/windows/desktop/ms644936.aspx
    https://msdn.microsoft.com/en-us/library/windows/desktop/ms644927.aspx
    
    Most of the Win32 WndProc that acquire SolarMutex do so via
    ImplSalYieldMutexAcquireWithWait(), but the main thread may also
    temporarily drop SolarMutex and re-aquire it with the questionable
    SolarMutexReleaser hack, which calls ImplSalAcquireYieldMutex()
    instead, which blocks on mpSalYieldMutex.
    
    Fix SolarMutexReleaser to call a new function
    Application::ReAcquireSolarMutex() that does the right thing here:
    acquire SolarMutex via ImplSalYieldMutexAcquireWithWait().
    
    It turns out that this problem was already fixed before in commit
    6a8fd4c76a969ac98d1aff91ff7442f43aee0006 but the problem was
    insufficiently documented in the commit and it introduced the bug
    that Application::Reschedule() was called without having the SolarMutex
    locked, which caused timers to run without SolarMutex, so the commit
    was reverted in 1ef1781390845d03b6e1518bbac81b818be62f3d.
    
    Change-Id: I60aae555a9ee3c6390f584feddbc6b3cb7de0250

diff --git a/include/vcl/svapp.hxx b/include/vcl/svapp.hxx
index 78f758c..7727b6e 100644
--- a/include/vcl/svapp.hxx
+++ b/include/vcl/svapp.hxx
@@ -504,6 +504,12 @@ public:
     */
     static void                 EndYield();
 
+    /** Acquire SolarMutex after it has been temporarily dropped completely.
+
+        This will Reschedule() on WNT and just acquire on other platforms.
+    */
+    static void                 ReAcquireSolarMutex(sal_uLong nReleased);
+
     /** @brief Get the Solar Mutex for this thread.
 
      Get the Solar Mutex that prevents other threads from accessing VCL
@@ -1687,7 +1693,7 @@ public:
 
     ~SolarMutexReleaser()
     {
-        Application::AcquireSolarMutex( mnReleased );
+        Application::ReAcquireSolarMutex(mnReleased);
     }
 };
 
diff --git a/vcl/headless/svpinst.cxx b/vcl/headless/svpinst.cxx
index ddb48b8..17d98b0 100644
--- a/vcl/headless/svpinst.cxx
+++ b/vcl/headless/svpinst.cxx
@@ -259,8 +259,10 @@ SalBitmap* SvpSalInstance::CreateSalBitmap()
 #endif
 }
 
-void SvpSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents )
+void SvpSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong const nReleased)
 {
+    (void) nReleased;
+    assert(nReleased == 0); // not implemented
     // first, check for already queued events.
 
     // release yield mutex
diff --git a/vcl/inc/headless/svpinst.hxx b/vcl/inc/headless/svpinst.hxx
index 44795d5..f8c5d6e 100644
--- a/vcl/inc/headless/svpinst.hxx
+++ b/vcl/inc/headless/svpinst.hxx
@@ -157,7 +157,7 @@ public:
     // wait next event and dispatch
     // must returned by UserEvent (SalFrame::PostEvent)
     // and timer
-    virtual void            Yield( bool bWait, bool bHandleAllCurrentEvents ) SAL_OVERRIDE;
+    virtual void            DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong nReleased) SAL_OVERRIDE;
     virtual bool            AnyInput( VclInputFlags nType ) SAL_OVERRIDE;
 
     // may return NULL to disable session management
diff --git a/vcl/inc/osx/salinst.h b/vcl/inc/osx/salinst.h
index b2d6133..24b7b6f 100644
--- a/vcl/inc/osx/salinst.h
+++ b/vcl/inc/osx/salinst.h
@@ -109,7 +109,7 @@ public:
     virtual sal_uLong       ReleaseYieldMutex() SAL_OVERRIDE;
     virtual void            AcquireYieldMutex( sal_uLong nCount ) SAL_OVERRIDE;
     virtual bool            CheckYieldMutex() SAL_OVERRIDE;
-    virtual void            Yield( bool bWait, bool bHandleAllCurrentEvents ) SAL_OVERRIDE;
+    virtual void            DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong nReleased) SAL_OVERRIDE;
     virtual bool            AnyInput( VclInputFlags nType ) SAL_OVERRIDE;
     virtual SalMenu*        CreateMenu( bool bMenuBar, Menu* pVCLMenu ) SAL_OVERRIDE;
     virtual void            DestroyMenu( SalMenu* ) SAL_OVERRIDE;
diff --git a/vcl/inc/salinst.hxx b/vcl/inc/salinst.hxx
index eb53177..4ad66af 100644
--- a/vcl/inc/salinst.hxx
+++ b/vcl/inc/salinst.hxx
@@ -127,7 +127,7 @@ public:
     // wait next event and dispatch
     // must returned by UserEvent (SalFrame::PostEvent)
     // and timer
-    virtual void            Yield( bool bWait, bool bHandleAllCurrentEvents ) = 0;
+    virtual void            DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong nReleased) = 0;
     virtual bool            AnyInput( VclInputFlags nType ) = 0;
 
     // menus
diff --git a/vcl/inc/unx/gtk/gtkinst.hxx b/vcl/inc/unx/gtk/gtkinst.hxx
index 28bca36..9a11df1 100644
--- a/vcl/inc/unx/gtk/gtkinst.hxx
+++ b/vcl/inc/unx/gtk/gtkinst.hxx
@@ -80,7 +80,7 @@ public:
                                                      const SystemGraphicsData* ) SAL_OVERRIDE;
     virtual SalBitmap*          CreateSalBitmap() SAL_OVERRIDE;
 
-    virtual void                Yield( bool bWait, bool bHandleAllCurrentEvents ) SAL_OVERRIDE;
+    virtual void                DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong nReleased) SAL_OVERRIDE;
     virtual bool                AnyInput( VclInputFlags nType ) SAL_OVERRIDE;
 
     virtual GenPspGraphics     *CreatePrintGraphics() SAL_OVERRIDE;
diff --git a/vcl/inc/unx/salinst.h b/vcl/inc/unx/salinst.h
index 381ddda..7197e7c 100644
--- a/vcl/inc/unx/salinst.h
+++ b/vcl/inc/unx/salinst.h
@@ -71,7 +71,7 @@ public:
     virtual SalBitmap*          CreateSalBitmap() SAL_OVERRIDE;
     virtual SalSession*         CreateSalSession() SAL_OVERRIDE;
 
-    virtual void                Yield( bool bWait, bool bHandleAllCurrentEvents ) SAL_OVERRIDE;
+    virtual void                DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong nReleased) SAL_OVERRIDE;
     virtual bool                AnyInput( VclInputFlags nType ) SAL_OVERRIDE;
 
     virtual void*               GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes ) SAL_OVERRIDE;
diff --git a/vcl/inc/win/salinst.h b/vcl/inc/win/salinst.h
index 450d07c..b3337ac 100644
--- a/vcl/inc/win/salinst.h
+++ b/vcl/inc/win/salinst.h
@@ -62,7 +62,7 @@ public:
     virtual void                AcquireYieldMutex( sal_uIntPtr nCount ) SAL_OVERRIDE;
     virtual bool                CheckYieldMutex() SAL_OVERRIDE;
 
-    virtual void                Yield( bool bWait, bool bHandleAllCurrentEvents ) SAL_OVERRIDE;
+    virtual void                DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong nReleased) SAL_OVERRIDE;
     virtual bool                AnyInput( VclInputFlags nType ) SAL_OVERRIDE;
     virtual SalMenu*            CreateMenu( bool bMenuBar, Menu* ) SAL_OVERRIDE;
     virtual void                DestroyMenu( SalMenu* ) SAL_OVERRIDE;
diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx
index 0d6c710..f05b15a 100644
--- a/vcl/osx/salinst.cxx
+++ b/vcl/osx/salinst.cxx
@@ -559,8 +559,10 @@ class ReleasePoolHolder
     ~ReleasePoolHolder() { [mpPool release]; }
 };
 
-void AquaSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents )
+void AquaSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong const nReleased)
 {
+    (void) nReleased;
+    assert(nReleased == 0); // not implemented
     // ensure that the per thread autorelease pool is top level and
     // will therefore not be destroyed by cocoa implicitly
     SalData::ensureThreadAutoreleasePool();
diff --git a/vcl/qa/cppunit/timer.cxx b/vcl/qa/cppunit/timer.cxx
index 70f832d..88807fc 100644
--- a/vcl/qa/cppunit/timer.cxx
+++ b/vcl/qa/cppunit/timer.cxx
@@ -127,7 +127,7 @@ void TimerTest::testIdleMainloop()
         // can't test this via Application::Yield since this
         // also processes all tasks directly via the scheduler.
         pSVData->maAppData.mnDispatchLevel++;
-        pSVData->mpDefInst->Yield( true, false );
+        pSVData->mpDefInst->DoYield(true, false, 0);
         pSVData->maAppData.mnDispatchLevel--;
     }
     CPPUNIT_ASSERT_MESSAGE("mainloop idle triggered", bTriggered);
diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx
index 536e81b..42efa3b 100644
--- a/vcl/source/app/svapp.cxx
+++ b/vcl/source/app/svapp.cxx
@@ -338,19 +338,23 @@ void Application::Execute()
     pSVData->maAppData.mbInAppExecute = false;
 }
 
-inline void ImplYield( bool i_bWait, bool i_bAllEvents )
+inline void ImplYield(bool i_bWait, bool i_bAllEvents, sal_uLong const nReleased)
 {
     ImplSVData* pSVData = ImplGetSVData();
 
-    //Process all Tasks
-    Scheduler::ProcessTaskScheduling(false);
+    if (nReleased == 0) // else thread doesn't have SolarMutex so avoid race
+    {   // Process all Tasks
+        Scheduler::ProcessTaskScheduling(false);
+    }
 
     pSVData->maAppData.mnDispatchLevel++;
     // do not wait for events if application was already quit; in that
     // case only dispatch events already available
     // do not wait for events either if the app decided that it is too busy for timers
     // (feature added for the slideshow)
-    pSVData->mpDefInst->Yield( i_bWait && !pSVData->maAppData.mbAppQuit && !pSVData->maAppData.mbNoYield, i_bAllEvents );
+    pSVData->mpDefInst->DoYield(
+        i_bWait && !pSVData->maAppData.mbAppQuit && !pSVData->maAppData.mbNoYield,
+        i_bAllEvents, nReleased);
     pSVData->maAppData.mnDispatchLevel--;
 
     DBG_TESTSOLARMUTEX(); // must be locked on return from Yield
@@ -374,12 +378,32 @@ inline void ImplYield( bool i_bWait, bool i_bAllEvents )
 
 void Application::Reschedule( bool i_bAllEvents )
 {
-    ImplYield( false, i_bAllEvents );
+    ImplYield(false, i_bAllEvents, 0);
 }
 
 void Application::Yield()
 {
-    ImplYield( true, false );
+    ImplYield(true, false, 0);
+}
+
+void Application::ReAcquireSolarMutex(sal_uLong const nReleased)
+{
+    // 0 would mean that events/timers will be handled without locking
+    // SolarMutex (racy)
+    assert(nReleased != 0);
+#ifdef WNT
+    if (ImplGetSVData()->mbDeInit) // do not Yield in DeInitVCL
+        AcquireSolarMutex(nReleased);
+    else
+        ImplYield(false, false, nReleased);
+#else
+    // a) Yield is not needed on non-WNT platforms
+    // b) some Yield implementations for X11 (e.g. kde4) make it non-obvious
+    //    how to use nReleased
+    // c) would require a review of what all Yield implementations do
+    //    currently _before_ releasing SolarMutex that would run without lock
+    AcquireSolarMutex(nReleased);
+#endif
 }
 
 IMPL_STATIC_LINK_NOARG( ImplSVAppData, ImplQuitMsg )
diff --git a/vcl/unx/generic/app/salinst.cxx b/vcl/unx/generic/app/salinst.cxx
index 47b6429..4b5f7e2 100644
--- a/vcl/unx/generic/app/salinst.cxx
+++ b/vcl/unx/generic/app/salinst.cxx
@@ -151,8 +151,10 @@ bool X11SalInstance::AnyInput(VclInputFlags nType)
     return bRet;
 }
 
-void X11SalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents )
+void X11SalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong const nReleased)
 {
+    (void) nReleased;
+    assert(nReleased == 0); // not implemented
     mpXLib->Yield( bWait, bHandleAllCurrentEvents );
 }
 
diff --git a/vcl/unx/gtk/app/gtkinst.cxx b/vcl/unx/gtk/app/gtkinst.cxx
index be1bfc2..d31563e 100644
--- a/vcl/unx/gtk/app/gtkinst.cxx
+++ b/vcl/unx/gtk/app/gtkinst.cxx
@@ -392,8 +392,10 @@ void GtkInstance::RemoveTimer (SalTimer *pTimer)
         m_aTimers.erase( it );
 }
 
-void GtkInstance::Yield( bool bWait, bool bHandleAllCurrentEvents )
+void GtkInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong const nReleased)
 {
+    (void) nReleased;
+    assert(nReleased == 0); // not implemented
     EnsureInit();
     GetGtkSalData()->Yield( bWait, bHandleAllCurrentEvents );
 }
diff --git a/vcl/win/source/app/salinst.cxx b/vcl/win/source/app/salinst.cxx
index eb39ad3..36b93ff 100644
--- a/vcl/win/source/app/salinst.cxx
+++ b/vcl/win/source/app/salinst.cxx
@@ -628,13 +628,17 @@ void ImplSalYield( bool bWait, bool bHandleAllCurrentEvents )
     }
 }
 
-void WinSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents )
+void WinSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong const nReleased)
 {
+    // NOTE: if nReleased != 0 this will be called without SolarMutex
+    //       so don't do anything dangerous before releasing it here
     SalYieldMutex*  pYieldMutex = mpSalYieldMutex;
     SalData*        pSalData = GetSalData();
     DWORD           nCurThreadId = GetCurrentThreadId();
-    sal_uLong           nCount = pYieldMutex->GetAcquireCount( nCurThreadId );
-    sal_uLong           n = nCount;
+    sal_uLong const nCount = (nReleased != 0)
+                                ? nReleased
+                                : pYieldMutex->GetAcquireCount(nCurThreadId);
+    sal_uLong       n = (nReleased != 0) ? 0 : nCount;
     while ( n )
     {
         pYieldMutex->release();


More information about the Libreoffice-commits mailing list