derekf pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=13da63d26052b2839f2605fe20193a0da7fcea84

commit 13da63d26052b2839f2605fe20193a0da7fcea84
Author: Derek Foreman <der...@osg.samsung.com>
Date:   Thu Sep 15 16:02:10 2016 -0500

    eina_cpu: Add an internal api for getting a random fast core
    
    In a big.LITTLE ARM system cores can have different capabilities.  This
    gives an internal API that randomly returns the core id of any of the
    system's fastest cores.
    
    On systems where all cores are the same, it will return any available core.
    
    If we don't have cpufreq support we just return 0
---
 src/Makefile_Eina.am            |   1 +
 src/lib/eina/eina_cpu.c         | 106 ++++++++++++++++++++++++++++++++++++++++
 src/lib/eina/eina_cpu_private.h |  35 +++++++++++++
 3 files changed, 142 insertions(+)

diff --git a/src/Makefile_Eina.am b/src/Makefile_Eina.am
index 020052a..b442635 100644
--- a/src/Makefile_Eina.am
+++ b/src/Makefile_Eina.am
@@ -58,6 +58,7 @@ lib/eina/eina_trash.h \
 lib/eina/eina_iterator.h \
 lib/eina/eina_main.h \
 lib/eina/eina_cpu.h \
+lib/eina/eina_cpu_private.h \
 lib/eina/eina_inline_cpu.x \
 lib/eina/eina_sched.h \
 lib/eina/eina_tiler.h \
diff --git a/src/lib/eina/eina_cpu.c b/src/lib/eina/eina_cpu.c
index e6b9921..fe39861 100644
--- a/src/lib/eina/eina_cpu.c
+++ b/src/lib/eina/eina_cpu.c
@@ -49,12 +49,20 @@
 #include "eina_log.h"
 #include "eina_cpu.h"
 
+#include <Eina.h>
+
+#include "eina_cpu_private.h"
+
 /*============================================================================*
 *                                  Local                                     *
 *============================================================================*/
 
 static void _eina_page_size(void);
 
+static int fastest_core_speed = 0;
+static int slowest_core_speed = INT_MAX;
+static Eina_Hash *cpu_hash = NULL;
+
 /* FIXME this ifdefs should be replaced */
 #if defined(__i386__) || defined(__x86_64__)
 /* We save ebx and restore it to be PIC compatible */
@@ -151,6 +159,9 @@ eina_cpu_init(void)
 Eina_Bool
 eina_cpu_shutdown(void)
 {
+   eina_hash_free(cpu_hash);
+   cpu_hash = NULL;
+   fastest_core_speed = 0;
    return EINA_TRUE;
 }
 
@@ -286,3 +297,98 @@ void eina_cpu_count_internal(void)
    else
      _cpu_count = _eina_cpu_count_internal();
 }
+
+static void
+eina_cpu_map_init(void)
+{
+   fastest_core_speed = -1;
+
+#if defined (__linux__) || defined(__GLIBC__)
+   Eina_Iterator *it;
+   Eina_Strbuf *fname;
+   const Eina_File_Direct_Info *f_info;
+
+   it = eina_file_stat_ls("/sys/devices/system/cpu/cpufreq");
+   if (!it) return;
+
+   cpu_hash = eina_hash_int32_new(free);
+
+   fname = eina_strbuf_new();
+   EINA_ITERATOR_FOREACH(it, f_info)
+     {
+        if ((f_info->type == EINA_FILE_DIR) &&
+            eina_str_has_prefix(f_info->path,
+                                "/sys/devices/system/cpu/cpufreq/policy"))
+          {
+             FILE *f;
+             int num, speed;
+
+             eina_strbuf_append_printf(fname, "%s%s", f_info->path, 
"/cpuinfo_max_freq");
+             f = fopen(eina_strbuf_string_get(fname), "r");
+             eina_strbuf_reset(fname);
+             if (!f) goto err;
+             speed = -1;
+             num = fscanf(f, "%d", &speed);
+             fclose(f);
+             if ((num != 1) || (speed == -1)) goto err;
+
+             slowest_core_speed = MIN(speed, slowest_core_speed);
+             fastest_core_speed = MAX(speed, fastest_core_speed);
+
+             eina_strbuf_append_printf(fname, "%s%s", f_info->path, 
"/affected_cpus");
+             f = fopen(eina_strbuf_string_get(fname), "r");
+             eina_strbuf_reset(fname);
+             if (!f) goto err;
+             do
+               {
+                  int core;
+                  uint64_t *corelist;
+                  num = fscanf(f, "%d", &core);
+                  if ((num == EOF) || (core > 63)) break;
+
+                  corelist = eina_hash_find(cpu_hash, &speed);
+                  if (!corelist)
+                    {
+                       corelist = malloc(sizeof(*corelist));
+                       if (!corelist) goto err;
+                       *corelist = 1 << core;
+                       eina_hash_add(cpu_hash, &speed, corelist);
+                    }
+                  *corelist |= 1 << core;
+               } while (num != EOF);
+             fclose(f);
+          }
+     }
+err:
+   eina_strbuf_free(fname);
+   eina_iterator_free(it);
+#endif
+}
+
+EAPI int
+_eina_cpu_fast_core_get(void)
+{
+#if defined (__linux__) || defined(__GLIBC__)
+   uint64_t *corelist;
+   uint64_t cores;
+   int bit, place = 0;
+
+   if (fastest_core_speed == -1) return -1;
+
+   if (fastest_core_speed == 0) eina_cpu_map_init();
+
+   corelist = eina_hash_find(cpu_hash, &fastest_core_speed);
+   cores = *corelist;
+   bit = rand() % __builtin_popcount(cores);
+   while (bit || !(cores & 1))
+     {
+        if (cores & 1) bit--;
+        cores = cores >> 1;
+        place++;
+     }
+
+   return place;
+#else
+   return 0;
+#endif
+}
diff --git a/src/lib/eina/eina_cpu_private.h b/src/lib/eina/eina_cpu_private.h
new file mode 100644
index 0000000..667f0a7
--- /dev/null
+++ b/src/lib/eina/eina_cpu_private.h
@@ -0,0 +1,35 @@
+#ifndef EINA_CPU_PRIVATE_H_
+#define EINA_CPU_PRIVATE_H_
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef EFL_ECORE_BUILD
+#  ifdef DLL_EXPORT
+#   define EAPI __declspec(dllexport)
+#  else
+#   define EAPI
+#  endif /* ! DLL_EXPORT */
+# else
+#  define EAPI __declspec(dllimport)
+# endif /* ! EFL_ECORE_BUILD */
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif /* ! _WIN32 */
+
+EAPI int _eina_cpu_fast_core_get(void);
+
+#undef EAPI
+#define EAPI
+
+#endif

-- 


Reply via email to