[x265] [PATCH] restore WINXP_SUPPORT build option, workaround for CONDITION_VARIABLE on XP

Steve Borho steve at borho.org
Sat Mar 29 22:06:45 CET 2014


# HG changeset patch
# User Steve Borho <steve at borho.org>
# Date 1396123561 18000
#      Sat Mar 29 15:06:01 2014 -0500
# Node ID 5919c3815cf65970e3d2ef8184875954ff888138
# Parent  9b378e860ddbba528625d56da8915ac05247bffa
restore WINXP_SUPPORT build option, workaround for CONDITION_VARIABLE on XP

This adapts x264's code for an XP-safe pthread_cond_t to make an XP-safe
CONDITION_VARIABLE (which was introduced in Windows Vista)

x265 will use native CONDITION_VARIABLE unless the WINXP_SUPPORT cmake option is
enabled. It forces _WIN32_WINNT=_WIN32_WINNT_VISTA for MinGW for this purpose.

diff -r 9b378e860ddb -r 5919c3815cf6 source/CMakeLists.txt
--- a/source/CMakeLists.txt	Thu Mar 27 18:14:55 2014 -0700
+++ b/source/CMakeLists.txt	Sat Mar 29 15:06:01 2014 -0500
@@ -191,10 +191,16 @@
         set(PLATFORM_LIBS ${PLATFORM_LIBS} ${VLD_LIBRARIES})
         link_directories(${VLD_LIBRARY_DIRS})
     endif()
-    if(MINGW)
-        # MinGW requires a forced Windows version in order to use CONDITION_VARIABLE
+    option(WINXP_SUPPORT "Make binaries compatible with Windows XP" OFF)
+    if(WINXP_SUPPORT)
+        # force use of workarounds for CONDITION_VARIABLE and atomic
+        # intrinsics introduced after XP
+        add_definitions(-D_WIN32_WINNT=_WIN32_WINNT_WINXP)
+    elseif(MINGW)
+        # Unless the user requires XP support, allow MinGW builds to use
+        # native condition variables introduced in Vista
         add_definitions(-D_WIN32_WINNT=_WIN32_WINNT_VISTA)
-    endif(MINGW)
+    endif()
 endif()
 
 include(version) # determine X265_VERSION and X265_LATEST_TAG
diff -r 9b378e860ddb -r 5919c3815cf6 source/common/CMakeLists.txt
--- a/source/common/CMakeLists.txt	Thu Mar 27 18:14:55 2014 -0700
+++ b/source/common/CMakeLists.txt	Sat Mar 29 15:06:01 2014 -0500
@@ -145,6 +145,7 @@
     pixel.cpp dct.cpp ipfilter.cpp intrapred.cpp
     cpu.cpp cpu.h version.cpp
     threading.cpp threading.h
+    winxp.h winxp.cpp
     threadpool.cpp threadpool.h
     wavefront.h wavefront.cpp
     md5.cpp md5.h
diff -r 9b378e860ddb -r 5919c3815cf6 source/common/threading.h
--- a/source/common/threading.h	Thu Mar 27 18:14:55 2014 -0700
+++ b/source/common/threading.h	Sat Mar 29 15:06:01 2014 -0500
@@ -31,6 +31,7 @@
 
 #ifdef _WIN32
 #include <windows.h>
+#include "winxp.h"  // XP workarounds for CONDITION_VARIABLE and ATOMIC_OR
 #else
 #include <pthread.h>
 #include <semaphore.h>
@@ -98,29 +99,9 @@
 
 #endif // if !_WIN64
 
-#if _WIN32_WINNT <= _WIN32_WINNT_WINXP
-/* Windows XP did not define this intrinsic */
-FORCEINLINE LONGLONG x265_interlocked_OR64(__inout LONGLONG volatile *Destination,
-                                           __in    LONGLONG           Value)
-{
-    LONGLONG Old;
-
-    do
-    {
-        Old = *Destination;
-    }
-    while (_InterlockedCompareExchange64(Destination, Old | Value, Old) != Old);
-
-    return Old;
-}
-
-#define ATOMIC_OR(ptr, mask)            x265_interlocked_OR64((volatile LONG64*)ptr, mask)
-#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
-#pragma intrinsic(_InterlockedCompareExchange64)
+#ifndef ATOMIC_OR
+#define ATOMIC_OR(ptr, mask)                InterlockedOr64((volatile LONG64*)ptr, mask)
 #endif
