Add CPU core count queries to deThread.h
authorPyry Haulos <phaulos@google.com>
Thu, 9 Apr 2015 23:01:03 +0000 (16:01 -0700)
committerPyry Haulos <phaulos@google.com>
Fri, 10 Apr 2015 19:51:48 +0000 (12:51 -0700)
Change-Id: I87f6af93204d63b0e31f499c1913497d73a58750

framework/delibs/dethread/CMakeLists.txt
framework/delibs/dethread/deThread.h
framework/delibs/dethread/unix/deThreadUnix.c
framework/delibs/dethread/win32/deThreadWin32.c
modules/internal/ditDelibsTests.cpp

index 96f70e3..1be5d7d 100644 (file)
@@ -37,8 +37,14 @@ if (DE_OS_IS_WIN32 OR DE_OS_IS_WINCE)
                win32/deThreadLocalWin32.c
                )
 
-elseif (DE_OS_IS_UNIX OR DE_OS_IS_ANDROID OR DE_OS_IS_SYMBIAN)
-       add_definitions(-D_XOPEN_SOURCE=600)
+elseif (DE_OS_IS_UNIX OR DE_OS_IS_ANDROID)
+       if (DE_OS_IS_UNIX)
+               add_definitions(-D_GNU_SOURCE)
+               set(DETHREAD_LIBS ${DETHREAD_LIBS} pthread)
+       else ()
+               add_definitions(-D_XOPEN_SOURCE=600)
+       endif ()
+
        set(DETHREAD_SRCS
                ${DETHREAD_SRCS}
                unix/deMutexUnix.c
@@ -47,13 +53,6 @@ elseif (DE_OS_IS_UNIX OR DE_OS_IS_ANDROID OR DE_OS_IS_SYMBIAN)
                unix/deThreadLocalUnix.c
                )
 
-       if (DE_OS_IS_UNIX)
-               set(DETHREAD_LIBS ${DETHREAD_LIBS} pthread)
-       elseif (DE_OS_IS_SYMBIAN)
-               find_file(PTHREAD_LIB libpthread.dso PATHS ${SYMBIAN_LIB_DIR} NO_CMAKE_FIND_ROOT_PATH)
-               set(DETHREAD_LIBS ${DETHREAD_LIBS} ${PTHREAD_LIB})
-    endif ()
-
 elseif (DE_OS_IS_OSX OR DE_OS_IS_IOS)
        add_definitions(-D_XOPEN_SOURCE=600)
        # \note OS X doesn't support unnamed semaphores.
index 8ce3eee..1eee465 100644 (file)
@@ -53,12 +53,16 @@ typedef struct deThreadAttributes_s
        deThreadPriority                priority;
 } deThreadAttributes;
 
-void                   deSleep                                 (deUint32 milliseconds);
-void                   deYield                                 (void);
+void                   deSleep                                                 (deUint32 milliseconds);
+void                   deYield                                                 (void);
 
-deThread               deThread_create                 (deThreadFunc func, void* arg, const deThreadAttributes* attributes);
-deBool                 deThread_join                   (deThread thread);
-void                   deThread_destroy                (deThread thread);
+deThread               deThread_create                                 (deThreadFunc func, void* arg, const deThreadAttributes* attributes);
+deBool                 deThread_join                                   (deThread thread);
+void                   deThread_destroy                                (deThread thread);
+
+deUint32               deGetNumTotalPhysicalCores              (void);
+deUint32               deGetNumTotalLogicalCores               (void);
+deUint32               deGetNumAvailableLogicalCores   (void);
 
 DE_END_EXTERN_C
 
index 8e8ee41..4f46ddb 100644 (file)
@@ -28,7 +28,7 @@
 #include "deMemory.h"
 
 #if !defined(_XOPEN_SOURCE) || (_XOPEN_SOURCE < 500)
-#      error You are using too old posix API!
+#      error "You are using too old posix API!"
 #endif
 
 #include <unistd.h>
@@ -147,4 +147,38 @@ void deYield (void)
        sched_yield();
 }
 
