[Libreoffice-commits] core.git: Branch 'private/jmux/scheduler-fixes' - 7 commits - canvas/source include/osl include/sal include/tools sal/osl sal/util tools/source vcl/headless vcl/inc vcl/osx vcl/README.scheduler vcl/source

Jan-Marek Glogowski glogow at fbihome.de
Thu Aug 17 13:13:47 UTC 2017


Rebased ref, commits from common ancestor:
commit 4b9b72b7d36e54f44d42998ee39e3e0ddf5c587d
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Aug 15 22:16:49 2017 +0200

    Drop SystemTicks from scheduler logging
    
    If you want to see system ticks, add +SYSTEMTICKS to your SAL_LOG.
    
    Change-Id: I8d67fbc64873a800555866f34023ac83ddfb7f02

diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index 4187af3f3e8b..7bb2fbcce645 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -332,15 +332,14 @@ bool Scheduler::ProcessTaskScheduling()
     {
         const Timer *timer = dynamic_cast<Timer*>( pSchedulerData->mpTask );
         if ( timer )
-            SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
-                << pSchedulerData << " " << *pSchedulerData << " " << *timer );
+            SAL_INFO( "vcl.schedule", pSchedulerData << " "
+                << *pSchedulerData << " " << *timer );
         else if ( pSchedulerData->mpTask )
-            SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
-                << pSchedulerData << " " << *pSchedulerData
-                << " " << *pSchedulerData->mpTask );
+            SAL_INFO( "vcl.schedule", pSchedulerData << " "
+                << *pSchedulerData << " " << *pSchedulerData->mpTask );
         else
-            SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
-                << pSchedulerData << " " << *pSchedulerData << " (to be deleted)" );
+            SAL_INFO( "vcl.schedule", pSchedulerData << " "
+                << *pSchedulerData << " (to be deleted)" );
 
         // Should the Task be released from scheduling or stacked?
         if ( !pSchedulerData->mpTask || !pSchedulerData->mpTask->IsActive()
@@ -392,8 +391,8 @@ next_entry:
 
     if ( pMostUrgent )
     {
-        SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
-                  << pMostUrgent << "  invoke-in  " << *pMostUrgent->mpTask );
+        SAL_INFO( "vcl.schedule", pMostUrgent
+            << "  invoke-in  " << *pMostUrgent->mpTask );
 
         Task *pTask = pMostUrgent->mpTask;
 
@@ -421,8 +420,7 @@ next_entry:
         Lock( nLockCount );
         pMostUrgent->mbInScheduler = false;
 
-        SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
-                  << pMostUrgent << "  invoke-out" );
+        SAL_INFO( "vcl.schedule", pMostUrgent << "  invoke-out" );
 
         // eventually pop the scheduler stack
         // this just happens for nested calls, which renders all accounting
@@ -489,20 +487,20 @@ void Task::Start()
         mpSchedulerData = pSchedulerData;
 
         AppendSchedulerData( rSchedCtx, pSchedulerData );
-        SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks()
-                  << " " << mpSchedulerData << "  added      " << *this );
+        SAL_INFO( "vcl.schedule",
+                  mpSchedulerData << "  added      " << *this );
     }
     else
-        SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks()
-                  << " " << mpSchedulerData << "  restarted  " << *this );
+        SAL_INFO( "vcl.schedule",
+                  mpSchedulerData << "  restarted  " << *this );
 
-    mpSchedulerData->mnUpdateTime  = tools::Time::GetSystemTicks();
+    mpSchedulerData->mnUpdateTime = tools::Time::GetSystemTicks();
 }
 
 void Task::Stop()
 {
-    SAL_INFO_IF( mbActive, "vcl.schedule", tools::Time::GetSystemTicks()
-                  << " " << mpSchedulerData << "  stopped    " << *this );
+    SAL_INFO_IF( mbActive, "vcl.schedule",
+                 mpSchedulerData << "  stopped    " << *this );
     mbActive = false;
 }
 
commit 6869c63fe324f62e11efd2974e46ab899491e174
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Aug 15 22:35:49 2017 +0200

    Add +SYSTEMTICKS to log format
    
    Prefixes SAL_* output lines with tools::Time::GetSystemTicks().
    Now we can drop this information from the scheduler log output.
    
    Change-Id: I4840d0d56dbb5df55edf08fe664faf3a344196d0

