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
This commit is contained in:
Derek Foreman 2016-09-15 16:02:10 -05:00
parent 1881b0d343
commit 13da63d260
3 changed files with 142 additions and 0 deletions

View File

@ -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 \

View File

@ -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
}

View File

@ -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