+#if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
+
+deUint32 deGetNumAvailableLogicalCores (void)
+{
+       cpu_set_t       cpuSet;
+
+       CPU_ZERO(&cpuSet);
+
+       if (sched_getaffinity(0, sizeof(cpuSet), &cpuSet) != 0)
+               return 1;
+
+       return (deUint32)(CPU_COUNT(&cpuSet));
+}
+
+#else
+
+deUint32 deGetNumAvailableLogicalCores (void)
+{
+       return (deUint32)sysconf(_SC_NPROCESSORS_ONLN);
+}
+
+#endif
+
+deUint32 deGetNumTotalLogicalCores (void)
+{
+       return (deUint32)sysconf(_SC_NPROCESSORS_CONF);
+}
+
+deUint32 deGetNumTotalPhysicalCores (void)
+{
+       /* \todo [2015-04-09 pyry] Parse /proc/cpuinfo perhaps? */
+       return deGetNumTotalLogicalCores();
+}
+
 #endif /* DE_OS */
index 75b1a8b..44120b4 100644 (file)
@@ -26,6 +26,7 @@
 #if (DE_OS == DE_OS_WIN32 || DE_OS == DE_OS_WINCE)
 
 #include "deMemory.h"
+#include "deInt32.h"
 
 #define VC_EXTRALEAN
 #define WIN32_LEAN_AND_MEAN
@@ -115,4 +116,104 @@ void deYield (void)
        SwitchToThread();
 }
 
+static SYSTEM_LOGICAL_PROCESSOR_INFORMATION* getWin32ProcessorInfo (deUint32* numBytes)
+{
+       deUint32                                                                curSize = (deUint32)sizeof(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)*8;
+       SYSTEM_LOGICAL_PROCESSOR_INFORMATION*   info    = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION*)deMalloc(curSize);
+
+       for (;;)
+       {
+               DWORD   inOutLen        = curSize;
+               DWORD   err;
+
+               if (GetLogicalProcessorInformation(info, &inOutLen))
+               {
+                       *numBytes = inOutLen;
+                       return info;
+               }
+               else
+               {
+                       err = GetLastError();
+
+                       if (err == ERROR_INSUFFICIENT_BUFFER)
+                       {
+                               curSize <<= 1;
+                               info = deRealloc(info, curSize);
+                       }
+                       else
+                       {
+                               deFree(info);
+                               return DE_NULL;
+                       }
+               }
+       }
+}
+
+typedef struct ProcessorInfo_s
+{
+       deUint32        numPhysicalCores;
+       deUint32        numLogicalCores;
+} ProcessorInfo;
+
+void parseWin32ProcessorInfo (ProcessorInfo* dst, const SYSTEM_LOGICAL_PROCESSOR_INFORMATION* src, deUint32 numBytes)
+{
+       const SYSTEM_LOGICAL_PROCESSOR_INFORMATION*     cur             = src;
+
+       deMemset(dst, 0, sizeof(ProcessorInfo));
+
+       while (((const deUint8*)cur - (const deUint8*)src) + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= numBytes)
+       {
+               if (cur->Relationship == RelationProcessorCore)
+               {
+                       dst->numPhysicalCores   += 1;
+#if (DE_PTR_SIZE == 8)
+                       dst->numLogicalCores    += dePop64(cur->ProcessorMask);
+#else
+                       dst->numLogicalCores    += dePop32(cur->ProcessorMask);
+#endif
+               }
+
+               cur++;
+       }
+}
+
+deBool getProcessorInfo (ProcessorInfo* info)
+{
+       deUint32                                                                numBytes        = 0;
+       SYSTEM_LOGICAL_PROCESSOR_INFORMATION*   rawInfo         = getWin32ProcessorInfo(&numBytes);
+
+       if (!numBytes)
+               return DE_FALSE;
+
+       parseWin32ProcessorInfo(info, rawInfo, numBytes);
+       deFree(rawInfo);
+
+       return DE_TRUE;
+}
+
+deUint32 deGetNumTotalPhysicalCores (void)
+{
+       ProcessorInfo   info;
+
+       if (!getProcessorInfo(&info))
+               return 1u;
+
+       return info.numPhysicalCores;
+}
+
+deUint32 deGetNumTotalLogicalCores (void)
+{
+       ProcessorInfo   info;
+
+       if (!getProcessorInfo(&info))
+               return 1u;
+
+       return info.numLogicalCores;
+}
+
+deUint32 deGetNumAvailableLogicalCores (void)
+{
+       return deGetNumTotalLogicalCores();
+}
+
 #endif /* DE_OS */