diff --git a/include/sal/log.hxx b/include/sal/log.hxx
index c096d52a0e47..9b8e518db50a 100644
--- a/include/sal/log.hxx
+++ b/include/sal/log.hxx
@@ -235,7 +235,7 @@ inline char const * unwrapStream(SAL_UNUSED_PARAMETER StreamIgnore const &) {
       <switch> ::= <sense><item>
       <sense> ::= "+"|"-"
       <item> ::= <flag>|<level>("."<area>)?
-      <flag> ::= "TIMESTAMP"|"RELATIVETIMER"
+      <flag> ::= "TIMESTAMP"|"RELATIVETIMER"|"SYSTEMTICKS"
       <level> ::= "INFO"|"WARN"
     @endverbatim
 
@@ -245,14 +245,16 @@ inline char const * unwrapStream(SAL_UNUSED_PARAMETER StreamIgnore const &) {
     "+INFO+WARN" is used instead (which in turn results in everything
     being output).
 
-    The "+TIMESTAMP" flag causes each output line (as selected by the level
-    switch(es)) to be prefixed by a timestamp like 2016-08-18:14:04:43.
+    The "+TIMESTAMP" flag causes each SAL_* output line to be prefixed by
+    a timestamp like 2016-08-18:14:04:43.
 
-    The "+RELATIVETIMER" flag causes each output line (as selected by
-    the level switch(es)) to be prefixed by a relative timestamp in
-    seconds since the first output line like 1.312.
+    The "+RELATIVETIMER" flag causes each SAL_* output line to be prefixed by
+    a relative timestamp in seconds since the first output line like 1.312.
 
-    If both +TIMESTAMP and +RELATIVETIMER are specified, they are
+    The "+SYSTEMTICKS" flag causes each SAL_* output line to be prefixed by
+    the current value of tools::Time::GetSystemTicks().
+
+    If +TIMESTAMP, +RELATIVETIMER and +SYSTEMTICKS are specified, they are
     output in that order.
 
     Specifying a flag with a negative sense has no effect. Specifying
@@ -274,7 +276,7 @@ inline char const * unwrapStream(SAL_UNUSED_PARAMETER StreamIgnore const &) {
     SAL_INFO("other", ...) generate output, while calls like
     SAL_INFO("foo", ...) or SAL_INFO("foo.barzzz", ...) do not.
 
-    The generated log output consists of the optinal timestamp, the given level
+    The generated log output consists of the optional timestamp, the given level
     ("info" or "warn"), the given area, the process ID, the thread ID, the
     source file, and the source line number, each followed by a colon, followed
     by a space, the given message, and a newline.  The precise format of the log
diff --git a/sal/osl/all/log.cxx b/sal/osl/all/log.cxx
index 1f0138f1266d..ac095a348733 100644
--- a/sal/osl/all/log.cxx
+++ b/sal/osl/all/log.cxx
@@ -22,6 +22,8 @@
 #include <fstream>
 
 #include "osl/thread.hxx"
+#include "osl/mutex.hxx"
+#include "osl/time.h"
 #include "rtl/string.h"
 #include "sal/detail/log.h"
 #include "sal/log.hxx"
@@ -53,6 +55,22 @@ bool const sal_use_syslog = false;
 
 namespace {
 
+enum OutputItem
+{
+    EMPTY,
+    TIMESTAMP,
+    RELATIVETIMER,
+    SYSTEMTICKS,
+    LAST,
+    COUNT = LAST - 1,
+};
+
+bool bParsedLogEnvironment = false;
+osl::Mutex aParserMutex;
+OutputItem aOutputList[ OutputItem::COUNT ] = { OutputItem::EMPTY, };
+
+void parseLogEnvironment();
+
 bool equalStrings(
     char const * string1, std::size_t length1, char const * string2,
     std::size_t length2)
@@ -61,7 +79,8 @@ bool equalStrings(
 }
 
 #if !defined ANDROID
-char const * toString(sal_detail_LogLevel level) {
+char const * toString(sal_detail_LogLevel level)
+{
     switch (level) {
     case SAL_DETAIL_LOG_LEVEL_INFO:
         return "info";
@@ -81,13 +100,15 @@ char const * toString(sal_detail_LogLevel level) {
 // the process is running":
 #if defined ANDROID
 
-char const * getEnvironmentVariable() {
+char const * getEnvironmentVariable()
+{
     return std::getenv("SAL_LOG");
 }
 
 #else
 
-char const * getEnvironmentVariable_(const char* env) {
+char const * getEnvironmentVariable_(const char* env)
+{
     char const * p1 = std::getenv(env);
     if (p1 == nullptr) {
         return nullptr;
@@ -99,98 +120,150 @@ char const * getEnvironmentVariable_(const char* env) {
     return p2;
 }
 
-char const * getEnvironmentVariable() {
+char const * getEnvironmentVariable()
+{
     static char const * env = getEnvironmentVariable_("SAL_LOG");
     return env;
 }
 
-char const * getLogFile() {
+char const * getLogFile()
+{
     static char const * logFile = getEnvironmentVariable_("SAL_LOG_FILE");
     return logFile;
 }
 
-void maybeOutputTimestamp(std::ostringstream &s) {
+void maybeOutputTimestamp(std::ostringstream &s)
+{
+    assert( bParsedLogEnvironment );
+    for ( unsigned int i = 0;
+          i < OutputItem::COUNT && OutputItem::EMPTY != aOutputList[ i ];
+          ++i )
+    {
+        switch (aOutputList[ i ])
+        {
+        case OutputItem::TIMESTAMP:
+        {
+            char ts[100];
+            TimeValue systemTime;
+            osl_getSystemTime(&systemTime);
+            TimeValue localTime;
+            osl_getLocalTimeFromSystemTime(&systemTime, &localTime);
+            oslDateTime dateTime;
+            osl_getDateTimeFromTimeValue(&localTime, &dateTime);
+            struct tm tm;
+            tm.tm_sec = dateTime.Seconds;
+            tm.tm_min = dateTime.Minutes;
+            tm.tm_hour = dateTime.Hours;
+            tm.tm_mday = dateTime.Day;
+            tm.tm_mon = dateTime.Month - 1;
+            tm.tm_year = dateTime.Year - 1900;
+            strftime(ts, sizeof(ts), "%Y-%m-%d:%H:%M:%S", &tm);
+            char milliSecs[11];
+            sprintf(milliSecs, "%03u", static_cast<unsigned>(dateTime.NanoSeconds/1000000));
+            s << ts << '.' << milliSecs << ':';
+            break;
+        } // case OutputItem::TIMESTAMP
+
+        case OutputItem::RELATIVETIMER:
+        {
+            static bool beenHere = false;
+            static TimeValue first;
+            if (!beenHere) {
+                osl_getSystemTime(&first);
+                beenHere = true;
+            }
+            TimeValue now;
+            osl_getSystemTime(&now);
+            int seconds = now.Seconds - first.Seconds;
+            int milliSeconds;
+            if (now.Nanosec < first.Nanosec) {
+                seconds--;
+                milliSeconds = 1000-(first.Nanosec-now.Nanosec)/1000000;
+            }
+            else
+                milliSeconds = (now.Nanosec-first.Nanosec)/1000000;
+            char relativeTimestamp[100];
+            sprintf(relativeTimestamp, "%d.%03d", seconds, milliSeconds);
+            s << relativeTimestamp << ':';
+            break;
+        } // case OutputItem::RELATIVETIMER
+
+        case OutputItem::SYSTEMTICKS:
+            s << osl_getSystemTicks() << ':';
+            break;
+
+        default:
+            return;
+        }
+    }
+}
+
+#endif
+
+void parseLogEnvironment()
+{
+    if (bParsedLogEnvironment)
+        return;
+    osl::MutexGuard aGuard( aParserMutex );
+    if (bParsedLogEnvironment)
+        return;
+    bParsedLogEnvironment = true;
     char const * env = getEnvironmentVariable();
-    if (env == nullptr)
+    if (nullptr == env)
         return;
-    bool outputTimestamp = false;
-    bool outputRelativeTimer = false;
-    for (char const * p = env;;) {
-        switch (*p++) {
+    unsigned int nOutputItem = 0;
+    bool aOutputSeenList[ OutputItem::LAST ] = { false, };
+    for (char const * p = env;;)
+    {
+        switch (*p++)
+        {
         case '\0':
-            if (outputTimestamp) {
-                char ts[100];
-                TimeValue systemTime;
-                osl_getSystemTime(&systemTime);
-                TimeValue localTime;
-                osl_getLocalTimeFromSystemTime(&systemTime, &localTime);
-                oslDateTime dateTime;
-                osl_getDateTimeFromTimeValue(&localTime, &dateTime);
-                struct tm tm;
-                tm.tm_sec = dateTime.Seconds;
-                tm.tm_min = dateTime.Minutes;
-                tm.tm_hour = dateTime.Hours;
-                tm.tm_mday = dateTime.Day;
-                tm.tm_mon = dateTime.Month - 1;
-                tm.tm_year = dateTime.Year - 1900;
-                strftime(ts, sizeof(ts), "%Y-%m-%d:%H:%M:%S", &tm);
-                char milliSecs[11];
-                sprintf(milliSecs, "%03u", static_cast<unsigned>(dateTime.NanoSeconds/1000000));
-                s << ts << '.' << milliSecs << ':';
-            }
-            if (outputRelativeTimer) {
-                static bool beenHere = false;
-                static TimeValue first;
-                if (!beenHere) {
-                    osl_getSystemTime(&first);
-                    beenHere = true;
-                }
-                TimeValue now;
-                osl_getSystemTime(&now);
-                int seconds = now.Seconds - first.Seconds;
-                int milliSeconds;
-                if (now.Nanosec < first.Nanosec) {
-                    seconds--;
-                    milliSeconds = 1000-(first.Nanosec-now.Nanosec)/1000000;
-                }
-                else
-                    milliSeconds = (now.Nanosec-first.Nanosec)/1000000;
-                char relativeTimestamp[100];
-                sprintf(relativeTimestamp, "%d.%03d", seconds, milliSeconds);
-                s << relativeTimestamp << ':';
-            }
             return;
         case '+':
+        {
+            char const * p1 = p;
+            while (*p1 != '.' && *p1 != '+' && *p1 != '-' && *p1 != '\0') {
+                ++p1;
+            }
+            if (!aOutputSeenList[ OutputItem::TIMESTAMP ]
+                && equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("TIMESTAMP")))
             {
-                char const * p1 = p;
-                while (*p1 != '.' && *p1 != '+' && *p1 != '-' && *p1 != '\0') {
-                    ++p1;
-                }
-                if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("TIMESTAMP")))
-                    outputTimestamp = true;
-                else if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("RELATIVETIMER")))
-                    outputRelativeTimer = true;
-                char const * p2 = p1;
-                while (*p2 != '+' && *p2 != '-' && *p2 != '\0') {
-                    ++p2;
-                }
-                p = p2;
+                aOutputSeenList[ OutputItem::TIMESTAMP ] = true;
+                aOutputList[ nOutputItem++ ] = OutputItem::TIMESTAMP;
             }
+            else if (!aOutputSeenList[ OutputItem::RELATIVETIMER ]
+                && equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("RELATIVETIMER")))
+            {
+                aOutputSeenList[ OutputItem::RELATIVETIMER ] = true;
+                aOutputList[ nOutputItem++ ] = OutputItem::RELATIVETIMER;
+            }
+            else if (!aOutputSeenList[ OutputItem::SYSTEMTICKS ]
+                && equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("SYSTEMTICKS")))
+            {
+                aOutputSeenList[ OutputItem::SYSTEMTICKS ] = true;
+                aOutputList[ nOutputItem++ ] = OutputItem::SYSTEMTICKS;
+            }
+            char const * p2 = p1;
+            while (*p2 != '+' && *p2 != '-' && *p2 != '\0') {
+                ++p2;
+            }
+            p = p2;
             break;
+        } // case '+'
+
         default:
-            ; // nothing
+            break; // nothing
         }
     }
 }
 
-#endif
-
-}
+} // anonymous namespace
 
 void sal_detail_log(
     sal_detail_LogLevel level, char const * area, char const * where,
     char const * message, sal_uInt32 backtraceDepth)
 {
+    parseLogEnvironment();
     std::ostringstream s;
 #if !defined ANDROID
     // On Android, the area will be used as the "tag," and log info already
commit 75e2e892cae586eeb47d7cf161fc9d3a561f266d
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Aug 15 23:22:36 2017 +0200

    Move tools::time::getSystemTicks() into osl
    
    Moves the code into osl_getSystemTicks and marks the original
    funtion as deprecated. Also merges a duplicate W32 implementation.
    
    Change-Id: I5c9263540b8af55b2eeca6126e288129427f6e8e

diff --git a/canvas/source/tools/elapsedtime.cxx b/canvas/source/tools/elapsedtime.cxx
index e82df7dbe3fb..fc5d7f9967d9 100644
--- a/canvas/source/tools/elapsedtime.cxx
+++ b/canvas/source/tools/elapsedtime.cxx
@@ -48,57 +48,6 @@
 namespace canvas {
 namespace tools {
 
-
-#if defined(_WIN32)
-// TODO(Q2): is 0 okay for the failure case here?
-double ElapsedTime::getSystemTime()
-{
-    // TEMP!!!
-    // Awaiting corresponding functionality in OSL
-
-
-    // is there a performance counter available?
-    static bool bTimeSetupDone( false );
-    static bool bPerfTimerAvailable( false );
-    static LONGLONG nPerfCountFreq;
-
-    // TODO(F1): This _might_ cause problems, as it prevents correct
-    // time handling for very long lifetimes of this class's
-    // surrounding component in memory. When the difference between
-    // current sys time and nInitialCount exceeds IEEE double's
-    // mantissa, time will start to run jerky.
-    static LONGLONG nInitialCount;
-
-    if( !bTimeSetupDone )
-    {
-        if( QueryPerformanceFrequency(
-                reinterpret_cast<LARGE_INTEGER *>(&nPerfCountFreq) ) )
-        {
-            // read initial time:
-            QueryPerformanceCounter(
-                reinterpret_cast<LARGE_INTEGER *>(&nInitialCount) );
-            bPerfTimerAvailable = true;
-        }
-        bTimeSetupDone = true;
-    }
-
-    if( bPerfTimerAvailable )
-    {
-        LONGLONG nCurrCount;
-        QueryPerformanceCounter(
-            reinterpret_cast<LARGE_INTEGER *>(&nCurrCount) );
-        nCurrCount -= nInitialCount;
-        return double(nCurrCount) / nPerfCountFreq;
-    }
-    else
-    {
-        LONGLONG nCurrTime = timeGetTime();
-        return double(nCurrTime) / 1000.0;
-    }
-}
-
-#else // ! WNT
-
 // TODO(Q2): is 0 okay for the failure case here?
 double ElapsedTime::getSystemTime()
 {
@@ -109,8 +58,6 @@ double ElapsedTime::getSystemTime()
         return 0.0;
 }
 
-#endif
-
 ElapsedTime::ElapsedTime()
     : m_pTimeBase(),
       m_fLastQueriedTime( 0.0 ),
diff --git a/include/osl/time.h b/include/osl/time.h
index 4843a9d02e25..b263ea1735d8 100644
--- a/include/osl/time.h
+++ b/include/osl/time.h
@@ -167,11 +167,16 @@ SAL_DLLPUBLIC sal_Bool SAL_CALL osl_getSystemTimeFromLocalTime(
 
 
 /** Get the value of the global timer
-    @return current timer value in milli seconds
+    @return current timer value in milliseconds
  */
-
 SAL_DLLPUBLIC sal_uInt32 SAL_CALL osl_getGlobalTimer(void);
 
+
+/** Get the elapsed time since epoch in milliseconds
+    @return current system ticks
+ */
+SAL_DLLPUBLIC sal_uInt64 SAL_CALL osl_getSystemTicks(void);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/tools/time.hxx b/include/tools/time.hxx
index d8b4e6d06fc6..77d2d12dbea4 100644
--- a/include/tools/time.hxx
+++ b/include/tools/time.hxx
@@ -121,7 +121,9 @@ public:
 
     static Time     GetUTCOffset();
 
-    /// Elapsed time since epoch in milliseconds
+    /** Elapsed time since epoch in milliseconds
+     * @deprecated use osl_getSystemTicks
+     */
     static sal_uInt64 GetSystemTicks();
 
     tools::Time&           operator =( const tools::Time& rTime );
diff --git a/sal/osl/unx/time.cxx b/sal/osl/unx/time.cxx
index 61d452434d64..ca567ed3f0a5 100644
--- a/sal/osl/unx/time.cxx
+++ b/sal/osl/unx/time.cxx
@@ -308,4 +308,16 @@ sal_uInt32 SAL_CALL osl_getGlobalTimer()
     return nSeconds;
 }
 
+sal_uInt64 SAL_CALL osl_getSystemTicks()
+{
+    timeval tv;
+    int n = gettimeofday (&tv, nullptr);
+    if (n == -1) {
+        fprintf(stderr, "gettimeofday failed: %i\n", errno);
+        abort();
+    }
+    return static_cast<sal_uInt64>(tv.tv_sec) * 1000
+         + static_cast<sal_uInt64>(tv.tv_usec) / 1000;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/osl/w32/time.cxx b/sal/osl/w32/time.cxx
index 1a6e6ceaa181..d1f1961b3ac6 100644
--- a/sal/osl/w32/time.cxx
+++ b/sal/osl/w32/time.cxx
@@ -200,4 +200,30 @@ sal_uInt32 SAL_CALL osl_getGlobalTimer(void)
   return ( nSeconds * 1000 ) + (long)( currentTime.millitm - startTime.millitm );
 }
 
+sal_uInt64 SAL_CALL osl_getSystemTicks(void)
+{
+    static LARGE_INTEGER nTicksPerSecond = 0;
+    static bool bTicksPerSecondInitialized = false;
+
+    if (!bTicksPerSecondInitialized)
+    {
+        bTicksPerSecondInitialized = true;
+        if (!QueryPerformanceFrequency(&nTicksPerSecond))
+            nTicksPerSecond = 0;
+    }
+
+    if (nTicksPerSecond > 0)
+    {
+        LARGE_INTEGER nPerformanceCount;
+        QueryPerformanceCounter(&nPerformanceCount);
+        return static_cast<sal_uInt64>(
+            (nPerformanceCount.QuadPart*1000)/nTicksPerSecond.QuadPart);
+    }
+    else
+    {
+        LONGLONG nCurrTime = timeGetTime();
+        return double(nCurrTime) / 1000.0;
+    }
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/util/sal.map b/sal/util/sal.map
index 1a5e2c2f9401..057d95d1fd50 100644
--- a/sal/util/sal.map
+++ b/sal/util/sal.map
@@ -710,6 +710,7 @@ LIBO_UDK_5.3 { # symbols available in >= LibO 5.3
 LIBO_UDK_6_0 { # symbols available in >= LibO 6.0
     global:
         osl_getThreadSystemID;
+        osl_getSystemTicks;
 } LIBO_UDK_5.3;
 
 PRIVATE_1.0 {
diff --git a/tools/source/datetime/ttime.cxx b/tools/source/datetime/ttime.cxx
index 83812f72171a..32ec7a150cf4 100644
--- a/tools/source/datetime/ttime.cxx
+++ b/tools/source/datetime/ttime.cxx
@@ -39,6 +39,7 @@
 #include <sal/log.hxx>
 #include <tools/time.hxx>
 #include <osl/diagnose.h>
+#include <osl/time.h>
 
 #if defined(__sun) && defined(__GNUC__)
 extern long altzone;
@@ -411,30 +412,7 @@ Time tools::Time::GetUTCOffset()
 
 sal_uInt64 tools::Time::GetSystemTicks()
 {
-#if defined(_WIN32)
-    static LARGE_INTEGER nTicksPerSecond;
-    static bool bTicksPerSecondInitialized = false;
-    if (!bTicksPerSecondInitialized)
-    {
-        QueryPerformanceFrequency(&nTicksPerSecond);
-        bTicksPerSecondInitialized = true;
-    }
-
-    LARGE_INTEGER nPerformanceCount;
-    QueryPerformanceCounter(&nPerformanceCount);
-
-    return static_cast<sal_uInt64>(
-        (nPerformanceCount.QuadPart*1000)/nTicksPerSecond.QuadPart);
-#else
-    timeval tv;
-    int n = gettimeofday (&tv, nullptr);
-    if (n == -1) {
-        int e = errno;
-        SAL_WARN("tools.datetime", "gettimeofday failed: " << e);
-    }
-    return static_cast<sal_uInt64>(tv.tv_sec) * 1000
-        + static_cast<sal_uInt64>(tv.tv_usec) / 1000;
-#endif
+    return osl_getSystemTicks();
 }
 
 } /* namespace tools */
commit 3cff9cedd0d2d4557efff6eb55f3b5b35bdc9135
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Aug 15 09:03:49 2017 +0200

    Abort on critical Scheduler problems
    
    There is not much sense in trying to continue without the main
    lock. An other aspect are tasks with uncaught exceptions, which
    must not happen. In both cases simply abort.
    
    Change-Id: I4d52a6ef0526a1e46b64f9f3a6e0cc1a718618cc

diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index 50a45006ced1..4187af3f3e8b 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -28,6 +28,7 @@
 #include <saltimer.hxx>
 #include <salinst.hxx>
 #include <comphelper/profilezone.hxx>
+#include <tools/diagnose_ex.h>
 #include <schedulerimpl.hxx>
 
 namespace {
@@ -155,20 +156,22 @@ void Scheduler::ImplDeInitScheduler()
 
 void SchedulerMutex::acquire( sal_uInt32 nLockCount )
 {
+    assert(nLockCount > 0);
     for (sal_uInt32 i = 0; i != nLockCount; ++i) {
-        bool ok = maMutex.acquire();
-        assert(ok); (void) ok;
-        ++mnLockDepth;
+        if (!maMutex.acquire())
+            abort();
     }
+    mnLockDepth += nLockCount;
 }
 
 sal_uInt32 SchedulerMutex::release( bool bUnlockAll )
 {
-    assert(mnLockDepth != 0);
+    assert(mnLockDepth > 0);
     sal_uInt32 nLockCount = bUnlockAll ? mnLockDepth : 1;
     mnLockDepth -= nLockCount;
     for (sal_uInt32 i = 0; i != nLockCount; ++i) {
-        maMutex.release();
+        if (!maMutex.release())
+            abort();
     }
     return nLockCount;
 }
@@ -404,7 +407,17 @@ next_entry:
         // not run a nested Scheduler loop and don't need a stack push!
         pMostUrgent->mbInScheduler = true;
         sal_uInt32 nLockCount = Unlock( true );
-        pTask->Invoke();
+        try
+        {
+            pTask->Invoke();
+        }
+        catch (...)
+        {
+            SAL_WARN( "vcl.schedule",
+                      "Uncaught exception during Task::Invoke()!" );
+            DBG_UNHANDLED_EXCEPTION();
+            abort();
+        }
         Lock( nLockCount );
         pMostUrgent->mbInScheduler = false;
 
commit 66f8f77a23435ea8a3ebc685a4d0b59703f1306c
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Aug 15 09:02:16 2017 +0200

    SVP always drain the wakeup pipe
    
    Even when we have a lot of idle events, the pipe gets filled,
    so just drain it on every run.
    
    Change-Id: I7b6366b2649133b63138dc77fe51508404132890

diff --git a/vcl/headless/svpinst.cxx b/vcl/headless/svpinst.cxx
index 4b76f0c3fbec..4ebeac8f4a3c 100644
--- a/vcl/headless/svpinst.cxx
+++ b/vcl/headless/svpinst.cxx
@@ -370,6 +370,12 @@ bool SvpSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong
 
         DoReleaseYield(nTimeoutMS);
     }
+    else if ( bEvent )
+    {
+        // Drain the wakeup pipe
+        int buffer;
+        while (read (m_pTimeoutFDS[0], &buffer, sizeof(buffer)) > 0);
+    }
 
     return bEvent;
 }
@@ -394,8 +400,7 @@ void SvpSalInstance::DoReleaseYield( int nTimeoutMS )
     if( (aPoll.revents & POLLIN) != 0 )
     {
         int buffer;
-        while (read (m_pTimeoutFDS[0], &buffer, sizeof(buffer)) > 0)
-            continue;
+        while (read (m_pTimeoutFDS[0], &buffer, sizeof(buffer)) > 0);
     }
 }
 
commit 5c8c8e677326bf4503e718a49e37cd6b6de4695b
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Aug 15 09:19:37 2017 +0200

    tdf#99784 update Scheduler documentation
    
    Reflect special handling in the OSX backend.
    
    Change-Id: I6493ba6b6cf1c69f9fafc7ab583c430d72f73247

diff --git a/vcl/README.scheduler b/vcl/README.scheduler
index 1f2d617734a0..80435c3a2468 100644
--- a/vcl/README.scheduler
+++ b/vcl/README.scheduler
@@ -91,13 +91,26 @@ can be added to the scheduler reasonably.
 
 == MacOS implementation details ==
 
-Generally the Scheduler is handled as expected. There is a workaround for a
-problem for pushing tasks to an empty queue, as [NSApp postEvent: ...
-atStart: NO] doesn't append the event, if the message queue is empty.
+Generally the Scheduler is handled as expected, except on resize, which is
+handled with different runloop-modes in MacOS.
+In case of a resize, the normal runloop is suspended in sendEvent, so we
+can't call the scheduler via posted main loop-events.
+
+Like the Windows backend, all Cocoa / GUI handling also has to be done in
+the main thread. But unless Windows out-of-order PeekMessage processing,
+via MsgWaitForMultipleObjects, we have to rely on a wakeup message, if
+the SolarMutex is unlocked.
+
+There is also a workaround for a problem for pushing tasks to an empty queue,
+as [NSApp postEvent: ... atStart: NO] doesn't append the event, if the
+message queue is empty.
 
 Probably that's the reason, why some code comments spoke of lost events and
 there was some distinct additional event processing implemented.
 
+OTOH we can use a closure like feature to execute the GUI code block in the
+main thread, without much hazzle.
+
 == Windows implementation details ==
 
 Posted or sent event messages often trigger processing of WndProc in
@@ -154,3 +167,8 @@ easy way to process just a single event).
 Since the Scheduler is always handled by the system message queue, there is
 really no more reasoning to stop after 100 events to prevent LO Scheduler
 starvation.
+
+== Run the LO application in it's own thread ==
+
+Thi swould probably get rid of most of the MacOS and Windows implementation
+details / workarounds. But this seems to be even more work to do.
commit ac2dbe7b4c4eb85c1229aa84324d7140bcfb7f56
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Aug 15 08:23:31 2017 +0200

    tdf#99784 OSX fix painting on resize
    
    While resizing MacOS suspends the NSDefaultRunLoopMode. So in this
    caae we can't post to the system event loop, but must use timers
    to restart ourself.
    
    Since the timer itself is scheduled on the NSEventTrackingRunLoopMode
    it' also triggers on resize events.
    
    There is still some minor glitch: when resizing too fast some part
    of LibreOffice isn't painted, while the left mouse button is down.
    
    Since there isn't any layouting triggered by the mouse up, there has
    to be an other inconsistency.
    
    Change-Id: I3ccba78bd23ec8526f21e7b93b027f3d3279f901

diff --git a/vcl/inc/osx/salinst.h b/vcl/inc/osx/salinst.h
index 48f029e5d06d..c9b10143e00c 100644
--- a/vcl/inc/osx/salinst.h
+++ b/vcl/inc/osx/salinst.h
@@ -79,6 +79,7 @@ public:
     osl::Condition                          maWaitingYieldCond;
     bool                                    mbNoNotificationLock;
     bool                                    mbTryToAcquireYield;
+    bool                                    mbIsLiveResize;
 
     static std::list<const ApplicationEvent*> aAppEventList;
 
diff --git a/vcl/osx/salframeview.mm b/vcl/osx/salframeview.mm
index fb78b39b1833..99b48b2ee439 100644
--- a/vcl/osx/salframeview.mm
+++ b/vcl/osx/salframeview.mm
@@ -541,6 +541,17 @@ private:
 
 -(void)drawRect: (NSRect)aRect
 {
+    if( GetSalData()->mpFirstInstance )
+    {
+        const bool bIsLiveResize = [self inLiveResize];
+        const bool bWasLiveResize = GetSalData()->mpFirstInstance->mbIsLiveResize;
+        if ( bWasLiveResize != bIsLiveResize )
+        {
+            GetSalData()->mpFirstInstance->mbIsLiveResize = bIsLiveResize;
+            Scheduler::ProcessTaskScheduling();
+        }
+    }
+
     // HOTFIX: #i93512# prevent deadlocks if any other thread already has the SalYieldMutex
     TryGuard aTryGuard;
     if( !aTryGuard.IsGuarded() )
diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx
index cead8a362c1c..9ca0bae28c29 100644
--- a/vcl/osx/salinst.cxx
+++ b/vcl/osx/salinst.cxx
@@ -351,6 +351,7 @@ AquaSalInstance::AquaSalInstance()
  , maWaitingYieldCond()
  , mbNoNotificationLock( false )
  , mbTryToAcquireYield( false )
+ , mbIsLiveResize( false )
 {
     mpSalYieldMutex = new SalYieldMutex;
     mpSalYieldMutex->acquire();
diff --git a/vcl/osx/salnstimer.mm b/vcl/osx/salnstimer.mm
index c9867cf7a79e..c9b657dcd776 100644
--- a/vcl/osx/salnstimer.mm
+++ b/vcl/osx/salnstimer.mm
@@ -30,7 +30,13 @@
 -(void)timerElapsed:(NSTimer*)pTimer
 {
     (void)pTimer;
-    ImplNSAppPostEvent( AquaSalInstance::DispatchTimerEvent, YES );
+    // nil the timer, as it is just invalidated after the firing function
+    AquaSalTimer::pRunningTimer = nil;
+    const AquaSalInstance *pInst = GetSalData()->mpFirstInstance;
+    if (pInst->mbIsLiveResize)
+        AquaSalTimer::handleDispatchTimerEvent();
+    else
+        ImplNSAppPostEvent( AquaSalInstance::DispatchTimerEvent, YES );
 }
 
 @end
diff --git a/vcl/osx/saltimer.cxx b/vcl/osx/saltimer.cxx
index 62814759ae1a..23aa0f583707 100644
--- a/vcl/osx/saltimer.cxx
+++ b/vcl/osx/saltimer.cxx
@@ -83,7 +83,7 @@ static void ImplSalStartTimer( sal_uLong nMS )
         return;
     }
 
-    if ( 0 == nMS )
+    if ( 0 == nMS && !pSalData->mpFirstInstance->mbIsLiveResize )
     {
         ImplSalStopTimer();
         ImplNSAppPostEvent( AquaSalInstance::DispatchTimerEvent, NO );
@@ -93,7 +93,7 @@ static void ImplSalStartTimer( sal_uLong nMS )
         NSTimeInterval aTI = double(nMS) / 1000.0;
         if( AquaSalTimer::pRunningTimer != nil )
         {
-            if (rtl::math::approxEqual(
+            if ([AquaSalTimer::pRunningTimer isValid] && rtl::math::approxEqual(
                     [AquaSalTimer::pRunningTimer timeInterval], aTI))
             {
                 // set new fire date


More information about the Libreoffice-commits mailing list