0027854: Foundation Classes - OSD_Parallel::NbLogicalProcessors() should handle Andro...
authorkgv <kgv@opencascade.com>
Thu, 8 Sep 2016 19:54:54 +0000 (22:54 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 15 Sep 2016 08:55:53 +0000 (11:55 +0300)
Read CPU info from sysfs.

src/OSD/OSD_Parallel.cxx

index 28de4c6..2a6cbf2 100644 (file)
 #include <OSD_Parallel.hxx>
 
 #ifdef _WIN32
-    #include <windows.h>
-    #include <process.h>
+  #include <windows.h>
+  #include <process.h>
 #else
-    #include <sys/types.h>
-
-    #ifdef __sun
-        #include <sys/processor.h>
-        #include <sys/procset.h>
-    #else
-        #include <sched.h>
-    #endif
+  #include <sys/types.h>
+
+  #ifdef __sun
+    #include <sys/processor.h>
+    #include <sys/procset.h>
+  #else
+    #include <sched.h>
+  #endif
 #endif
 
-#if defined(_WIN32) && !defined(OCCT_UWP)
 namespace {
-  // for a 64-bit app running under 64-bit Windows, this is FALSE
+
+#if defined(_WIN32) && !defined(OCCT_UWP)
+  //! For a 64-bit app running under 64-bit Windows, this is FALSE.
   static bool isWow64()
   {
     typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE , PBOOL);
@@ -46,9 +47,131 @@ namespace {
            aFunIsWow64(GetCurrentProcess(), &bIsWow64) &&
            bIsWow64 != FALSE;
   }
-}
+
+#elif defined(__ANDROID__)
+
+  //! Simple number parser.
+  static const char* parseNumber (int&        theResult,
+                                  const char* theInput,
+                                  const char* theLimit,
+                                  const int   theBase = 10)
+  {
+    const char* aCharIter = theInput;
+    int aValue = 0;
+    while (aCharIter < theLimit)
+    {
+      int aDigit = (*aCharIter - '0');
+      if ((unsigned int )aDigit >= 10U)
+      {
+        aDigit = (*aCharIter - 'a');
+        if ((unsigned int )aDigit >= 6U)
+        {
+          aDigit = (*aCharIter - 'A');
+        }
+        if ((unsigned int )aDigit >= 6U)
+        {
+          break;
+        }
+        aDigit += 10;
+      }
+      if (aDigit >= theBase)
+      {
+        break;
+      }
+      aValue = aValue * theBase + aDigit;
+      ++aCharIter;
+    }
+    if (aCharIter == theInput)
+    {
+      return NULL;
+    }
+
+    theResult = aValue;
+    return aCharIter;
+  }
+
+  //! Read CPUs mask from sysfs.
+  static uint32_t readCpuMask (const char* thePath)
+  {
+    FILE* aFileHandle = fopen (thePath, "rb");
+    if (aFileHandle == NULL)
+    {
+      return 0;
+    }
+
+    fseek (aFileHandle, 0, SEEK_END);
+    long aFileLen = ftell (aFileHandle);
+    if (aFileLen <= 0L)
+    {
+      fclose (aFileHandle);
+      return 0;
+    }
+
+    char* aBuffer = (char* )Standard::Allocate (aFileLen);
+    if (aBuffer == NULL)
+    {
+      return 0;
+    }
+
+    fseek (aFileHandle, 0, SEEK_SET);
+    size_t aCountRead = fread (aBuffer, 1, aFileLen, aFileHandle);
+    (void )aCountRead;
+    fclose (aFileHandle);
+
+    uint32_t aCpuMask = 0;
+    const char* anEnd = aBuffer + aFileLen;
+    for (const char* aCharIter = aBuffer; aCharIter < anEnd && *aCharIter != '\n';)
+    {
+      const char* aChunkEnd = (const char* )::memchr (aCharIter, ',', anEnd - aCharIter);
+      if (aChunkEnd == NULL)
+      {
+        aChunkEnd = anEnd;
+      }
+
+      // get first value
+      int anIndexLower = 0;
+      aCharIter = parseNumber (anIndexLower, aCharIter, aChunkEnd);
+      if (aCharIter == NULL)
+      {
+        Standard::Free (aBuffer);
+        return aCpuMask;
+      }
+
+      // if we're not at the end of the item, expect a dash and and integer; extract end value.
+      int anIndexUpper = anIndexLower;
+      if (aCharIter < aChunkEnd && *aCharIter == '-')
+      {
+        aCharIter = parseNumber (anIndexUpper, aCharIter + 1, aChunkEnd);
+        if (aCharIter == NULL)
+        {
+          Standard::Free (aBuffer);
+          return aCpuMask;
+        }
+      }
+
+      // set bits CPU list
+      for (int aCpuIndex = anIndexLower; aCpuIndex <= anIndexUpper; ++aCpuIndex)
+      {
+        if ((unsigned int )aCpuIndex < 32)
+        {
+          aCpuMask |= (uint32_t )(1U << aCpuIndex);
+        }
+      }
+
+      aCharIter = aChunkEnd;
+      if (aCharIter < anEnd)
+      {
+        ++aCharIter;
+      }
+    }
+
+    Standard::Free (aBuffer);
+    return aCpuMask;
+  }
 #endif
 
+}
+
 //=======================================================================
 //function : NbLogicalProcessors
 //purpose  : Returns number of logical proccessors.
@@ -90,6 +213,18 @@ Standard_Integer OSD_Parallel::NbLogicalProcessors()
 #endif
   aNumLogicalProcessors = aSysInfo.dwNumberOfProcessors;
 #else
+
+#if defined(__ANDROID__)
+  uint32_t aCpuMaskPresent  = readCpuMask ("/sys/devices/system/cpu/present");
+  uint32_t aCpuMaskPossible = readCpuMask ("/sys/devices/system/cpu/possible");
+  aCpuMaskPresent &= aCpuMaskPossible;
+  aNumLogicalProcessors = __builtin_popcount (aCpuMaskPresent);
+  if (aNumLogicalProcessors >= 1)
+  {
+    return aNumLogicalProcessors;
+  }
+#endif
+
   // These are the choices. We'll check number of processors online.
   // _SC_NPROCESSORS_CONF   Number of processors configured
   // _SC_NPROCESSORS_MAX    Max number of processors supported by platform