index 5e95336..bdda4ff 100644 (file)
@@ -22,6 +22,7 @@
  *//*--------------------------------------------------------------------*/
 
 #include "ditDelibsTests.hpp"
+#include "tcuTestLog.hpp"
 
 // depool
 #include "dePoolArray.h"
@@ -34,6 +35,7 @@
 
 // dethread
 #include "deThreadTest.h"
+#include "deThread.h"
 
 // deutil
 #include "deTimerTest.h"
@@ -54,6 +56,8 @@
 namespace dit
 {
 
+using tcu::TestLog;
+
 class DepoolTests : public tcu::TestCaseGroup
 {
 public:
@@ -74,6 +78,31 @@ public:
        }
 };
 
+extern "C"
+{
+typedef deUint32       (*GetUint32Func)        (void);
+}
+
+class GetUint32Case : public tcu::TestCase
+{
+public:
+       GetUint32Case (tcu::TestContext& testCtx, const char* name, const char* description, GetUint32Func func)
+               : tcu::TestCase (testCtx, name, description)
+               , m_func                (func)
+       {
+       }
+
+       IterateResult iterate (void)
+       {
+               m_testCtx.getLog() << TestLog::Message << getDescription() << " returned " << m_func() << TestLog::EndMessage;
+               m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+               return STOP;
+       }
+
+private:
+       GetUint32Func   m_func;
+};
+
 class DethreadTests : public tcu::TestCaseGroup
 {
 public:
@@ -84,11 +113,14 @@ public:
 
        void init (void)
        {
-               addChild(new SelfCheckCase(m_testCtx, "thread",         "deThread_selfTest()",          deThread_selfTest));
-               addChild(new SelfCheckCase(m_testCtx, "mutex",          "deMutex_selfTest()",           deMutex_selfTest));
-               addChild(new SelfCheckCase(m_testCtx, "semaphore",      "deSemaphore_selfTest()",       deSemaphore_selfTest));
-               addChild(new SelfCheckCase(m_testCtx, "atomic",         "deAtomic_selfTest()",          deAtomic_selfTest));
-               addChild(new SelfCheckCase(m_testCtx, "singleton",      "deSingleton_selfTest()",       deSingleton_selfTest));
+               addChild(new SelfCheckCase(m_testCtx, "thread",                                         "deThread_selfTest()",                          deThread_selfTest));
+               addChild(new SelfCheckCase(m_testCtx, "mutex",                                          "deMutex_selfTest()",                           deMutex_selfTest));
+               addChild(new SelfCheckCase(m_testCtx, "semaphore",                                      "deSemaphore_selfTest()",                       deSemaphore_selfTest));
+               addChild(new SelfCheckCase(m_testCtx, "atomic",                                         "deAtomic_selfTest()",                          deAtomic_selfTest));
+               addChild(new SelfCheckCase(m_testCtx, "singleton",                                      "deSingleton_selfTest()",                       deSingleton_selfTest));
+               addChild(new GetUint32Case(m_testCtx, "total_physical_cores",           "deGetNumTotalPhysicalCores()",         deGetNumTotalPhysicalCores));
+               addChild(new GetUint32Case(m_testCtx, "total_logical_cores",            "deGetNumTotalLogicalCores()",          deGetNumTotalLogicalCores));
+               addChild(new GetUint32Case(m_testCtx, "available_logical_cores",        "deGetNumAvailableLogicalCores()",      deGetNumAvailableLogicalCores));
        }
 };