-#else // if _WIN32_WINNT <= _WIN32_WINNT_WINXP
-#define ATOMIC_OR(ptr, mask)            InterlockedOr64((volatile LONG64*)ptr, mask)
-#endif // if _WIN32_WINNT <= _WIN32_WINNT_WINXP
 
 #define CLZ32(id, x)                        _BitScanReverse(&id, x)
 #define CTZ64(id, x)                        _BitScanForward64(&id, x)
@@ -223,6 +204,7 @@
     ~ThreadSafeInteger()
     {
         DeleteCriticalSection(&m_cs);
+        XP_CONDITION_VAR_FREE(&m_cv);
     }
 
     int waitForChange(int prev)
diff -r 9b378e860ddb -r 5919c3815cf6 source/common/winxp.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/common/winxp.cpp	Sat Mar 29 15:06:01 2014 -0500
@@ -0,0 +1,130 @@
+/*****************************************************************************
+ * Copyright (C) 2013 x265 project
+ *
+ * Authors: Steve Borho <steve at borho.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
+ *
+ * This program is also available under a commercial proprietary license.
+ * For more information, contact us at licensing at multicorewareinc.com
+ *****************************************************************************/
+
+#include "threading.h"
+#include "winxp.h"
+#include <windows.h>
+
+namespace x265
+{
+/* Mmimic CONDITION_VARIABLE functions only supported on Vista+ */
+
+#if _WIN32_WINNT <= _WIN32_WINNT_WINXP
+
+int WINAPI cond_init(ConditionVariable *cond)
+{ // InitializeConditionVariable
+    cond->semaphore = CreateSemaphore(NULL, 0, 0x7fffffff, NULL);
+    if (!cond->semaphore)
+        return -1;
+    cond->waitersDone = CreateEvent(NULL, FALSE, FALSE, NULL);
+    if (!cond->waitersDone)
+        return -1;
+
+    InitializeCriticalSection(&cond->waiterCountMutex);
+    InitializeCriticalSection(&cond->broadcastMutex);
+    cond->waiterCount = 0;
+    cond->bIsBroadcast = false;
+
+    return 0;
+}
+
+void WINAPI cond_broadcast(ConditionVariable *cond)
+{ // WakeAllConditionVariable
+    EnterCriticalSection(&cond->broadcastMutex);
+    EnterCriticalSection(&cond->waiterCountMutex);
+    int haveWaiter = 0;
+
+    if (cond->waiterCount)
+    {
+        cond->bIsBroadcast = 1;
+        haveWaiter = 1;
+    }
+
+    if (haveWaiter)
+    {
+        ReleaseSemaphore(cond->semaphore, cond->waiterCount, NULL);
+        LeaveCriticalSection(&cond->waiterCountMutex);
+        WaitForSingleObject(cond->waitersDone, INFINITE);
+        cond->bIsBroadcast = 0;
+    }
+    else
+        LeaveCriticalSection(&cond->waiterCountMutex);
+
+    LeaveCriticalSection(&cond->broadcastMutex);
+}
+
+void WINAPI cond_signal(ConditionVariable *cond)
+{ // WakeConditionVariable
+    EnterCriticalSection(&cond->broadcastMutex);
+    EnterCriticalSection(&cond->waiterCountMutex);
+    int haveWaiter = cond->waiterCount;
+    LeaveCriticalSection(&cond->waiterCountMutex);
+
+    if (haveWaiter)
+    {
+        ReleaseSemaphore(cond->semaphore, 1, NULL);
+        WaitForSingleObject(cond->waitersDone, INFINITE);
+    }
+
+    LeaveCriticalSection(&cond->broadcastMutex);
+}
+
+BOOL WINAPI cond_wait(ConditionVariable *cond, CRITICAL_SECTION *mutex, DWORD wait)
+{ // SleepConditionVariableCS
+    EnterCriticalSection(&cond->broadcastMutex);
+    EnterCriticalSection(&cond->waiterCountMutex);
+    cond->waiterCount++;
+    LeaveCriticalSection(&cond->waiterCountMutex);
+    LeaveCriticalSection(&cond->broadcastMutex);
+
+    // unlock the external mutex
+    LeaveCriticalSection(mutex);
+    BOOL ret = WaitForSingleObject(cond->semaphore, wait);
+
+    EnterCriticalSection(&cond->waiterCountMutex);
+    cond->waiterCount--;
+    int last_waiter = !cond->waiterCount || !cond->bIsBroadcast;
+    LeaveCriticalSection(&cond->waiterCountMutex);
+
+    if (last_waiter)
+        SetEvent(cond->waitersDone);
+
+    // lock the external mutex
+    EnterCriticalSection(mutex);
+
+    // returns false on timeout or error
+    return ret;
+}
+
+/* Native CONDITION_VARIABLE instances are not freed, so this is a special case */
+void cond_destroy(ConditionVariable *cond)
+{
+    CloseHandle(cond->semaphore);
+    CloseHandle(cond->waitersDone);
+    DeleteCriticalSection(&cond->broadcastMutex);
+    DeleteCriticalSection(&cond->waiterCountMutex);
+}
+
+#endif // _WIN32_WINNT <= _WIN32_WINNT_WINXP
+
+}
\ No newline at end of file
diff -r 9b378e860ddb -r 5919c3815cf6 source/common/winxp.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/common/winxp.h	Sat Mar 29 15:06:01 2014 -0500
@@ -0,0 +1,90 @@
+/*****************************************************************************
+ * Copyright (C) 2013 x265 project
+ *
+ * Authors: Steve Borho <steve at borho.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
+ *
+ * This program is also available under a commercial proprietary license.
+ * For more information, contact us at licensing at multicorewareinc.com
+ *****************************************************************************/
+
+#ifndef X265_WINXP_H
+#define X265_WINXP_H
+
+#if _WIN32_WINNT <= _WIN32_WINNT_WINXP
+
+#include <windows.h>
+
+namespace x265
+{
+
+/* non-native condition variable */
+typedef struct
+{
+    CRITICAL_SECTION broadcastMutex;
+    CRITICAL_SECTION waiterCountMutex;
+    HANDLE semaphore;
+    HANDLE waitersDone;
+    volatile int waiterCount;
+    volatile int bIsBroadcast;
+} ConditionVariable;
+
+int WINAPI cond_init(ConditionVariable *cond);
+void WINAPI cond_broadcast(ConditionVariable *cond);
+void WINAPI cond_signal(ConditionVariable *cond);
+BOOL WINAPI cond_wait(ConditionVariable *cond, CRITICAL_SECTION *mutex, DWORD wait);
+void cond_destroy(ConditionVariable *cond);
+
+/* map missing API symbols to our structure and functions */
+#define CONDITION_VARIABLE          x265::ConditionVariable
+#define InitializeConditionVariable x265::cond_init
+#define SleepConditionVariableCS    x265::cond_wait
+#define WakeConditionVariable       x265::cond_signal
+#define WakeAllConditionVariable    x265::cond_broadcast
+#define XP_CONDITION_VAR_FREE       x265::cond_destroy
+
+#if defined(_MSC_VER)
+/* Windows XP did not define atomic OR 64, but gcc has a good version, so
+ * only use this workaround when targeting XP with MSVC */
+FORCEINLINE LONGLONG interlocked_OR64(__inout LONGLONG volatile *Destination,
+                                      __in    LONGLONG           Value)
+{
+    LONGLONG Old;
+
+    do
+    {
+        Old = *Destination;
+    }
+    while (_InterlockedCompareExchange64(Destination, Old | Value, Old) != Old);
+
+    return Old;
+}
+#define ATOMIC_OR(ptr, mask) x265::interlocked_OR64((volatile LONG64*)ptr, mask)
+
+#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
+#pragma intrinsic(_InterlockedCompareExchange64)
+#endif
+#endif // defined(_MSC_VER)
+
+} // namespace x265
+
+#else
+
+#define XP_CONDITION_VAR_FREE(x)
+
+#endif // _WIN32_WINNT <= _WIN32_WINNT_WINXP
+
+#endif // ifndef X265_WINXP_H


More information about the x265-devel mailing list