forked from enlightenment/efl
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:
parent
1881b0d343
commit
13da63d260
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue